1 /* 2 Copyright (c) 2019, Michael Fisher <mfisher@kushview.net> 3 4 Permission to use, copy, modify, and/or distribute this software for any 5 purpose with or without fee is hereby granted, provided that the above 6 copyright notice and this permission notice appear in all copies. 7 8 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #pragma once 18 19 #include <map> 20 #include <string> 21 #include <lv2/lv2plug.in/ns/lv2core/lv2.h> 22 #include <lv2/lv2plug.in/ns/ext/urid/urid.h> 23 24 namespace lvtk { 25 26 /** Maintains a map of Strings/Symbols to integers 27 28 This class also implements LV2 URID Map/Unmap features. Plugin 29 implementations don't need to use this. You can, however, use this in a 30 LV2 host to easily provide URID map/unmaping features to plugins. 31 32 @headerfile lvtk/uri_directory.hpp 33 @ingroup urid 34 */ 35 class URIDirectory 36 { 37 public: 38 /** Create an empty symbol map and initialized LV2 URID features */ URIDirectory()39 URIDirectory() 40 { 41 map_feature.URI = LV2_URID__map; 42 map_data.handle = (void*) this; 43 map_data.map = &URIDirectory::_map; 44 map_feature.data = &map_data; 45 46 unmap_feature.URI = LV2_URID__unmap; 47 unmap_data.handle = this; 48 unmap_data.unmap = _unmap; 49 unmap_feature.data = &unmap_data; 50 } 51 ~URIDirectory()52 ~URIDirectory() 53 { 54 clear(); 55 } 56 57 /** Map a symbol/uri to an unsigned integer 58 @param key The symbol to map 59 @returns A mapped URID, a return of 0 indicates failure */ map(const char * key)60 inline uint32_t map (const char* key) 61 { 62 if (! contains (key)) 63 { 64 const uint32_t urid (1 + (uint32_t) mapped.size()); 65 mapped [key] = urid; 66 unmapped [urid] = std::string (key); 67 return urid; 68 } 69 70 return mapped [key]; 71 } 72 73 /** Containment test of a URI 74 75 @param uri The URI to test 76 @returns True if found */ contains(const char * uri)77 inline bool contains (const char* uri) { 78 return mapped.find (uri) != mapped.end(); 79 } 80 81 /** Containment test of a URID 82 83 @param urid The URID to test 84 @return True if found */ contains(uint32_t urid)85 inline bool contains (uint32_t urid) { 86 return unmapped.find (urid) != unmapped.end(); 87 } 88 89 /** Unmap an already mapped id to its symbol 90 91 @param urid The URID to unmap 92 @return The previously mapped symbol or 0 if the urid isn't in the cache 93 */ unmap(uint32_t urid)94 inline const char* unmap (uint32_t urid) { 95 if (contains (urid)) 96 return (const char*) unmapped [urid].c_str(); 97 return ""; 98 } 99 100 /** Clear the URIDirectory */ clear()101 inline void clear() 102 { 103 mapped.clear(); 104 unmapped.clear(); 105 } 106 107 /** @returns a LV2_Feature with LV2_URID_Map as the data member */ get_map_feature() const108 const LV2_Feature *const get_map_feature() const { return &map_feature; } 109 /** @returns a LV2_Feature with LV2_URID_Unmap as the data member */ get_unmap_feature() const110 const LV2_Feature *const get_unmap_feature() const { return &unmap_feature; } 111 112 private: 113 std::map<std::string, uint32_t> mapped; 114 std::map<uint32_t, std::string> unmapped; 115 116 LV2_Feature map_feature; 117 LV2_URID_Map map_data; 118 LV2_Feature unmap_feature; 119 LV2_URID_Unmap unmap_data; 120 _map(LV2_URID_Map_Handle self,const char * uri)121 static uint32_t _map (LV2_URID_Map_Handle self, const char* uri) { 122 return (static_cast<URIDirectory*> (self))->map (uri); 123 } 124 _unmap(LV2_URID_Unmap_Handle self,uint32_t urid)125 static const char* _unmap (LV2_URID_Unmap_Handle self, uint32_t urid) { 126 return (static_cast<URIDirectory*> (self))->unmap (urid); 127 } 128 }; 129 130 } 131