Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

miditable.h 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Copyright (c) 2012 Mark McCurry
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. */
  24. #ifndef RTOSC_MIDITABLE_H
  25. #define RTOSC_MIDITABLE_H
  26. #include <rtosc/ports.h>
  27. #include <string.h>
  28. #include <algorithm>
  29. #include <map>
  30. #include <sstream>
  31. #include <deque>
  32. #include <utility>
  33. #include <cassert>
  34. namespace rtosc {
  35. /**
  36. * Module Overview
  37. *
  38. * Actions:
  39. * - Add a mapping {coarse/fine} [nRT]
  40. * - Delete a mapping {coarse/fine} [nRT]
  41. * - Transform mapping value based on passive observation [nRT]
  42. * - Find unused CC numbers [RT]
  43. * - Transform CC into event {coarse/fine} [RT]
  44. */
  45. class MidiMapperStorage
  46. {
  47. public:
  48. //Almost immutable short vector class
  49. template<class T>
  50. class TinyVector {
  51. int n;
  52. T *t;
  53. public:
  54. TinyVector(void):n(0),t(0){}
  55. TinyVector(int i):n(i),t(new T[i]){}
  56. T&operator[](int i) {assert(i>=0 && i<n);return t[i];}
  57. T operator[](int i) const {assert(i>=0 && i<n);return t[i];}
  58. TinyVector insert(const T &t_)
  59. {TinyVector next(n+1); for(int i=0;i<n; ++i) next.t[i]=t[i]; next.t[n] = t_;return std::move(next);}
  60. TinyVector one_larger(void)
  61. {TinyVector next(n+1); for(int i=0;i<n + 1; ++i) next.t[i]=0; return std::move(next);}
  62. TinyVector sized_clone(void)
  63. {TinyVector next(n); for(int i=0;i<n; ++i) next.t[i]=0; return std::move(next);}
  64. TinyVector clone(void)
  65. {TinyVector next(n); for(int i=0;i<n; ++i) next.t[i]=t[i]; return std::move(next);}
  66. int size(void) const{return n;}
  67. };
  68. typedef std::function<void(const char*)> write_cb;
  69. typedef std::function<void(int16_t,write_cb)> callback_t;
  70. //RT Read Only
  71. TinyVector<std::tuple<int, bool, int>> mapping;//CC->{coarse, val-cb offset}
  72. TinyVector<callback_t> callbacks;
  73. //RT RW
  74. TinyVector<int> values;
  75. bool handleCC(int ID, int val, write_cb write);
  76. //TODO try to change O(n^2) algorithm to O(n)
  77. void cloneValues(const MidiMapperStorage &storage);
  78. MidiMapperStorage *clone(void);
  79. };
  80. struct MidiBijection
  81. {
  82. int mode;//0:linear,1:log
  83. float min;
  84. float max;
  85. int operator()(float x) const;
  86. float operator()(int x) const;
  87. };
  88. #include <cassert>
  89. class MidiMappernRT
  90. {
  91. public:
  92. MidiMappernRT(void);
  93. void map(const char *addr, bool coarse = true);
  94. MidiMapperStorage *generateNewBijection(const Port &port, std::string);
  95. void addNewMapper(int ID, const Port &port, std::string addr);
  96. void addFineMapper(int ID, const Port &port, std::string addr);
  97. void useFreeID(int ID);
  98. void unMap(const char *addr, bool coarse);
  99. void delMapping(int ID, bool coarse, const char *addr);
  100. void replaceMapping(int, bool, const char *);
  101. void clear(void);
  102. std::map<std::string, std::string> getMidiMappingStrings(void);
  103. //unclear if this should be be here as a helper or not
  104. std::string getMappedString(std::string addr);
  105. MidiBijection getBijection(std::string s);
  106. void snoop(const char *msg);
  107. void apply_high(int v, int ID);
  108. void apply_low(int v, int ID);
  109. void apply_midi(int val, int ID);
  110. void setBounds(const char *str, float low, float high);
  111. std::tuple<float,float,float,float> getBounds(const char *str);
  112. bool has(std::string addr);
  113. bool hasPending(std::string addr);
  114. bool hasCoarse(std::string addr);
  115. bool hasFine(std::string addr);
  116. bool hasCoarsePending(std::string addr);
  117. bool hasFinePending(std::string addr);
  118. int getCoarse(std::string addr);
  119. int getFine(std::string addr);
  120. //(Location, Coarse, Fine, Bijection)
  121. std::map<std::string, std::tuple<int, int, int, MidiBijection>> inv_map;
  122. std::deque<std::pair<std::string,bool>> learnQueue;
  123. std::function<void(const char *)> rt_cb;
  124. MidiMapperStorage *storage;
  125. const Ports *base_ports;
  126. };
  127. class MidiMapperRT
  128. {
  129. public:
  130. MidiMapperRT(void);
  131. void setBackendCb(std::function<void(const char*)> cb);
  132. void setFrontendCb(std::function<void(const char*)> cb);
  133. void handleCC(int ID, int val);
  134. void addWatch(void);
  135. void remWatch(void);
  136. //Depricated
  137. Port addWatchPort(void);
  138. Port removeWatchPort(void);
  139. Port bindPort(void);
  140. static const Ports ports;
  141. //Fixed upper bounded size set of integer IDs
  142. class PendingQueue
  143. {
  144. public:
  145. PendingQueue()
  146. :pos_r(0), pos_w(0), size(0)
  147. {
  148. for(int i=0; i<32; ++i)
  149. vals[i] = -1;
  150. }
  151. void insert(int x)
  152. {
  153. if(has(x) || size > 31)
  154. return;
  155. vals[pos_w] = x;
  156. size++;
  157. pos_w = (pos_w+1)%32;
  158. }
  159. void pop(void)
  160. {
  161. if(size == 0)
  162. return;
  163. size--;
  164. vals[pos_r] = -1;
  165. pos_r = (1+pos_r)%32;
  166. }
  167. bool has(int x)
  168. {
  169. for(int i=0; i<32; ++i)
  170. if(vals[i] == x)
  171. return true;
  172. return false;
  173. }
  174. int vals[32];
  175. int pos_r;
  176. int pos_w;
  177. int size;
  178. };
  179. /***************
  180. * Member Data *
  181. ***************/
  182. PendingQueue pending;
  183. MidiMapperStorage *storage;
  184. unsigned watchSize;
  185. std::function<void(const char*)> backend;
  186. std::function<void(const char*)> frontend;
  187. };
  188. struct MidiAddr
  189. {
  190. //The midi values that map to the specified action
  191. uint8_t ch, ctl;
  192. //The type of the event 'f', 'i', 'T', 'c'
  193. char type;
  194. //The path of the event
  195. char *path;
  196. //The conversion function for 'f' types
  197. const char *conversion;
  198. };
  199. /**
  200. * Table of midi mappings - Deprecated
  201. *
  202. */
  203. class MidiTable
  204. {
  205. public:
  206. const Ports &dispatch_root;
  207. short unhandled_ch;
  208. short unhandled_ctl;
  209. char *unhandled_path;
  210. void (*error_cb)(const char *, const char *);
  211. void (*event_cb)(const char *);
  212. void (*modify_cb)(const char *, const char *, const char *, int, int);
  213. MidiTable(const Ports &_dispatch_root);
  214. ~MidiTable();
  215. bool has(uint8_t ch, uint8_t ctl) const;
  216. MidiAddr *get(uint8_t ch, uint8_t ctl);
  217. const MidiAddr *get(uint8_t ch, uint8_t ctl) const;
  218. bool mash_port(MidiAddr &e, const Port &port);
  219. void addElm(uint8_t ch, uint8_t ctl, const char *path);
  220. void check_learn(void);
  221. void learn(const char *s);
  222. void clear_entry(const char *s);
  223. void process(uint8_t ch, uint8_t ctl, uint8_t val);
  224. Port learnPort(void);
  225. Port unlearnPort(void);
  226. Port registerPort(void);
  227. //TODO generalize to an addScalingFunction() system
  228. static float translate(uint8_t val, const char *meta);
  229. private:
  230. class MidiTable_Impl *impl;
  231. };
  232. };
  233. #endif