Collect plugin runtime profile statistics.
[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_sample          = 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         state_StateChanged  = uri_map.uri_to_id("http://lv2plug.in/ns/ext/state#StateChanged"); // since LV2 1.15.1
66 #ifdef LV2_EXTENDED
67         auto_event         = uri_map.uri_to_id(LV2_AUTOMATE_URI__event);
68         auto_setup         = uri_map.uri_to_id(LV2_AUTOMATE_URI__setup);
69         auto_finalize      = uri_map.uri_to_id(LV2_AUTOMATE_URI__finalize);
70         auto_start         = uri_map.uri_to_id(LV2_AUTOMATE_URI__start);
71         auto_end           = uri_map.uri_to_id(LV2_AUTOMATE_URI__end);
72         auto_parameter     = uri_map.uri_to_id(LV2_AUTOMATE_URI__parameter);
73         auto_value         = uri_map.uri_to_id(LV2_AUTOMATE_URI__value);
74 #endif
75 }
76
77 URIMap&
78 URIMap::instance()
79 {
80         if (!URIMap::uri_map) {
81                 URIMap::uri_map = new URIMap();
82         }
83         return *URIMap::uri_map;
84 }
85
86 static uint32_t
87 c_uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
88                     const char*               map,
89                     const char*               uri)
90 {
91         URIMap* const me = (URIMap*)callback_data;
92         const uint32_t id = me->uri_to_id(uri);
93
94         /* The event context with the uri-map extension guarantees a value in the
95            range of uint16_t.  Ardour used to map to a separate range to achieve
96            this, but unfortunately some plugins are broken and use the incorrect
97            context.  To compensate, we simply use the same context for everything
98            and hope that anything in the event context gets mapped before
99            UINT16_MAX is reached (which will be fine unless something seriously
100            weird is going on).  If this fails there is nothing we can do, die.
101         */
102         assert(!map || strcmp(map, "http://lv2plug.in/ns/ext/event")
103                || id < UINT16_MAX);
104
105         return id;
106 }
107
108 static LV2_URID
109 c_urid_map(LV2_URID_Map_Handle handle,
110            const char*         uri)
111 {
112         URIMap* const me = (URIMap*)handle;
113         return me->uri_to_id(uri);
114 }
115
116 static const char*
117 c_urid_unmap(LV2_URID_Unmap_Handle handle,
118              LV2_URID              urid)
119 {
120         URIMap* const me = (URIMap*)handle;
121         return me->id_to_uri(urid);
122 }
123
124 URIMap::URIMap()
125 {
126         _uri_map_feature_data.uri_to_id     = c_uri_map_uri_to_id;
127         _uri_map_feature_data.callback_data = this;
128         _uri_map_feature.URI                = LV2_URI_MAP_URI;
129         _uri_map_feature.data               = &_uri_map_feature_data;
130
131         _urid_map_feature_data.map    = c_urid_map;
132         _urid_map_feature_data.handle = this;
133         _urid_map_feature.URI         = LV2_URID_MAP_URI;
134         _urid_map_feature.data        = &_urid_map_feature_data;
135
136         _urid_unmap_feature_data.unmap  = c_urid_unmap;
137         _urid_unmap_feature_data.handle = this;
138         _urid_unmap_feature.URI         = LV2_URID_UNMAP_URI;
139         _urid_unmap_feature.data        = &_urid_unmap_feature_data;
140
141         urids.init(*this);
142 }
143
144 uint32_t
145 URIMap::uri_to_id(const char* uri)
146 {
147         Glib::Threads::Mutex::Lock lm (_lock);
148
149         const std::string urimm(uri);
150         const Map::const_iterator i = _map.find(urimm);
151         if (i != _map.end()) {
152                 return i->second;
153         }
154         const uint32_t id = _map.size() + 1;
155         _map.insert(std::make_pair(urimm, id));
156         _unmap.insert(std::make_pair(id, urimm));
157         return id;
158 }
159
160 const char*
161 URIMap::id_to_uri(const uint32_t id) const
162 {
163         Glib::Threads::Mutex::Lock lm (_lock);
164
165         const Unmap::const_iterator i = _unmap.find(id);
166         return (i != _unmap.end()) ? i->second.c_str() : NULL;
167 }
168
169 } // namespace ARDOUR
170