+ for (RegionMap::iterator i = region_map.begin(); i != region_map.end(); ++i) {
+ if (i->second->name() == name) {
+ return i->second;
+ }
+ }
+ return boost::shared_ptr<Region>();
+}
+
+void
+RegionFactory::clear_map ()
+{
+ if (region_list_connections) {
+ region_list_connections->drop_connections ();
+ }
+
+ {
+ Glib::Threads::Mutex::Lock lm (region_map_lock);
+ region_map.clear ();
+ _compound_associations.clear ();
+ region_name_map.clear ();
+ }
+}
+
+void
+RegionFactory::delete_all_regions ()
+{
+ RegionMap copy;
+
+ /* copy region list */
+ {
+ Glib::Threads::Mutex::Lock lm (region_map_lock);
+ copy = region_map;
+ }
+
+ /* clear existing map */
+ clear_map ();
+
+ /* tell everyone to drop references */
+ for (RegionMap::iterator i = copy.begin(); i != copy.end(); ++i) {
+ i->second->drop_references ();
+ }
+
+ /* the copy should now hold the only references, which will
+ vanish as we leave this scope, thus calling all destructors.
+ */
+}
+
+uint32_t
+RegionFactory::nregions ()
+{
+ Glib::Threads::Mutex::Lock lm (region_map_lock);
+ return region_map.size ();
+}
+
+/** Add a region to the two region name maps */
+void
+RegionFactory::add_to_region_name_maps (boost::shared_ptr<Region> region)
+{
+ update_region_name_number_map (region);
+
+ Glib::Threads::Mutex::Lock lm (region_name_maps_mutex);
+ region_name_map[region->name()] = region->id ();
+}
+
+/** Account for a region rename in the two region name maps */
+void
+RegionFactory::rename_in_region_name_maps (boost::shared_ptr<Region> region)
+{
+ update_region_name_number_map (region);
+
+ Glib::Threads::Mutex::Lock lm (region_name_maps_mutex);
+
+ map<string, PBD::ID>::iterator i = region_name_map.begin();
+ while (i != region_name_map.end() && i->second != region->id ()) {
+ ++i;
+ }
+
+ /* Erase the entry for the old name and put in a new one */
+ if (i != region_name_map.end()) {
+ region_name_map.erase (i);
+ region_name_map[region->name()] = region->id ();
+ }
+}
+
+/** Remove a region's details from the region_name_map */
+void
+RegionFactory::remove_from_region_name_map (string n)
+{
+ map<string, PBD::ID>::iterator i = region_name_map.find (n);
+ if (i != region_name_map.end ()) {
+ region_name_map.erase (i);
+ }
+}
+
+/** Update a region's entry in the region_name_number_map */
+void
+RegionFactory::update_region_name_number_map (boost::shared_ptr<Region> region)
+{
+ string::size_type const last_period = region->name().find_last_of ('.');
+
+ if (last_period != string::npos && last_period < region->name().length() - 1) {
+
+ string const base = region->name().substr (0, last_period);
+ string const number = region->name().substr (last_period + 1);
+
+ /* note that if there is no number, we get zero from atoi,
+ which is just fine
+ */
+
+ Glib::Threads::Mutex::Lock lm (region_name_maps_mutex);
+ region_name_number_map[base] = atoi (number.c_str ());
+ }
+}
+
+void
+RegionFactory::region_changed (PropertyChange const & what_changed, boost::weak_ptr<Region> w)
+{
+ boost::shared_ptr<Region> r = w.lock ();
+ if (!r) {
+ return;
+ }
+
+ if (what_changed.contains (Properties::name)) {
+ rename_in_region_name_maps (r);
+ }
+}
+
+int
+RegionFactory::region_name (string& result, string base, bool newlevel)
+{
+ char buf[16];
+ string subbase;
+
+ if (base.find("/") != string::npos) {
+ base = base.substr(base.find_last_of("/") + 1);
+ }
+
+ if (base == "") {
+
+ snprintf (buf, sizeof (buf), "%d", RegionFactory::nregions() + 1);
+ result = "region.";
+ result += buf;
+
+ } else {
+
+ if (newlevel) {
+ subbase = base;
+ } else {
+ string::size_type pos;
+
+ pos = base.find_last_of ('.');
+
+ /* pos may be npos, but then we just use entire base */
+
+ subbase = base.substr (0, pos);