@tialro2/rnbokit 1.0.15 → 1.0.18

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.
@@ -1,15 +1,15 @@
1
- <script>
2
- //A file drop in/media player for audio
3
- import { flip } from 'svelte/animate';
4
- import { crossfade } from 'svelte/transition';
5
- const [send, receive] = crossfade({
6
- duration: (d) => Math.sqrt(d * 200)
7
- });
8
-
9
- import FileDropZone from '../UIcomponents/FileDropZone.svelte';
10
-
11
-
12
-
1
+ <script>
2
+ //A file drop in/media player for audio
3
+ import { flip } from 'svelte/animate';
4
+ import { crossfade } from 'svelte/transition';
5
+ const [send, receive] = crossfade({
6
+ duration: (d) => Math.sqrt(d * 200)
7
+ });
8
+
9
+ import FileDropZone from '../UIcomponents/FileDropZone.svelte';
10
+
11
+
12
+
13
13
  /**
14
14
  * @typedef {Object} Props
15
15
  * @property {AudioContext} context
@@ -18,116 +18,116 @@
18
18
 
19
19
  /** @type {Props & { [key: string]: any }} */
20
20
  let { context, audio = $bindable(), ...rest } = $props();
21
-
22
- /** @type {Array<File>} */
23
- let files = $state([]);
24
- /** @type {HTMLMediaElement[]} */
25
- let audioElements = $state([]);
26
-
27
- /** @type {HTMLMediaElement|undefined} */
28
- let current;
29
-
30
- /**
31
- * pause other running audio and connect new playing source on play
32
- * @param {Event} e
33
- */
34
- function onPlay(e) {
35
- if (current === e.target) return;
36
-
37
- for (const audioElement of audioElements) {
38
- if (audioElement !== e.target) {
39
- // console.log('pause');
40
- audioElement.pause();
41
- continue;
42
- }
43
- // console.log('connect');
44
- current = audioElement;
45
- }
46
- try {
47
- audio = context.createMediaElementSource(current);
48
- } catch (e) {
49
- //ignore DOMexception error, as the correct source will still be used,
50
- // no easy way around arror (need to investigate)
51
- console.log('failed to (re)connect MediaElementSource');
52
- }
53
- }
54
-
55
- /**
56
- * put files in an array, so we can do array operations like splice. e.target.files is read-only
57
- * @param {Event} e
58
- */
59
- function loadFiles(e) {
60
- // @ts-expect-error - quick fix for: TS2339: Property 'files' does not exist on type 'Event'.
61
- files = [...e.target.files];
62
- }
63
-
64
- /**
65
- * remove a file from the files array when we click the 'x'. If no more files,
66
- * show audio drop in again
67
- * @param {Number} index
68
- */
69
- function removeFile(index) {
70
- if (!files) return;
71
- audioElements = [];
72
-
73
- files.splice(index, 1);
74
- files = files;
75
- if (files.length === 0) {
76
- files = [];
77
- audioElements = [];
78
- }
79
- }
80
- </script>
81
-
82
- <div class="RNBOsubcomponent" {...rest}>
83
- {#if files.length === 0}
84
- <FileDropZone name="audio files" on:change={loadFiles} multiple accept="audio/*" />
85
- {:else}
86
- {#each files as file, i (file)}
87
- <div
88
- class="RNBOsection RNBOaudio"
89
- in:receive={{ key: file }}
90
- out:send={{ key: file }}
91
- animate:flip={{ duration: 200 }}
92
- >
93
- <p class="RNBOtext">{file.name}</p>
94
- <audio
95
- src={URL.createObjectURL(file)}
96
- bind:this={audioElements[i]}
97
- onplay={onPlay}
98
- controls
99
- ></audio>
100
- <button
101
- type="button"
102
- class="RNBObtn RNBOclose"
103
- onclick={() => removeFile(i)}
104
- onkeydown={() => removeFile(i)}
105
- >
106
- x
107
- </button>
108
- </div>
109
- {/each}
110
- {/if}
111
- </div>
112
-
113
- <style>
114
- .RNBOclose {
115
- position: absolute;
116
- top: -0.5rem;
117
- right: -0.5rem;
118
- padding-top: 0.2rem;
119
- padding-bottom: 0.2rem;
120
- padding-left: 0.5rem;
121
- padding-right: 0.5rem;
122
- cursor: pointer;
123
- border-radius: var(--local-rounded-base);
124
- border-style: none;
125
- background-color: rgb(var(--local-accent-color));
126
- }
127
- .RNBOaudio {
128
- position: relative;
129
- display: inline-block;
130
- padding: 0.5rem;
131
- margin: 0.5rem;
132
- }
133
- </style>
21
+
22
+ /** @type {Array<File>} */
23
+ let files = $state([]);
24
+ /** @type {HTMLMediaElement[]} */
25
+ let audioElements = $state([]);
26
+
27
+ /** @type {HTMLMediaElement|undefined} */
28
+ let current;
29
+
30
+ /**
31
+ * pause other running audio and connect new playing source on play
32
+ * @param {Event} e
33
+ */
34
+ function onPlay(e) {
35
+ if (current === e.target) return;
36
+
37
+ for (const audioElement of audioElements) {
38
+ if (audioElement !== e.target) {
39
+ // console.log('pause');
40
+ audioElement.pause();
41
+ continue;
42
+ }
43
+ // console.log('connect');
44
+ current = audioElement;
45
+ }
46
+ try {
47
+ audio = context.createMediaElementSource(current);
48
+ } catch (e) {
49
+ //ignore DOMexception error, as the correct source will still be used,
50
+ // no easy way around arror (need to investigate)
51
+ console.log('failed to (re)connect MediaElementSource');
52
+ }
53
+ }
54
+
55
+ /**
56
+ * put files in an array, so we can do array operations like splice. e.target.files is read-only
57
+ * @param {Event} e
58
+ */
59
+ function loadFiles(e) {
60
+ // @ts-expect-error - quick fix for: TS2339: Property 'files' does not exist on type 'Event'.
61
+ files = [...e.target.files];
62
+ }
63
+
64
+ /**
65
+ * remove a file from the files array when we click the 'x'. If no more files,
66
+ * show audio drop in again
67
+ * @param {Number} index
68
+ */
69
+ function removeFile(index) {
70
+ if (!files) return;
71
+ audioElements = [];
72
+
73
+ files.splice(index, 1);
74
+ files = files;
75
+ if (files.length === 0) {
76
+ files = [];
77
+ audioElements = [];
78
+ }
79
+ }
80
+ </script>
81
+
82
+ <div class="RNBOsubcomponent" {...rest}>
83
+ {#if files.length === 0}
84
+ <FileDropZone name="audio files" on:change={loadFiles} multiple accept="audio/*" />
85
+ {:else}
86
+ {#each files as file, i (file)}
87
+ <div
88
+ class="RNBOsection RNBOaudio"
89
+ in:receive={{ key: file }}
90
+ out:send={{ key: file }}
91
+ animate:flip={{ duration: 200 }}
92
+ >
93
+ <p class="RNBOtext">{file.name}</p>
94
+ <audio
95
+ src={URL.createObjectURL(file)}
96
+ bind:this={audioElements[i]}
97
+ onplay={onPlay}
98
+ controls
99
+ ></audio>
100
+ <button
101
+ type="button"
102
+ class="RNBObtn RNBOclose"
103
+ onclick={() => removeFile(i)}
104
+ onkeydown={() => removeFile(i)}
105
+ >
106
+ x
107
+ </button>
108
+ </div>
109
+ {/each}
110
+ {/if}
111
+ </div>
112
+
113
+ <style>
114
+ .RNBOclose {
115
+ position: absolute;
116
+ top: -0.5rem;
117
+ right: -0.5rem;
118
+ padding-top: 0.2rem;
119
+ padding-bottom: 0.2rem;
120
+ padding-left: 0.5rem;
121
+ padding-right: 0.5rem;
122
+ cursor: pointer;
123
+ border-radius: var(--local-rounded-base);
124
+ border-style: none;
125
+ background-color: rgb(var(--local-accent-color));
126
+ }
127
+ .RNBOaudio {
128
+ position: relative;
129
+ display: inline-block;
130
+ padding: 0.5rem;
131
+ margin: 0.5rem;
132
+ }
133
+ </style>
@@ -1,17 +1,17 @@
1
- <script>
2
- import RadioGroup from '../UIcomponents/RadioGroup.svelte';
3
- import RadioItem from '../UIcomponents/RadioItem.svelte';
4
- /** @type {MIDIAccess|null|false} */
5
- let midi = $state(null); // global MIDIAccess object
6
- /**@type {MIDIInputMap|null} */
7
- let inports = $state(null); // available MIDI inports
8
-
9
- //TODO: choose port by name rather than index
10
-
11
-
12
- /** @type {MIDIInput|null} */
13
- let inport = null;
14
-
1
+ <script>
2
+ import RadioGroup from '../UIcomponents/RadioGroup.svelte';
3
+ import RadioItem from '../UIcomponents/RadioItem.svelte';
4
+ /** @type {MIDIAccess|null|false} */
5
+ let midi = $state(null); // global MIDIAccess object
6
+ /**@type {MIDIInputMap|null} */
7
+ let inports = $state(null); // available MIDI inports
8
+
9
+ //TODO: choose port by name rather than index
10
+
11
+
12
+ /** @type {MIDIInput|null} */
13
+ let inport = null;
14
+
15
15
  /**
16
16
  * @typedef {Object} Props
17
17
  * @property {number|null} [port]
@@ -20,74 +20,74 @@
20
20
 
21
21
  /** @type {Props} */
22
22
  let { port = $bindable(null), midiMessage = $bindable() } = $props();
23
-
24
- /**
25
- * set the midi access point and get the midi input port
26
- * @param {MIDIAccess} midiAccess
27
- */
28
- function onMIDISuccess(midiAccess) {
29
- midi = midiAccess;
30
- inports = midi.inputs; // store in the global (in real usage, would probably keep in an object instance)
31
- if (port) {
32
- setPort();
33
- }
34
- }
35
-
36
- /**
37
- * handle if external MIDI not available
38
- * @param {string} msg
39
- */
40
- function onMIDIFailure(msg) {
41
- console.error(`Failed to get MIDI access - ${msg}`);
42
- midi = false;
43
- }
44
-
45
- /**
46
- * set the input port when selected
47
- */
48
- function setPort() {
49
- if (inports === null || port === null) return;
50
-
51
- // @ts-ignore - ts getting their types wrong...
52
- inport = [...inports][port];
53
- console.log(
54
- // @ts-ignore - because inports will always exist, since we use the #if block
55
- 'connecting to MIDI input port: %c' + inports.get(inport[0]).name,
56
- 'font-style:italic'
57
- );
58
- // @ts-ignore - see previous comment
59
- inports.get(inport[0]).onmidimessage = onMIDIMessage;
60
- }
61
-
62
- /** @param {MIDIMessageEvent} event */
63
- function onMIDIMessage(event) {
64
- midiMessage = event.data;
65
- console.log(
66
- 'MIDI message from %c' + event.target.name + ': ' + midiMessage,
67
- 'font-style:italic'
68
- );
69
- }
70
-
71
- navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
72
- </script>
73
-
74
- <div class="RNBOsubcomponent">
75
- <p class="RNBOtext">External MIDI inputs</p>
76
-
77
- {#if midi && inports}
78
- <!-- <slot {midi} {inports} {port}> -->
79
- <RadioGroup>
80
- {#each [...inports.entries()] as input, i}
81
- <!-- first index of the input array is the id, second the object -->
82
- <RadioItem bind:group={port} name="inports" value={i} on:change={setPort}
83
- >{input[1].name}
84
- </RadioItem>
85
- {/each}
86
- </RadioGroup>
87
- <!-- </slot> -->
88
- {:else if midi === false}
89
- <p>MIDI access failed, please try in a different browser</p>
90
- {:else}
91
- <p>loading MIDI ports</p>
92
- {/if}
93
- </div>
23
+
24
+ /**
25
+ * set the midi access point and get the midi input port
26
+ * @param {MIDIAccess} midiAccess
27
+ */
28
+ function onMIDISuccess(midiAccess) {
29
+ midi = midiAccess;
30
+ inports = midi.inputs; // store in the global (in real usage, would probably keep in an object instance)
31
+ if (port) {
32
+ setPort();
33
+ }
34
+ }
35
+
36
+ /**
37
+ * handle if external MIDI not available
38
+ * @param {string} msg
39
+ */
40
+ function onMIDIFailure(msg) {
41
+ console.error(`Failed to get MIDI access - ${msg}`);
42
+ midi = false;
43
+ }
44
+
45
+ /**
46
+ * set the input port when selected
47
+ */
48
+ function setPort() {
49
+ if (inports === null || port === null) return;
50
+
51
+ // @ts-ignore - ts getting their types wrong...
52
+ inport = [...inports][port];
53
+ console.log(
54
+ // @ts-ignore - because inports will always exist, since we use the #if block
55
+ 'connecting to MIDI input port: %c' + inports.get(inport[0]).name,
56
+ 'font-style:italic'
57
+ );
58
+ // @ts-ignore - see previous comment
59
+ inports.get(inport[0]).onmidimessage = onMIDIMessage;
60
+ }
61
+
62
+ /** @param {MIDIMessageEvent} event */
63
+ function onMIDIMessage(event) {
64
+ midiMessage = event.data;
65
+ console.log(
66
+ 'MIDI message from %c' + event.target.name + ': ' + midiMessage,
67
+ 'font-style:italic'
68
+ );
69
+ }
70
+
71
+ navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
72
+ </script>
73
+
74
+ <div class="RNBOsubcomponent">
75
+ <p class="RNBOtext">External MIDI inputs</p>
76
+
77
+ {#if midi && inports}
78
+ <!-- <slot {midi} {inports} {port}> -->
79
+ <RadioGroup>
80
+ {#each [...inports.entries()] as input, i}
81
+ <!-- first index of the input array is the id, second the object -->
82
+ <RadioItem bind:group={port} name="inports" value={i} on:change={setPort}
83
+ >{input[1].name}
84
+ </RadioItem>
85
+ {/each}
86
+ </RadioGroup>
87
+ <!-- </slot> -->
88
+ {:else if midi === false}
89
+ <p>MIDI access failed, please try in a different browser</p>
90
+ {:else}
91
+ <p>loading MIDI ports</p>
92
+ {/if}
93
+ </div>
@@ -1,17 +1,17 @@
1
- <script>
2
- import RadioGroup from '../UIcomponents/RadioGroup.svelte';
3
- import RadioItem from '../UIcomponents/RadioItem.svelte';
4
- /** @type {MIDIAccess|null|false} */
5
- let midi = $state(null); // global MIDIAccess object
6
- /**@type {MIDIInputMap|null} */
7
- let outports = $state(null); // available MIDI outports
8
-
9
- //TODO: choose port by name rather than index
10
-
11
-
12
- /** @type {MIDIInput|null} */
13
- let outport = null;
14
-
1
+ <script>
2
+ import RadioGroup from '../UIcomponents/RadioGroup.svelte';
3
+ import RadioItem from '../UIcomponents/RadioItem.svelte';
4
+ /** @type {MIDIAccess|null|false} */
5
+ let midi = $state(null); // global MIDIAccess object
6
+ /**@type {MIDIInputMap|null} */
7
+ let outports = $state(null); // available MIDI outports
8
+
9
+ //TODO: choose port by name rather than index
10
+
11
+
12
+ /** @type {MIDIInput|null} */
13
+ let outport = null;
14
+
15
15
  /**
16
16
  * @typedef {Object} Props
17
17
  * @property {number|null} [port]
@@ -20,74 +20,74 @@
20
20
 
21
21
  /** @type {Props} */
22
22
  let { port = $bindable(null), midiMessage = $bindable() } = $props();
23
-
24
- /**
25
- * set the midi access point and get the midi output port
26
- * @param {MIDIAccess} midiAccess
27
- */
28
- function onMIDISuccess(midiAccess) {
29
- midi = midiAccess;
30
- outports = midi.outputs; // store in the global (in real usage, would probably keep in an object instance)
31
- if (port) {
32
- setPort();
33
- }
34
- }
35
-
36
- /**
37
- * handle if external MIDI not available
38
- * @param {string} msg
39
- */
40
- function onMIDIFailure(msg) {
41
- console.error(`Failed to get MIDI access - ${msg}`);
42
- midi = false;
43
- }
44
-
45
- /**
46
- * set the output port when selected
47
- */
48
- function setPort() {
49
- if (!outports || !port) return;
50
-
51
- // @ts-ignore - ts getting their types wrong...
52
- outport = [...outports][port];
53
- console.log(
54
- // @ts-ignore - because outports will always exist, since we use the #if block
55
- 'connecting to MIDI output port: %c' + outports.get(outport[0]).name,
56
- 'font-style:italic'
57
- );
58
- // @ts-ignore - see previous comment
59
- outports.get(outport[0]).onmidimessage = onMIDIMessage;
60
- }
61
-
62
- /** @param {MIDIMessageEvent} event */
63
- function onMIDIMessage(event) {
64
- midiMessage = event.data;
65
- console.log(
66
- 'MIDI message from %c' + event.target.name + ': ' + midiMessage,
67
- 'font-style:italic'
68
- );
69
- }
70
-
71
- navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
72
- </script>
73
-
74
- <div class="RNBOsubcomponent">
75
- <p class="RNBOtext">External MIDI outputs</p>
76
-
77
- {#if midi && outports}
78
- <!-- <slot {midi} {outports} {port}> -->
79
- <RadioGroup>
80
- {#each [...outports.entries()] as output, i}
81
- <!-- first index of the output array is the id, second the object -->
82
- <RadioItem bind:group={port} name="outports" value={i} on:change={setPort}
83
- >{output[1].name}
84
- </RadioItem>
85
- {/each}
86
- </RadioGroup>
87
- <!-- </slot> -->
88
- {:else if midi === false}
89
- <p>MIDI access failed, please try in a different browser</p>
90
- {:else}
91
- <p>loading MIDI ports</p>
92
- {/if}
93
- </div>
23
+
24
+ /**
25
+ * set the midi access point and get the midi output port
26
+ * @param {MIDIAccess} midiAccess
27
+ */
28
+ function onMIDISuccess(midiAccess) {
29
+ midi = midiAccess;
30
+ outports = midi.outputs; // store in the global (in real usage, would probably keep in an object instance)
31
+ if (port) {
32
+ setPort();
33
+ }
34
+ }
35
+
36
+ /**
37
+ * handle if external MIDI not available
38
+ * @param {string} msg
39
+ */
40
+ function onMIDIFailure(msg) {
41
+ console.error(`Failed to get MIDI access - ${msg}`);
42
+ midi = false;
43
+ }
44
+
45
+ /**
46
+ * set the output port when selected
47
+ */
48
+ function setPort() {
49
+ if (!outports || !port) return;
50
+
51
+ // @ts-ignore - ts getting their types wrong...
52
+ outport = [...outports][port];
53
+ console.log(
54
+ // @ts-ignore - because outports will always exist, since we use the #if block
55
+ 'connecting to MIDI output port: %c' + outports.get(outport[0]).name,
56
+ 'font-style:italic'
57
+ );
58
+ // @ts-ignore - see previous comment
59
+ outports.get(outport[0]).onmidimessage = onMIDIMessage;
60
+ }
61
+
62
+ /** @param {MIDIMessageEvent} event */
63
+ function onMIDIMessage(event) {
64
+ midiMessage = event.data;
65
+ console.log(
66
+ 'MIDI message from %c' + event.target.name + ': ' + midiMessage,
67
+ 'font-style:italic'
68
+ );
69
+ }
70
+
71
+ navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
72
+ </script>
73
+
74
+ <div class="RNBOsubcomponent">
75
+ <p class="RNBOtext">External MIDI outputs</p>
76
+
77
+ {#if midi && outports}
78
+ <!-- <slot {midi} {outports} {port}> -->
79
+ <RadioGroup>
80
+ {#each [...outports.entries()] as output, i}
81
+ <!-- first index of the output array is the id, second the object -->
82
+ <RadioItem bind:group={port} name="outports" value={i} on:change={setPort}
83
+ >{output[1].name}
84
+ </RadioItem>
85
+ {/each}
86
+ </RadioGroup>
87
+ <!-- </slot> -->
88
+ {:else if midi === false}
89
+ <p>MIDI access failed, please try in a different browser</p>
90
+ {:else}
91
+ <p>loading MIDI ports</p>
92
+ {/if}
93
+ </div>