effect-web-midi 0.1.0

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 (222) hide show
  1. package/README.md +7 -0
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/EMIDIAccess.js +68 -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 +225 -0
  9. package/dist/src/EMIDIOutput.js.map +1 -0
  10. package/dist/src/EMIDIPort.js +213 -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/Parsing.js +2 -0
  15. package/dist/src/Parsing.js.map +1 -0
  16. package/dist/src/StreamMaker.js +1 -0
  17. package/dist/src/StreamMaker.js.map +1 -0
  18. package/dist/src/Util.js +4 -0
  19. package/dist/src/Util.js.map +1 -0
  20. package/dist/src/index.js +9 -0
  21. package/dist/src/index.js.map +1 -0
  22. package/dist/src/internal/EMIDIAccess.js +409 -0
  23. package/dist/src/internal/EMIDIAccess.js.map +1 -0
  24. package/dist/src/internal/EMIDIInput.js +69 -0
  25. package/dist/src/internal/EMIDIInput.js.map +1 -0
  26. package/dist/src/internal/EMIDIOutput.js +120 -0
  27. package/dist/src/internal/EMIDIOutput.js.map +1 -0
  28. package/dist/src/internal/EMIDIPort.js +125 -0
  29. package/dist/src/internal/EMIDIPort.js.map +1 -0
  30. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.js +27 -0
  31. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.js.map +1 -0
  32. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.js +19 -0
  33. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.js.map +1 -0
  34. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.js +16 -0
  35. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.js.map +1 -0
  36. package/dist/src/internal/MIDIPortMethodCalls/actOnPort.js +18 -0
  37. package/dist/src/internal/MIDIPortMethodCalls/actOnPort.js.map +1 -0
  38. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.js +27 -0
  39. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.js.map +1 -0
  40. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.js +18 -0
  41. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.js.map +1 -0
  42. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.js +16 -0
  43. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.js.map +1 -0
  44. package/dist/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.js +21 -0
  45. package/dist/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.js.map +1 -0
  46. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.js +30 -0
  47. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.js.map +1 -0
  48. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.js +18 -0
  49. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.js.map +1 -0
  50. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.js +16 -0
  51. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.js.map +1 -0
  52. package/dist/src/internal/StreamMaker.js +101 -0
  53. package/dist/src/internal/StreamMaker.js.map +1 -0
  54. package/dist/src/internal/errors.js +161 -0
  55. package/dist/src/internal/errors.js.map +1 -0
  56. package/dist/src/internal/getPortByPortId/getPortByPortIdAndAccess.js +53 -0
  57. package/dist/src/internal/getPortByPortId/getPortByPortIdAndAccess.js.map +1 -0
  58. package/dist/src/internal/getPortByPortId/getPortByPortIdInContext.js +18 -0
  59. package/dist/src/internal/getPortByPortId/getPortByPortIdInContext.js.map +1 -0
  60. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.js +52 -0
  61. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.js.map +1 -0
  62. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.js +13 -0
  63. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.js.map +1 -0
  64. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.js +18 -0
  65. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.js.map +1 -0
  66. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.js +66 -0
  67. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.js.map +1 -0
  68. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.js +61 -0
  69. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.js.map +1 -0
  70. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.js +61 -0
  71. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.js.map +1 -0
  72. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.js +42 -0
  73. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.js.map +1 -0
  74. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.js +42 -0
  75. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.js.map +1 -0
  76. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.js +29 -0
  77. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.js.map +1 -0
  78. package/dist/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.js +6 -0
  79. package/dist/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.js.map +1 -0
  80. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.js +46 -0
  81. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.js.map +1 -0
  82. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.js +25 -0
  83. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.js.map +1 -0
  84. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.js +31 -0
  85. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.js.map +1 -0
  86. package/dist/src/internal/parsing.js +117 -0
  87. package/dist/src/internal/parsing.js.map +1 -0
  88. package/dist/src/internal/util.js +59 -0
  89. package/dist/src/internal/util.js.map +1 -0
  90. package/dist-types/index.d.ts +2 -0
  91. package/dist-types/index.d.ts.map +1 -0
  92. package/dist-types/src/EMIDIAccess.d.ts +27 -0
  93. package/dist-types/src/EMIDIAccess.d.ts.map +1 -0
  94. package/dist-types/src/EMIDIInput.d.ts +26 -0
  95. package/dist-types/src/EMIDIInput.d.ts.map +1 -0
  96. package/dist-types/src/EMIDIOutput.d.ts +26 -0
  97. package/dist-types/src/EMIDIOutput.d.ts.map +1 -0
  98. package/dist-types/src/EMIDIPort.d.ts +26 -0
  99. package/dist-types/src/EMIDIPort.d.ts.map +1 -0
  100. package/dist-types/src/MIDIErrors.d.ts +2 -0
  101. package/dist-types/src/MIDIErrors.d.ts.map +1 -0
  102. package/dist-types/src/Parsing.d.ts +2 -0
  103. package/dist-types/src/Parsing.d.ts.map +1 -0
  104. package/dist-types/src/StreamMaker.d.ts +2 -0
  105. package/dist-types/src/StreamMaker.d.ts.map +1 -0
  106. package/dist-types/src/Util.d.ts +2 -0
  107. package/dist-types/src/Util.d.ts.map +1 -0
  108. package/dist-types/src/index.d.ts +9 -0
  109. package/dist-types/src/index.d.ts.map +1 -0
  110. package/dist-types/src/internal/EMIDIAccess.d.ts +339 -0
  111. package/dist-types/src/internal/EMIDIAccess.d.ts.map +1 -0
  112. package/dist-types/src/internal/EMIDIInput.d.ts +48 -0
  113. package/dist-types/src/internal/EMIDIInput.d.ts.map +1 -0
  114. package/dist-types/src/internal/EMIDIOutput.d.ts +93 -0
  115. package/dist-types/src/internal/EMIDIOutput.d.ts.map +1 -0
  116. package/dist-types/src/internal/EMIDIPort.d.ts +87 -0
  117. package/dist-types/src/internal/EMIDIPort.d.ts.map +1 -0
  118. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.d.ts +16 -0
  119. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.d.ts.map +1 -0
  120. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.d.ts +15 -0
  121. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.d.ts.map +1 -0
  122. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.d.ts +13 -0
  123. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.d.ts.map +1 -0
  124. package/dist-types/src/internal/MIDIPortMethodCalls/actOnPort.d.ts +11 -0
  125. package/dist-types/src/internal/MIDIPortMethodCalls/actOnPort.d.ts.map +1 -0
  126. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.d.ts +23 -0
  127. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.d.ts.map +1 -0
  128. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.d.ts +15 -0
  129. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.d.ts.map +1 -0
  130. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.d.ts +13 -0
  131. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.d.ts.map +1 -0
  132. package/dist-types/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.d.ts +15 -0
  133. package/dist-types/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.d.ts.map +1 -0
  134. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.d.ts +21 -0
  135. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.d.ts.map +1 -0
  136. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.d.ts +15 -0
  137. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.d.ts.map +1 -0
  138. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.d.ts +13 -0
  139. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.d.ts.map +1 -0
  140. package/dist-types/src/internal/StreamMaker.d.ts +202 -0
  141. package/dist-types/src/internal/StreamMaker.d.ts.map +1 -0
  142. package/dist-types/src/internal/errors.d.ts +260 -0
  143. package/dist-types/src/internal/errors.d.ts.map +1 -0
  144. package/dist-types/src/internal/getPortByPortId/getPortByPortIdAndAccess.d.ts +27 -0
  145. package/dist-types/src/internal/getPortByPortId/getPortByPortIdAndAccess.d.ts.map +1 -0
  146. package/dist-types/src/internal/getPortByPortId/getPortByPortIdInContext.d.ts +20 -0
  147. package/dist-types/src/internal/getPortByPortId/getPortByPortIdInContext.d.ts.map +1 -0
  148. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.d.ts +71 -0
  149. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.d.ts.map +1 -0
  150. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.d.ts +4 -0
  151. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.d.ts.map +1 -0
  152. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.d.ts +20 -0
  153. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.d.ts.map +1 -0
  154. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.d.ts +62 -0
  155. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.d.ts.map +1 -0
  156. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.d.ts +16 -0
  157. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.d.ts.map +1 -0
  158. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.d.ts +16 -0
  159. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.d.ts.map +1 -0
  160. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.d.ts +36 -0
  161. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.d.ts.map +1 -0
  162. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.d.ts +22 -0
  163. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.d.ts.map +1 -0
  164. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.d.ts +17 -0
  165. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.d.ts.map +1 -0
  166. package/dist-types/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.d.ts +7 -0
  167. package/dist-types/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.d.ts.map +1 -0
  168. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.d.ts +71 -0
  169. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.d.ts.map +1 -0
  170. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.d.ts +7 -0
  171. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.d.ts.map +1 -0
  172. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.d.ts +28 -0
  173. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.d.ts.map +1 -0
  174. package/dist-types/src/internal/parsing.d.ts +72 -0
  175. package/dist-types/src/internal/parsing.d.ts.map +1 -0
  176. package/dist-types/src/internal/util.d.ts +33 -0
  177. package/dist-types/src/internal/util.d.ts.map +1 -0
  178. package/index.ts +1 -0
  179. package/package.json +83 -0
  180. package/src/EMIDIAccess.ts +271 -0
  181. package/src/EMIDIInput.ts +270 -0
  182. package/src/EMIDIOutput.ts +269 -0
  183. package/src/EMIDIPort.ts +267 -0
  184. package/src/MIDIErrors.ts +13 -0
  185. package/src/Parsing.ts +12 -0
  186. package/src/StreamMaker.ts +12 -0
  187. package/src/Util.ts +19 -0
  188. package/src/index.ts +8 -0
  189. package/src/internal/EMIDIAccess.ts +893 -0
  190. package/src/internal/EMIDIInput.ts +114 -0
  191. package/src/internal/EMIDIOutput.ts +228 -0
  192. package/src/internal/EMIDIPort.ts +233 -0
  193. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.ts +43 -0
  194. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.ts +39 -0
  195. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.ts +27 -0
  196. package/src/internal/MIDIPortMethodCalls/actOnPort.ts +66 -0
  197. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.ts +38 -0
  198. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.ts +38 -0
  199. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.ts +27 -0
  200. package/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.ts +73 -0
  201. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.ts +44 -0
  202. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.ts +38 -0
  203. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.ts +27 -0
  204. package/src/internal/StreamMaker.ts +414 -0
  205. package/src/internal/errors.ts +220 -0
  206. package/src/internal/getPortByPortId/getPortByPortIdAndAccess.ts +116 -0
  207. package/src/internal/getPortByPortId/getPortByPortIdInContext.ts +26 -0
  208. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.ts +148 -0
  209. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.ts +14 -0
  210. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.ts +51 -0
  211. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.ts +127 -0
  212. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.ts +74 -0
  213. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.ts +74 -0
  214. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.ts +63 -0
  215. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.ts +110 -0
  216. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.ts +37 -0
  217. package/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.ts +12 -0
  218. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.ts +183 -0
  219. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.ts +29 -0
  220. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.ts +86 -0
  221. package/src/internal/parsing.ts +219 -0
  222. package/src/internal/util.ts +152 -0
@@ -0,0 +1,893 @@
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
+ import * as EMIDIInput from './EMIDIInput.ts'
22
+ import * as EMIDIOutput from './EMIDIOutput.ts'
23
+ import type * as EMIDIPort from './EMIDIPort.ts'
24
+ import * as Errors from './errors.ts'
25
+ import * as GetPort from './getPortByPortId/getPortByPortIdInContext.ts'
26
+ import { isOutputConnectionOpenByPort } from './mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.ts'
27
+ import { getOutputDeviceStateByPort } from './mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.ts'
28
+ import * as StreamMaker from './StreamMaker.ts'
29
+ import * as Util from './util.ts'
30
+
31
+ // TODO: add stream of messages sent from this device to target midi device
32
+
33
+ // TODO: fat service APIs, where all the methods are attached to instance and
34
+ // where you don't have to constantly write the prefix
35
+
36
+ // TODO: implement scoping of midi access that will clean up all message queues
37
+ // and streams, and remove listeners
38
+
39
+ // TODO: implement scope inheritance
40
+
41
+ // TODO: make a Ref with a port map that would be automatically updated by
42
+ // listening to the stream of connection events?
43
+
44
+ // TODO: add a stream to listen for all messages of all currently
45
+ // connected inputs, all present inputs, specific input
46
+
47
+ // TODO: add sinks that will accept command streams to redirect midi commands
48
+ // from something into an actual API
49
+
50
+ // TODO: add effect to wait until connected by port ID
51
+
52
+ // TODO: reflect sysex and software flags in type-system
53
+
54
+ // TODO: make matchers that support returning effects from the callback instead of plain values
55
+
56
+ /**
57
+ * Unique symbol used for distinguishing {@linkcode EMIDIAccessInstance}
58
+ * instances from other objects at both runtime and type-level
59
+ * @internal
60
+ */
61
+ const TypeId: unique symbol = Symbol.for('effect-web-midi/EMIDIAccessInstance')
62
+
63
+ /**
64
+ * Unique symbol used for distinguishing {@linkcode EMIDIAccessInstance}
65
+ * instances from other objects at both runtime and type-level
66
+ */
67
+ export type TypeId = typeof TypeId
68
+
69
+ /**
70
+ * A tag that allows to provide
71
+ * {@linkcode EMIDIAccessInstance|access instance} once with e.g.
72
+ * {@linkcode layer}, {@linkcode layerSystemExclusiveSupported}, etc. and reuse
73
+ * it anywhere, instead of repeatedly {@linkcode request}ing it.
74
+ *
75
+ * The downside of using DI might be that in different places of the app it
76
+ * would be harder to maintain tight MIDI permission scopes.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * import { EMIDIAccess } from 'effect-web-midi'
81
+ * import * as Effect from 'effect/Effect'
82
+ *
83
+ * const program = Effect.gen(function* () {
84
+ * // ^ Effect.Effect<
85
+ * // void,
86
+ * // | AbortError
87
+ * // | UnderlyingSystemError
88
+ * // | MIDIAccessNotAllowedError
89
+ * // | MIDIAccessNotSupportedError
90
+ * // never
91
+ * // >
92
+ *
93
+ * const access = yield* EMIDIAccess.EMIDIAccess
94
+ * // ^ EMIDIAccessInstance
95
+ *
96
+ * console.log(access.sysexEnabled)
97
+ * // ^ true
98
+ * }).pipe(Effect.provide(EMIDIAccess.layerSystemExclusiveSupported))
99
+ * ```
100
+ *
101
+ * @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}
102
+ */
103
+ export class EMIDIAccess extends Context.Tag('effect-web-midi/EMIDIAccess')<
104
+ EMIDIAccess,
105
+ EMIDIAccessInstance
106
+ >() {}
107
+
108
+ export interface RequestMIDIAccessOptions {
109
+ /**
110
+ * This field informs the system whether the ability to send and receive
111
+ * `System Exclusive` messages is requested or allowed on a given
112
+ * {@linkcode EMIDIAccessInstance} object.
113
+ *
114
+ * If this field is set to `true`, but `System Exclusive` support is denied
115
+ * (either by policy or by user action), the access request will fail with a
116
+ * {@linkcode Errors.MIDIAccessNotAllowedError} error.
117
+ *
118
+ * If this support is not requested (and allowed), the system will throw
119
+ * exceptions if the user tries to send `System Exclusive` messages, and will
120
+ * silently mask out any `System Exclusive` messages received on the port.
121
+ *
122
+ * @default false
123
+ * @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}
124
+ */
125
+ readonly sysex?: boolean
126
+
127
+ /**
128
+ * This field informs the system whether the ability to utilize any software
129
+ * synthesizers installed in the host system is requested or allowed on a
130
+ * given {@linkcode EMIDIAccessInstance} object.
131
+ *
132
+ * If this field is set to `true`, but software synthesizer support is denied
133
+ * (either by policy or by user action), the access request will fail with a
134
+ * {@linkcode Errors.MIDIAccessNotAllowedError} error.
135
+ *
136
+ * If this support is not requested, {@linkcode AllPortsRecord},
137
+ * {@linkcode getInputsRecord}, {@linkcode OutputsRecord}, etc. would
138
+ * not include any software synthesizers.
139
+ *
140
+ * Note that may result in a two-step request procedure if software
141
+ * synthesizer support is desired but not required - software synthesizers may
142
+ * be disabled when MIDI hardware device access is allowed.
143
+ *
144
+ * @default false
145
+ * @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}
146
+ */
147
+ readonly software?: boolean
148
+ }
149
+
150
+ /**
151
+ * Prototype of all {@linkcode EMIDIAccessInstance} instances
152
+ * @internal
153
+ */
154
+ const Proto = {
155
+ _tag: 'EMIDIAccess' as const,
156
+ [TypeId]: TypeId,
157
+ [Hash.symbol](this: EMIDIAccessImplementationInstance) {
158
+ return Hash.structure(this._config)
159
+ },
160
+ [Equal.symbol](that: Equal.Equal) {
161
+ return this === that
162
+ },
163
+ pipe() {
164
+ // biome-ignore lint/complexity/noArguments: Effect's tradition
165
+ return Pipeable.pipeArguments(this, arguments)
166
+ },
167
+ toString(this: EMIDIAccessImplementationInstance) {
168
+ return Inspectable.format(this.toJSON())
169
+ },
170
+ toJSON(this: EMIDIAccessImplementationInstance) {
171
+ return { _id: 'EMIDIAccess', config: this._config }
172
+ },
173
+ [Inspectable.NodeInspectSymbol](this: EMIDIAccessImplementationInstance) {
174
+ return this.toJSON()
175
+ },
176
+
177
+ get sysexEnabled() {
178
+ return assumeImpl(this)._access.sysexEnabled
179
+ },
180
+
181
+ get softwareSynthEnabled() {
182
+ return !!assumeImpl(this)._config.software
183
+ },
184
+ } satisfies EMIDIAccessInstance
185
+
186
+ // !!! DOCUMENTATION CURSOR !!!
187
+
188
+ /**
189
+ * Thin wrapper around {@linkcode MIDIAccess} instance. Will be seen in all the
190
+ * external code.
191
+ */
192
+ export interface EMIDIAccessInstance
193
+ extends Equal.Equal,
194
+ Pipeable.Pipeable,
195
+ Inspectable.Inspectable {
196
+ readonly [TypeId]: TypeId
197
+ readonly _tag: 'EMIDIAccess'
198
+
199
+ /**
200
+ * The **`sysexEnabled`** read-only property of the MIDIAccess interface indicates whether system exclusive support is enabled on the current MIDIAccess instance.
201
+ *
202
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/sysexEnabled)
203
+ */
204
+ readonly sysexEnabled: boolean
205
+
206
+ readonly softwareSynthEnabled: boolean
207
+ }
208
+
209
+ /**
210
+ * Thin wrapper around {@linkcode MIDIAccess} instance giving access to the
211
+ * actual field storing it.
212
+ * @internal
213
+ */
214
+ interface EMIDIAccessImplementationInstance extends EMIDIAccessInstance {
215
+ readonly _access: MIDIAccess
216
+ readonly _config: Readonly<RequestMIDIAccessOptions>
217
+ }
218
+
219
+ /**
220
+ *
221
+ *
222
+ * @internal
223
+ */
224
+ const makeImpl = (
225
+ rawAccess: MIDIAccess,
226
+ config?: Readonly<RequestMIDIAccessOptions>,
227
+ ): EMIDIAccessImplementationInstance => {
228
+ const instance = Object.create(Proto)
229
+ instance._access = rawAccess
230
+ // TODO: set individual software and sysex flags instead
231
+ instance._config = config ?? {}
232
+ return instance
233
+ }
234
+
235
+ /**
236
+ * Asserts an object to be valid `EMIDIAccess` and casts it to internal
237
+ * implementation type
238
+ *
239
+ * @internal
240
+ */
241
+ const assertImpl = (access: unknown) => {
242
+ if (!isImpl(access)) throw new Error('Failed to cast to EMIDIAccess')
243
+ return access
244
+ }
245
+
246
+ /**
247
+ * Asserts an object to be valid `EMIDIAccess`
248
+ *
249
+ * @internal
250
+ */
251
+ export const assert: (access: unknown) => EMIDIAccessInstance = assertImpl
252
+
253
+ /**
254
+ * @internal
255
+ */
256
+ export const assumeImpl = (access: EMIDIAccessInstance) =>
257
+ access as EMIDIAccessImplementationInstance
258
+
259
+ /**
260
+ *
261
+ *
262
+ * @internal
263
+ */
264
+ const make: (
265
+ rawAccess: MIDIAccess,
266
+ config?: Readonly<RequestMIDIAccessOptions>,
267
+ ) => EMIDIAccessInstance = makeImpl
268
+
269
+ /**
270
+ *
271
+ *
272
+ * @internal
273
+ */
274
+ const isImpl = (access: unknown): access is EMIDIAccessImplementationInstance =>
275
+ typeof access === 'object' &&
276
+ access !== null &&
277
+ Object.getPrototypeOf(access) === Proto &&
278
+ TypeId in access &&
279
+ '_access' in access &&
280
+ typeof access._access === 'object' &&
281
+ '_config' in access &&
282
+ typeof access._config === 'object' &&
283
+ access._config !== null &&
284
+ access._access instanceof MIDIAccess
285
+
286
+ /**
287
+ *
288
+ *
289
+ */
290
+ export const is: (access: unknown) => access is EMIDIAccessInstance = isImpl
291
+
292
+ /**
293
+ *
294
+ * @internal
295
+ */
296
+ export const resolve = <E = never, R = never>(
297
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
298
+ ) => Util.fromPolymorphic(polymorphicAccess, is)
299
+
300
+ /**
301
+ *
302
+ *
303
+ */
304
+ export type PolymorphicAccessInstance<E, R> = Util.PolymorphicEffect<
305
+ EMIDIAccessInstance,
306
+ E,
307
+ R
308
+ >
309
+
310
+ /**
311
+ *
312
+ *
313
+ */
314
+ export type PolymorphicAccessInstanceClean = PolymorphicAccessInstance<
315
+ never,
316
+ never
317
+ >
318
+
319
+ /**
320
+ *
321
+ *
322
+ */
323
+ type ValueOfReadonlyMap<T> = T extends ReadonlyMap<unknown, infer V> ? V : never
324
+
325
+ /**
326
+ *
327
+ * @internal
328
+ */
329
+ const getPortEntriesFromRawAccess =
330
+ <
331
+ const TMIDIPortType extends MIDIPortType,
332
+ const TMIDIAccessObjectKey extends `${TMIDIPortType}s`,
333
+ TRawMIDIPort extends ValueOfReadonlyMap<MIDIAccess[TMIDIAccessObjectKey]>,
334
+ >(
335
+ key: TMIDIAccessObjectKey,
336
+ make: (port: TRawMIDIPort) => EMIDIPort.EMIDIPort<TMIDIPortType>,
337
+ ) =>
338
+ (rawAccess: MIDIAccess) =>
339
+ Iterable.map(
340
+ rawAccess[key] as ReadonlyMap<EMIDIPort.Id<TMIDIPortType>, TRawMIDIPort>,
341
+ ([id, raw]) =>
342
+ [id as EMIDIPort.Id<TMIDIPortType>, make(raw)] satisfies Types.TupleOf<
343
+ 2,
344
+ unknown
345
+ >,
346
+ )
347
+
348
+ /**
349
+ *
350
+ * @internal
351
+ */
352
+ const getInputEntriesFromRaw = getPortEntriesFromRawAccess(
353
+ 'inputs',
354
+ EMIDIInput.make,
355
+ )
356
+
357
+ /**
358
+ *
359
+ * @internal
360
+ */
361
+ const getOutputEntriesFromRaw = getPortEntriesFromRawAccess(
362
+ 'outputs',
363
+ EMIDIOutput.make,
364
+ )
365
+
366
+ /**
367
+ *
368
+ * @internal
369
+ */
370
+ const getAllPortsEntriesFromRaw = (rawAccess: MIDIAccess) =>
371
+ Iterable.appendAll(
372
+ getInputEntriesFromRaw(rawAccess),
373
+ getOutputEntriesFromRaw(rawAccess),
374
+ )
375
+
376
+ /**
377
+ *
378
+ * @param accessor
379
+ * @returns
380
+ * @internal
381
+ */
382
+ const decorateToTakePolymorphicAccessAndReturnRecord =
383
+ <T extends [string, unknown]>(
384
+ accessor: (rawAccess: MIDIAccess) => Iterable<T>,
385
+ ) =>
386
+ <E = never, R = never>(polymorphicAccess: PolymorphicAccessInstance<E, R>) =>
387
+ Effect.map(
388
+ resolve(polymorphicAccess),
389
+ EFunction.flow(assumeImpl, e => e._access, accessor, Record.fromEntries),
390
+ ) as Effect.Effect<
391
+ Types.UnionToIntersection<T extends unknown ? Record<T[0], T[1]> : never>,
392
+ E,
393
+ R
394
+ >
395
+
396
+ /**
397
+ * Because `MIDIInputMap` can potentially be a mutable object, meaning new
398
+ * devices can be added or removed at runtime, it is effectful.
399
+ *
400
+ * The **`inputs`** read-only property of the MIDIAccess interface provides
401
+ * access to any available MIDI input ports.
402
+ *
403
+ * [MDN
404
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/inputs)
405
+ */
406
+ export const getInputsRecord = decorateToTakePolymorphicAccessAndReturnRecord(
407
+ getInputEntriesFromRaw,
408
+ )
409
+
410
+ /**
411
+ * Because `MIDIOutputMap` can potentially be a mutable object, meaning new
412
+ * devices can be added or removed at runtime, it is effectful.
413
+ *
414
+ * The **`outputs`** read-only property of the MIDIAccess interface provides
415
+ * access to any available MIDI output ports.
416
+ *
417
+ * [MDN
418
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIAccess/outputs)
419
+ */
420
+ export const getOutputsRecord = decorateToTakePolymorphicAccessAndReturnRecord(
421
+ getOutputEntriesFromRaw,
422
+ )
423
+
424
+ /**
425
+ *
426
+ *
427
+ */
428
+ export const getAllPortsRecord = decorateToTakePolymorphicAccessAndReturnRecord(
429
+ getAllPortsEntriesFromRaw,
430
+ )
431
+
432
+ /**
433
+ *
434
+ *
435
+ */
436
+ export const InputsRecord = getInputsRecord(EMIDIAccess)
437
+
438
+ /**
439
+ *
440
+ *
441
+ */
442
+ export const OutputsRecord = getOutputsRecord(EMIDIAccess)
443
+
444
+ /**
445
+ *
446
+ *
447
+ */
448
+ export const AllPortsRecord = getAllPortsRecord(EMIDIAccess)
449
+
450
+ /**
451
+ * [MIDIConnectionEvent MDN
452
+ * Reference](https://developer.mozilla.org/docs/Web/API/MIDIConnectionEvent)
453
+ */
454
+ export const makeAllPortsStateChangesStream =
455
+ StreamMaker.createStreamMakerFrom<MIDIPortEventMap>()(
456
+ is,
457
+ access => ({
458
+ tag: 'MIDIPortStateChange',
459
+ eventListener: {
460
+ target: assumeImpl(access)._access,
461
+ type: 'statechange',
462
+ },
463
+ spanAttributes: {
464
+ spanTargetName: 'MIDI access handle',
465
+ requestedAccessConfig: assumeImpl(access)._config,
466
+ },
467
+ nullableFieldName: 'port',
468
+ }),
469
+ rawPort =>
470
+ ({
471
+ newState: rawPort
472
+ ? ({
473
+ ofDevice: rawPort.state,
474
+ ofConnection: rawPort.connection,
475
+ } as const)
476
+ : null,
477
+ port:
478
+ rawPort instanceof globalThis.MIDIInput
479
+ ? EMIDIInput.make(rawPort)
480
+ : rawPort instanceof globalThis.MIDIOutput
481
+ ? EMIDIOutput.make(rawPort)
482
+ : null,
483
+ }) as const,
484
+ )
485
+
486
+ /**
487
+ * beware that it's not possible to ensure the messages will either be all
488
+ * delivered, or all not delivered, as in ACID transactions. There's not even a
489
+ * mechanism to remove a specific message (not all) from the sending queue
490
+ */
491
+ export const send: DualSendMIDIMessageFromAccess = EFunction.dual<
492
+ SendMIDIMessageAccessLast,
493
+ SendMIDIMessageAccessFirst
494
+ >(
495
+ Util.polymorphicCheckInDual(is),
496
+ Effect.fn('EMIDIAccess.send')(
497
+ function* (polymorphicAccess, target, midiMessage, timestamp) {
498
+ const access = yield* resolve(polymorphicAccess)
499
+
500
+ const outputs = yield* getOutputsRecord(access)
501
+
502
+ if (target === 'all existing outputs at effect execution')
503
+ return yield* EFunction.pipe(
504
+ Record.values(outputs),
505
+ Effect.forEach(EMIDIOutput.send(midiMessage, timestamp)),
506
+ Effect.as(access),
507
+ )
508
+
509
+ if (target === 'all open connections at effect execution')
510
+ return yield* EFunction.pipe(
511
+ Record.values(outputs),
512
+ // TODO: maybe also do something about pending?
513
+ Effect.filter(isOutputConnectionOpenByPort),
514
+ Effect.flatMap(
515
+ Effect.forEach(EMIDIOutput.send(midiMessage, timestamp)),
516
+ ),
517
+ Effect.as(access),
518
+ )
519
+
520
+ // TODO: maybe since deviceState returns always connected devices we can
521
+ // simplify this check by applying intersections and comparing lengths
522
+
523
+ const portsIdsToSend: EMIDIOutput.Id[] = EArray.ensure(target)
524
+
525
+ const deviceStatusesEffect = portsIdsToSend.map(id =>
526
+ EFunction.pipe(
527
+ Record.get(outputs, id),
528
+ Option.match({
529
+ onNone: () => Effect.succeed('disconnected' as const),
530
+ onSome: EFunction.flow(getOutputDeviceStateByPort),
531
+ }),
532
+ effect => Unify.unify(effect),
533
+ Effect.map(state => ({ id, state })),
534
+ ),
535
+ )
536
+
537
+ const disconnectedDevice = EArray.findFirst(
538
+ yield* Effect.all(deviceStatusesEffect),
539
+ _ => _.state === 'disconnected',
540
+ )
541
+
542
+ if (Option.isSome(disconnectedDevice))
543
+ return yield* new Errors.DisconnectedPortError({
544
+ portId: disconnectedDevice.value.id,
545
+ cause: new DOMException(
546
+ // TODO: make an experiment and paste the error text here
547
+ 'TODO: imitate there an error thats thrown when the port is disconnected',
548
+ 'InvalidStateError',
549
+ ) as DOMException & { name: 'InvalidStateError' },
550
+ })
551
+
552
+ const sendToSome = (predicate: (id: EMIDIOutput.Id) => boolean) =>
553
+ Effect.all(
554
+ Record.reduce(
555
+ outputs,
556
+ [] as EMIDIOutput.SentMessageEffectFromPort<never, never>[],
557
+ // TODO: investigate what the fuck is going on, why the fuck can't I
558
+ // make it a simple expression without either nesting it in
559
+ // curly-braced function body or adding manual type-annotation
560
+ (acc, port, id) =>
561
+ predicate(id)
562
+ ? [
563
+ ...acc,
564
+ EMIDIOutput.send(
565
+ port,
566
+ midiMessage,
567
+ timestamp,
568
+ ) as EMIDIOutput.SentMessageEffectFromPort,
569
+ ]
570
+ : acc,
571
+ ),
572
+ )
573
+
574
+ yield* sendToSome(id => portsIdsToSend.includes(id))
575
+
576
+ return access
577
+ },
578
+ ),
579
+ )
580
+
581
+ /**
582
+ * @param options Passing a value of a `boolean` type is equivalent to setting
583
+ * `options.capture` property
584
+ */
585
+ export const makeMessagesStreamByInputId = <
586
+ const TOnNullStrategy extends StreamMaker.OnNullStrategy = undefined,
587
+ >(
588
+ id: EMIDIInput.Id,
589
+ options?: StreamMaker.StreamMakerOptions<TOnNullStrategy>,
590
+ ) =>
591
+ EMIDIInput.makeMessagesStreamByPort(
592
+ GetPort.getInputByPortIdInContext(id),
593
+ options,
594
+ )
595
+
596
+ // TODO: makeMessagesStreamByInputIdAndAccess
597
+ export const makeMessagesStreamByInputIdAndAccess = () => {
598
+ throw new Error('not implemented')
599
+ }
600
+
601
+ /**
602
+ *
603
+ */
604
+ export const sendToPortById = (
605
+ id: EMIDIOutput.Id,
606
+ ...args: EMIDIOutput.SendFromPortArgs
607
+ ) =>
608
+ Effect.asVoid(
609
+ EMIDIOutput.send(GetPort.getOutputByPortIdInContext(id), ...args),
610
+ )
611
+
612
+ /**
613
+ *
614
+ */
615
+ export const clearPortById = EFunction.flow(
616
+ GetPort.getOutputByPortIdInContext,
617
+ EMIDIOutput.clear,
618
+ Effect.asVoid,
619
+ )
620
+
621
+ /**
622
+ * @param options Passing a value of a `boolean` type is equivalent to setting
623
+ * `options.capture` property
624
+ */
625
+ export const makeAllPortsStateChangesStreamInContext = <
626
+ const TOnNullStrategy extends StreamMaker.OnNullStrategy = undefined,
627
+ >(
628
+ options?: StreamMaker.StreamMakerOptions<TOnNullStrategy>,
629
+ ) => makeAllPortsStateChangesStream(EMIDIAccess, options)
630
+
631
+ /**
632
+ *
633
+ *
634
+ */
635
+ export const sendInContext = (...args: SendFromAccessArgs) =>
636
+ Effect.asVoid(send(EMIDIAccess, ...args))
637
+
638
+ /**
639
+ * @param options
640
+ *
641
+ * @returns An Effect representing a request for access to MIDI devices on a
642
+ * user's system. Available only in secure contexts.
643
+ */
644
+ export const request = Effect.fn('EMIDIAccess.request')(function* (
645
+ options?: RequestMIDIAccessOptions,
646
+ ) {
647
+ yield* Effect.annotateCurrentSpan({ options })
648
+
649
+ const rawAccess = yield* Effect.tryPromise({
650
+ try: () => navigator.requestMIDIAccess(options),
651
+ catch: Errors.remapErrorByName(
652
+ {
653
+ AbortError: Errors.AbortError,
654
+
655
+ InvalidStateError: Errors.UnderlyingSystemError,
656
+
657
+ NotAllowedError: Errors.MIDIAccessNotAllowedError,
658
+ // SecurityError is kept for compatibility reason
659
+ // (https://github.com/WebAudio/web-midi-api/pull/267):
660
+ SecurityError: Errors.MIDIAccessNotAllowedError,
661
+
662
+ NotSupportedError: Errors.MIDIAccessNotSupportedError,
663
+ // For case when navigator doesn't exist
664
+ ReferenceError: Errors.MIDIAccessNotSupportedError,
665
+ // For case when navigator.requestMIDIAccess is undefined
666
+ TypeError: Errors.MIDIAccessNotSupportedError,
667
+ },
668
+ 'EMIDIAccess.request error handling absurd',
669
+ { whileAskingForPermissions: options ?? {} },
670
+ ),
671
+ })
672
+
673
+ // TODO: finish this
674
+
675
+ const ref = yield* Ref.make(
676
+ SortedMap.empty<EMIDIPort.BothId, MIDIPortType>(Order.string),
677
+ )
678
+
679
+ // return make(rawAccess, options, ref)
680
+ return make(rawAccess, options)
681
+ })
682
+
683
+ // TODO: clear all outputs
684
+
685
+ /**
686
+ *
687
+ * **Errors:**
688
+ *
689
+ * - {@linkcode Errors.AbortError} Argument x must be non-zero
690
+ * - {@linkcode Errors.UnderlyingSystemError} Argument x must be non-zero
691
+ * - {@linkcode Errors.MIDIAccessNotSupportedError} Argument x must be non-zero
692
+ * - {@linkcode Errors.MIDIAccessNotAllowedError} Argument x must be non-zero
693
+ *
694
+ * @param config
695
+ * @returns
696
+ */
697
+ export const layer = (config?: RequestMIDIAccessOptions) =>
698
+ Layer.effect(EMIDIAccess, request(config))
699
+
700
+ /**
701
+ *
702
+ */
703
+ export const layerMostRestricted = layer()
704
+
705
+ /**
706
+ *
707
+ */
708
+ export const layerSystemExclusiveSupported = layer({ sysex: true })
709
+
710
+ /**
711
+ *
712
+ */
713
+ export const layerSoftwareSynthSupported = layer({ software: true })
714
+
715
+ /**
716
+ *
717
+ */
718
+ export const layerSystemExclusiveAndSoftwareSynthSupported = layer({
719
+ software: true,
720
+ sysex: true,
721
+ })
722
+
723
+ export interface SentMessageEffectFromAccess<E = never, R = never>
724
+ extends Util.SentMessageEffectFrom<EMIDIAccessInstance, E, R> {}
725
+
726
+ export type TargetPortSelector =
727
+ | 'all existing outputs at effect execution'
728
+ | 'all open connections at effect execution'
729
+ | EMIDIOutput.Id
730
+ | EMIDIOutput.Id[]
731
+
732
+ export interface DualSendMIDIMessageFromAccess
733
+ extends SendMIDIMessageAccessFirst,
734
+ SendMIDIMessageAccessLast {}
735
+
736
+ export type SendFromAccessArgs = [
737
+ targetPortSelector: TargetPortSelector,
738
+ ...args: EMIDIOutput.SendFromPortArgs,
739
+ ]
740
+
741
+ export interface SendMIDIMessageAccessFirst {
742
+ /**
743
+ *
744
+ *
745
+ */
746
+ <E = never, R = never>(
747
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
748
+ ...args: SendFromAccessArgs
749
+ ): SentMessageEffectFromAccess<E, R>
750
+ }
751
+
752
+ export interface SendMIDIMessageAccessLast {
753
+ /**
754
+ *
755
+ *
756
+ */
757
+ (
758
+ ...args: SendFromAccessArgs
759
+ ): {
760
+ /**
761
+ *
762
+ *
763
+ */
764
+ <E = never, R = never>(
765
+ polymorphicAccess: PolymorphicAccessInstance<E, R>,
766
+ ): SentMessageEffectFromAccess<E, R>
767
+ }
768
+ }
769
+
770
+ export interface GetThingByPortId<
771
+ TSuccess,
772
+ TTypeOfPortId extends MIDIPortType,
773
+ TAccessGettingFallbackError,
774
+ TAccessGettingFallbackRequirement,
775
+ TAdditionalError,
776
+ TAdditionalRequirement,
777
+ > extends GetThingByPortIdAccessFirst<
778
+ TSuccess,
779
+ TTypeOfPortId,
780
+ TAccessGettingFallbackError,
781
+ TAccessGettingFallbackRequirement,
782
+ TAdditionalError,
783
+ TAdditionalRequirement
784
+ >,
785
+ GetThingByPortIdAccessLast<
786
+ TSuccess,
787
+ TTypeOfPortId,
788
+ TAccessGettingFallbackError,
789
+ TAccessGettingFallbackRequirement,
790
+ TAdditionalError,
791
+ TAdditionalRequirement
792
+ > {}
793
+
794
+ export interface GetThingByPortIdAccessFirst<
795
+ TSuccess,
796
+ TTypeOfPortId extends MIDIPortType,
797
+ TAccessGettingFallbackError,
798
+ TAccessGettingFallbackRequirement,
799
+ TAdditionalError,
800
+ TAdditionalRequirement,
801
+ > {
802
+ /**
803
+ *
804
+ *
805
+ */
806
+ <TAccessGettingError = never, TAccessGettingRequirement = never>(
807
+ polymorphicAccess: PolymorphicAccessInstance<
808
+ TAccessGettingError,
809
+ TAccessGettingRequirement
810
+ >,
811
+ id: EMIDIPort.Id<TTypeOfPortId>,
812
+ ): AcquiredThing<
813
+ TSuccess,
814
+ TAccessGettingError,
815
+ TAccessGettingRequirement,
816
+ TAccessGettingFallbackError,
817
+ TAccessGettingFallbackRequirement,
818
+ TAdditionalError,
819
+ TAdditionalRequirement
820
+ >
821
+ }
822
+
823
+ export interface GetThingByPortIdAccessLast<
824
+ TSuccess,
825
+ TTypeOfPortId extends MIDIPortType,
826
+ TAccessGettingFallbackError,
827
+ TAccessGettingFallbackRequirement,
828
+ TAdditionalError,
829
+ TAdditionalRequirement,
830
+ > {
831
+ /**
832
+ *
833
+ *
834
+ */
835
+ (
836
+ id: EMIDIPort.Id<TTypeOfPortId>,
837
+ ): GetThingByPortIdAccessLastSecondHalf<
838
+ TSuccess,
839
+ TAccessGettingFallbackError,
840
+ TAccessGettingFallbackRequirement,
841
+ TAdditionalError,
842
+ TAdditionalRequirement
843
+ >
844
+ }
845
+
846
+ export interface GetThingByPortIdAccessLastSecondHalf<
847
+ TSuccess,
848
+ TAccessGettingFallbackError,
849
+ TAccessGettingFallbackRequirement,
850
+ TAdditionalError,
851
+ TAdditionalRequirement,
852
+ > {
853
+ /**
854
+ *
855
+ *
856
+ */
857
+ <TAccessGettingError = never, TAccessGettingRequirement = never>(
858
+ polymorphicAccess: PolymorphicAccessInstance<
859
+ TAccessGettingError,
860
+ TAccessGettingRequirement
861
+ >,
862
+ ): AcquiredThing<
863
+ TSuccess,
864
+ TAccessGettingError,
865
+ TAccessGettingRequirement,
866
+ TAccessGettingFallbackError,
867
+ TAccessGettingFallbackRequirement,
868
+ TAdditionalError,
869
+ TAdditionalRequirement
870
+ >
871
+ }
872
+
873
+ export interface AcquiredThing<
874
+ TSuccess,
875
+ TAccessGettingError,
876
+ TAccessGettingRequirement,
877
+ TAccessGettingFallbackError,
878
+ TAccessGettingFallbackRequirement,
879
+ TAdditionalError,
880
+ TAdditionalRequirement,
881
+ > extends Effect.Effect<
882
+ TSuccess,
883
+ | Util.FallbackOnUnknownOrAny<
884
+ TAccessGettingError,
885
+ TAccessGettingFallbackError
886
+ >
887
+ | TAdditionalError,
888
+ | Util.FallbackOnUnknownOrAny<
889
+ TAccessGettingRequirement,
890
+ TAccessGettingFallbackRequirement
891
+ >
892
+ | TAdditionalRequirement
893
+ > {}