Skip to content

Commit 2356b1f

Browse files
committed
feat: add scheduling bindings
Add ReScript bindings for Tone.js scheduling modules: - Loop (looping callback with interval, iterations, probability) - Event (schedulable event with loop and playback control) - Part (collection of events on a timeline) - Sequence (ordered series of events with subdivision) Each module exposes constructors, start/stop/cancel, and properties for loop, playbackRate, probability, humanize, and mute. Includes 4 test suites verifying binding correctness.
1 parent c124a83 commit 2356b1f

7 files changed

Lines changed: 271 additions & 0 deletions

File tree

src/ToneJs.res

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,9 @@ module Volume = ToneJs_Volume
5656
module Gain = ToneJs_Gain
5757
module Channel = ToneJs_Channel
5858
module CrossFade = ToneJs_CrossFade
59+
60+
// Scheduling
61+
module Loop = ToneJs_Loop
62+
module Event = ToneJs_Event
63+
module Part = ToneJs_Part
64+
module Sequence = ToneJs_Sequence

src/ToneJs_Event.res

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Bindings for Tone.ToneEvent - schedulable event
2+
open ToneJs_Types
3+
4+
type t
5+
6+
@module("tone") @new external make: ((seconds, 'a) => unit, 'a) => t = "ToneEvent"
7+
8+
@send external start: (t, ~time: transportTime=?) => t = "start"
9+
@send external stop: (t, ~time: transportTime=?) => t = "stop"
10+
@send external cancel: (t, ~time: transportTime=?) => t = "cancel"
11+
@send external dispose: t => t = "dispose"
12+
13+
@get external state: t => basicPlaybackState = "state"
14+
@get external progress: t => normalRange = "progress"
15+
@get external loop: t => bool = "loop"
16+
@set external setLoop: (t, bool) => unit = "loop"
17+
@get external loopEnd: t => time = "loopEnd"
18+
@set external setLoopEnd: (t, time) => unit = "loopEnd"
19+
@get external loopStart: t => time = "loopStart"
20+
@set external setLoopStart: (t, time) => unit = "loopStart"
21+
@get external playbackRate: t => positive = "playbackRate"
22+
@set external setPlaybackRate: (t, positive) => unit = "playbackRate"
23+
@get external probability: t => normalRange = "probability"
24+
@set external setProbability: (t, normalRange) => unit = "probability"
25+
@get external mute: t => bool = "mute"
26+
@set external setMute: (t, bool) => unit = "mute"
27+
@get external humanize: t => bool = "humanize"
28+
@set external setHumanize: (t, bool) => unit = "humanize"

src/ToneJs_Loop.res

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Bindings for Tone.Loop - looping callback
2+
open ToneJs_Types
3+
4+
type t
5+
6+
type options = {
7+
callback?: seconds => unit,
8+
interval?: time,
9+
playbackRate?: positive,
10+
iterations?: int,
11+
probability?: normalRange,
12+
mute?: bool,
13+
humanize?: bool,
14+
}
15+
16+
@module("tone") @new external make: (seconds => unit, time) => t = "Loop"
17+
@module("tone") @new external makeWithOptions: options => t = "Loop"
18+
19+
@send external start: (t, ~time: transportTime=?) => t = "start"
20+
@send external stop: (t, ~time: transportTime=?) => t = "stop"
21+
@send external cancel: (t, ~time: transportTime=?) => t = "cancel"
22+
@send external dispose: t => t = "dispose"
23+
24+
@get external state: t => basicPlaybackState = "state"
25+
@get external progress: t => normalRange = "progress"
26+
@get external interval: t => time = "interval"
27+
@set external setInterval: (t, time) => unit = "interval"
28+
@get external playbackRate: t => positive = "playbackRate"
29+
@set external setPlaybackRate: (t, positive) => unit = "playbackRate"
30+
@get external humanize: t => bool = "humanize"
31+
@set external setHumanize: (t, bool) => unit = "humanize"
32+
@get external probability: t => normalRange = "probability"
33+
@set external setProbability: (t, normalRange) => unit = "probability"
34+
@get external mute: t => bool = "mute"
35+
@set external setMute: (t, bool) => unit = "mute"
36+
@get external iterations: t => int = "iterations"
37+
@set external setIterations: (t, int) => unit = "iterations"
38+
@get external callback: t => seconds => unit = "callback"
39+
@set external setCallback: (t, seconds => unit) => unit = "callback"

src/ToneJs_Part.res

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Bindings for Tone.Part - a collection of events on a timeline
2+
open ToneJs_Types
3+
4+
type t
5+
6+
@module("tone") @new external make: ((seconds, 'a) => unit, array<'a>) => t = "Part"
7+
8+
@send external start: (t, ~time: transportTime=?) => t = "start"
9+
@send external startWithOffset: (t, ~time: transportTime=?, ~offset: time=?) => t = "start"
10+
@send external stop: (t, ~time: transportTime=?) => t = "stop"
11+
@send external cancel: (t, ~time: transportTime=?) => t = "cancel"
12+
@send external clear: t => t = "clear"
13+
@send external dispose: t => t = "dispose"
14+
15+
@send external add: (t, time, 'a) => t = "add"
16+
@send external remove: (t, time, 'a) => t = "remove"
17+
@send external at: (t, time) => Null.t<ToneJs_Event.t> = "at"
18+
19+
@get external state: t => basicPlaybackState = "state"
20+
@get external progress: t => normalRange = "progress"
21+
@get external length: t => int = "length"
22+
@get external loop: t => bool = "loop"
23+
@set external setLoop: (t, bool) => unit = "loop"
24+
@set external setLoopCount: (t, int) => unit = "loop"
25+
@get external loopEnd: t => time = "loopEnd"
26+
@set external setLoopEnd: (t, time) => unit = "loopEnd"
27+
@get external loopStart: t => time = "loopStart"
28+
@set external setLoopStart: (t, time) => unit = "loopStart"
29+
@get external playbackRate: t => positive = "playbackRate"
30+
@set external setPlaybackRate: (t, positive) => unit = "playbackRate"
31+
@get external probability: t => normalRange = "probability"
32+
@set external setProbability: (t, normalRange) => unit = "probability"
33+
@get external mute: t => bool = "mute"
34+
@set external setMute: (t, bool) => unit = "mute"
35+
@get external humanize: t => bool = "humanize"
36+
@set external setHumanize: (t, bool) => unit = "humanize"

src/ToneJs_Sequence.res

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Bindings for Tone.Sequence - a series of events in order
2+
open ToneJs_Types
3+
4+
type t
5+
6+
@module("tone") @new external make: ((seconds, 'a) => unit, array<'a>) => t = "Sequence"
7+
@module("tone") @new external makeWithSubdivision: ((seconds, 'a) => unit, array<'a>, time) => t = "Sequence"
8+
9+
@send external start: (t, ~time: transportTime=?) => t = "start"
10+
@send external startWithOffset: (t, ~time: transportTime=?, ~offset: int=?) => t = "start"
11+
@send external stop: (t, ~time: transportTime=?) => t = "stop"
12+
@send external clear: t => t = "clear"
13+
@send external dispose: t => t = "dispose"
14+
15+
@get external events: t => array<'a> = "events"
16+
@set external setEvents: (t, array<'a>) => unit = "events"
17+
@get external subdivision: t => seconds = "subdivision"
18+
@get external state: t => basicPlaybackState = "state"
19+
@get external progress: t => normalRange = "progress"
20+
@get external length: t => int = "length"
21+
@get external loop: t => bool = "loop"
22+
@set external setLoop: (t, bool) => unit = "loop"
23+
@set external setLoopCount: (t, int) => unit = "loop"
24+
@get external loopEnd: t => int = "loopEnd"
25+
@set external setLoopEnd: (t, int) => unit = "loopEnd"
26+
@get external loopStart: t => int = "loopStart"
27+
@set external setLoopStart: (t, int) => unit = "loopStart"
28+
@get external playbackRate: t => positive = "playbackRate"
29+
@set external setPlaybackRate: (t, positive) => unit = "playbackRate"
30+
@get external probability: t => normalRange = "probability"
31+
@set external setProbability: (t, normalRange) => unit = "probability"
32+
@get external mute: t => bool = "mute"
33+
@set external setMute: (t, bool) => unit = "mute"
34+
@get external humanize: t => bool = "humanize"
35+
@set external setHumanize: (t, bool) => unit = "humanize"

tests/SchedulingTests.res

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
open Zekr
2+
3+
let loopSuite = suite("Loop", [
4+
test("bindings type-check", () => {
5+
let _ = ToneJs_Loop.make
6+
let _ = ToneJs_Loop.makeWithOptions
7+
let _ = ToneJs_Loop.start
8+
let _ = ToneJs_Loop.stop
9+
let _ = ToneJs_Loop.cancel
10+
let _ = ToneJs_Loop.dispose
11+
let _ = ToneJs_Loop.state
12+
let _ = ToneJs_Loop.progress
13+
let _ = ToneJs_Loop.interval
14+
let _ = ToneJs_Loop.setInterval
15+
let _ = ToneJs_Loop.playbackRate
16+
let _ = ToneJs_Loop.setPlaybackRate
17+
let _ = ToneJs_Loop.humanize
18+
let _ = ToneJs_Loop.setHumanize
19+
let _ = ToneJs_Loop.probability
20+
let _ = ToneJs_Loop.setProbability
21+
let _ = ToneJs_Loop.mute
22+
let _ = ToneJs_Loop.setMute
23+
let _ = ToneJs_Loop.iterations
24+
let _ = ToneJs_Loop.setIterations
25+
let _ = ToneJs_Loop.callback
26+
let _ = ToneJs_Loop.setCallback
27+
Pass
28+
}),
29+
])
30+
31+
let eventSuite = suite("Event", [
32+
test("bindings type-check", () => {
33+
let _ = ToneJs_Event.make
34+
let _ = ToneJs_Event.start
35+
let _ = ToneJs_Event.stop
36+
let _ = ToneJs_Event.cancel
37+
let _ = ToneJs_Event.dispose
38+
let _ = ToneJs_Event.state
39+
let _ = ToneJs_Event.progress
40+
let _ = ToneJs_Event.loop
41+
let _ = ToneJs_Event.setLoop
42+
let _ = ToneJs_Event.loopEnd
43+
let _ = ToneJs_Event.setLoopEnd
44+
let _ = ToneJs_Event.loopStart
45+
let _ = ToneJs_Event.setLoopStart
46+
let _ = ToneJs_Event.playbackRate
47+
let _ = ToneJs_Event.setPlaybackRate
48+
let _ = ToneJs_Event.probability
49+
let _ = ToneJs_Event.setProbability
50+
let _ = ToneJs_Event.mute
51+
let _ = ToneJs_Event.setMute
52+
let _ = ToneJs_Event.humanize
53+
let _ = ToneJs_Event.setHumanize
54+
Pass
55+
}),
56+
])
57+
58+
let partSuite = suite("Part", [
59+
test("bindings type-check", () => {
60+
let _ = ToneJs_Part.make
61+
let _ = ToneJs_Part.start
62+
let _ = ToneJs_Part.startWithOffset
63+
let _ = ToneJs_Part.stop
64+
let _ = ToneJs_Part.cancel
65+
let _ = ToneJs_Part.clear
66+
let _ = ToneJs_Part.dispose
67+
let _ = ToneJs_Part.add
68+
let _ = ToneJs_Part.remove
69+
let _ = ToneJs_Part.at
70+
let _ = ToneJs_Part.state
71+
let _ = ToneJs_Part.progress
72+
let _ = ToneJs_Part.length
73+
let _ = ToneJs_Part.loop
74+
let _ = ToneJs_Part.setLoop
75+
let _ = ToneJs_Part.setLoopCount
76+
let _ = ToneJs_Part.loopEnd
77+
let _ = ToneJs_Part.setLoopEnd
78+
let _ = ToneJs_Part.loopStart
79+
let _ = ToneJs_Part.setLoopStart
80+
let _ = ToneJs_Part.playbackRate
81+
let _ = ToneJs_Part.setPlaybackRate
82+
let _ = ToneJs_Part.probability
83+
let _ = ToneJs_Part.setProbability
84+
let _ = ToneJs_Part.mute
85+
let _ = ToneJs_Part.setMute
86+
let _ = ToneJs_Part.humanize
87+
let _ = ToneJs_Part.setHumanize
88+
Pass
89+
}),
90+
])
91+
92+
let sequenceSuite = suite("Sequence", [
93+
test("bindings type-check", () => {
94+
let _ = ToneJs_Sequence.make
95+
let _ = ToneJs_Sequence.makeWithSubdivision
96+
let _ = ToneJs_Sequence.start
97+
let _ = ToneJs_Sequence.startWithOffset
98+
let _ = ToneJs_Sequence.stop
99+
let _ = ToneJs_Sequence.clear
100+
let _ = ToneJs_Sequence.dispose
101+
let _ = ToneJs_Sequence.events
102+
let _ = ToneJs_Sequence.setEvents
103+
let _ = ToneJs_Sequence.subdivision
104+
let _ = ToneJs_Sequence.state
105+
let _ = ToneJs_Sequence.progress
106+
let _ = ToneJs_Sequence.length
107+
let _ = ToneJs_Sequence.loop
108+
let _ = ToneJs_Sequence.setLoop
109+
let _ = ToneJs_Sequence.setLoopCount
110+
let _ = ToneJs_Sequence.loopEnd
111+
let _ = ToneJs_Sequence.setLoopEnd
112+
let _ = ToneJs_Sequence.loopStart
113+
let _ = ToneJs_Sequence.setLoopStart
114+
let _ = ToneJs_Sequence.playbackRate
115+
let _ = ToneJs_Sequence.setPlaybackRate
116+
let _ = ToneJs_Sequence.probability
117+
let _ = ToneJs_Sequence.setProbability
118+
let _ = ToneJs_Sequence.mute
119+
let _ = ToneJs_Sequence.setMute
120+
let _ = ToneJs_Sequence.humanize
121+
let _ = ToneJs_Sequence.setHumanize
122+
Pass
123+
}),
124+
])
125+
126+
let suites = [loopSuite, eventSuite, partSuite, sequenceSuite]

tests/Tests.res

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ let allSuites = Array.flat([
55
SourceTests.suites,
66
EffectTests.suites,
77
SignalTests.suites,
8+
SchedulingTests.suites,
89
])
910

1011
runSuites(allSuites)

0 commit comments

Comments
 (0)