163a460624fe8e544d3a2b6ad5a02963a2c33d9f
[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
31 namespace ARDOUR {
32
33 static uint32_t
34 c_uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
35                     const char*               map,
36                     const char*               uri)
37 {
38         URIMap* const me = (URIMap*)callback_data;
39         const uint32_t id = me->uri_to_id(uri);
40
41         /* The event context with the uri-map extension guarantees a value in the
42            range of uint16_t.  Ardour used to map to a separate range to achieve
43            this, but unfortunately some plugins are broken and use the incorrect
44            context.  To compensate, we simply use the same context for everything
45            and hope that anything in the event context gets mapped before
46            UINT16_MAX is reached (which will be fine unless something seriously
47            weird is going on).  If this fails there is nothing we can do, die.
48         */
49         assert(!map || strcmp(map, "http://lv2plug.in/ns/ext/event")
50                || id < UINT16_MAX);
51
52         return id;
53 }
54
55 static LV2_URID
56 c_urid_map(LV2_URID_Map_Handle handle,
57            const char*         uri)
58 {
59         URIMap* const me = (URIMap*)handle;
60         return me->uri_to_id(uri);
61 }
62
63 static const char*
64 c_urid_unmap(LV2_URID_Unmap_Handle handle,
65            LV2_URID              urid)
66 {
67         URIMap* const me = (URIMap*)handle;
68         return me->id_to_uri(urid);
69 }
70
71 URIMap::URIMap()
72 {
73         _uri_map_feature_data.uri_to_id     = c_uri_map_uri_to_id;
74         _uri_map_feature_data.callback_data = this;
75         _uri_map_feature.URI                = LV2_URI_MAP_URI;
76         _uri_map_feature.data               = &_uri_map_feature_data;
77
78         _urid_map_feature_data.map    = c_urid_map;
79         _urid_map_feature_data.handle = this;
80         _urid_map_feature.URI         = LV2_URID_MAP_URI;
81         _urid_map_feature.data        = &_urid_map_feature_data;
82
83         _urid_unmap_feature_data.unmap  = c_urid_unmap;
84         _urid_unmap_feature_data.handle = this;
85         _urid_unmap_feature.URI         = LV2_URID_UNMAP_URI;
86         _urid_unmap_feature.data        = &_urid_unmap_feature_data;
87 }
88
89 uint32_t
90 URIMap::uri_to_id(const char* uri)
91 {
92         const std::string urimm(uri);
93         const Map::const_iterator i = _map.find(urimm);
94         if (i != _map.end()) {
95                 return i->second;
96         }
97         const uint32_t id = _map.size() + 1;
98         _map.insert(std::make_pair(urimm, id));
99         _unmap.insert(std::make_pair(id, urimm));
100         return id;
101 }
102
103 const char*
104 URIMap::id_to_uri(const uint32_t id) const
105 {
106         const Unmap::const_iterator i = _unmap.find(id);
107         return (i != _unmap.end()) ? i->second.c_str() : NULL;
108 }
109
110 } // namespace ARDOUR
111