fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / uri_map.cc
1 /*
2     Copyright (C) 2008-2011 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <cassert>
21 #include <string>
22 #include <utility>
23
24 #include <stdint.h>
25 #include <string.h>
26
27 #include "pbd/error.h"
28
29 #include "ardour/uri_map.h"
30 #include "ardour/lv2_extensions.h"
31
32 namespace ARDOUR {
33
34 URIMap* URIMap::uri_map;
35
36 void
37 URIMap::URIDs::init(URIMap& uri_map)
38 {
39         // Use string literals here instead of LV2 defines to avoid LV2 dependency
40         atom_Chunk          = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#Chunk");
41         atom_Path           = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#Path");
42         atom_Sequence       = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#Sequence");
43         atom_eventTransfer  = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#eventTransfer");
44         atom_URID           = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#URID");
45         atom_Blank          = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#Blank");
46         atom_Object         = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#Object");
47         atom_Float          = uri_map.uri_to_id("http://lv2plug.in/ns/ext/atom#Float");
48         log_Error           = uri_map.uri_to_id("http://lv2plug.in/ns/ext/log#Error");
49         log_Note            = uri_map.uri_to_id("http://lv2plug.in/ns/ext/log#Note");
50         log_Trace           = uri_map.uri_to_id("http://lv2plug.in/ns/ext/log#Trace");
51         log_Warning         = uri_map.uri_to_id("http://lv2plug.in/ns/ext/log#Warning");
52         midi_MidiEvent      = uri_map.uri_to_id("http://lv2plug.in/ns/ext/midi#MidiEvent");
53         time_Position       = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#Position");
54         time_bar            = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#bar");
55         time_barBeat        = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#barBeat");
56         time_beatUnit       = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#beatUnit");
57         time_beatsPerBar    = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#beatsPerBar");
58         time_beatsPerMinute = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#beatsPerMinute");
59         time_frame          = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#frame");
60         time_speed          = uri_map.uri_to_id("http://lv2plug.in/ns/ext/time#speed");
61         patch_Get           = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#Get");
62         patch_Set           = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#Set");
63         patch_property      = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#property");
64         patch_value         = uri_map.uri_to_id("http://lv2plug.in/ns/ext/patch#value");
65 #ifdef LV2_EXTENDED
66         auto_event         = uri_map.uri_to_id(LV2_AUTOMATE_URI__event);
67         auto_setup         = uri_map.uri_to_id(LV2_AUTOMATE_URI__setup);
68         auto_finalize      = uri_map.uri_to_id(LV2_AUTOMATE_URI__finalize);
69         auto_start         = uri_map.uri_to_id(LV2_AUTOMATE_URI__start);
70         auto_end           = uri_map.uri_to_id(LV2_AUTOMATE_URI__end);
71         auto_parameter     = uri_map.uri_to_id(LV2_AUTOMATE_URI__parameter);
72         auto_value         = uri_map.uri_to_id(LV2_AUTOMATE_URI__value);
73 #endif
74 }
75
76 URIMap&
77 URIMap::instance()
78 {
79         if (!URIMap::uri_map) {
80                 URIMap::uri_map = new URIMap();
81         }
82         return *URIMap::uri_map;
83 }
84
85 static uint32_t
86 c_uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
87                     const char*               map,
88                     const char*               uri)
89 {
90         URIMap* const me = (URIMap*)callback_data;
91         const uint32_t id = me->uri_to_id(uri);
92
93         /* The event context with the uri-map extension guarantees a value in the
94            range of uint16_t.  Ardour used to map to a separate range to achieve
95            this, but unfortunately some plugins are broken and use the incorrect
96            context.  To compensate, we simply use the same context for everything
97            and hope that anything in the event context gets mapped before
98            UINT16_MAX is reached (which will be fine unless something seriously
99            weird is going on).  If this fails there is nothing we can do, die.
100         */
101         assert(!map || strcmp(map, "http://lv2plug.in/ns/ext/event")
102                || id < UINT16_MAX);
103
104         return id;
105 }
106
107 static LV2_URID
108 c_urid_map(LV2_URID_Map_Handle handle,
109            const char*         uri)
110 {
111         URIMap* const me = (URIMap*)handle;
112         return me->uri_to_id(uri);
113 }
114
115 static const char*
116 c_urid_unmap(LV2_URID_Unmap_Handle handle,
117              LV2_URID              urid)
118 {
119         URIMap* const me = (URIMap*)handle;
120         return me->id_to_uri(urid);
121 }
122
123 URIMap::URIMap()
124 {
125         _uri_map_feature_data.uri_to_id     = c_uri_map_uri_to_id;
126         _uri_map_feature_data.callback_data = this;
127         _uri_map_feature.URI                = LV2_URI_MAP_URI;
128         _uri_map_feature.data               = &_uri_map_feature_data;
129
130         _urid_map_feature_data.map    = c_urid_map;
131         _urid_map_feature_data.handle = this;
132         _urid_map_feature.URI         = LV2_URID_MAP_URI;
133         _urid_map_feature.data        = &_urid_map_feature_data;
134
135         _urid_unmap_feature_data.unmap  = c_urid_unmap;
136         _urid_unmap_feature_data.handle = this;
137         _urid_unmap_feature.URI         = LV2_URID_UNMAP_URI;
138         _urid_unmap_feature.data        = &_urid_unmap_feature_data;
139
140         urids.init(*this);
141 }
142
143 uint32_t
144 URIMap::uri_to_id(const char* uri)
145 {
146         Glib::Threads::Mutex::Lock lm (_lock);
147
148         const std::string urimm(uri);
149         const Map::const_iterator i = _map.find(urimm);
150         if (i != _map.end()) {
151                 return i->second;
152         }
153         const uint32_t id = _map.size() + 1;
154         _map.insert(std::make_pair(urimm, id));
155         _unmap.insert(std::make_pair(id, urimm));
156         return id;
157 }
158
159 const char*
160 URIMap::id_to_uri(const uint32_t id) const
161 {
162         Glib::Threads::Mutex::Lock lm (_lock);
163
164         const Unmap::const_iterator i = _unmap.find(id);
165         return (i != _unmap.end()) ? i->second.c_str() : NULL;
166 }
167
168 } // namespace ARDOUR
169