Committed underlay support (from Audun).
git-svn-id: svn://localhost/ardour2/branches/3.0@3037 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
e76b028ffd
commit
1b65758557
|
@ -348,6 +348,8 @@ AudioRegionView::region_renamed ()
|
|||
void
|
||||
AudioRegionView::region_resized (Change what_changed)
|
||||
{
|
||||
AudioGhostRegion* agr;
|
||||
|
||||
RegionView::region_resized(what_changed);
|
||||
|
||||
if (what_changed & Change (StartChanged|LengthChanged)) {
|
||||
|
@ -357,10 +359,12 @@ AudioRegionView::region_resized (Change what_changed)
|
|||
}
|
||||
|
||||
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
if((agr = dynamic_cast<AudioGhostRegion*>(*i)) != 0) {
|
||||
|
||||
for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
|
||||
(*w)->property_region_start() = _region->start();
|
||||
}
|
||||
for (vector<WaveView*>::iterator w = agr->waves.begin(); w != agr->waves.end(); ++w) {
|
||||
(*w)->property_region_start() = _region->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1078,13 +1082,13 @@ AudioRegionView::set_waveform_scale (WaveformScale scale)
|
|||
|
||||
|
||||
GhostRegion*
|
||||
AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
|
||||
AudioRegionView::add_ghost (TimeAxisView& tv)
|
||||
{
|
||||
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&trackview);
|
||||
assert(rtv);
|
||||
|
||||
double unit_position = _region->position () / samples_per_unit;
|
||||
GhostRegion* ghost = new GhostRegion (atv, unit_position);
|
||||
AudioGhostRegion* ghost = new AudioGhostRegion (tv, trackview, unit_position);
|
||||
uint32_t nchans;
|
||||
|
||||
nchans = rtv->get_diskstream()->n_channels().n_audio();
|
||||
|
@ -1107,10 +1111,7 @@ AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
|
|||
wave->property_x() = 0.0;
|
||||
wave->property_samples_per_unit() = samples_per_unit;
|
||||
wave->property_amplitude_above_axis() = _amplitude_above_axis;
|
||||
wave->property_wave_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWave.get();
|
||||
wave->property_fill_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWave.get();
|
||||
wave->property_clip_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWaveClip.get();
|
||||
wave->property_zero_color() = ARDOUR_UI::config()->canvasvar_GhostTrackZeroLine.get();
|
||||
|
||||
wave->property_region_start() = _region->start();
|
||||
|
||||
ghost->waves.push_back(wave);
|
||||
|
@ -1118,6 +1119,7 @@ AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
|
|||
|
||||
ghost->set_height ();
|
||||
ghost->set_duration (_region->length() / samples_per_unit);
|
||||
ghost->set_colors();
|
||||
ghosts.push_back (ghost);
|
||||
|
||||
ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
|
||||
|
@ -1170,7 +1172,7 @@ AudioRegionView::envelope_active_changed ()
|
|||
void
|
||||
AudioRegionView::set_waveview_data_src()
|
||||
{
|
||||
|
||||
AudioGhostRegion* agr;
|
||||
double unit_length= _region->length() / samples_per_unit;
|
||||
|
||||
for (uint32_t n = 0; n < waves.size(); ++n) {
|
||||
|
@ -1182,8 +1184,10 @@ AudioRegionView::set_waveview_data_src()
|
|||
|
||||
(*i)->set_duration (unit_length);
|
||||
|
||||
for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
|
||||
(*w)->property_data_src() = _region.get();
|
||||
if((agr = dynamic_cast<AudioGhostRegion*>(*i)) != 0) {
|
||||
for (vector<WaveView*>::iterator w = agr->waves.begin(); w != agr->waves.end(); ++w) {
|
||||
(*w)->property_data_src() = _region.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class AudioRegionView : public RegionView
|
|||
void region_changed (ARDOUR::Change);
|
||||
void envelope_active_changed ();
|
||||
|
||||
GhostRegion* add_ghost (AutomationTimeAxisView&);
|
||||
GhostRegion* add_ghost (TimeAxisView&);
|
||||
|
||||
void reset_fade_in_shape_width (nframes_t);
|
||||
void reset_fade_out_shape_width (nframes_t);
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace ARDOUR {
|
|||
class AutomationList;
|
||||
};
|
||||
|
||||
class AutomationTimeAxisView;
|
||||
class TimeAxisView;
|
||||
|
||||
class AutomationRegionView : public RegionView
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
boost::shared_ptr<AutomationLine> line() { return _line; }
|
||||
|
||||
// We are a ghost. Meta ghosts? Crazy talk.
|
||||
virtual GhostRegion* add_ghost(AutomationTimeAxisView&) { return NULL; }
|
||||
virtual GhostRegion* add_ghost(TimeAxisView&) { return NULL; }
|
||||
|
||||
void reset_width_dependent_items(double pixel_width);
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "public_editor.h"
|
||||
#include "simplerect.h"
|
||||
#include "selection.h"
|
||||
#include "ghostregion.h"
|
||||
#include "rgb_macros.h"
|
||||
#include "automation_selectable.h"
|
||||
#include "point_selection.h"
|
||||
|
@ -74,7 +73,6 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
|
|||
}
|
||||
|
||||
automation_menu = 0;
|
||||
in_destructor = false;
|
||||
auto_off_item = 0;
|
||||
auto_touch_item = 0;
|
||||
auto_write_item = 0;
|
||||
|
@ -228,11 +226,6 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
|
|||
|
||||
AutomationTimeAxisView::~AutomationTimeAxisView ()
|
||||
{
|
||||
in_destructor = true;
|
||||
|
||||
for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -399,10 +392,6 @@ AutomationTimeAxisView::set_height (TrackHeight ht)
|
|||
_view->update_contents_y_position_and_height();
|
||||
}
|
||||
|
||||
for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
(*i)->set_height ();
|
||||
}
|
||||
|
||||
TimeAxisView* state_parent = get_parent_with_state ();
|
||||
assert(state_parent);
|
||||
|
||||
|
@ -801,30 +790,6 @@ AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float ti
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::add_ghost (GhostRegion* gr)
|
||||
{
|
||||
ghosts.push_back (gr);
|
||||
gr->GoingAway.connect (mem_fun(*this, &AutomationTimeAxisView::remove_ghost));
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::remove_ghost (GhostRegion* gr)
|
||||
{
|
||||
if (in_destructor) {
|
||||
return;
|
||||
}
|
||||
|
||||
list<GhostRegion*>::iterator i;
|
||||
|
||||
for (i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
if ((*i) == gr) {
|
||||
ghosts.erase (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
|
||||
{
|
||||
|
@ -916,7 +881,7 @@ AutomationTimeAxisView::exited ()
|
|||
_line->track_exited();
|
||||
}
|
||||
|
||||
void
|
||||
/*void
|
||||
AutomationTimeAxisView::set_colors ()
|
||||
{
|
||||
for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
|
||||
|
@ -925,12 +890,14 @@ AutomationTimeAxisView::set_colors ()
|
|||
|
||||
if (_line)
|
||||
_line->set_colors();
|
||||
}
|
||||
}*/
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::color_handler ()
|
||||
{
|
||||
set_colors ();
|
||||
if (_line) {
|
||||
_line->set_colors();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -50,7 +50,6 @@ class TimeSelection;
|
|||
class RegionSelection;
|
||||
class PointSelection;
|
||||
class AutomationLine;
|
||||
class GhostRegion;
|
||||
class Selection;
|
||||
class Selectable;
|
||||
class AutomationStreamView;
|
||||
|
@ -95,9 +94,6 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
bool paste (nframes_t, float times, Selection&, size_t nth);
|
||||
void reset_objects (PointSelection&);
|
||||
|
||||
void add_ghost (GhostRegion*);
|
||||
void remove_ghost (GhostRegion*);
|
||||
|
||||
void set_state (const XMLNode&);
|
||||
|
||||
guint32 show_at (double y, int& nth, Gtk::VBox *parent);
|
||||
|
@ -121,7 +117,6 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
AutomationStreamView* _view;
|
||||
|
||||
string _name;
|
||||
bool in_destructor;
|
||||
bool ignore_toggle;
|
||||
|
||||
bool first_call_to_set_height;
|
||||
|
@ -151,8 +146,6 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
|
||||
void build_display_menu ();
|
||||
|
||||
list<GhostRegion*> ghosts;
|
||||
|
||||
bool cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
|
||||
bool cut_copy_clear_objects_one (AutomationLine&, PointSelection&, Editing::CutCopyOp);
|
||||
bool paste_one (AutomationLine&, nframes_t, float times, Selection&, size_t nth);
|
||||
|
@ -173,7 +166,7 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
void entered ();
|
||||
void exited ();
|
||||
|
||||
void set_colors ();
|
||||
//void set_colors ();
|
||||
void color_handler ();
|
||||
|
||||
static Pango::FontDescription* name_font;
|
||||
|
|
|
@ -15,6 +15,7 @@ CANVAS_VARIABLE(canvasvar_CrossfadeEditorLineShading, "crossfade editor line sha
|
|||
CANVAS_VARIABLE(canvasvar_CrossfadeEditorPointFill, "crossfade editor point fill")
|
||||
CANVAS_VARIABLE(canvasvar_CrossfadeEditorPointOutline, "crossfade editor point outline")
|
||||
CANVAS_VARIABLE(canvasvar_CrossfadeEditorWave, "crossfade editor wave")
|
||||
CANVAS_VARIABLE(canvasvar_SelectedCrossfadeEditorWaveFill, "selected crossfade editor wave fill")
|
||||
CANVAS_VARIABLE(canvasvar_CrossfadeLine, "crossfade line")
|
||||
CANVAS_VARIABLE(canvasvar_EditPoint, "edit point")
|
||||
CANVAS_VARIABLE(canvasvar_EnteredAutomationLine, "entered automation line")
|
||||
|
@ -28,8 +29,10 @@ CANVAS_VARIABLE(canvasvar_FrameHandle, "frame handle")
|
|||
CANVAS_VARIABLE(canvasvar_GainLine, "gain line")
|
||||
CANVAS_VARIABLE(canvasvar_GainLineInactive, "gain line inactive")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackBase, "ghost track base")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackWaveClip, "ghost track wave clip")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackMidiOutline, "ghost track midi outline")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackWave, "ghost track wave")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackWaveFill, "ghost track wave fill")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackWaveClip, "ghost track wave clip")
|
||||
CANVAS_VARIABLE(canvasvar_GhostTrackZeroLine, "ghost track zero line")
|
||||
CANVAS_VARIABLE(canvasvar_ImageTrack, "image track")
|
||||
CANVAS_VARIABLE(canvasvar_InactiveCrossfade, "inactive crossfade")
|
||||
|
|
|
@ -521,9 +521,10 @@ Editor::Editor ()
|
|||
route_list_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
|
||||
route_list_display.set_headers_visible (true);
|
||||
route_list_display.set_name ("TrackListDisplay");
|
||||
route_list_display.get_selection()->set_mode (SELECTION_NONE);
|
||||
route_list_display.get_selection()->set_mode (SELECTION_SINGLE);
|
||||
route_list_display.set_reorderable (true);
|
||||
route_list_display.set_size_request (100,-1);
|
||||
route_list_display.add_object_drag (route_display_columns.route.index(), "routes");
|
||||
|
||||
CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (0));
|
||||
route_list_visible_cell->property_activatable() = true;
|
||||
|
@ -1537,6 +1538,10 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
|
|||
|
||||
}
|
||||
|
||||
if (item_type == StreamItem && clicked_routeview) {
|
||||
clicked_routeview->build_underlay_menu(menu);
|
||||
}
|
||||
|
||||
menu->popup (button, time);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,8 @@ class Editor : public PublicEditor
|
|||
TimeAxisView* get_named_time_axis(const std::string & name) ;
|
||||
#endif
|
||||
|
||||
RouteTimeAxisView* get_route_view_by_id (PBD::ID& id);
|
||||
|
||||
void consider_auditioning (boost::shared_ptr<ARDOUR::Region>);
|
||||
void hide_a_region (boost::shared_ptr<ARDOUR::Region>);
|
||||
void remove_a_region (boost::shared_ptr<ARDOUR::Region>);
|
||||
|
@ -313,6 +315,7 @@ class Editor : public PublicEditor
|
|||
bool dragging_playhead () const { return _dragging_playhead; }
|
||||
|
||||
void toggle_waveform_visibility ();
|
||||
void toggle_zero_line_visibility ();
|
||||
void toggle_waveforms_while_recording ();
|
||||
void toggle_measure_visibility ();
|
||||
void toggle_logo_visibility ();
|
||||
|
@ -1111,6 +1114,8 @@ class Editor : public PublicEditor
|
|||
void insert_region_list_drag (boost::shared_ptr<ARDOUR::Region>, int x, int y);
|
||||
void insert_region_list_selection (float times);
|
||||
|
||||
void insert_route_list_drag (boost::shared_ptr<ARDOUR::Route>, int x, int y);
|
||||
|
||||
/* import & embed */
|
||||
|
||||
void add_external_audio_action (Editing::ImportMode);
|
||||
|
@ -1870,6 +1875,13 @@ class Editor : public PublicEditor
|
|||
guint info,
|
||||
guint time);
|
||||
|
||||
void drop_routes (const Glib::RefPtr<Gdk::DragContext>& context,
|
||||
gint x,
|
||||
gint y,
|
||||
const Gtk::SelectionData& data,
|
||||
guint info,
|
||||
guint time);
|
||||
|
||||
/* audio export */
|
||||
|
||||
ExportDialog *export_dialog;
|
||||
|
|
|
@ -127,6 +127,7 @@ Editor::initialize_canvas ()
|
|||
|
||||
// Drag-N-Drop from the region list can generate this target
|
||||
target_table.push_back (TargetEntry ("regions"));
|
||||
target_table.push_back (TargetEntry ("routes"));
|
||||
|
||||
target_table.push_back (TargetEntry ("text/plain"));
|
||||
target_table.push_back (TargetEntry ("text/uri-list"));
|
||||
|
@ -457,7 +458,11 @@ Editor::track_canvas_drag_data_received (const RefPtr<Gdk::DragContext>& context
|
|||
|
||||
if (data.get_target() == "regions") {
|
||||
drop_regions (context, x, y, data, info, time);
|
||||
} else {
|
||||
}
|
||||
else if(data.get_target() == "routes") {
|
||||
drop_routes (context, x, y, data, info, time);
|
||||
}
|
||||
else {
|
||||
drop_paths (context, x, y, data, info, time);
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +545,22 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& context,
|
|||
context->drag_finish (true, false, time);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::drop_routes (const Glib::RefPtr<Gdk::DragContext>& context,
|
||||
int x, int y,
|
||||
const Gtk::SelectionData& data,
|
||||
guint info, guint time) {
|
||||
const SerializedObjectPointers<boost::shared_ptr<Route> >* sr =
|
||||
reinterpret_cast<const SerializedObjectPointers<boost::shared_ptr<Route> > *> (data.get_data());
|
||||
|
||||
for (uint32_t i = 0; i < sr->cnt; ++i) {
|
||||
boost::shared_ptr<Route> r = sr->data[i];
|
||||
insert_route_list_drag (r, x, y);
|
||||
}
|
||||
|
||||
context->drag_finish (true, false, time);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::maybe_autoscroll (GdkEvent* event)
|
||||
{
|
||||
|
|
|
@ -2095,6 +2095,48 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
|
|||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) {
|
||||
double wx, wy;
|
||||
double cx, cy;
|
||||
TimeAxisView *tv;
|
||||
nframes_t where;
|
||||
RouteTimeAxisView *dest_rtv = 0;
|
||||
RouteTimeAxisView *source_rtv = 0;
|
||||
|
||||
track_canvas.window_to_world (x, y, wx, wy);
|
||||
wx += horizontal_adjustment.get_value();
|
||||
wy += vertical_adjustment.get_value();
|
||||
|
||||
GdkEvent event;
|
||||
event.type = GDK_BUTTON_RELEASE;
|
||||
event.button.x = wx;
|
||||
event.button.y = wy;
|
||||
|
||||
where = event_frame (&event, &cx, &cy);
|
||||
|
||||
if ((tv = trackview_by_y_position (cy)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dest_rtv = dynamic_cast<RouteTimeAxisView*>(tv)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* use this drag source to add underlay to a track. But we really don't care
|
||||
about the Route, only the view of the route, so find it first */
|
||||
for(TrackViewList::iterator it = track_views.begin(); it != track_views.end(); ++it) {
|
||||
if((source_rtv = dynamic_cast<RouteTimeAxisView*>(*it)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(source_rtv->route() == route && source_rtv != dest_rtv) {
|
||||
dest_rtv->add_underlay(source_rtv->view());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::insert_region_list_selection (float times)
|
||||
{
|
||||
|
|
|
@ -613,3 +613,20 @@ Editor::route_list_display_drag_data_received (const RefPtr<Gdk::DragContext>& c
|
|||
cerr << "some other kind of drag\n";
|
||||
context->drag_finish (true, false, time);
|
||||
}
|
||||
|
||||
|
||||
RouteTimeAxisView*
|
||||
Editor::get_route_view_by_id (PBD::ID& id)
|
||||
{
|
||||
RouteTimeAxisView* v;
|
||||
|
||||
for(TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
|
||||
if(v->route()->id() == id) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,23 +20,23 @@
|
|||
#include "simplerect.h"
|
||||
#include "waveview.h"
|
||||
#include "ghostregion.h"
|
||||
#include "midi_time_axis.h"
|
||||
#include "automation_time_axis.h"
|
||||
#include "midi_streamview.h"
|
||||
#include "rgb_macros.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "canvas-hit.h"
|
||||
#include "canvas-note.h"
|
||||
|
||||
using namespace Editing;
|
||||
using namespace ArdourCanvas;
|
||||
using namespace ARDOUR;
|
||||
|
||||
GhostRegion::GhostRegion (AutomationTimeAxisView& atv, double initial_pos)
|
||||
: trackview (atv)
|
||||
GhostRegion::GhostRegion (ArdourCanvas::Group* parent, TimeAxisView& tv, TimeAxisView& source_tv, double initial_pos)
|
||||
: trackview (tv)
|
||||
, source_trackview (source_tv)
|
||||
{
|
||||
//group = gnome_canvas_item_new (GNOME_CANVAS_GROUP(trackview.canvas_display),
|
||||
// gnome_canvas_group_get_type(),
|
||||
// "x", initial_pos,
|
||||
// "y", 0.0,
|
||||
// NULL);
|
||||
group = new ArdourCanvas::Group (*trackview.canvas_display);
|
||||
group = new ArdourCanvas::Group (*parent);
|
||||
group->property_x() = initial_pos;
|
||||
group->property_y() = 0.0;
|
||||
|
||||
|
@ -45,11 +45,16 @@ GhostRegion::GhostRegion (AutomationTimeAxisView& atv, double initial_pos)
|
|||
base_rect->property_y1() = (double) 0.0;
|
||||
base_rect->property_y2() = (double) trackview.height;
|
||||
base_rect->property_outline_what() = (guint32) 0;
|
||||
base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackBase.get();
|
||||
base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackBase.get();
|
||||
group->lower_to_bottom ();
|
||||
|
||||
atv.add_ghost (this);
|
||||
if(!is_automation_ghost()) {
|
||||
base_rect->hide();
|
||||
}
|
||||
|
||||
GhostRegion::set_colors();
|
||||
|
||||
/* the parent group of a ghostregion is a dedicated group for ghosts,
|
||||
so the new ghost would want to get to the top of that group*/
|
||||
group->raise_to_top ();
|
||||
}
|
||||
|
||||
GhostRegion::~GhostRegion ()
|
||||
|
@ -59,14 +64,6 @@ GhostRegion::~GhostRegion ()
|
|||
delete group;
|
||||
}
|
||||
|
||||
void
|
||||
GhostRegion::set_samples_per_unit (double spu)
|
||||
{
|
||||
for (vector<WaveView*>::iterator i = waves.begin(); i != waves.end(); ++i) {
|
||||
(*i)->property_samples_per_unit() = spu;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GhostRegion::set_duration (double units)
|
||||
{
|
||||
|
@ -75,12 +72,55 @@ GhostRegion::set_duration (double units)
|
|||
|
||||
void
|
||||
GhostRegion::set_height ()
|
||||
{
|
||||
base_rect->property_y2() = (double) trackview.height;
|
||||
}
|
||||
|
||||
void
|
||||
GhostRegion::set_colors ()
|
||||
{
|
||||
if(is_automation_ghost()) {
|
||||
base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackBase.get();
|
||||
base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackBase.get();
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
GhostRegion::source_track_color(unsigned char alpha) {
|
||||
Gdk::Color color = source_trackview.color();
|
||||
unsigned char r,g,b ;
|
||||
r = color.get_red()/256;
|
||||
g = color.get_green()/256;
|
||||
b = color.get_blue()/256;
|
||||
return RGBA_TO_UINT(r, g, b, alpha);
|
||||
}
|
||||
|
||||
bool
|
||||
GhostRegion::is_automation_ghost() {
|
||||
return (dynamic_cast<AutomationTimeAxisView*>(&trackview)) != 0;
|
||||
}
|
||||
|
||||
AudioGhostRegion::AudioGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos)
|
||||
: GhostRegion(tv.ghost_group, tv, source_tv, initial_unit_pos) {
|
||||
}
|
||||
|
||||
void
|
||||
AudioGhostRegion::set_samples_per_unit (double spu)
|
||||
{
|
||||
for (vector<WaveView*>::iterator i = waves.begin(); i != waves.end(); ++i) {
|
||||
(*i)->property_samples_per_unit() = spu;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioGhostRegion::set_height ()
|
||||
{
|
||||
gdouble ht;
|
||||
vector<WaveView*>::iterator i;
|
||||
uint32_t n;
|
||||
|
||||
base_rect->property_y2() = (double) trackview.height;
|
||||
GhostRegion::set_height();
|
||||
|
||||
ht = ((trackview.height) / (double) waves.size());
|
||||
|
||||
for (n = 0, i = waves.begin(); i != waves.end(); ++i, ++n) {
|
||||
|
@ -91,16 +131,177 @@ GhostRegion::set_height ()
|
|||
}
|
||||
|
||||
void
|
||||
GhostRegion::set_colors ()
|
||||
AudioGhostRegion::set_colors ()
|
||||
{
|
||||
base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackBase.get();
|
||||
base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackBase.get();
|
||||
GhostRegion::set_colors();
|
||||
guint fill_color;
|
||||
|
||||
for (uint32_t n=0; n < waves.size(); ++n) {
|
||||
waves[n]->property_wave_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWave.get();
|
||||
waves[n]->property_fill_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWave.get();
|
||||
if(is_automation_ghost()) {
|
||||
fill_color = ARDOUR_UI::config()->canvasvar_GhostTrackWaveFill.get();
|
||||
}
|
||||
else {
|
||||
fill_color = source_track_color(200);
|
||||
}
|
||||
|
||||
waves[n]->property_clip_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWaveClip.get();
|
||||
waves[n]->property_zero_color() = ARDOUR_UI::config()->canvasvar_GhostTrackZeroLine.get();
|
||||
}
|
||||
for (uint32_t n=0; n < waves.size(); ++n) {
|
||||
waves[n]->property_wave_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWave.get();
|
||||
waves[n]->property_fill_color() = fill_color;
|
||||
waves[n]->property_clip_color() = ARDOUR_UI::config()->canvasvar_GhostTrackWaveClip.get();
|
||||
waves[n]->property_zero_color() = ARDOUR_UI::config()->canvasvar_GhostTrackZeroLine.get();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the general constructor, and is called when the destination timeaxisview doesn't have
|
||||
* a midistreamview. But what to do when positioning the midi ghost here? For example, there is
|
||||
* no range controller in these tracks. maybe show the whole range.
|
||||
*/
|
||||
MidiGhostRegion::MidiGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos)
|
||||
: GhostRegion(tv.ghost_group, tv, source_tv, initial_unit_pos) {
|
||||
|
||||
base_rect->lower_to_bottom();
|
||||
}
|
||||
|
||||
MidiGhostRegion::MidiGhostRegion(MidiStreamView& msv, TimeAxisView& source_tv, double initial_unit_pos)
|
||||
: GhostRegion(msv.midi_underlay_group, msv.trackview(), source_tv, initial_unit_pos) {
|
||||
|
||||
base_rect->lower_to_bottom();
|
||||
}
|
||||
|
||||
MidiGhostRegion::Event::Event(ArdourCanvas::CanvasMidiEvent* e)
|
||||
: event(e) {
|
||||
}
|
||||
|
||||
MidiGhostRegion::Note::Note(ArdourCanvas::CanvasNote* n, ArdourCanvas::Group* g)
|
||||
: Event(n) {
|
||||
|
||||
rect = new ArdourCanvas::SimpleRect(*g, n->x1(), n->y1(), n->x2(), n->y2());
|
||||
}
|
||||
|
||||
MidiGhostRegion::Note::~Note() {
|
||||
delete rect;
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::Note::x_changed() {
|
||||
rect->property_x1() = event->x1();
|
||||
rect->property_x2() = event->x2();
|
||||
}
|
||||
|
||||
MidiGhostRegion::Hit::Hit(ArdourCanvas::CanvasHit* h, ArdourCanvas::Group*)
|
||||
: Event(h) {
|
||||
cerr << "Hit ghost item does not work yet" << endl;
|
||||
}
|
||||
|
||||
MidiGhostRegion::Hit::~Hit() {
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::Hit::x_changed() {
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::set_samples_per_unit (double spu)
|
||||
{
|
||||
}
|
||||
|
||||
MidiStreamView*
|
||||
MidiGhostRegion::midi_view() {
|
||||
MidiTimeAxisView* mtv;
|
||||
|
||||
if((mtv = dynamic_cast<MidiTimeAxisView*>(&trackview)) != 0) {
|
||||
return mtv->midi_view();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::set_height() {
|
||||
GhostRegion::set_height();
|
||||
update_range();
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::set_colors() {
|
||||
MidiGhostRegion::Note* note;
|
||||
guint fill = source_track_color(200);
|
||||
|
||||
GhostRegion::set_colors();
|
||||
|
||||
for(EventList::iterator it = events.begin(); it != events.end(); ++it) {
|
||||
if((note = dynamic_cast<MidiGhostRegion::Note*>(*it)) != 0) {
|
||||
note->rect->property_fill_color_rgba() = fill;
|
||||
note->rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackMidiOutline.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::update_range() {
|
||||
MidiStreamView* mv = midi_view();
|
||||
|
||||
if(!mv) {
|
||||
return;
|
||||
}
|
||||
|
||||
MidiGhostRegion::Note* note;
|
||||
uint8_t note_num;
|
||||
double y;
|
||||
|
||||
for(EventList::iterator it = events.begin(); it != events.end(); ++it) {
|
||||
if((note = dynamic_cast<MidiGhostRegion::Note*>(*it)) != 0) {
|
||||
note_num = note->event->note()->note();
|
||||
|
||||
if(note_num < mv->lowest_note() || note_num > mv->highest_note()) {
|
||||
note->rect->hide();
|
||||
}
|
||||
else {
|
||||
note->rect->show();
|
||||
y = mv->note_to_y(note_num);
|
||||
note->rect->property_y1() = y;
|
||||
note->rect->property_y2() = y + mv->note_height();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::add_note(ArdourCanvas::CanvasNote* n) {
|
||||
Note* note = new Note(n, group);
|
||||
events.push_back(note);
|
||||
|
||||
note->rect->property_fill_color_rgba() = source_track_color(200);
|
||||
note->rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_GhostTrackMidiOutline.get();
|
||||
|
||||
MidiStreamView* mv = midi_view();
|
||||
|
||||
if(mv) {
|
||||
uint8_t note_num = n->note()->note();
|
||||
double y;
|
||||
|
||||
if(note_num < mv->lowest_note() || note_num > mv->highest_note()) {
|
||||
note->rect->hide();
|
||||
}
|
||||
else {
|
||||
y = mv->note_to_y(note_num);
|
||||
note->rect->property_y1() = y;
|
||||
note->rect->property_y2() = y + mv->note_height();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::add_hit(ArdourCanvas::CanvasHit* h) {
|
||||
//events.push_back(new Hit(h, group));
|
||||
}
|
||||
|
||||
void
|
||||
MidiGhostRegion::clear_events() {
|
||||
for(EventList::iterator it = events.begin(); it != events.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
|
||||
events.clear();
|
||||
}
|
||||
|
|
|
@ -25,26 +25,100 @@
|
|||
#include <libgnomecanvasmm.h>
|
||||
#include <ardour/configuration.h>
|
||||
#include "canvas.h"
|
||||
#include "simplerect.h"
|
||||
|
||||
class AutomationTimeAxisView;
|
||||
namespace Gnome {
|
||||
namespace Canvas {
|
||||
class CanvasMidiEvent;
|
||||
class CanvasNote;
|
||||
class CanvasHit;
|
||||
class Diamond;
|
||||
}
|
||||
}
|
||||
|
||||
struct GhostRegion : public sigc::trackable
|
||||
class MidiStreamView;
|
||||
class TimeAxisView;
|
||||
|
||||
class GhostRegion : public sigc::trackable
|
||||
{
|
||||
AutomationTimeAxisView& trackview;
|
||||
ArdourCanvas::Group* group;
|
||||
ArdourCanvas::SimpleRect* base_rect;
|
||||
std::vector<ArdourCanvas::WaveView*> waves;
|
||||
public:
|
||||
GhostRegion(ArdourCanvas::Group* parent, TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos);
|
||||
virtual ~GhostRegion();
|
||||
|
||||
GhostRegion (AutomationTimeAxisView& tv, double initial_unit_pos);
|
||||
~GhostRegion ();
|
||||
virtual void set_samples_per_unit(double spu) = 0;
|
||||
virtual void set_height();
|
||||
virtual void set_colors();
|
||||
|
||||
void set_samples_per_unit (double spu);
|
||||
void set_duration (double units);
|
||||
void set_height ();
|
||||
void set_colors ();
|
||||
void set_duration(double units);
|
||||
|
||||
sigc::signal<void,GhostRegion*> GoingAway;
|
||||
guint source_track_color(unsigned char alpha = 0xff);
|
||||
bool is_automation_ghost();
|
||||
|
||||
sigc::signal<void,GhostRegion*> GoingAway;
|
||||
|
||||
TimeAxisView& trackview;
|
||||
TimeAxisView& source_trackview;
|
||||
ArdourCanvas::Group* group;
|
||||
ArdourCanvas::SimpleRect* base_rect;
|
||||
};
|
||||
|
||||
class AudioGhostRegion : public GhostRegion {
|
||||
public:
|
||||
AudioGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos);
|
||||
|
||||
void set_samples_per_unit(double spu);
|
||||
void set_height();
|
||||
void set_colors();
|
||||
|
||||
std::vector<ArdourCanvas::WaveView*> waves;
|
||||
};
|
||||
|
||||
class MidiGhostRegion : public GhostRegion {
|
||||
public:
|
||||
class Event : public sigc::trackable {
|
||||
public:
|
||||
Event(ArdourCanvas::CanvasMidiEvent*);
|
||||
virtual ~Event() {}
|
||||
|
||||
virtual void x_changed() = 0;
|
||||
ArdourCanvas::CanvasMidiEvent* event;
|
||||
};
|
||||
|
||||
class Note : public Event {
|
||||
public:
|
||||
Note(ArdourCanvas::CanvasNote*, ArdourCanvas::Group*);
|
||||
~Note();
|
||||
|
||||
void x_changed();
|
||||
ArdourCanvas::SimpleRect* rect;
|
||||
};
|
||||
|
||||
class Hit : public Event {
|
||||
public:
|
||||
Hit(ArdourCanvas::CanvasHit*, ArdourCanvas::Group*);
|
||||
~Hit();
|
||||
|
||||
void x_changed();
|
||||
ArdourCanvas::Diamond* diamond;
|
||||
};
|
||||
|
||||
MidiGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos);
|
||||
MidiGhostRegion(MidiStreamView& msv, TimeAxisView& source_tv, double initial_unit_pos);
|
||||
|
||||
MidiStreamView* midi_view();
|
||||
|
||||
void set_height();
|
||||
void set_samples_per_unit(double spu);
|
||||
void set_colors();
|
||||
|
||||
void update_range();
|
||||
|
||||
void add_note(ArdourCanvas::CanvasNote*);
|
||||
void add_hit(ArdourCanvas::CanvasHit*);
|
||||
|
||||
void clear_events();
|
||||
|
||||
typedef std::list<MidiGhostRegion::Event*> EventList;
|
||||
EventList events;
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_ghost_region_h__ */
|
||||
|
|
|
@ -488,12 +488,6 @@ Lineset::update_bounds() {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some key concepts
|
||||
* don't allow modifying line data outside the update function. We don't want any line data outside the visible view range,
|
||||
* and view range is only "known" in the update function
|
||||
*/
|
||||
|
||||
/*
|
||||
* what to do here?
|
||||
* 1. find out if any line data has been modified since last update.
|
||||
|
|
|
@ -380,6 +380,14 @@ MidiRegionView::clear_events()
|
|||
for (std::vector<CanvasMidiEvent*>::iterator i = _events.begin(); i != _events.end(); ++i)
|
||||
delete *i;
|
||||
|
||||
MidiGhostRegion* gr;
|
||||
|
||||
for(vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
|
||||
if((gr = dynamic_cast<MidiGhostRegion*>(*g)) != 0) {
|
||||
gr->clear_events();
|
||||
}
|
||||
}
|
||||
|
||||
_events.clear();
|
||||
}
|
||||
|
||||
|
@ -505,11 +513,23 @@ MidiRegionView::set_y_position_and_height (double y, double h)
|
|||
for (std::vector<CanvasMidiEvent*>::const_iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||
CanvasNote* note = dynamic_cast<CanvasNote*>(*i);
|
||||
if (note && note->note()) {
|
||||
const double y1 = midi_stream_view()->note_to_y(note->note()->note());
|
||||
const double y2 = y1 + floor(midi_stream_view()->note_height());
|
||||
if(note->note()->note() < midi_stream_view()->lowest_note() ||
|
||||
note->note()->note() > midi_stream_view()->highest_note()) {
|
||||
if(canvas_item_visible(note)) {
|
||||
note->hide();
|
||||
}
|
||||
}
|
||||
else {
|
||||
const double y1 = midi_stream_view()->note_to_y(note->note()->note());
|
||||
const double y2 = y1 + floor(midi_stream_view()->note_height());
|
||||
|
||||
if(!canvas_item_visible(note)) {
|
||||
note->show();
|
||||
}
|
||||
|
||||
note->property_y1() = y1;
|
||||
note->property_y2() = y2;
|
||||
note->property_y1() = y1;
|
||||
note->property_y2() = y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,18 +542,37 @@ MidiRegionView::set_y_position_and_height (double y, double h)
|
|||
}
|
||||
|
||||
GhostRegion*
|
||||
MidiRegionView::add_ghost (AutomationTimeAxisView& atv)
|
||||
MidiRegionView::add_ghost (TimeAxisView& tv)
|
||||
{
|
||||
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&trackview);
|
||||
CanvasNote* note;
|
||||
assert(rtv);
|
||||
|
||||
double unit_position = _region->position () / samples_per_unit;
|
||||
GhostRegion* ghost = new GhostRegion (atv, unit_position);
|
||||
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&tv);
|
||||
MidiGhostRegion* ghost;
|
||||
|
||||
if(mtv && mtv->midi_view()) {
|
||||
/* if ghost is inserted into midi track, use a dedicated midi ghost canvas group.
|
||||
this is because it's nice to have midi notes on top of the note lines and
|
||||
audio waveforms under it.
|
||||
*/
|
||||
ghost = new MidiGhostRegion (*mtv->midi_view(), trackview, unit_position);
|
||||
}
|
||||
else {
|
||||
ghost = new MidiGhostRegion (tv, trackview, unit_position);
|
||||
}
|
||||
|
||||
ghost->set_height ();
|
||||
ghost->set_duration (_region->length() / samples_per_unit);
|
||||
ghosts.push_back (ghost);
|
||||
|
||||
for (std::vector<CanvasMidiEvent*>::iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||
if((note = dynamic_cast<CanvasNote*>(*i)) != 0) {
|
||||
ghost->add_note(note);
|
||||
}
|
||||
}
|
||||
|
||||
ghost->GoingAway.connect (mem_fun(*this, &MidiRegionView::remove_ghost));
|
||||
|
||||
return ghost;
|
||||
|
@ -638,6 +677,14 @@ MidiRegionView::add_note(const boost::shared_ptr<Note> note)
|
|||
ev_rect->show();
|
||||
_events.push_back(ev_rect);
|
||||
|
||||
MidiGhostRegion* gr;
|
||||
|
||||
for(vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
|
||||
if((gr = dynamic_cast<MidiGhostRegion*>(*g)) != 0) {
|
||||
gr->add_note(ev_rect);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (midi_view()->note_mode() == Percussive) {
|
||||
|
||||
//cerr << "MRV::add_note percussive " << note->note() << " @ " << note->time()
|
||||
|
|
|
@ -76,7 +76,7 @@ class MidiRegionView : public RegionView
|
|||
|
||||
void redisplay_model();
|
||||
|
||||
GhostRegion* add_ghost (AutomationTimeAxisView&);
|
||||
GhostRegion* add_ghost (TimeAxisView&);
|
||||
|
||||
void add_note(const boost::shared_ptr<ARDOUR::Note> note);
|
||||
void resolve_note(uint8_t note_num, double end_time);
|
||||
|
|
|
@ -54,7 +54,7 @@ MidiScroomer::on_expose_event(GdkEventExpose* ev) {
|
|||
double note_width = 0.8 * get_width();
|
||||
double note_height = 1.4 * note2y;
|
||||
double black_shift = 0.1 * note2y;
|
||||
double colors[6];
|
||||
double colors[6] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
//cerr << ev->area.y << " " << ev->area.height << endl;
|
||||
|
||||
|
@ -71,8 +71,8 @@ MidiScroomer::on_expose_event(GdkEventExpose* ev) {
|
|||
cc->rectangle(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
|
||||
cc->set_source_rgb (colors[3], colors[4], colors[5]);
|
||||
cc->fill_preserve();
|
||||
|
||||
cc->clip();
|
||||
|
||||
cc->set_source_rgb(colors[0], colors[1], colors[2]);
|
||||
cc->set_line_width(note_height);
|
||||
|
||||
|
@ -109,6 +109,13 @@ MidiScroomer::on_expose_event(GdkEventExpose* ev) {
|
|||
}
|
||||
}
|
||||
|
||||
if(i == Handle1 || i == Handle2) {
|
||||
cc->rectangle(comp_rect.x + 0.5f, comp_rect.y + 0.5f, comp_rect.width - 1.0f, comp_rect.height - 1.0f);
|
||||
cc->set_line_width(1.0f);
|
||||
cc->set_source_rgb (1.0f, 1.0f, 1.0f);
|
||||
cc->stroke();
|
||||
}
|
||||
|
||||
cc->reset_clip();
|
||||
}
|
||||
}
|
||||
|
@ -121,29 +128,29 @@ MidiScroomer::get_colors(double color[], Component comp) {
|
|||
switch (comp) {
|
||||
case TopBase:
|
||||
case BottomBase:
|
||||
color[0] = 0.24;
|
||||
color[1] = 0.24;
|
||||
color[2] = 0.24;
|
||||
color[3] = 0.33;
|
||||
color[4] = 0.33;
|
||||
color[5] = 0.33;
|
||||
color[0] = 0.24f;
|
||||
color[1] = 0.24f;
|
||||
color[2] = 0.24f;
|
||||
color[3] = 0.33f;
|
||||
color[4] = 0.33f;
|
||||
color[5] = 0.33f;
|
||||
break;
|
||||
case Handle1:
|
||||
case Handle2:
|
||||
color[0] = 0.38;
|
||||
color[1] = 0.38;
|
||||
color[2] = 0.38;
|
||||
color[3] = 0.91;
|
||||
color[4] = 0.91;
|
||||
color[5] = 0.91;
|
||||
color[0] = 0.91f;
|
||||
color[1] = 0.91f;
|
||||
color[2] = 0.91f;
|
||||
color[3] = 0.0f;
|
||||
color[4] = 0.0f;
|
||||
color[5] = 0.0f;
|
||||
break;
|
||||
case Slider:
|
||||
color[0] = 0.38;
|
||||
color[1] = 0.38;
|
||||
color[2] = 0.38;
|
||||
color[3] = 0.77;
|
||||
color[4] = 0.77;
|
||||
color[5] = 0.77;
|
||||
color[0] = 0.38f;
|
||||
color[1] = 0.38f;
|
||||
color[2] = 0.38f;
|
||||
color[3] = 0.77f;
|
||||
color[4] = 0.77f;
|
||||
color[5] = 0.77f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -68,6 +68,12 @@ MidiStreamView::MidiStreamView (MidiTimeAxisView& tv)
|
|||
|
||||
use_rec_regions = tv.editor.show_waveforms_recording ();
|
||||
|
||||
/* use a group dedicated to MIDI underlays. Audio underlays are not in this group. */
|
||||
midi_underlay_group = new ArdourCanvas::Group (*canvas_group);
|
||||
midi_underlay_group->lower_to_bottom();
|
||||
|
||||
/* put the note lines in the timeaxisview's group, so it
|
||||
can be put below ghost regions from MIDI underlays*/
|
||||
_note_lines = new ArdourCanvas::Lineset(*canvas_group, ArdourCanvas::Lineset::Horizontal);
|
||||
|
||||
_note_lines->property_x1() = 0;
|
||||
|
@ -76,6 +82,7 @@ MidiStreamView::MidiStreamView (MidiTimeAxisView& tv)
|
|||
_note_lines->property_y2() = 0;
|
||||
|
||||
_note_lines->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), _note_lines, &_trackview));
|
||||
_note_lines->lower_to_bottom();
|
||||
|
||||
note_range_adjustment.signal_value_changed().connect (mem_fun (*this, &MidiStreamView::note_range_adjustment_changed));
|
||||
ColorsChanged.connect(mem_fun(*this, &MidiStreamView::draw_note_lines));
|
||||
|
|
|
@ -67,6 +67,7 @@ class MidiStreamView : public StreamView
|
|||
};
|
||||
|
||||
Gtk::Adjustment note_range_adjustment;
|
||||
ArdourCanvas::Group* midi_underlay_group;
|
||||
|
||||
VisibleNoteRange note_range() { return _range; }
|
||||
void set_note_range(VisibleNoteRange r);
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "utils.h"
|
||||
#include "midi_scroomer.h"
|
||||
#include "piano_roll_header.h"
|
||||
#include "ghostregion.h"
|
||||
|
||||
#include <ardour/midi_track.h>
|
||||
|
||||
|
@ -126,13 +127,25 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar
|
|||
controls_base_selected_name = "MidiTrackControlsBaseSelected";
|
||||
controls_base_unselected_name = "MidiTrackControlsBaseUnselected";
|
||||
|
||||
midi_view()->NoteRangeChanged.connect (mem_fun(*this, &MidiTimeAxisView::update_range));
|
||||
|
||||
/* ask for notifications of any new RegionViews */
|
||||
_view->RegionViewAdded.connect (mem_fun(*this, &MidiTimeAxisView::region_view_added));
|
||||
_view->attach ();
|
||||
}
|
||||
}
|
||||
|
||||
MidiTimeAxisView::~MidiTimeAxisView ()
|
||||
{
|
||||
if(_piano_roll_header) {
|
||||
delete _piano_roll_header;
|
||||
_piano_roll_header = 0;
|
||||
}
|
||||
|
||||
if(_range_scroomer) {
|
||||
delete _range_scroomer;
|
||||
_range_scroomer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MidiStreamView*
|
||||
|
@ -248,6 +261,17 @@ MidiTimeAxisView::set_note_range(MidiStreamView::VisibleNoteRange range)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
MidiTimeAxisView::update_range() {
|
||||
MidiGhostRegion* mgr;
|
||||
|
||||
for(list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
if((mgr = dynamic_cast<MidiGhostRegion*>(*i)) != 0) {
|
||||
mgr->update_range();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Prompt for a controller with a dialog and add an automation track for it
|
||||
*/
|
||||
void
|
||||
|
|
|
@ -70,6 +70,8 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
|||
|
||||
ARDOUR::NoteMode note_mode() const { return _note_mode; }
|
||||
|
||||
void update_range();
|
||||
|
||||
private:
|
||||
|
||||
void append_extra_display_menu_items ();
|
||||
|
|
|
@ -60,7 +60,8 @@ PianoRollHeader::Color::set(const PianoRollHeader::Color& c) {
|
|||
PianoRollHeader::PianoRollHeader(MidiStreamView& v)
|
||||
: _view(v)
|
||||
, _highlighted_note(no_note)
|
||||
, _clicked_note(no_note) {
|
||||
, _clicked_note(no_note)
|
||||
, _dragging(false) {
|
||||
|
||||
add_events (Gdk::BUTTON_PRESS_MASK |
|
||||
Gdk::BUTTON_RELEASE_MASK |
|
||||
|
@ -295,7 +296,7 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev) {
|
|||
}
|
||||
|
||||
cr->select_font_face ("Georgia", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_BOLD);
|
||||
font_size = min(10.0, _note_height);
|
||||
font_size = min((double) 10.0f, _note_height - 4.0f);
|
||||
cr->set_font_size(font_size);
|
||||
|
||||
/* fill the entire rect with the color for non-highlighted white notes.
|
||||
|
@ -445,7 +446,7 @@ PianoRollHeader::on_expose_event (GdkEventExpose* ev) {
|
|||
|
||||
//cr->get_text_extents(s.str(), te);
|
||||
cr->set_source_rgb(0.30f, 0.30f, 0.30f);
|
||||
cr->move_to(0, y + font_size + (note_height - font_size) / 2.0f);
|
||||
cr->move_to(2.0f, y + note_height - 1.0f - (note_height - font_size) / 2.0f);
|
||||
cr->show_text(s.str());
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +492,9 @@ PianoRollHeader::on_button_press_event (GdkEventButton* ev) {
|
|||
int note = _view.y_to_note(ev->y);
|
||||
|
||||
if(ev->type == GDK_BUTTON_PRESS && note >= 0 && note < 128) {
|
||||
add_modal_grab();
|
||||
_dragging = true;
|
||||
|
||||
if(!_active_notes[note]) {
|
||||
_active_notes[note] = true;
|
||||
_clicked_note = note;
|
||||
|
@ -510,12 +514,17 @@ bool
|
|||
PianoRollHeader::on_button_release_event (GdkEventButton* ev) {
|
||||
int note = _view.y_to_note(ev->y);
|
||||
|
||||
if(note == _clicked_note) {
|
||||
_active_notes[note] = false;
|
||||
_clicked_note = no_note;
|
||||
send_note_off(note);
|
||||
|
||||
invalidate_note_range(note, note);
|
||||
if(_dragging) {
|
||||
remove_modal_grab();
|
||||
_dragging = false;
|
||||
|
||||
if(note == _clicked_note) {
|
||||
_active_notes[note] = false;
|
||||
_clicked_note = no_note;
|
||||
send_note_off(note);
|
||||
|
||||
invalidate_note_range(note, note);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -524,6 +533,7 @@ PianoRollHeader::on_button_release_event (GdkEventButton* ev) {
|
|||
bool
|
||||
PianoRollHeader::on_enter_notify_event (GdkEventCrossing* ev) {
|
||||
_highlighted_note = _view.y_to_note(ev->y);
|
||||
|
||||
invalidate_note_range(_highlighted_note, _highlighted_note);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ private:
|
|||
uint8_t _highlighted_note;
|
||||
uint8_t _clicked_note;
|
||||
double _grab_y;
|
||||
bool _dragging;
|
||||
|
||||
double _note_height;
|
||||
double _black_note_width;
|
||||
|
|
|
@ -264,6 +264,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
|
|||
virtual TimeAxisView* get_named_time_axis(const std::string & name) = 0;
|
||||
#endif
|
||||
|
||||
virtual RouteTimeAxisView* get_route_view_by_id (PBD::ID& id) = 0;
|
||||
|
||||
virtual void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&) const = 0;
|
||||
|
||||
sigc::signal<void> ZoomFocusChanged;
|
||||
|
|
|
@ -529,6 +529,16 @@ RegionView::move (double x_delta, double y_delta)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RegionView::remove_ghost_in (TimeAxisView& tv) {
|
||||
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
if (&(*i)->trackview == &tv) {
|
||||
delete *i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RegionView::remove_ghost (GhostRegion* ghost)
|
||||
{
|
||||
|
|
|
@ -77,8 +77,9 @@ class RegionView : public TimeAxisViewItem
|
|||
|
||||
virtual void region_changed (ARDOUR::Change);
|
||||
|
||||
virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0;
|
||||
void remove_ghost (GhostRegion*);
|
||||
virtual GhostRegion* add_ghost (TimeAxisView&) = 0;
|
||||
void remove_ghost_in (TimeAxisView&);
|
||||
void remove_ghost (GhostRegion*);
|
||||
|
||||
uint32_t get_fill_color ();
|
||||
|
||||
|
|
|
@ -95,7 +95,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
|
|||
size_button (_("h")), // height
|
||||
automation_button (_("a")),
|
||||
visual_button (_("v")),
|
||||
lm (rt, sess)
|
||||
lm (rt, sess),
|
||||
underlay_xml_node (0)
|
||||
{
|
||||
lm.set_no_show_all();
|
||||
lm.setup_meters(50);
|
||||
|
@ -302,28 +303,34 @@ RouteTimeAxisView::set_state (const XMLNode& node)
|
|||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
child_node = *niter;
|
||||
|
||||
if (child_node->name() != AutomationTimeAxisView::state_node_name)
|
||||
continue;
|
||||
|
||||
XMLProperty* prop = child_node->property ("automation-id");
|
||||
if (!prop)
|
||||
continue;
|
||||
|
||||
Parameter param(prop->value());
|
||||
if (!param)
|
||||
continue;
|
||||
|
||||
bool show = false;
|
||||
|
||||
prop = child_node->property ("shown");
|
||||
|
||||
if (prop && prop->value() == "yes") {
|
||||
show = true;
|
||||
_show_automation.insert(param);
|
||||
if (child_node->name() == AutomationTimeAxisView::state_node_name) {
|
||||
XMLProperty* prop = child_node->property ("automation-id");
|
||||
if (!prop)
|
||||
continue;
|
||||
|
||||
Parameter param(prop->value());
|
||||
if (!param)
|
||||
continue;
|
||||
|
||||
bool show = false;
|
||||
|
||||
prop = child_node->property ("shown");
|
||||
|
||||
if (prop && prop->value() == "yes") {
|
||||
show = true;
|
||||
_show_automation.insert(param);
|
||||
}
|
||||
|
||||
if (_automation_tracks.find(param) == _automation_tracks.end()) {
|
||||
create_automation_child(param, show);
|
||||
}
|
||||
}
|
||||
else if (child_node->name() == "Underlays") {
|
||||
underlay_xml_node = child_node;
|
||||
|
||||
/* Wait for all gui tracks to be loaded as underlays are cross referencing tracks*/
|
||||
Glib::signal_idle().connect(mem_fun(*this, &RouteTimeAxisView::set_underlay_state));
|
||||
}
|
||||
|
||||
if (_automation_tracks.find(param) == _automation_tracks.end())
|
||||
create_automation_child(param, show);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1694,19 +1701,20 @@ RouteTimeAxisView::hide_all_automation ()
|
|||
void
|
||||
RouteTimeAxisView::region_view_added (RegionView* rv)
|
||||
{
|
||||
for (Children::iterator i = children.begin(); i != children.end(); ++i) {
|
||||
boost::shared_ptr<AutomationTimeAxisView> atv;
|
||||
|
||||
if ((atv = boost::dynamic_pointer_cast<AutomationTimeAxisView> (*i)) != 0) {
|
||||
rv->add_ghost (*atv.get());
|
||||
/* XXX need to find out if automation children have automationstreamviews. If yes, no ghosts */
|
||||
if(is_audio_track()) {
|
||||
for (Children::iterator i = children.begin(); i != children.end(); ++i) {
|
||||
boost::shared_ptr<AutomationTimeAxisView> atv;
|
||||
|
||||
if ((atv = boost::dynamic_pointer_cast<AutomationTimeAxisView> (*i)) != 0) {
|
||||
atv->add_ghost(rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::add_ghost_to_processor (RegionView* rv, boost::shared_ptr<AutomationTimeAxisView> atv)
|
||||
{
|
||||
rv->add_ghost (*atv.get());
|
||||
for (UnderlayMirrorList::iterator i = _underlay_mirrors.begin(); i != _underlay_mirrors.end(); ++i) {
|
||||
(*i)->add_ghost(rv);
|
||||
}
|
||||
}
|
||||
|
||||
RouteTimeAxisView::ProcessorAutomationInfo::~ProcessorAutomationInfo ()
|
||||
|
@ -1812,7 +1820,7 @@ RouteTimeAxisView::add_processor_automation_curve (boost::shared_ptr<Processor>
|
|||
add_child (pan->view);
|
||||
|
||||
if (_view) {
|
||||
_view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_processor), pan->view));
|
||||
_view->foreach_regionview (mem_fun(*pan->view.get(), &TimeAxisView::add_ghost));
|
||||
}
|
||||
|
||||
processor->mark_automation_visible (what, true);
|
||||
|
@ -2133,3 +2141,117 @@ RouteTimeAxisView::io_changed (IOChange change, void *src)
|
|||
{
|
||||
reset_meter ();
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::build_underlay_menu(Gtk::Menu* parent_menu) {
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
if(!_underlay_streams.empty()) {
|
||||
MenuList& parent_items = parent_menu->items();
|
||||
Menu* gs_menu = manage (new Menu);
|
||||
gs_menu->set_name ("ArdourContextMenu");
|
||||
MenuList& gs_items = gs_menu->items();
|
||||
|
||||
parent_items.push_back (MenuElem (_("Underlays"), *gs_menu));
|
||||
|
||||
for(UnderlayList::iterator it = _underlay_streams.begin(); it != _underlay_streams.end(); ++it) {
|
||||
gs_items.push_back(MenuElem(string_compose(_("Remove \"%1\""), (*it)->trackview().name()),
|
||||
bind(mem_fun(*this, &RouteTimeAxisView::remove_underlay), *it)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RouteTimeAxisView::set_underlay_state()
|
||||
{
|
||||
if(!underlay_xml_node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XMLNodeList nlist = underlay_xml_node->children();
|
||||
XMLNodeConstIterator niter;
|
||||
XMLNode *child_node;
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
child_node = *niter;
|
||||
|
||||
if(child_node->name() != "Underlay") {
|
||||
continue;
|
||||
}
|
||||
|
||||
XMLProperty* prop = child_node->property ("id");
|
||||
if(prop) {
|
||||
PBD::ID id(prop->value());
|
||||
|
||||
RouteTimeAxisView* v = editor.get_route_view_by_id(id);
|
||||
|
||||
if(v) {
|
||||
add_underlay(v->view(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::add_underlay(StreamView* v, bool update_xml)
|
||||
{
|
||||
if(!v) {
|
||||
return;
|
||||
}
|
||||
|
||||
RouteTimeAxisView& other = v->trackview();
|
||||
|
||||
if(find(_underlay_streams.begin(), _underlay_streams.end(), v) == _underlay_streams.end()) {
|
||||
if(find(other._underlay_mirrors.begin(), other._underlay_mirrors.end(), this) != other._underlay_mirrors.end()) {
|
||||
fatal << _("programming error: underlay reference pointer pairs are inconsistent!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
_underlay_streams.push_back(v);
|
||||
other._underlay_mirrors.push_back(this);
|
||||
|
||||
v->foreach_regionview(mem_fun(*this, &RouteTimeAxisView::add_ghost));
|
||||
|
||||
if(update_xml) {
|
||||
if(!underlay_xml_node) {
|
||||
ensure_xml_node();
|
||||
underlay_xml_node = xml_node->add_child("Underlays");
|
||||
}
|
||||
|
||||
XMLNode* node = underlay_xml_node->add_child("Underlay");
|
||||
XMLProperty* prop = node->add_property("id");
|
||||
prop->set_value(v->trackview().route()->id().to_s());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::remove_underlay(StreamView* v)
|
||||
{
|
||||
if(!v) {
|
||||
return;
|
||||
}
|
||||
|
||||
UnderlayList::iterator it = find(_underlay_streams.begin(), _underlay_streams.end(), v);
|
||||
RouteTimeAxisView& other = v->trackview();
|
||||
|
||||
if(it != _underlay_streams.end()) {
|
||||
UnderlayMirrorList::iterator gm = find(other._underlay_mirrors.begin(), other._underlay_mirrors.end(), this);
|
||||
|
||||
if(gm == other._underlay_mirrors.end()) {
|
||||
fatal << _("programming error: underlay reference pointer pairs are inconsistent!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
v->foreach_regionview(mem_fun(*this, &RouteTimeAxisView::remove_ghost));
|
||||
|
||||
_underlay_streams.erase(it);
|
||||
other._underlay_mirrors.erase(gm);
|
||||
|
||||
if(underlay_xml_node) {
|
||||
underlay_xml_node->remove_nodes_and_delete("id", v->trackview().route()->id().to_s());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,10 @@ public:
|
|||
void clear_playlist ();
|
||||
|
||||
void build_playlist_menu (Gtk::Menu *);
|
||||
|
||||
void add_underlay (StreamView*, bool update_xml = true);
|
||||
void remove_underlay (StreamView*);
|
||||
void build_underlay_menu(Gtk::Menu*);
|
||||
|
||||
/* This is a bit nasty to expose :/ */
|
||||
struct RouteAutomationNode {
|
||||
|
@ -239,8 +243,7 @@ protected:
|
|||
void color_handler ();
|
||||
|
||||
void region_view_added (RegionView*);
|
||||
void add_ghost_to_processor (RegionView*, boost::shared_ptr<AutomationTimeAxisView>);
|
||||
|
||||
|
||||
StreamView* _view;
|
||||
ArdourCanvas::Canvas& parent_canvas;
|
||||
bool no_redraw;
|
||||
|
@ -296,6 +299,14 @@ protected:
|
|||
XMLNode* get_automation_child_xml_node (ARDOUR::Parameter param);
|
||||
|
||||
LevelMeter lm;
|
||||
|
||||
XMLNode* underlay_xml_node;
|
||||
bool set_underlay_state();
|
||||
|
||||
typedef list<StreamView*> UnderlayList;
|
||||
UnderlayList _underlay_streams;
|
||||
typedef list<RouteTimeAxisView*> UnderlayMirrorList;
|
||||
UnderlayMirrorList _underlay_mirrors;
|
||||
};
|
||||
|
||||
#endif /* __ardour_route_time_axis_h__ */
|
||||
|
|
|
@ -62,7 +62,6 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Group* group)
|
|||
{
|
||||
/* set_position() will position the group */
|
||||
|
||||
canvas_rect = new ArdourCanvas::SimpleRect (*canvas_group);
|
||||
canvas_rect->property_x1() = 0.0;
|
||||
canvas_rect->property_y1() = 0.0;
|
||||
canvas_rect->property_x2() = _trackview.editor.frame_to_pixel (max_frames);
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "ardour_ui.h"
|
||||
#include "public_editor.h"
|
||||
#include "time_axis_view.h"
|
||||
#include "region_view.h"
|
||||
#include "ghostregion.h"
|
||||
#include "simplerect.h"
|
||||
#include "simpleline.h"
|
||||
#include "selection.h"
|
||||
|
@ -83,7 +85,11 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
|
|||
}
|
||||
|
||||
canvas_display = new Group (*canvas.root(), 0.0, 0.0);
|
||||
|
||||
|
||||
ghost_group = new Group (*canvas_display);
|
||||
ghost_group->lower_to_bottom();
|
||||
ghost_group->show();
|
||||
|
||||
selection_group = new Group (*canvas_display);
|
||||
selection_group->hide();
|
||||
|
||||
|
@ -92,6 +98,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
|
|||
size_menu = 0;
|
||||
_marked_for_display = false;
|
||||
_hidden = false;
|
||||
in_destructor = false;
|
||||
height = 0;
|
||||
effective_height = 0;
|
||||
parent = rent;
|
||||
|
@ -156,6 +163,12 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
|
|||
|
||||
TimeAxisView::~TimeAxisView()
|
||||
{
|
||||
in_destructor = true;
|
||||
|
||||
for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
|
||||
for (list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) {
|
||||
delete (*i)->rect;
|
||||
delete (*i)->start_trim;
|
||||
|
@ -356,6 +369,10 @@ TimeAxisView::set_height (TrackHeight h)
|
|||
{
|
||||
height_style = h;
|
||||
set_height_pixels (height_to_pixels (h));
|
||||
|
||||
for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
(*i)->set_height ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -846,6 +863,37 @@ TimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& resul
|
|||
return;
|
||||
}
|
||||
|
||||
void
|
||||
TimeAxisView::add_ghost (RegionView* rv) {
|
||||
GhostRegion* gr = rv->add_ghost (*this);
|
||||
|
||||
if(gr) {
|
||||
ghosts.push_back(gr);
|
||||
gr->GoingAway.connect (mem_fun(*this, &TimeAxisView::erase_ghost));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimeAxisView::remove_ghost (RegionView* rv) {
|
||||
rv->remove_ghost_in (*this);
|
||||
}
|
||||
|
||||
void
|
||||
TimeAxisView::erase_ghost (GhostRegion* gr) {
|
||||
if(in_destructor) {
|
||||
return;
|
||||
}
|
||||
|
||||
list<GhostRegion*>::iterator i;
|
||||
|
||||
for (i = ghosts.begin(); i != ghosts.end(); ++i) {
|
||||
if ((*i) == gr) {
|
||||
ghosts.erase (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TimeAxisView::touched (double top, double bot)
|
||||
{
|
||||
|
@ -1055,7 +1103,10 @@ TimeAxisView::hide_name_entry ()
|
|||
void
|
||||
TimeAxisView::color_handler ()
|
||||
{
|
||||
|
||||
for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
|
||||
(*i)->set_colors();
|
||||
}
|
||||
|
||||
for (list<SelectionRect*>::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) {
|
||||
|
||||
(*i)->rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectionRect.get();
|
||||
|
|
|
@ -61,6 +61,8 @@ class PointSelection;
|
|||
class TimeAxisViewItem;
|
||||
class Selection;
|
||||
class Selectable;
|
||||
class RegionView;
|
||||
class GhostRegion;
|
||||
|
||||
/** Abstract base class for time-axis views (horizontal editor 'strips')
|
||||
*
|
||||
|
@ -202,6 +204,12 @@ class TimeAxisView : public virtual AxisView
|
|||
virtual void get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results);
|
||||
virtual void get_inverted_selectables (Selection&, list<Selectable *>& results);
|
||||
|
||||
ArdourCanvas::Group* ghost_group;
|
||||
|
||||
void add_ghost (RegionView*);
|
||||
void remove_ghost (RegionView*);
|
||||
void erase_ghost (GhostRegion*);
|
||||
|
||||
/* state/serialization management */
|
||||
|
||||
TimeAxisView* get_parent () { return parent; }
|
||||
|
@ -296,6 +304,8 @@ class TimeAxisView : public virtual AxisView
|
|||
|
||||
ArdourCanvas::Group *selection_group;
|
||||
|
||||
list<GhostRegion*> ghosts;
|
||||
|
||||
list<SelectionRect*> free_selection_rects;
|
||||
list<SelectionRect*> used_selection_rects;
|
||||
|
||||
|
@ -305,6 +315,7 @@ class TimeAxisView : public virtual AxisView
|
|||
|
||||
bool _hidden;
|
||||
bool _has_state;
|
||||
bool in_destructor;
|
||||
NamePackingBits name_packing;
|
||||
|
||||
static void compute_controls_size_info ();
|
||||
|
|
|
@ -202,8 +202,6 @@ Scroomer::on_button_press_event (GdkEventButton* ev) {
|
|||
if(ev->button == 1) {
|
||||
Component comp = point_in(ev->y);
|
||||
|
||||
cerr << get_comp_name(comp) << " pressed" << endl;
|
||||
|
||||
if(comp == Total || comp == None) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,8 @@ public:
|
|||
void remove_nodes(const string &);
|
||||
/** Remove and delete all nodes with the name passed to remove_nodes */
|
||||
void remove_nodes_and_delete(const string &);
|
||||
/** Remove and delete all nodes with property prop matching val */
|
||||
void remove_nodes_and_delete(const string& propname, const string& val);
|
||||
};
|
||||
|
||||
class XMLProperty {
|
||||
|
|
|
@ -379,6 +379,27 @@ XMLNode::remove_nodes_and_delete(const string & n)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
XMLNode::remove_nodes_and_delete(const string& propname, const string& val)
|
||||
{
|
||||
XMLNodeIterator i = _children.begin();
|
||||
XMLNodeIterator tmp;
|
||||
XMLProperty* prop;
|
||||
|
||||
while (i != _children.end()) {
|
||||
tmp = i;
|
||||
++tmp;
|
||||
|
||||
prop = (*i)->property(propname);
|
||||
if(prop && prop->value() == val) {
|
||||
delete *i;
|
||||
_children.erase(i);
|
||||
}
|
||||
|
||||
i = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
XMLProperty::XMLProperty(const string &n, const string &v)
|
||||
: _name(n),
|
||||
_value(v)
|
||||
|
|
Loading…
Reference in New Issue