effect-web-midi 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +276 -0
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/EMIDIAccess.js +129 -0
  5. package/dist/src/EMIDIAccess.js.map +1 -0
  6. package/dist/src/EMIDIInput.js +226 -0
  7. package/dist/src/EMIDIInput.js.map +1 -0
  8. package/dist/src/EMIDIOutput.js +227 -0
  9. package/dist/src/EMIDIOutput.js.map +1 -0
  10. package/dist/src/EMIDIPort.js +218 -0
  11. package/dist/src/EMIDIPort.js.map +1 -0
  12. package/dist/src/MIDIErrors.js +4 -0
  13. package/dist/src/MIDIErrors.js.map +1 -0
  14. package/dist/src/MIDIEventStreams.js +2 -0
  15. package/dist/src/MIDIEventStreams.js.map +1 -0
  16. package/dist/src/Parsing.js +2 -0
  17. package/dist/src/Parsing.js.map +1 -0
  18. package/dist/src/StreamMaker.js +1 -0
  19. package/dist/src/StreamMaker.js.map +1 -0
  20. package/dist/src/Util.js +2 -0
  21. package/dist/src/Util.js.map +1 -0
  22. package/dist/src/index.js +10 -0
  23. package/dist/src/index.js.map +1 -0
  24. package/dist/src/internal/EMIDIAccess.js +634 -0
  25. package/dist/src/internal/EMIDIAccess.js.map +1 -0
  26. package/dist/src/internal/EMIDIInput.js +66 -0
  27. package/dist/src/internal/EMIDIInput.js.map +1 -0
  28. package/dist/src/internal/EMIDIOutput.js +120 -0
  29. package/dist/src/internal/EMIDIOutput.js.map +1 -0
  30. package/dist/src/internal/EMIDIPort.js +125 -0
  31. package/dist/src/internal/EMIDIPort.js.map +1 -0
  32. package/dist/src/internal/MIDIErrors.js +190 -0
  33. package/dist/src/internal/MIDIErrors.js.map +1 -0
  34. package/dist/src/internal/MIDIEventStreams.js +41 -0
  35. package/dist/src/internal/MIDIEventStreams.js.map +1 -0
  36. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.js +27 -0
  37. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.js.map +1 -0
  38. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.js +19 -0
  39. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.js.map +1 -0
  40. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.js +16 -0
  41. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.js.map +1 -0
  42. package/dist/src/internal/MIDIPortMethodCalls/actOnPort.js +17 -0
  43. package/dist/src/internal/MIDIPortMethodCalls/actOnPort.js.map +1 -0
  44. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.js +27 -0
  45. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.js.map +1 -0
  46. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.js +18 -0
  47. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.js.map +1 -0
  48. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.js +16 -0
  49. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.js.map +1 -0
  50. package/dist/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.js +21 -0
  51. package/dist/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.js.map +1 -0
  52. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.js +34 -0
  53. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.js.map +1 -0
  54. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.js +18 -0
  55. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.js.map +1 -0
  56. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.js +16 -0
  57. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.js.map +1 -0
  58. package/dist/src/internal/Parsing.js +119 -0
  59. package/dist/src/internal/Parsing.js.map +1 -0
  60. package/dist/src/internal/StreamMaker.js +105 -0
  61. package/dist/src/internal/StreamMaker.js.map +1 -0
  62. package/dist/src/internal/Util.js +59 -0
  63. package/dist/src/internal/Util.js.map +1 -0
  64. package/dist/src/internal/getPortByPortId/getPortByPortIdAndAccess.js +53 -0
  65. package/dist/src/internal/getPortByPortId/getPortByPortIdAndAccess.js.map +1 -0
  66. package/dist/src/internal/getPortByPortId/getPortByPortIdInContext.js +18 -0
  67. package/dist/src/internal/getPortByPortId/getPortByPortIdInContext.js.map +1 -0
  68. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.js +52 -0
  69. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.js.map +1 -0
  70. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.js +21 -0
  71. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.js.map +1 -0
  72. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.js +21 -0
  73. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.js.map +1 -0
  74. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.js +66 -0
  75. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.js.map +1 -0
  76. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.js +61 -0
  77. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.js.map +1 -0
  78. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.js +68 -0
  79. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.js.map +1 -0
  80. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.js +42 -0
  81. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.js.map +1 -0
  82. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.js +43 -0
  83. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.js.map +1 -0
  84. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.js +33 -0
  85. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.js.map +1 -0
  86. package/dist/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.js +6 -0
  87. package/dist/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.js.map +1 -0
  88. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.js +46 -0
  89. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.js.map +1 -0
  90. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.js +25 -0
  91. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.js.map +1 -0
  92. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.js +31 -0
  93. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.js.map +1 -0
  94. package/dist-types/index.d.ts +2 -0
  95. package/dist-types/index.d.ts.map +1 -0
  96. package/dist-types/src/EMIDIAccess.d.ts +18 -0
  97. package/dist-types/src/EMIDIAccess.d.ts.map +1 -0
  98. package/dist-types/src/EMIDIInput.d.ts +26 -0
  99. package/dist-types/src/EMIDIInput.d.ts.map +1 -0
  100. package/dist-types/src/EMIDIOutput.d.ts +26 -0
  101. package/dist-types/src/EMIDIOutput.d.ts.map +1 -0
  102. package/dist-types/src/EMIDIPort.d.ts +26 -0
  103. package/dist-types/src/EMIDIPort.d.ts.map +1 -0
  104. package/dist-types/src/MIDIErrors.d.ts +2 -0
  105. package/dist-types/src/MIDIErrors.d.ts.map +1 -0
  106. package/dist-types/src/MIDIEventStreams.d.ts +2 -0
  107. package/dist-types/src/MIDIEventStreams.d.ts.map +1 -0
  108. package/dist-types/src/Parsing.d.ts +2 -0
  109. package/dist-types/src/Parsing.d.ts.map +1 -0
  110. package/dist-types/src/StreamMaker.d.ts +2 -0
  111. package/dist-types/src/StreamMaker.d.ts.map +1 -0
  112. package/dist-types/src/Util.d.ts +2 -0
  113. package/dist-types/src/Util.d.ts.map +1 -0
  114. package/dist-types/src/index.d.ts +10 -0
  115. package/dist-types/src/index.d.ts.map +1 -0
  116. package/dist-types/src/internal/EMIDIAccess.d.ts +551 -0
  117. package/dist-types/src/internal/EMIDIAccess.d.ts.map +1 -0
  118. package/dist-types/src/internal/EMIDIInput.d.ts +50 -0
  119. package/dist-types/src/internal/EMIDIInput.d.ts.map +1 -0
  120. package/dist-types/src/internal/EMIDIOutput.d.ts +95 -0
  121. package/dist-types/src/internal/EMIDIOutput.d.ts.map +1 -0
  122. package/dist-types/src/internal/EMIDIPort.d.ts +90 -0
  123. package/dist-types/src/internal/EMIDIPort.d.ts.map +1 -0
  124. package/dist-types/src/internal/MIDIErrors.d.ts +270 -0
  125. package/dist-types/src/internal/MIDIErrors.d.ts.map +1 -0
  126. package/dist-types/src/internal/MIDIEventStreams.d.ts +74 -0
  127. package/dist-types/src/internal/MIDIEventStreams.d.ts.map +1 -0
  128. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.d.ts +16 -0
  129. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.d.ts.map +1 -0
  130. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.d.ts +15 -0
  131. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.d.ts.map +1 -0
  132. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.d.ts +13 -0
  133. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.d.ts.map +1 -0
  134. package/dist-types/src/internal/MIDIPortMethodCalls/actOnPort.d.ts +11 -0
  135. package/dist-types/src/internal/MIDIPortMethodCalls/actOnPort.d.ts.map +1 -0
  136. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.d.ts +23 -0
  137. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.d.ts.map +1 -0
  138. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.d.ts +15 -0
  139. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.d.ts.map +1 -0
  140. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.d.ts +13 -0
  141. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.d.ts.map +1 -0
  142. package/dist-types/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.d.ts +15 -0
  143. package/dist-types/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.d.ts.map +1 -0
  144. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.d.ts +21 -0
  145. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.d.ts.map +1 -0
  146. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.d.ts +15 -0
  147. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.d.ts.map +1 -0
  148. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.d.ts +13 -0
  149. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.d.ts.map +1 -0
  150. package/dist-types/src/internal/Parsing.d.ts +110 -0
  151. package/dist-types/src/internal/Parsing.d.ts.map +1 -0
  152. package/dist-types/src/internal/StreamMaker.d.ts +204 -0
  153. package/dist-types/src/internal/StreamMaker.d.ts.map +1 -0
  154. package/dist-types/src/internal/Util.d.ts +33 -0
  155. package/dist-types/src/internal/Util.d.ts.map +1 -0
  156. package/dist-types/src/internal/getPortByPortId/getPortByPortIdAndAccess.d.ts +27 -0
  157. package/dist-types/src/internal/getPortByPortId/getPortByPortIdAndAccess.d.ts.map +1 -0
  158. package/dist-types/src/internal/getPortByPortId/getPortByPortIdInContext.d.ts +20 -0
  159. package/dist-types/src/internal/getPortByPortId/getPortByPortIdInContext.d.ts.map +1 -0
  160. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.d.ts +76 -0
  161. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.d.ts.map +1 -0
  162. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.d.ts +39 -0
  163. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.d.ts.map +1 -0
  164. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.d.ts +29 -0
  165. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.d.ts.map +1 -0
  166. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.d.ts +62 -0
  167. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.d.ts.map +1 -0
  168. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.d.ts +16 -0
  169. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.d.ts.map +1 -0
  170. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.d.ts +65 -0
  171. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.d.ts.map +1 -0
  172. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.d.ts +36 -0
  173. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.d.ts.map +1 -0
  174. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.d.ts +23 -0
  175. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.d.ts.map +1 -0
  176. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.d.ts +35 -0
  177. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.d.ts.map +1 -0
  178. package/dist-types/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.d.ts +7 -0
  179. package/dist-types/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.d.ts.map +1 -0
  180. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.d.ts +71 -0
  181. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.d.ts.map +1 -0
  182. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.d.ts +7 -0
  183. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.d.ts.map +1 -0
  184. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.d.ts +28 -0
  185. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.d.ts.map +1 -0
  186. package/index.ts +1 -0
  187. package/package.json +87 -0
  188. package/src/EMIDIAccess.ts +285 -0
  189. package/src/EMIDIInput.ts +273 -0
  190. package/src/EMIDIOutput.ts +272 -0
  191. package/src/EMIDIPort.ts +270 -0
  192. package/src/MIDIErrors.ts +13 -0
  193. package/src/MIDIEventStreams.ts +36 -0
  194. package/src/Parsing.ts +32 -0
  195. package/src/StreamMaker.ts +12 -0
  196. package/src/Util.ts +19 -0
  197. package/src/index.ts +9 -0
  198. package/src/internal/EMIDIAccess.ts +1280 -0
  199. package/src/internal/EMIDIInput.ts +114 -0
  200. package/src/internal/EMIDIOutput.ts +231 -0
  201. package/src/internal/EMIDIPort.ts +239 -0
  202. package/src/internal/MIDIErrors.ts +260 -0
  203. package/src/internal/MIDIEventStreams.ts +255 -0
  204. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.ts +48 -0
  205. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.ts +31 -0
  206. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.ts +28 -0
  207. package/src/internal/MIDIPortMethodCalls/actOnPort.ts +66 -0
  208. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.ts +38 -0
  209. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.ts +38 -0
  210. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.ts +28 -0
  211. package/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.ts +68 -0
  212. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.ts +48 -0
  213. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.ts +38 -0
  214. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.ts +28 -0
  215. package/src/internal/Parsing.ts +304 -0
  216. package/src/internal/StreamMaker.ts +416 -0
  217. package/src/internal/Util.ts +152 -0
  218. package/src/internal/getPortByPortId/getPortByPortIdAndAccess.ts +117 -0
  219. package/src/internal/getPortByPortId/getPortByPortIdInContext.ts +26 -0
  220. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.ts +148 -0
  221. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.ts +135 -0
  222. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.ts +70 -0
  223. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.ts +128 -0
  224. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.ts +74 -0
  225. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.ts +132 -0
  226. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.ts +64 -0
  227. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.ts +114 -0
  228. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.ts +47 -0
  229. package/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.ts +12 -0
  230. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.ts +182 -0
  231. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.ts +29 -0
  232. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.ts +87 -0
@@ -0,0 +1,1280 @@
1
+ /** biome-ignore-all lint/style/useShorthandFunctionType: It's a nice way to
2
+ * preserve JSDoc comments attached to the function signature */
3
+
4
+ import * as EArray from 'effect/Array'
5
+ import * as Context from 'effect/Context'
6
+ import * as Effect from 'effect/Effect'
7
+ import * as Equal from 'effect/Equal'
8
+ import * as EFunction from 'effect/Function'
9
+ import * as Hash from 'effect/Hash'
10
+ import * as Inspectable from 'effect/Inspectable'
11
+ import * as Iterable from 'effect/Iterable'
12
+ import * as Layer from 'effect/Layer'
13
+ import * as Option from 'effect/Option'
14
+ import * as Order from 'effect/Order'
15
+ import * as Pipeable from 'effect/Pipeable'
16
+ import * as Record from 'effect/Record'
17
+ import * as Ref from 'effect/Ref'
18
+ import * as SortedMap from 'effect/SortedMap'
19
+ import type * as Types from 'effect/Types'
20
+ import * as Unify from 'effect/Unify'
21
+
22
+ import * as EMIDIInput from './EMIDIInput.ts'
23
+ import * as EMIDIOutput from './EMIDIOutput.ts'
24
+ import type * as EMIDIPort from './EMIDIPort.ts'
25
+ import * as GetPort from './getPortByPortId/getPortByPortIdInContext.ts'
26
+ import * as MIDIErrors from './MIDIErrors.ts'
27
+ import * as Check from './mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.ts'
28
+ import * as GetProperty from './mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.ts'
29
+ import * as StreamMaker from './StreamMaker.ts'
30
+ import * as Util from './Util.ts'
31
+
32
+ // Todo research in web midi api
33
+
34
+ // Focus on Uniqueness: On Windows, MIDI device IDs can be unstable (sometimes just an index). Focusing your library on robustly identifying the same device across reconnections is a much more valuable feature than worrying about memory leaks from too many IDs.
35
+
36
+ // TODO: add stream of messages sent from this device to target midi device
37
+
38
+ // TODO: fat service APIs, where all the methods are attached to instance and
39
+ // where you don't have to constantly write the prefix
40
+
41
+ // TODO: implement scoping of midi access that will clean up all message queues
42
+ // and streams, and remove listeners
43
+
44
+ // TODO: implement scope inheritance
45
+
46
+ // TODO: make a Ref with a port map that would be automatically updated by
47
+ // listening to the stream of connection events?
48
+
49
+ // TODO: add a stream to listen for all messages of all currently
50
+ // connected inputs, all present inputs, specific input
51
+
52
+ // TODO: add sinks that will accept command streams to redirect midi commands
53
+ // from something into an actual API
54
+
55
+ // TODO: add effect to wait until connected by port ID
56
+
57
+ // TODO: reflect sysex and software flags in type-system
58
+
59
+ // TODO: make matchers that support returning effects from the callback instead of plain values
60
+
61
+ // TODO: utilities to create mock implementations of objects because, all make methods are internal
62
+
63
+ // TODO: document that in tests, you need to manually provide the mock access with the tag
64
+
65
+ // TODO: export react and atom related stuff
66
+
67
+ // TODO: add streams with reactive live port/input/output maps snapshots
68
+
69
+ /**
70
+ * Unique symbol used for distinguishing
71
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}s from other objects at
72
+ * both runtime and type-level
73
+ * @internal
74
+ */
75
+ const TypeId: unique symbol = Symbol.for('effect-web-midi/EMIDIAccessInstance')
76
+
77
+ /**
78
+ * Unique symbol used for distinguishing
79
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}s from other objects at
80
+ * both runtime and type-level
81
+ */
82
+ export type TypeId = typeof TypeId
83
+
84
+ /**
85
+ * A tag that allows to provide
86
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance} once with e.g.
87
+ * {@linkcode layer}, {@linkcode layerSystemExclusiveSupported}, etc. and reuse
88
+ * it anywhere, instead of repeatedly {@linkcode request}ing it.
89
+ *
90
+ * The downside of using DI might be that in different places of the app it
91
+ * would be harder to maintain tight MIDI permission scopes.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
96
+ * import * as Effect from 'effect/Effect'
97
+ *
98
+ * const program = Effect.gen(function* () {
99
+ * // ^ Effect.Effect<
100
+ * // void,
101
+ * // | AbortError
102
+ * // | UnderlyingSystemError
103
+ * // | MIDIAccessNotAllowedError
104
+ * // | MIDIAccessNotSupportedError
105
+ * // never
106
+ * // >
107
+ *
108
+ * const access = yield* EMIDIAccess.EMIDIAccess
109
+ * // ^ EMIDIAccess.Instance
110
+ *
111
+ * console.log(access.sysexEnabled)
112
+ * // ^ true
113
+ * }).pipe(Effect.provide(EMIDIAccess.layerSystemExclusiveSupported))
114
+ * ```
115
+ *
116
+ * @see `navigator.requestMIDIAccess` {@link https://www.w3.org/TR/webmidi/#dom-navigator-requestmidiaccess|Web MIDI spec}, {@link https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMIDIAccess|MDN reference}
117
+ */
118
+ export class EMIDIAccess extends Context.Tag('effect-web-midi/EMIDIAccess')<
119
+ EMIDIAccess,
120
+ EMIDIAccessInstance
121
+ >() {}
122
+
123
+ export interface RequestMIDIAccessOptions {
124
+ /**
125
+ * This field informs the system whether the ability to send and receive
126
+ * `System Exclusive` messages is requested or allowed on a given
127
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance} object.
128
+ *
129
+ * If this field is set to `true`, but `System Exclusive` support is denied
130
+ * (either by policy or by user action), the access request will fail with a
131
+ * {@linkcode MIDIErrors.MIDIAccessNotAllowedError} error.
132
+ *
133
+ * If this support is not requested (and allowed), the system will throw
134
+ * exceptions if the user tries to send `System Exclusive` messages, and will
135
+ * silently mask out any `System Exclusive` messages received on the port.
136
+ *
137
+ * @default false
138
+ * @see {@link https://www.w3.org/TR/webmidi/#dom-midioptions-sysex|Web MIDI spec}, {@link https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMIDIAccess#sysex|MDN reference}
139
+ */
140
+ readonly sysex?: boolean
141
+
142
+ /**
143
+ * This field informs the system whether the ability to utilize any software
144
+ * synthesizers installed in the host system is requested or allowed on a
145
+ * given {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance} object.
146
+ *
147
+ * If this field is set to `true`, but software synthesizer support is denied
148
+ * (either by policy or by user action), the access request will fail with a
149
+ * {@linkcode MIDIErrors.MIDIAccessNotAllowedError} error.
150
+ *
151
+ * If this support is not requested,
152
+ * {@linkcode AllPortsRecord|EMIDIAccess.AllPortsRecord},
153
+ * {@linkcode getInputsRecord|EMIDIAccess.getInputsRecord},
154
+ * {@linkcode OutputsArray|EMIDIAccess.OutputsArray}, etc. would not include
155
+ * any software synthesizers.
156
+ *
157
+ * Note that may result in a two-step request procedure if software
158
+ * synthesizer support is desired but not required - software synthesizers may
159
+ * be disabled when MIDI hardware device access is allowed.
160
+ *
161
+ * @default false
162
+ * @see {@link https://www.w3.org/TR/webmidi/#dom-midioptions-software|Web MIDI spec}, {@link https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMIDIAccess#software|MDN reference}
163
+ */
164
+ readonly software?: boolean
165
+ }
166
+
167
+ /**
168
+ * Prototype of all objects satisfying the
169
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance} type.
170
+ * @internal
171
+ */
172
+ const Proto = {
173
+ _tag: 'EMIDIAccess' as const,
174
+ [TypeId]: TypeId,
175
+ [Hash.symbol]() {
176
+ return Hash.structure(this._config)
177
+ },
178
+ [Equal.symbol](that: Equal.Equal) {
179
+ return this === that
180
+ },
181
+ pipe() {
182
+ // biome-ignore lint/complexity/noArguments: Effect's tradition
183
+ return Pipeable.pipeArguments(this, arguments)
184
+ },
185
+ toString() {
186
+ return Inspectable.format(this.toJSON())
187
+ },
188
+ toJSON() {
189
+ return { _id: 'EMIDIAccess', config: this._config }
190
+ },
191
+ [Inspectable.NodeInspectSymbol]() {
192
+ return this.toJSON()
193
+ },
194
+
195
+ get sysexEnabled() {
196
+ return assumeImpl(this)._access.sysexEnabled
197
+ },
198
+
199
+ get softwareSynthEnabled() {
200
+ return !!assumeImpl(this)._config.software
201
+ },
202
+ } as EMIDIAccessImplementationInstance
203
+
204
+ /**
205
+ * Thin wrapper around raw {@linkcode MIDIAccess} instance. Will be seen in all the
206
+ * external code. Has a word `Instance` in the name to avoid confusion with
207
+ * {@linkcode EMIDIAccess|EMIDIAccess.EMIDIAccess} context tag.
208
+ */
209
+ export interface EMIDIAccessInstance
210
+ extends Equal.Equal,
211
+ Pipeable.Pipeable,
212
+ Inspectable.Inspectable {
213
+ readonly [TypeId]: TypeId
214
+ readonly _tag: 'EMIDIAccess'
215
+
216
+ /**
217
+ * The **`sysexEnabled`** read-only property of the MIDIAccess interface indicates whether system exclusive support is enabled on the current MIDIAccess instance.
218
+ *
219
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/sysexEnabled)
220
+ */
221
+ readonly sysexEnabled: boolean
222
+
223
+ readonly softwareSynthEnabled: boolean
224
+ }
225
+
226
+ /**
227
+ * Thin wrapper around raw {@linkcode MIDIAccess} instance giving access to the
228
+ * actual field storing it. Has a word `Instance` in the name to avoid confusion
229
+ * with {@linkcode EMIDIAccess|EMIDIAccess.EMIDIAccess} context tag.
230
+ * @internal
231
+ */
232
+ interface EMIDIAccessImplementationInstance extends EMIDIAccessInstance {
233
+ readonly _access: MIDIAccess
234
+ readonly _config: Readonly<RequestMIDIAccessOptions>
235
+ }
236
+
237
+ /**
238
+ * @param rawAccess The raw {@linkcode MIDIAccess} object from the browser's Web
239
+ * MIDI API to be wrapped.
240
+ * @param config Optional configuration options used to acquire the `rawAccess`,
241
+ * to preserve alongside it.
242
+ *
243
+ * @returns An object with private fields like
244
+ * {@linkcode EMIDIAccessImplementationInstance._access|_access} and
245
+ * {@linkcode EMIDIAccessImplementationInstance._config|_config} that are not
246
+ * supposed to be used externally by user-facing code.
247
+ *
248
+ * @internal
249
+ * @example
250
+ * ```ts
251
+ * const config = { sysex: true };
252
+ * const rawAccess = await navigator.requestMIDIAccess(config);
253
+ * const internalInstance = makeImpl(rawAccess, config);
254
+ * ```
255
+ */
256
+ const makeImpl = (
257
+ rawAccess: MIDIAccess,
258
+ config?: Readonly<RequestMIDIAccessOptions>,
259
+ ): EMIDIAccessImplementationInstance => {
260
+ const instance = Object.create(Proto)
261
+ instance._access = rawAccess
262
+ // TODO: set individual software and sysex flags instead
263
+ instance._config = config ?? {}
264
+ return instance
265
+ }
266
+
267
+ /**
268
+ * Asserts that an `unknown` value is a valid
269
+ * {@linkcode EMIDIAccessImplementationInstance} and casts it to the type.
270
+ * Throws an error if the assertion fails.
271
+ *
272
+ * @internal
273
+ * @example
274
+ * ```ts
275
+ * const unknownValue: null | EMIDIAccessInstance = null
276
+ * try {
277
+ * const validatedAccess = assertImpl(unknownValue);
278
+ * // validatedAccess is now known to be EMIDIAccessImplementationInstance
279
+ * } catch (error) {
280
+ * console.error("Assertion failed:", error);
281
+ * }
282
+ * ```
283
+ */
284
+ const assertImpl = (access: unknown) => {
285
+ if (!isImpl(access)) throw new Error('Failed to cast to EMIDIAccess')
286
+ return access
287
+ }
288
+
289
+ /**
290
+ * Asserts that an `unknown` value is a valid {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}
291
+ * and casts it to the type. Throws an error if the assertion fails.
292
+ *
293
+ * @internal
294
+ * @example
295
+ * ```ts
296
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
297
+ *
298
+ * const unknownValue: null | EMIDIAccess.Instance = null
299
+ *
300
+ * try {
301
+ * const validatedAccess = EMIDIAccess.assert(unknownValue);
302
+ * // validatedAccess is now known to be EMIDIAccess.Instance
303
+ * } catch (error) {
304
+ * console.error("Assertion failed:", error);
305
+ * }
306
+ * ```
307
+ *
308
+ * @see {@linkcode is|EMIDIAccess.is}
309
+ */
310
+ export const assert: (access: unknown) => EMIDIAccessInstance = assertImpl
311
+
312
+ /**
313
+ * Purely a type-level typecast to expose internal fields. Does no runtime
314
+ * validation and assumes you provided
315
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance} acquired legitimately
316
+ * from `effect-web-midi`.
317
+ *
318
+ * @internal
319
+ * @example
320
+ * ```ts
321
+ * // Assume `accessInstance` is known to be an internal implementation
322
+ * declare const accessPublic: EMIDIAccessInstance;
323
+ * const accessInternal = assumeImpl(accessPublic);
324
+ * console.log('No type error here: ', accessInternal._config)
325
+ * ```
326
+ */
327
+ export const assumeImpl = (access: EMIDIAccessInstance) =>
328
+ access as EMIDIAccessImplementationInstance
329
+
330
+ /**
331
+ * Creates a public-facing {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}
332
+ * from a raw {@linkcode MIDIAccess} object and optional configuration options
333
+ * used to acquire it. Prevents revealing internal fields set by
334
+ * `effect-web-midi` to the end user.
335
+ *
336
+ * @internal
337
+ * @example
338
+ * ```ts
339
+ * // This is an internal helper, typically not called directly by users.
340
+ * // It's used by the 'request' function to create the instance.
341
+ * const config = { sysex: true }
342
+ * const rawAccess = await navigator.requestMIDIAccess(config);
343
+ * const instance = make(rawAccess, config);
344
+ * ```
345
+ */
346
+ const make: (
347
+ rawAccess: MIDIAccess,
348
+ config?: Readonly<RequestMIDIAccessOptions>,
349
+ ) => EMIDIAccessInstance = makeImpl
350
+
351
+ /**
352
+ * @internal
353
+ * @example
354
+ * ```ts
355
+ * const accessOrNot: null | EMIDIAccessInstance = null
356
+ *
357
+ * if (isImpl(accessOrNot)) {
358
+ * const accessInternal = accessOrNot;
359
+ * // will not be logged
360
+ * console.log('No type error here: ', accessInternal._config)
361
+ * } else {
362
+ * console.log('This will be logged because null is not EMIDIAccessInstance')
363
+ * }
364
+ * ```
365
+ */
366
+ const isImpl = (access: unknown): access is EMIDIAccessImplementationInstance =>
367
+ typeof access === 'object' &&
368
+ access !== null &&
369
+ Object.getPrototypeOf(access) === Proto &&
370
+ TypeId in access &&
371
+ '_access' in access &&
372
+ typeof access._access === 'object' &&
373
+ '_config' in access &&
374
+ typeof access._config === 'object' &&
375
+ access._config !== null &&
376
+ access._access instanceof MIDIAccess
377
+
378
+ /**
379
+ * @example
380
+ * ```ts
381
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
382
+ *
383
+ * const accessOrNot: null | EMIDIAccess.Instance = null
384
+ *
385
+ * if (EMIDIAccess.is(accessOrNot)) {
386
+ * const accessPublic = accessOrNot;
387
+ * // ts-expect-error You're exposed only to public facing fields
388
+ * console.log(accessPublic._config)
389
+ * // will not be logged
390
+ * } else {
391
+ * console.log('This will be logged because null is not EMIDIAccessInstance')
392
+ * }
393
+ * ```
394
+ *
395
+ * @see {@linkcode assert|EMIDIAccess.assert}
396
+ */
397
+ export const is: (access: unknown) => access is EMIDIAccessInstance = isImpl
398
+
399
+ /**
400
+ * This utility function is used internally to handle different ways MIDI access
401
+ * might be provided, ensuring a consistent type for further operations. It uses
402
+ * the public {@linkcode is|EMIDIAccess.is} type guard for validation. If an
403
+ * effect is passed, errors and requirements are passed-through without
404
+ * modifications.
405
+ *
406
+ * @internal
407
+ * @param polymorphicAccess Either just {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}, or an
408
+ * Effect having it in the success channel.
409
+ * @returns An effect with type-asserted at runtime
410
+ * {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}.
411
+ *
412
+ * @example
413
+ * ```ts
414
+ * import * as Effect from 'effect/Effect';
415
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
416
+ *
417
+ * const getValidatedAccess = Effect.gen(function* () {
418
+ * // Assume `polymorphicAccess` is obtained elsewhere
419
+ * const polymorphicAccess = {} as EMIDIAccess.PolymorphicInstance;
420
+ * const validatedAccess = yield* EMIDIAccess.simplify(polymorphicAccess);
421
+ * // The operation above will throw a defect, because {} is not an access instance
422
+ * return validatedAccess;
423
+ * });
424
+ * ```
425
+ *
426
+ * @see {@linkcode Util.fromPolymorphic}
427
+ * @see {@linkcode PolymorphicAccessInstance|EMIDIAccess.PolymorphicInstance}
428
+ * @see {@linkcode PolymorphicAccessInstanceClean|EMIDIAccess.PolymorphicCleanInstance}
429
+ */
430
+ export const simplify = <E = never, R = never>(
431
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
432
+ ) => Util.fromPolymorphic(polymorphicAccess, is)
433
+
434
+ /**
435
+ * Represents a MIDI access instance that can be provided polymorphically:
436
+ * directly as a value ({@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}),
437
+ * or wrapped in effect. Typically processed by
438
+ * {@linkcode simplify|EMIDIAccess.simplify}.
439
+ *
440
+ * @template E The type of errors that can be thrown while acquiring the access.
441
+ * @template R The environment required to simplify the access.
442
+ *
443
+ * @example
444
+ * ```ts
445
+ * import * as Effect from 'effect/Effect';
446
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
447
+ * import type * as MIDIErrors from 'effect-web-midi/MIDIErrors';
448
+ *
449
+ * let polymorphicAccess: EMIDIAccess.PolymorphicInstance<
450
+ * | MIDIErrors.MIDIAccessNotAllowedError
451
+ * | MIDIErrors.MIDIAccessNotSupportedError,
452
+ * never
453
+ * > = EMIDIAccess.request().pipe(
454
+ * Effect.catchTag('AbortError', 'UnderlyingSystemError', () =>
455
+ * Effect.dieMessage('YOLO'),
456
+ * ),
457
+ * )
458
+ *
459
+ * if (Effect.isEffect(polymorphicAccess)) {
460
+ * const access: EMIDIAccess.Instance = await Effect.runPromise(polymorphicAccess)
461
+ * // Assignment of plain instance works just fine
462
+ * polymorphicAccess = access
463
+ * }
464
+ * ```
465
+ *
466
+ * @see {@linkcode simplify|EMIDIAccess.simplify}
467
+ * @see {@linkcode PolymorphicAccessInstanceClean|EMIDIAccess.PolymorphicCleanInstance}
468
+ */
469
+ export type PolymorphicAccessInstance<E, R> = Util.PolymorphicEffect<
470
+ EMIDIAccessInstance,
471
+ E,
472
+ R
473
+ >
474
+
475
+ /**
476
+ * Represents a MIDI access instance that can be provided polymorphically:
477
+ * directly as a value ({@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}),
478
+ * or wrapped in effect that never fails and doesn't require any context.
479
+ * Typically processed by {@linkcode simplify|EMIDIAccess.simplify}.
480
+ *
481
+ * @example
482
+ * ```ts
483
+ * import * as Effect from 'effect/Effect';
484
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
485
+ *
486
+ * let polymorphicAccess: EMIDIAccess.PolymorphicCleanInstance =
487
+ * Effect.orDie(EMIDIAccess.request())
488
+ *
489
+ * if (Effect.isEffect(polymorphicAccess)) {
490
+ * const access: EMIDIAccess.Instance =
491
+ * await Effect.runPromise(polymorphicAccess)
492
+ * // Assignment of plain instance works just fine
493
+ * polymorphicAccess = access
494
+ * }
495
+ * ```
496
+ *
497
+ * @see {@linkcode simplify|EMIDIAccess.simplify}
498
+ * @see {@linkcode PolymorphicAccessInstance|EMIDIAccess.PolymorphicInstance}
499
+ */
500
+ export type PolymorphicAccessInstanceClean = PolymorphicAccessInstance<
501
+ never,
502
+ never
503
+ >
504
+
505
+ /**
506
+ * This utility type is used internally to infer the type of values stored in
507
+ * {@linkcode MIDIAccess} maps like in {@linkcode MIDIAccess.inputs|.inputs}
508
+ * ({@linkcode MIDIInputMap}) or {@linkcode MIDIAccess.outputs|.outputs}
509
+ * ({@linkcode MIDIOutputMap}) fields.
510
+ *
511
+ * @template T - The `ReadonlyMap` to take value from.
512
+ *
513
+ * @example
514
+ * ```ts
515
+ * declare const myMap: ReadonlyMap<string, number>;
516
+ * type MyMapValue = ValueOfReadonlyMap<typeof myMap>;
517
+ * // ^ type MyMapValue = number
518
+ * type MyMapValue2 = ValueOfReadonlyMap<MIDIOutputMap>;
519
+ * // ^ type MyMapValue2 = MIDIOutput
520
+ * ```
521
+ */
522
+ type ValueOfReadonlyMap<T> = T extends ReadonlyMap<unknown, infer V> ? V : never
523
+
524
+ /**
525
+ * Higher-order helper function to canonicalize a subset of raw ports from raw access object
526
+ * into their `effect-web-midi` counterparts using the provided `make` function.
527
+ *
528
+ * @internal
529
+ * @param key The property key of {@linkcode MIDIAccess} like {@linkcode MIDIAccess.inputs|inputs} or {@linkcode MIDIAccess.outputs|outputs} to access the map (e.g. {@linkcode MIDIInputMap} or {@linkcode MIDIOutputMap})
530
+ * @param make A function to wrap the raw MIDI port (e.g. {@linkcode MIDIInput}) from that map into a managed by `effect-web-midi` port instance (e.g. {@linkcode EMIDIInput}).
531
+ * @returns A function that, when given a raw {@linkcode MIDIAccess}, returns an iterable of `[ID, effectful port]` pairs.
532
+ * @example
533
+ * ```ts
534
+ * import * as EMIDIInput from 'effect-web-midi/EMIDIInput';
535
+ *
536
+ * declare const rawAccess: MIDIAccess;
537
+ * const getInputs = getPortEntriesFromRawAccess('inputs', EMIDIInput.make);
538
+ * const inputEntries: Iterable<InputRecordEntry> = getInputs(rawAccess);
539
+ * ```
540
+ */
541
+ const getPortEntriesFromRawAccess =
542
+ <
543
+ const TMIDIPortType extends MIDIPortType,
544
+ const TMIDIAccessObjectKey extends `${TMIDIPortType}s`,
545
+ TRawMIDIPort extends ValueOfReadonlyMap<MIDIAccess[TMIDIAccessObjectKey]>,
546
+ >(
547
+ key: TMIDIAccessObjectKey,
548
+ make: (port: TRawMIDIPort) => EMIDIPort.EMIDIPort<TMIDIPortType>,
549
+ ) =>
550
+ (rawAccess: MIDIAccess) =>
551
+ Iterable.map(
552
+ rawAccess[key] as ReadonlyMap<EMIDIPort.Id<TMIDIPortType>, TRawMIDIPort>,
553
+ ([id, raw]) =>
554
+ [id as EMIDIPort.Id<TMIDIPortType>, make(raw)] satisfies Types.TupleOf<
555
+ 2,
556
+ unknown
557
+ >,
558
+ )
559
+
560
+ /**
561
+ * @internal
562
+ * @example
563
+ * ```ts
564
+ * declare const rawAccess: MIDIAccess;
565
+ *
566
+ * for (const [inputId, inputPort] of getInputEntriesFromRaw(rawAccess)) {
567
+ * // ^ ^? EMIDIInput.EMIDIInput
568
+ * // ^? EMIDIInput.Id
569
+ * }
570
+ * ```
571
+ */
572
+ const getInputEntriesFromRaw: {
573
+ (rawAccess: MIDIAccess): Iterable<InputRecordEntry>
574
+ } = getPortEntriesFromRawAccess('inputs', EMIDIInput.make)
575
+
576
+ /**
577
+ * @internal
578
+ * @example
579
+ * ```ts
580
+ * declare const rawAccess: MIDIAccess;
581
+ *
582
+ * for (const [outputId, outputPort] of getOutputEntriesFromRaw(rawAccess)) {
583
+ * // ^ ^? EMIDIOutput.EMIDIOutput
584
+ * // ^? EMIDIOutput.Id
585
+ * }
586
+ * ```
587
+ */
588
+ const getOutputEntriesFromRaw: {
589
+ (rawAccess: MIDIAccess): Iterable<OutputRecordEntry>
590
+ } = getPortEntriesFromRawAccess('outputs', EMIDIOutput.make)
591
+
592
+ /**
593
+ * A single iterable with both inputs and outputs port entries from a raw {@linkcode MIDIAccess} instance.
594
+ *
595
+ * @internal
596
+ * @example
597
+ * ```ts
598
+ * declare const rawAccess: MIDIAccess;
599
+ *
600
+ * for (const entry of getOutputEntriesFromRaw(rawAccess)) {
601
+ * if (entry[1].type === 'input') {
602
+ * const [inputId, inputPort] = entry
603
+ * // ^ ^? EMIDIInput.EMIDIInput
604
+ * // ^? EMIDIInput.Id
605
+ * } else {
606
+ * const [outputId, outputPort] = entry
607
+ * // ^ ^? EMIDIOutput.EMIDIOutput
608
+ * // ^? EMIDIOutput.Id
609
+ * }
610
+ * }
611
+ * ```
612
+ */
613
+ const getAllPortsEntriesFromRaw: {
614
+ (rawAccess: MIDIAccess): Iterable<InputRecordEntry | OutputRecordEntry>
615
+ } = raw =>
616
+ Iterable.appendAll(getInputEntriesFromRaw(raw), getOutputEntriesFromRaw(raw))
617
+
618
+ /**
619
+ *
620
+ * @param getRecordEntriesFromRawAccess Function taking raw {@linkcode MIDIAccess} and returning `[EMIDIPort.Id, EMIDIPort.EMIDIPort]` tuples
621
+ * @returns Function taking {@linkcode PolymorphicAccessInstance|EMIDIAccess.PolymorphicInstance} and returning `Record<Id, EMIDIPort>`
622
+ * @internal
623
+ * @example
624
+ * ```ts
625
+ * import * as EMIDIAccess from 'effect-web-midi/EMIDIAccess';
626
+ * import * as EMIDIInput from 'effect-web-midi/EMIDIInput';
627
+ * import * as Effect from 'effect/Effect';
628
+ *
629
+ * const decorated = decorateToTakePolymorphicAccessAndReturnRecord(
630
+ * getInputEntriesFromRaw
631
+ * );
632
+ * const inputsEffect = decorated(EMIDIAccess.request());
633
+ * const inputs = await Effect.runPromise(inputsEffect);
634
+ * // ^? EMIDIInput.IdToInstanceMap
635
+ * ```
636
+ */
637
+ const decorateToTakePolymorphicAccessAndReturnRecord = <
638
+ T extends UnknownEntriesUnion,
639
+ >(
640
+ getRecordEntriesFromRawAccess: (rawAccess: MIDIAccess) => Iterable<T>,
641
+ ) =>
642
+ (polymorphicAccess =>
643
+ Effect.map(
644
+ simplify(polymorphicAccess),
645
+ EFunction.flow(
646
+ assumeImpl,
647
+ impl => impl._access,
648
+ getRecordEntriesFromRawAccess,
649
+ Record.fromEntries,
650
+ ),
651
+ )) as GetPortRecordFromPolymorphicAccess<T>
652
+
653
+ /**
654
+ * Interface for functions that retrieve a port record from polymorphic access.
655
+ */
656
+ export interface GetPortRecordFromPolymorphicAccess<
657
+ RecordEntries extends UnknownEntriesUnion,
658
+ > {
659
+ /**
660
+ * @param polymorphicAccess Optionally wrapped in effect {@linkcode EMIDIAccessInstance|EMIDIAccess.Instance}.
661
+ * @returns Effect with `Record` of MIDI port ids mapped to according effectful ports
662
+ */
663
+ <E = never, R = never>(
664
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
665
+ ): Effect.Effect<EntriesToRecord<RecordEntries>, E, R>
666
+ }
667
+
668
+ /**
669
+ * Utility type to convert union of entries to a record type.
670
+ *
671
+ * @template Entries The union of entry tuples.
672
+ */
673
+ export type EntriesToRecord<Entries extends UnknownEntriesUnion> =
674
+ Types.UnionToIntersection<
675
+ Entries extends unknown ? Record<Entries[0], Entries[1]> : never
676
+ >
677
+
678
+ /**
679
+ * Placeholder tuple representing `Record` entry
680
+ */
681
+ export type UnknownEntriesUnion = [string, unknown]
682
+
683
+ /**
684
+ * Because `MIDIInputMap` can potentially be a mutable object, meaning new
685
+ * devices can be added or removed at runtime, it is effectful.
686
+ *
687
+ * The **`inputs`** read-only property of the MIDIAccess interface provides
688
+ * access to any available MIDI input ports.
689
+ *
690
+ * [MDN
691
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/inputs)
692
+ */
693
+ export const getInputsRecord: GetPortRecordFromPolymorphicAccess<InputRecordEntry> =
694
+ decorateToTakePolymorphicAccessAndReturnRecord(getInputEntriesFromRaw)
695
+
696
+ type InputRecordEntry = [EMIDIInput.Id, EMIDIInput.EMIDIInput]
697
+
698
+ /**
699
+ * Because `MIDIOutputMap` can potentially be a mutable object, meaning new
700
+ * devices can be added or removed at runtime, it is effectful.
701
+ *
702
+ * The **`outputs`** read-only property of the MIDIAccess interface provides
703
+ * access to any available MIDI output ports.
704
+ *
705
+ * [MDN
706
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/outputs)
707
+ */
708
+ export const getOutputsRecord: GetPortRecordFromPolymorphicAccess<OutputRecordEntry> =
709
+ decorateToTakePolymorphicAccessAndReturnRecord(getOutputEntriesFromRaw)
710
+
711
+ type OutputRecordEntry = [EMIDIOutput.Id, EMIDIOutput.EMIDIOutput]
712
+
713
+ /**
714
+ *
715
+ *
716
+ */
717
+ export const getAllPortsRecord: GetPortRecordFromPolymorphicAccess<AllPortEntryUnion> =
718
+ decorateToTakePolymorphicAccessAndReturnRecord(getAllPortsEntriesFromRaw)
719
+
720
+ type AllPortEntryUnion = InputRecordEntry | OutputRecordEntry
721
+
722
+ export interface InputsRecordInContextEffect
723
+ extends Effect.Effect<EMIDIInput.InputIdToInstanceMap, never, EMIDIAccess> {}
724
+
725
+ /**
726
+ *
727
+ *
728
+ */
729
+ export const InputsRecord: InputsRecordInContextEffect =
730
+ getInputsRecord(EMIDIAccess)
731
+
732
+ export interface OutputsRecordInContextEffect
733
+ extends Effect.Effect<
734
+ EMIDIOutput.OutputIdToInstanceMap,
735
+ never,
736
+ EMIDIAccess
737
+ > {}
738
+
739
+ /**
740
+ *
741
+ *
742
+ */
743
+ export const OutputsRecord: OutputsRecordInContextEffect =
744
+ getOutputsRecord(EMIDIAccess)
745
+
746
+ export interface AllPortsRecordInContextEffect
747
+ extends Effect.Effect<
748
+ EMIDIPort.BothIdToBothInstanceMap,
749
+ never,
750
+ EMIDIAccess
751
+ > {}
752
+
753
+ /**
754
+ *
755
+ *
756
+ */
757
+ export const AllPortsRecord: AllPortsRecordInContextEffect =
758
+ getAllPortsRecord(EMIDIAccess)
759
+
760
+ export interface GetPortArrayFromPolymorphicAccess<Port> {
761
+ /**
762
+ *
763
+ */
764
+ <E = never, R = never>(
765
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
766
+ ): Effect.Effect<Port[], E, R>
767
+ }
768
+
769
+ /**
770
+ * Because `MIDIInputMap` can potentially be a mutable object, meaning new
771
+ * devices can be added or removed at runtime, it is effectful.
772
+ *
773
+ * The **`inputs`** read-only property of the MIDIAccess interface provides
774
+ * access to any available MIDI input ports.
775
+ *
776
+ * [MDN
777
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/inputs)
778
+ */
779
+ export const getInputsArray: GetPortArrayFromPolymorphicAccess<EMIDIInput.EMIDIInput> =
780
+ EFunction.flow(getInputsRecord, Effect.map(Record.values))
781
+
782
+ /**
783
+ * Because `MIDIOutputMap` can potentially be a mutable object, meaning new
784
+ * devices can be added or removed at runtime, it is effectful.
785
+ *
786
+ * The **`outputs`** read-only property of the MIDIAccess interface provides
787
+ * access to any available MIDI output ports.
788
+ *
789
+ * [MDN
790
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/outputs)
791
+ */
792
+ export const getOutputsArray: GetPortArrayFromPolymorphicAccess<EMIDIOutput.EMIDIOutput> =
793
+ EFunction.flow(getOutputsRecord, Effect.map(Record.values))
794
+
795
+ /**
796
+ *
797
+ *
798
+ */
799
+ export const getAllPortsArray: GetPortArrayFromPolymorphicAccess<
800
+ EMIDIOutput.EMIDIOutput | EMIDIInput.EMIDIInput
801
+ > = EFunction.flow(getAllPortsRecord, Effect.map(Record.values))
802
+
803
+ export interface InputsArrayInContextEffect
804
+ extends Effect.Effect<EMIDIInput.EMIDIInput[], never, EMIDIAccess> {}
805
+
806
+ /**
807
+ *
808
+ *
809
+ */
810
+ export const InputsArray: InputsArrayInContextEffect =
811
+ getInputsArray(EMIDIAccess)
812
+
813
+ export interface OutputsArrayInContextEffect
814
+ extends Effect.Effect<EMIDIOutput.EMIDIOutput[], never, EMIDIAccess> {}
815
+
816
+ /**
817
+ *
818
+ *
819
+ */
820
+ export const OutputsArray: OutputsArrayInContextEffect =
821
+ getOutputsArray(EMIDIAccess)
822
+
823
+ export interface AllPortsArrayInContextEffect
824
+ extends Effect.Effect<
825
+ (EMIDIOutput.EMIDIOutput | EMIDIInput.EMIDIInput)[],
826
+ never,
827
+ EMIDIAccess
828
+ > {}
829
+
830
+ /**
831
+ *
832
+ *
833
+ */
834
+ export const AllPortsArray: AllPortsArrayInContextEffect =
835
+ getAllPortsArray(EMIDIAccess)
836
+
837
+ /**
838
+ * [MIDIConnectionEvent MDN
839
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIConnectionEvent)
840
+ */
841
+ export const makeAllPortsStateChangesStream =
842
+ StreamMaker.createStreamMakerFrom<MIDIPortEventMap>()(
843
+ is,
844
+ access => ({
845
+ tag: 'MIDIPortStateChange',
846
+ eventListener: {
847
+ target: assumeImpl(access)._access,
848
+ type: 'statechange',
849
+ },
850
+ spanAttributes: {
851
+ spanTargetName: 'MIDI access handle',
852
+ requestedAccessConfig: assumeImpl(access)._config,
853
+ },
854
+ nullableFieldName: 'port',
855
+ }),
856
+ rawPort =>
857
+ ({
858
+ newState: rawPort
859
+ ? ({
860
+ ofDevice: rawPort.state,
861
+ ofConnection: rawPort.connection,
862
+ } as const)
863
+ : null,
864
+ port:
865
+ rawPort instanceof globalThis.MIDIInput
866
+ ? EMIDIInput.make(rawPort)
867
+ : rawPort instanceof globalThis.MIDIOutput
868
+ ? EMIDIOutput.make(rawPort)
869
+ : null,
870
+ }) as const,
871
+ )
872
+
873
+ /**
874
+ * beware that it's not possible to ensure the messages will either be all
875
+ * delivered, or all not delivered, as in ACID transactions. There's not even a
876
+ * mechanism to remove a specific message (not all) from the sending queue
877
+ */
878
+ export const send: DualSendMIDIMessageFromAccess = EFunction.dual<
879
+ SendMIDIMessageAccessLast,
880
+ SendMIDIMessageAccessFirst
881
+ >(
882
+ Util.polymorphicCheckInDual(is),
883
+ Effect.fn('EMIDIAccess.send')(
884
+ function* (polymorphicAccess, target, midiMessage, timestamp) {
885
+ const access = yield* simplify(polymorphicAccess)
886
+
887
+ const outputs = yield* getOutputsRecord(access)
888
+
889
+ if (target === 'all existing outputs at effect execution')
890
+ return yield* EFunction.pipe(
891
+ Record.values(outputs),
892
+ Effect.forEach(EMIDIOutput.send(midiMessage, timestamp)),
893
+ Effect.as(access),
894
+ )
895
+
896
+ if (target === 'all open connections at effect execution')
897
+ return yield* EFunction.pipe(
898
+ Record.values(outputs),
899
+ // TODO: maybe also do something about pending?
900
+ Effect.filter(Check.isOutputConnectionOpenByPort),
901
+ Effect.flatMap(
902
+ Effect.forEach(EMIDIOutput.send(midiMessage, timestamp)),
903
+ ),
904
+ Effect.as(access),
905
+ )
906
+
907
+ // TODO: maybe since deviceState returns always connected devices we can
908
+ // simplify this check by applying intersections and comparing lengths
909
+
910
+ const portsIdsToSend: EMIDIOutput.Id[] = EArray.ensure(target)
911
+
912
+ const deviceStatusesEffect = portsIdsToSend.map(id =>
913
+ EFunction.pipe(
914
+ Record.get(outputs, id),
915
+ Option.match({
916
+ onNone: () => Effect.succeed('disconnected' as const),
917
+ onSome: EFunction.flow(GetProperty.getOutputDeviceStateByPort),
918
+ }),
919
+ effect => Unify.unify(effect),
920
+ Effect.map(state => ({ id, state })),
921
+ ),
922
+ )
923
+
924
+ const disconnectedDevice = EArray.findFirst(
925
+ yield* Effect.all(deviceStatusesEffect),
926
+ _ => _.state === 'disconnected',
927
+ )
928
+
929
+ if (Option.isSome(disconnectedDevice))
930
+ return yield* new MIDIErrors.CannotSendToDisconnectedPortError({
931
+ portId: disconnectedDevice.value.id,
932
+ cause: new DOMException(
933
+ // TODO: make an experiment and paste the error text here
934
+ 'TODO: imitate there an error thats thrown when the port is disconnected',
935
+ 'InvalidStateError',
936
+ ) as DOMException & { name: 'InvalidStateError' },
937
+ })
938
+
939
+ const sendToSome = (predicate: (id: EMIDIOutput.Id) => boolean) =>
940
+ Effect.all(
941
+ Record.reduce(
942
+ outputs,
943
+ [] as EMIDIOutput.SentMessageEffectFromPort<never, never>[],
944
+ // TODO: investigate what the fuck is going on, why the fuck can't I
945
+ // make it a simple expression without either nesting it in
946
+ // curly-braced function body or adding manual type-annotation
947
+ (acc, port, id) =>
948
+ predicate(id)
949
+ ? [
950
+ ...acc,
951
+ EMIDIOutput.send(
952
+ port,
953
+ midiMessage,
954
+ timestamp,
955
+ ) as EMIDIOutput.SentMessageEffectFromPort,
956
+ ]
957
+ : acc,
958
+ ),
959
+ )
960
+
961
+ yield* sendToSome(id => portsIdsToSend.includes(id))
962
+
963
+ return access
964
+ },
965
+ ),
966
+ )
967
+
968
+ /**
969
+ * @param options Passing a value of a `boolean` type is equivalent to setting
970
+ * `options.capture` property
971
+ */
972
+ export const makeMessagesStreamByInputId = <
973
+ const TOnNullStrategy extends StreamMaker.OnNullStrategy = undefined,
974
+ >(
975
+ id: EMIDIInput.Id,
976
+ options?: StreamMaker.StreamMakerOptions<TOnNullStrategy>,
977
+ ) =>
978
+ EMIDIInput.makeMessagesStreamByPort(
979
+ GetPort.getInputByPortIdInContext(id),
980
+ options,
981
+ )
982
+
983
+ // TODO: makeMessagesStreamByInputIdAndAccess
984
+ export const makeMessagesStreamByInputIdAndAccess = () => {
985
+ throw new Error('Not implemented 😿 YET!! 🤩')
986
+ }
987
+
988
+ /**
989
+ *
990
+ */
991
+ export const sendToPortById = (
992
+ id: EMIDIOutput.Id,
993
+ ...args: EMIDIOutput.SendFromPortArgs
994
+ ) =>
995
+ Effect.asVoid(
996
+ EMIDIOutput.send(GetPort.getOutputByPortIdInContext(id), ...args),
997
+ )
998
+
999
+ /**
1000
+ *
1001
+ */
1002
+ export const clearPortById = EFunction.flow(
1003
+ GetPort.getOutputByPortIdInContext,
1004
+ EMIDIOutput.clear,
1005
+ Effect.asVoid,
1006
+ )
1007
+
1008
+ /**
1009
+ * @param options Passing a value of a `boolean` type is equivalent to setting
1010
+ * `options.capture` property
1011
+ */
1012
+ export const makeAllPortsStateChangesStreamInContext = <
1013
+ const TOnNullStrategy extends StreamMaker.OnNullStrategy = undefined,
1014
+ >(
1015
+ options?: StreamMaker.StreamMakerOptions<TOnNullStrategy>,
1016
+ ) => makeAllPortsStateChangesStream(EMIDIAccess, options)
1017
+
1018
+ /**
1019
+ *
1020
+ *
1021
+ */
1022
+ export const sendInContext = (...args: SendFromAccessArgs) =>
1023
+ Effect.asVoid(send(EMIDIAccess, ...args))
1024
+
1025
+ /**
1026
+ * @param options
1027
+ *
1028
+ * @returns An Effect representing a request for access to MIDI devices on a
1029
+ * user's system. Available only in secure contexts.
1030
+ */
1031
+ export const request = Effect.fn('EMIDIAccess.request')(function* (
1032
+ options?: RequestMIDIAccessOptions,
1033
+ ) {
1034
+ yield* Effect.annotateCurrentSpan({ options })
1035
+
1036
+ const rawAccess = yield* Effect.tryPromise({
1037
+ try: () => navigator.requestMIDIAccess(options),
1038
+ catch: MIDIErrors.remapErrorByName(
1039
+ {
1040
+ AbortError: MIDIErrors.AbortError,
1041
+
1042
+ InvalidStateError: MIDIErrors.UnderlyingSystemError,
1043
+
1044
+ NotAllowedError: MIDIErrors.MIDIAccessNotAllowedError,
1045
+ // SecurityError is kept for compatibility reason
1046
+ // (https://github.com/WebAudio/web-midi-api/pull/267):
1047
+ SecurityError: MIDIErrors.MIDIAccessNotAllowedError,
1048
+
1049
+ NotSupportedError: MIDIErrors.MIDIAccessNotSupportedError,
1050
+ // For case when navigator doesn't exist
1051
+ ReferenceError: MIDIErrors.MIDIAccessNotSupportedError,
1052
+ // For case when navigator.requestMIDIAccess is undefined
1053
+ TypeError: MIDIErrors.MIDIAccessNotSupportedError,
1054
+ },
1055
+ 'EMIDIAccess.request error handling absurd',
1056
+ { whileAskingForPermissions: options ?? {} },
1057
+ ),
1058
+ })
1059
+
1060
+ // TODO: finish this
1061
+
1062
+ const _ref = yield* Ref.make(
1063
+ SortedMap.empty<EMIDIPort.BothId, MIDIPortType>(Order.string),
1064
+ )
1065
+
1066
+ // return make(rawAccess, options, ref)
1067
+ return make(rawAccess, options)
1068
+ })
1069
+
1070
+ // TODO: clear all outputs
1071
+
1072
+ /**
1073
+ *
1074
+ * **Errors:**
1075
+ *
1076
+ * - {@linkcode MIDIErrors.AbortError} Description
1077
+ * - {@linkcode MIDIErrors.UnderlyingSystemError} Description
1078
+ * - {@linkcode MIDIErrors.MIDIAccessNotSupportedError} Description
1079
+ * - {@linkcode MIDIErrors.MIDIAccessNotAllowedError} Description
1080
+ *
1081
+ * @param config
1082
+ * @returns
1083
+ */
1084
+ export const layer = (config?: RequestMIDIAccessOptions) =>
1085
+ Layer.effect(EMIDIAccess, request(config))
1086
+
1087
+ /**
1088
+ *
1089
+ */
1090
+ export const layerMostRestricted = layer()
1091
+
1092
+ /**
1093
+ *
1094
+ */
1095
+ export const layerSystemExclusiveSupported = layer({ sysex: true })
1096
+
1097
+ /**
1098
+ *
1099
+ */
1100
+ export const layerSoftwareSynthSupported = layer({ software: true })
1101
+
1102
+ /**
1103
+ *
1104
+ */
1105
+ export const layerSystemExclusiveAndSoftwareSynthSupported = layer({
1106
+ software: true,
1107
+ sysex: true,
1108
+ })
1109
+
1110
+ export interface SentMessageEffectFromAccess<E = never, R = never>
1111
+ extends Util.SentMessageEffectFrom<EMIDIAccessInstance, E, R> {}
1112
+
1113
+ export type TargetPortSelector =
1114
+ | 'all existing outputs at effect execution'
1115
+ | 'all open connections at effect execution'
1116
+ | EMIDIOutput.Id
1117
+ | EMIDIOutput.Id[]
1118
+
1119
+ export interface DualSendMIDIMessageFromAccess
1120
+ extends SendMIDIMessageAccessFirst,
1121
+ SendMIDIMessageAccessLast {}
1122
+
1123
+ export type SendFromAccessArgs = [
1124
+ targetPortSelector: TargetPortSelector,
1125
+ ...args: EMIDIOutput.SendFromPortArgs,
1126
+ ]
1127
+
1128
+ export interface SendMIDIMessageAccessFirst {
1129
+ /**
1130
+ *
1131
+ *
1132
+ */
1133
+ <E = never, R = never>(
1134
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
1135
+ ...args: SendFromAccessArgs
1136
+ ): SentMessageEffectFromAccess<E, R>
1137
+ }
1138
+
1139
+ export interface SendMIDIMessageAccessLast {
1140
+ /**
1141
+ *
1142
+ *
1143
+ */
1144
+ (
1145
+ ...args: SendFromAccessArgs
1146
+ ): {
1147
+ /**
1148
+ *
1149
+ *
1150
+ */
1151
+ <E = never, R = never>(
1152
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
1153
+ ): SentMessageEffectFromAccess<E, R>
1154
+ }
1155
+ }
1156
+
1157
+ export interface GetThingByPortId<
1158
+ TSuccess,
1159
+ TTypeOfPortId extends MIDIPortType,
1160
+ TAccessGettingFallbackError,
1161
+ TAccessGettingFallbackRequirement,
1162
+ TAdditionalError,
1163
+ TAdditionalRequirement,
1164
+ > extends GetThingByPortIdAccessFirst<
1165
+ TSuccess,
1166
+ TTypeOfPortId,
1167
+ TAccessGettingFallbackError,
1168
+ TAccessGettingFallbackRequirement,
1169
+ TAdditionalError,
1170
+ TAdditionalRequirement
1171
+ >,
1172
+ GetThingByPortIdAccessLast<
1173
+ TSuccess,
1174
+ TTypeOfPortId,
1175
+ TAccessGettingFallbackError,
1176
+ TAccessGettingFallbackRequirement,
1177
+ TAdditionalError,
1178
+ TAdditionalRequirement
1179
+ > {}
1180
+
1181
+ export interface GetThingByPortIdAccessFirst<
1182
+ TSuccess,
1183
+ TTypeOfPortId extends MIDIPortType,
1184
+ TAccessGettingFallbackError,
1185
+ TAccessGettingFallbackRequirement,
1186
+ TAdditionalError,
1187
+ TAdditionalRequirement,
1188
+ > {
1189
+ /**
1190
+ *
1191
+ *
1192
+ */
1193
+ <TAccessGettingError = never, TAccessGettingRequirement = never>(
1194
+ polymorphicAccess: PolymorphicAccessInstance<
1195
+ TAccessGettingError,
1196
+ TAccessGettingRequirement
1197
+ >,
1198
+ id: EMIDIPort.Id<TTypeOfPortId>,
1199
+ ): AcquiredThing<
1200
+ TSuccess,
1201
+ TAccessGettingError,
1202
+ TAccessGettingRequirement,
1203
+ TAccessGettingFallbackError,
1204
+ TAccessGettingFallbackRequirement,
1205
+ TAdditionalError,
1206
+ TAdditionalRequirement
1207
+ >
1208
+ }
1209
+
1210
+ export interface GetThingByPortIdAccessLast<
1211
+ TSuccess,
1212
+ TTypeOfPortId extends MIDIPortType,
1213
+ TAccessGettingFallbackError,
1214
+ TAccessGettingFallbackRequirement,
1215
+ TAdditionalError,
1216
+ TAdditionalRequirement,
1217
+ > {
1218
+ /**
1219
+ *
1220
+ *
1221
+ */
1222
+ (
1223
+ id: EMIDIPort.Id<TTypeOfPortId>,
1224
+ ): GetThingByPortIdAccessLastSecondHalf<
1225
+ TSuccess,
1226
+ TAccessGettingFallbackError,
1227
+ TAccessGettingFallbackRequirement,
1228
+ TAdditionalError,
1229
+ TAdditionalRequirement
1230
+ >
1231
+ }
1232
+
1233
+ export interface GetThingByPortIdAccessLastSecondHalf<
1234
+ TSuccess,
1235
+ TAccessGettingFallbackError,
1236
+ TAccessGettingFallbackRequirement,
1237
+ TAdditionalError,
1238
+ TAdditionalRequirement,
1239
+ > {
1240
+ /**
1241
+ *
1242
+ *
1243
+ */
1244
+ <TAccessGettingError = never, TAccessGettingRequirement = never>(
1245
+ polymorphicAccess: PolymorphicAccessInstance<
1246
+ TAccessGettingError,
1247
+ TAccessGettingRequirement
1248
+ >,
1249
+ ): AcquiredThing<
1250
+ TSuccess,
1251
+ TAccessGettingError,
1252
+ TAccessGettingRequirement,
1253
+ TAccessGettingFallbackError,
1254
+ TAccessGettingFallbackRequirement,
1255
+ TAdditionalError,
1256
+ TAdditionalRequirement
1257
+ >
1258
+ }
1259
+
1260
+ export interface AcquiredThing<
1261
+ TSuccess,
1262
+ TAccessGettingError,
1263
+ TAccessGettingRequirement,
1264
+ TAccessGettingFallbackError,
1265
+ TAccessGettingFallbackRequirement,
1266
+ TAdditionalError,
1267
+ TAdditionalRequirement,
1268
+ > extends Effect.Effect<
1269
+ TSuccess,
1270
+ | Util.FallbackOnUnknownOrAny<
1271
+ TAccessGettingError,
1272
+ TAccessGettingFallbackError
1273
+ >
1274
+ | TAdditionalError,
1275
+ | Util.FallbackOnUnknownOrAny<
1276
+ TAccessGettingRequirement,
1277
+ TAccessGettingFallbackRequirement
1278
+ >
1279
+ | TAdditionalRequirement
1280
+ > {}