rename Marker class
[ardour.git] / gtk2_ardour / selection.cc
index 6d07564f2cb276c9b6920af188f8ca0f386ce493..784f646f39a651583ceb2eff43eef0c1d5200efd 100644 (file)
@@ -43,9 +43,9 @@ using namespace ARDOUR;
 using namespace PBD;
 
 struct AudioRangeComparator {
-    bool operator()(AudioRange a, AudioRange b) {
-           return a.start < b.start;
-    }
+       bool operator()(AudioRange a, AudioRange b) {
+               return a.start < b.start;
+       }
 };
 
 Selection::Selection (const PublicEditor* e)
@@ -61,8 +61,8 @@ Selection::Selection (const PublicEditor* e)
        void (Selection::*track_remove)(TimeAxisView*) = &Selection::remove;
        TimeAxisView::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (track_remove, this, _1), gui_context());
 
-       void (Selection::*marker_remove)(Marker*) = &Selection::remove;
-       Marker::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (marker_remove, this, _1), gui_context());
+       void (Selection::*marker_remove)(ArdourMarker*) = &Selection::remove;
+       ArdourMarker::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (marker_remove, this, _1), gui_context());
 
        void (Selection::*point_remove)(ControlPoint*) = &Selection::remove;
        ControlPoint::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (point_remove, this, _1), gui_context());
@@ -109,6 +109,7 @@ Selection::clear ()
        clear_midi_notes ();
        clear_midi_regions ();
        clear_markers ();
+       pending_midi_note_selection.clear();
 }
 
 void
@@ -228,7 +229,7 @@ Selection::toggle (boost::shared_ptr<Playlist> pl)
 {
        clear_time();  //enforce object/range exclusivity
        clear_tracks();  //enforce object/track exclusivity
-       
+
        PlaylistSelection::iterator i;
 
        if ((i = find (playlists.begin(), playlists.end(), pl)) == playlists.end()) {
@@ -300,7 +301,7 @@ Selection::toggle (RegionView* r)
 {
        clear_time();  //enforce object/range exclusivity
        clear_tracks();  //enforce object/track exclusivity
-       
+
        RegionSelection::iterator i;
 
        if ((i = find (regions.begin(), regions.end(), r)) == regions.end()) {
@@ -371,7 +372,7 @@ Selection::add (boost::shared_ptr<Playlist> pl)
 {
        clear_time();  //enforce object/range exclusivity
        clear_tracks();  //enforce object/track exclusivity
-       
+
        if (find (playlists.begin(), playlists.end(), pl) == playlists.end()) {
                pl->use ();
                playlists.push_back(pl);
@@ -384,7 +385,7 @@ Selection::add (const list<boost::shared_ptr<Playlist> >& pllist)
 {
        clear_time();  //enforce object/range exclusivity
        clear_tracks();  //enforce object/track exclusivity
-       
+
        bool changed = false;
 
        for (list<boost::shared_ptr<Playlist> >::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
@@ -506,9 +507,9 @@ Selection::add (RegionView* r)
 
        if (find (regions.begin(), regions.end(), r) == regions.end()) {
                bool changed = regions.add (r);
-        if (changed) {
-            RegionsChanged ();
-        }
+               if (changed) {
+                       RegionsChanged ();
+               }
        }
 }
 
@@ -562,7 +563,7 @@ void
 Selection::replace (uint32_t sid, framepos_t start, framepos_t end)
 {
        clear_objects();  //enforce object/range exclusivity
-       
+
        for (list<AudioRange>::iterator i = time.begin(); i != time.end(); ++i) {
                if ((*i).id == sid) {
                        time.erase (i);
@@ -905,12 +906,12 @@ Selection::set (boost::shared_ptr<Evoral::ControlList> ac)
        clear_time();  //enforce region/object exclusivity
        clear_tracks();  //enforce object/track exclusivity
        clear_objects();
-       
+
        add (ac);
 }
 
 bool
-Selection::selected (Marker* m)
+Selection::selected (ArdourMarker* m)
 {
        return find (markers.begin(), markers.end(), m) != markers.end();
 }
@@ -991,7 +992,7 @@ Selection::toggle (list<Selectable*> const & selectables)
 {
        clear_time();  //enforce region/object exclusivity
        clear_tracks();  //enforce object/track exclusivity
-       
+
        RegionView* rv;
        ControlPoint* cp;
        vector<RegionView*> rvs;
@@ -1125,7 +1126,7 @@ Selection::set (ControlPoint* cp)
 }
 
 void
-Selection::set (Marker* m)
+Selection::set (ArdourMarker* m)
 {
        clear_time ();  //enforce region/object exclusivity
        clear_tracks();  //enforce object/track exclusivity
@@ -1135,7 +1136,7 @@ Selection::set (Marker* m)
 }
 
 void
-Selection::toggle (Marker* m)
+Selection::toggle (ArdourMarker* m)
 {
        MarkerSelection::iterator i;
 
@@ -1147,7 +1148,7 @@ Selection::toggle (Marker* m)
 }
 
 void
-Selection::remove (Marker* m)
+Selection::remove (ArdourMarker* m)
 {
        MarkerSelection::iterator i;
 
@@ -1158,7 +1159,7 @@ Selection::remove (Marker* m)
 }
 
 void
-Selection::add (Marker* m)
+Selection::add (ArdourMarker* m)
 {
        clear_time ();  //enforce region/object exclusivity
        clear_tracks();  //enforce object/track exclusivity
@@ -1170,7 +1171,7 @@ Selection::add (Marker* m)
 }
 
 void
-Selection::add (const list<Marker*>& m)
+Selection::add (const list<ArdourMarker*>& m)
 {
        clear_time ();  //enforce region/object exclusivity
        clear_tracks();  //enforce object/track exclusivity
@@ -1178,7 +1179,7 @@ Selection::add (const list<Marker*>& m)
        markers.insert (markers.end(), m.begin(), m.end());
        markers.sort ();
        markers.unique ();
-       
+
        MarkersChanged ();
 }
 
@@ -1229,7 +1230,56 @@ Selection::get_state () const
        for (RegionSelection::const_iterator i = regions.begin(); i != regions.end(); ++i) {
                XMLNode* r = node->add_child (X_("Region"));
                r->add_property (X_("id"), atoi ((*i)->region ()->id ().to_s ().c_str()));
-               
+       }
+
+       /* midi region views have thir own internal selection. */
+       XMLNode* n = NULL;
+       list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > rid_notes;
+       editor->get_per_region_note_selection (rid_notes);
+       if (!rid_notes.empty()) {
+               n = node->add_child (X_("MIDINote"));
+       }
+       list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rn_it;
+       for (rn_it = rid_notes.begin(); rn_it != rid_notes.end(); ++rn_it) {
+               assert(n); // hint for clang static analysis
+               n->add_property (X_("region_id"), atoi((*rn_it).first.to_s().c_str()));
+
+               for (std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > >::iterator i = (*rn_it).second.begin(); i != (*rn_it).second.end(); ++i) {
+                       XMLNode* nc = n->add_child(X_("note"));
+                       snprintf(buf, sizeof(buf), "%d", (*i)->channel());
+                       nc->add_property(X_("channel"), string(buf));
+
+                       snprintf(buf, sizeof(buf), "%f", (*i)->time().to_double());
+                       nc->add_property(X_("time"), string(buf));
+
+                       snprintf(buf, sizeof(buf), "%d", (*i)->note());
+                       nc->add_property(X_("note"), string(buf));
+
+                       snprintf(buf, sizeof(buf), "%f", (*i)->length().to_double());
+                       nc->add_property(X_("length"), string(buf));
+
+                       snprintf(buf, sizeof(buf), "%d", (*i)->velocity());
+                       nc->add_property(X_("velocity"), string(buf));
+
+                       snprintf(buf, sizeof(buf), "%d", (*i)->off_velocity());
+                       nc->add_property(X_("off-velocity"), string(buf));
+               }
+       }
+
+       for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
+               AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
+               if (atv) {
+
+                       XMLNode* r = node->add_child (X_("ControlPoint"));
+                       r->add_property (X_("type"), "track");
+                       r->add_property (X_("route-id"), atoi (atv->parent_route()->id ().to_s ().c_str()));
+                       r->add_property (X_("automation-list-id"), atoi ((*i)->line().the_list()->id ().to_s ().c_str()));
+                       r->add_property (X_("parameter"), EventTypeMap::instance().to_symbol ((*i)->line().the_list()->parameter ()));
+
+                       snprintf(buf, sizeof(buf), "%d", (*i)->view_index());
+                       r->add_property (X_("view-index"), string(buf));
+
+               }
        }
 
        for (TimeSelection::const_iterator i = time.begin(); i != time.end(); ++i) {
@@ -1239,10 +1289,10 @@ Selection::get_state () const
                snprintf(buf, sizeof(buf), "%" PRId64, (*i).end);
                t->add_property (X_("end"), string(buf));
        }
-       
+
        for (MarkerSelection::const_iterator i = markers.begin(); i != markers.end(); ++i) {
                XMLNode* t = node->add_child (X_("Marker"));
-               
+
                bool is_start;
                Location* loc = editor->find_location_from_marker (*i, is_start);
 
@@ -1261,6 +1311,7 @@ Selection::set_state (XMLNode const & node, int)
        }
 
        clear_regions ();
+       clear_midi_notes ();
        clear_points ();
        clear_time ();
        clear_tracks ();
@@ -1282,20 +1333,115 @@ Selection::set_state (XMLNode const & node, int)
                        XMLProperty* prop_id = (*i)->property (X_("id"));
                        assert (prop_id);
                        PBD::ID id (prop_id->value ());
-                       
+
                        RegionSelection rs;
                        editor->get_regionviews_by_id (id, rs);
-                       
+
                        if (!rs.empty ()) {
                                add (rs);
                        } else {
                                /*
-                                 regionviews are being constructed - stash the region IDs 
+                                 regionviews haven't been constructed - stash the region IDs
                                  so we can identify them in Editor::region_view_added ()
                                */
                                regions.pending.push_back (id);
                        }
-                       
+
+               } else if ((*i)->name() == X_("MIDINote")) {
+                       XMLProperty* prop_region_id = (*i)->property (X_("region-id"));
+
+                       assert (prop_region_id);
+
+                       PBD::ID const id (prop_region_id->value ());
+                       RegionSelection rs;
+
+                       editor->get_regionviews_by_id (id, rs); // there could be more than one
+
+                       std::list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > notes;
+                       XMLNodeList children = (*i)->children ();
+
+                       for (XMLNodeList::const_iterator ci = children.begin(); ci != children.end(); ++ci) {
+                               XMLProperty* prop_channel = (*ci)->property (X_("channel"));
+                               XMLProperty* prop_time = (*ci)->property (X_("time"));
+                               XMLProperty* prop_note = (*ci)->property (X_("note"));
+                               XMLProperty* prop_length = (*ci)->property (X_("length"));
+                               XMLProperty* prop_velocity = (*ci)->property (X_("velocity"));
+                               XMLProperty* prop_off_velocity = (*ci)->property (X_("off-velocity"));
+
+                               assert (prop_channel);
+                               assert (prop_time);
+                               assert (prop_note);
+                               assert (prop_length);
+                               assert (prop_velocity);
+                               assert (prop_off_velocity);
+
+                               uint8_t channel = atoi(prop_channel->value());
+                               Evoral::Beats time (atof(prop_time->value()));
+                               Evoral::Beats length (atof(prop_length->value()));
+                               uint8_t note = atoi(prop_note->value());
+                               uint8_t velocity = atoi(prop_velocity->value());
+                               uint8_t off_velocity = atoi(prop_off_velocity->value());
+                               boost::shared_ptr<Evoral::Note<Evoral::Beats> > the_note
+                                       (new Evoral::Note<Evoral::Beats>  (channel, time, length, note, velocity));
+                               the_note->set_off_velocity (off_velocity);
+
+                               notes.push_back (the_note);
+                       }
+
+                       for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) {
+                               MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*rsi);
+                               if (mrv) {
+                                       mrv->select_notes(notes);
+                               }
+                       }
+
+                       if (rs.empty()) {
+                               /* regionviews containing these notes don't yet exist on the canvas.*/
+                               pending_midi_note_selection.push_back (make_pair (id, notes));
+                       }
+
+               } else if  ((*i)->name() == X_("ControlPoint")) {
+                       XMLProperty* prop_type = (*i)->property (X_("type"));
+
+                       assert(prop_type);
+
+                       if (prop_type->value () == "track") {
+
+                               XMLProperty* prop_route_id = (*i)->property (X_("route-id"));
+                               XMLProperty* prop_alist_id = (*i)->property (X_("automation-list-id"));
+                               XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
+                               XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
+
+                               assert (prop_type);
+                               assert (prop_route_id);
+                               assert (prop_alist_id);
+                               assert (prop_parameter);
+                               assert (prop_view_index);
+
+                               PBD::ID route_id (prop_route_id->value ());
+                               RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (route_id);
+                               vector <ControlPoint *> cps;
+
+                               if (rtv) {
+                                       boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
+                                       if (atv) {
+                                               list<boost::shared_ptr<AutomationLine> > lines = atv->lines();
+                                               for (list<boost::shared_ptr<AutomationLine> > ::iterator li = lines.begin(); li != lines.end(); ++li) {
+                                                       if ((*li)->the_list()->id() == prop_alist_id->value()) {
+                                                               ControlPoint* cp = (*li)->nth(atol(prop_view_index->value().c_str()));
+                                                               if (cp) {
+                                                                       cps.push_back (cp);
+                                                                       cp->show();
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (!cps.empty()) {
+                                       add (cps);
+                               }
+                       }
+
                } else if  ((*i)->name() == X_("AudioRange")) {
                        XMLProperty* prop_start = (*i)->property (X_("start"));
                        XMLProperty* prop_end = (*i)->property (X_("end"));
@@ -1340,13 +1486,13 @@ Selection::set_state (XMLNode const & node, int)
                        assert (prop_start);
 
                        PBD::ID id (prop_id->value ());
-                       Marker* m = editor->find_marker_from_location_id (id, string_is_affirmative (prop_start->value ()));
+                       ArdourMarker* m = editor->find_marker_from_location_id (id, string_is_affirmative (prop_start->value ()));
                        if (m) {
                                add (m);
                        }
-                       
+
                }
-               
+
        }
 
        return 0;