X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fghostregion.cc;h=cb4a0d95d3da0a9d09d971e6d5b00481746c9c81;hb=5905b58bc0ad8383ef16631b6505c288c550192a;hp=844338cd45c50f2df036fefd737acc6903da04e5;hpb=666e0870554705f4fb466fc6b188fe9b4000ca49;p=ardour.git diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc index 844338cd45..cb4a0d95d3 100644 --- a/gtk2_ardour/ghostregion.cc +++ b/gtk2_ardour/ghostregion.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2007 Paul Davis + Copyright (C) 2000-2007 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,70 +17,115 @@ */ -#include "simplerect.h" -#include "waveview.h" -#include "ghostregion.h" +#include "evoral/Note.hpp" +#include "ardour_ui.h" #include "automation_time_axis.h" +#include "canvas-note.h" +#include "ghostregion.h" +#include "midi_streamview.h" +#include "midi_time_axis.h" #include "rgb_macros.h" +#include "simplerect.h" +#include "waveview.h" +using namespace std; using namespace Editing; using namespace ArdourCanvas; +using namespace ARDOUR; + +PBD::Signal1 GhostRegion::CatchDeletion; -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; base_rect = new ArdourCanvas::SimpleRect (*group); base_rect->property_x1() = (double) 0.0; base_rect->property_y1() = (double) 0.0; - base_rect->property_y2() = (double) trackview.height; + base_rect->property_y2() = (double) trackview.current_height(); base_rect->property_outline_what() = (guint32) 0; - base_rect->property_outline_color_rgba() = color_map[cGhostTrackBaseOutline]; - base_rect->property_fill_color_rgba() = color_map[cGhostTrackBaseFill]; - 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 () { - GoingAway (this); + CatchDeletion (this); delete base_rect; delete group; } void -GhostRegion::set_samples_per_unit (double spu) +GhostRegion::set_duration (double units) { - for (vector::iterator i = waves.begin(); i != waves.end(); ++i) { - (*i)->property_samples_per_unit() = spu; - } + base_rect->property_x2() = units; } void -GhostRegion::set_duration (double units) +GhostRegion::set_height () { - base_rect->property_x2() = units; + base_rect->property_y2() = (double) trackview.current_height(); } void -GhostRegion::set_height () +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(); + return RGBA_TO_UINT (color.get_red() / 256, color.get_green() / 256, color.get_blue() / 256, alpha); +} + +bool +GhostRegion::is_automation_ghost() +{ + return (dynamic_cast(&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::iterator i = waves.begin(); i != waves.end(); ++i) { + (*i)->property_samples_per_unit() = spu; + } +} + +void +AudioGhostRegion::set_height () { gdouble ht; vector::iterator i; uint32_t n; - base_rect->property_y2() = (double) trackview.height; - ht = ((trackview.height) / (double) waves.size()); - + GhostRegion::set_height(); + + ht = ((trackview.current_height()) / (double) waves.size()); + for (n = 0, i = waves.begin(); i != waves.end(); ++i, ++n) { gdouble yoff = n * ht; (*i)->property_height() = ht; @@ -89,12 +134,225 @@ GhostRegion::set_height () } void -GhostRegion::set_colors () +AudioGhostRegion::set_colors () +{ + GhostRegion::set_colors(); + guint fill_color; + + if (is_automation_ghost()) { + fill_color = ARDOUR_UI::config()->canvasvar_GhostTrackWaveFill.get(); + } + else { + fill_color = source_track_color(200); + } + + 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(); + } +} + +/** The general constructor; called when the destination timeaxisview doesn't have + * a midistreamview. + * + * @param tv TimeAxisView that this ghost region is on. + * @param source_tv TimeAxisView that we are the ghost for. + */ +MidiGhostRegion::MidiGhostRegion(TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos) + : GhostRegion(tv.ghost_group(), tv, source_tv, initial_unit_pos) + , _optimization_iterator (events.end ()) +{ + base_rect->lower_to_bottom(); + update_range (); + + midi_view()->NoteRangeChanged.connect (sigc::mem_fun (*this, &MidiGhostRegion::update_range)); +} + +/** + * @param msv MidiStreamView that this ghost region is on. + * @param source_tv TimeAxisView that we are the ghost for. + */ +MidiGhostRegion::MidiGhostRegion(MidiStreamView& msv, TimeAxisView& source_tv, double initial_unit_pos) + : GhostRegion(msv.midi_underlay_group, msv.trackview(), source_tv, initial_unit_pos) + , _optimization_iterator (events.end ()) +{ + base_rect->lower_to_bottom(); + update_range (); + + midi_view()->NoteRangeChanged.connect (sigc::mem_fun (*this, &MidiGhostRegion::update_range)); +} + +MidiGhostRegion::~MidiGhostRegion() +{ + clear_events (); +} + +MidiGhostRegion::Event::Event(ArdourCanvas::CanvasNoteEvent* e) + : event(e) +{ + +} + +MidiGhostRegion::Note::Note(ArdourCanvas::CanvasNote* n, ArdourCanvas::Group* g) + : Event(n) { - for (uint32_t n=0; n < waves.size(); ++n) { - waves[n]->property_wave_color() = color_map[cGhostTrackWave]; + rect = new ArdourCanvas::SimpleRect(*g, n->x1(), n->y1(), n->x2(), n->y2()); +} + +MidiGhostRegion::Note::~Note() +{ + delete rect; +} + +void +MidiGhostRegion::set_samples_per_unit (double /*spu*/) +{ +} + +/** @return MidiStreamView that we are providing a ghost for */ +MidiStreamView* +MidiGhostRegion::midi_view () +{ + StreamView* sv = source_trackview.view (); + assert (sv); + MidiStreamView* msv = dynamic_cast (sv); + assert (msv); + + return msv; +} + +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(*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; + double const h = trackview.current_height() / double (mv->contents_note_range ()); + + for (EventList::iterator it = events.begin(); it != events.end(); ++it) { + if ((note = dynamic_cast(*it)) != 0) { + uint8_t const note_num = note->event->note()->note(); + + if (note_num < mv->lowest_note() || note_num > mv->highest_note()) { + note->rect->hide(); + } else { + note->rect->show(); + double const y = trackview.current_height() - (note_num + 1 - mv->lowest_note()) * h + 1; + note->rect->property_y1() = y; + note->rect->property_y2() = y + h; + } + } + } +} + +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) { + const uint8_t note_num = n->note()->note(); + + if (note_num < mv->lowest_note() || note_num > mv->highest_note()) { + note->rect->hide(); + } else { + const double y = mv->note_to_y(note_num); + note->rect->property_y1() = y; + note->rect->property_y2() = y + mv->note_height(); + } + } +} + +void +MidiGhostRegion::clear_events() +{ + for (EventList::iterator it = events.begin(); it != events.end(); ++it) { + delete *it; + } + + events.clear(); +} + +/** Update the x positions of our representation of a parent's note. + * @param parent The CanvasNote from the parent MidiRegionView. + */ +void +MidiGhostRegion::update_note (ArdourCanvas::CanvasNote* parent) +{ + Event* ev = find_event (parent); + if (!ev) { + return; + } + + Note* note = dynamic_cast (ev); + if (note) { + double const x1 = parent->property_x1 (); + double const x2 = parent->property_x2 (); + note->rect->property_x1 () = x1; + note->rect->property_x2 () = x2; + } +} + +/** Given a note in our parent region (ie the actual MidiRegionView), find our + * representation of it. + * @return Our Event, or 0 if not found. + */ + +MidiGhostRegion::Event * +MidiGhostRegion::find_event (ArdourCanvas::CanvasNote* parent) +{ + /* we are using _optimization_iterator to speed up the common case where a caller + is going through our notes in order. + */ + + if (_optimization_iterator != events.end()) { + ++_optimization_iterator; + } + + if (_optimization_iterator != events.end() && (*_optimization_iterator)->event == parent) { + return *_optimization_iterator; + } + + for (_optimization_iterator = events.begin(); _optimization_iterator != events.end(); ++_optimization_iterator) { + if ((*_optimization_iterator)->event == parent) { + return *_optimization_iterator; + } + } - waves[n]->property_clip_color() = color_map[cGhostTrackWaveClip]; - waves[n]->property_zero_color() = color_map[cGhostTrackZeroLine]; - } + return 0; }