library_godot_webmidi.js 4.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**************************************************************************/
  2. /* library_godot_webmidi.js */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. const GodotWebMidi = {
  31. $GodotWebMidi__deps: ['$GodotRuntime'],
  32. $GodotWebMidi: {
  33. abortControllers: [],
  34. isListening: false,
  35. },
  36. godot_js_webmidi_open_midi_inputs__deps: ['$GodotWebMidi'],
  37. godot_js_webmidi_open_midi_inputs__proxy: 'sync',
  38. godot_js_webmidi_open_midi_inputs__sig: 'iiii',
  39. godot_js_webmidi_open_midi_inputs: function (pSetInputNamesCb, pOnMidiMessageCb, pDataBuffer, dataBufferLen) {
  40. if (GodotWebMidi.is_listening) {
  41. return 0; // OK
  42. }
  43. if (!navigator.requestMIDIAccess) {
  44. return 2; // ERR_UNAVAILABLE
  45. }
  46. const setInputNamesCb = GodotRuntime.get_func(pSetInputNamesCb);
  47. const onMidiMessageCb = GodotRuntime.get_func(pOnMidiMessageCb);
  48. GodotWebMidi.isListening = true;
  49. navigator.requestMIDIAccess().then((midi) => {
  50. const inputs = [...midi.inputs.values()];
  51. const inputNames = inputs.map((input) => input.name);
  52. const c_ptr = GodotRuntime.allocStringArray(inputNames);
  53. setInputNamesCb(inputNames.length, c_ptr);
  54. GodotRuntime.freeStringArray(c_ptr, inputNames.length);
  55. inputs.forEach((input, i) => {
  56. const abortController = new AbortController();
  57. GodotWebMidi.abortControllers.push(abortController);
  58. input.addEventListener('midimessage', (event) => {
  59. const status = event.data[0];
  60. const data = event.data.slice(1);
  61. const size = data.length;
  62. if (size > dataBufferLen) {
  63. throw new Error(`data too big ${size} > ${dataBufferLen}`);
  64. }
  65. HEAPU8.set(data, pDataBuffer);
  66. onMidiMessageCb(i, status, pDataBuffer, data.length);
  67. }, { signal: abortController.signal });
  68. });
  69. });
  70. return 0; // OK
  71. },
  72. godot_js_webmidi_close_midi_inputs__deps: ['$GodotWebMidi'],
  73. godot_js_webmidi_close_midi_inputs__proxy: 'sync',
  74. godot_js_webmidi_close_midi_inputs__sig: 'v',
  75. godot_js_webmidi_close_midi_inputs: function () {
  76. for (const abortController of GodotWebMidi.abortControllers) {
  77. abortController.abort();
  78. }
  79. GodotWebMidi.abortControllers = [];
  80. GodotWebMidi.isListening = false;
  81. },
  82. };
  83. mergeInto(LibraryManager.library, GodotWebMidi);