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