Files
playdate-kit/Sources/PlaydateKit/Sound/Source/Classes/Source.swift
T

52 lines
1.9 KiB
Swift
Raw Normal View History

internal import CPlaydate
extension Sound {
2026-09-18 13:15:08 +00:00
/// Base class of `FilePlayer`, `SamplePlayer`, `Synth`, `DelayLineTap`, and
/// `CallbackSource`. Wraps `SoundSource`.
public class Source {
private static var api: UnsafePointer<playdate_sound_source> { Playdate.sourceAPI.unsafelyUnwrapped }
2026-09-18 13:15:08 +00:00
/// Set once, right after creation.
var pointer: OpaquePointer!
let isOwned: Bool
var finishCallback: ((Source) -> Void)?
init(pointer: OpaquePointer?, isOwned: Bool) {
self.pointer = pointer
self.isOwned = isOwned
}
2026-09-18 13:15:08 +00:00
/// Per-channel volume, 01.
public var volume: (left: Float, right: Float) {
get {
var left: Float = 0, right: Float = 0
Source.api.pointee.getVolume.unsafelyUnwrapped(pointer, &left, &right)
return (left, right)
}
set { Source.api.pointee.setVolume.unsafelyUnwrapped(pointer, newValue.left, newValue.right) }
}
public func setVolume(_ volume: Float) {
self.volume = (volume, volume)
}
public var isPlaying: Bool {
Source.api.pointee.isPlaying.unsafelyUnwrapped(pointer) != 0
}
2026-09-18 13:15:08 +00:00
/// Called when the source finishes playing; `nil` removes it.
public func setFinishCallback(_ callback: ((Source) -> Void)?) {
finishCallback = callback
if callback != nil {
Source.api.pointee.setFinishCallback.unsafelyUnwrapped(pointer, { _, userdata in
guard let userdata else { return }
let source = Unmanaged<Source>.fromOpaque(userdata).takeUnretainedValue()
source.finishCallback?(source)
}, Unmanaged.passUnretained(self).toOpaque())
} else {
Source.api.pointee.setFinishCallback.unsafelyUnwrapped(pointer, nil, nil)
}
}
}
}