Adopted Span and MutableSpan for buffers across the library to adapt to Swift 6.4.
This commit is contained in:
@@ -31,9 +31,10 @@ extension File {
|
||||
|
||||
/// Reads up to `buffer.count` bytes into `buffer`. Returns the number
|
||||
/// of bytes read; 0 indicates end of file.
|
||||
public func read(into buffer: UnsafeMutableRawBufferPointer) throws(PlaydateError) -> Int {
|
||||
let result = fileAPI.pointee.read.unsafelyUnwrapped(
|
||||
pointer, buffer.baseAddress, UInt32(buffer.count))
|
||||
public func read(into buffer: inout MutableSpan<UInt8>) throws(PlaydateError) -> Int {
|
||||
let result = buffer.withUnsafeMutableBufferPointer { buffer in
|
||||
fileAPI.pointee.read.unsafelyUnwrapped(pointer, buffer.baseAddress, UInt32(buffer.count))
|
||||
}
|
||||
if result < 0 { throw lastFileError() }
|
||||
return Int(result)
|
||||
}
|
||||
@@ -49,11 +50,12 @@ extension File {
|
||||
return bytes
|
||||
}
|
||||
|
||||
/// Writes the buffer to the file. Returns the number of bytes written.
|
||||
/// Writes the bytes to the file. Returns the number of bytes written.
|
||||
@discardableResult
|
||||
public func write(_ buffer: UnsafeRawBufferPointer) throws(PlaydateError) -> Int {
|
||||
let result = fileAPI.pointee.write.unsafelyUnwrapped(
|
||||
pointer, buffer.baseAddress, UInt32(buffer.count))
|
||||
public func write(_ bytes: Span<UInt8>) throws(PlaydateError) -> Int {
|
||||
let result = bytes.withUnsafeBufferPointer { buffer in
|
||||
fileAPI.pointee.write.unsafelyUnwrapped(pointer, buffer.baseAddress, UInt32(buffer.count))
|
||||
}
|
||||
if result < 0 { throw lastFileError() }
|
||||
return Int(result)
|
||||
}
|
||||
@@ -61,11 +63,9 @@ extension File {
|
||||
/// Writes the bytes to the file. Returns the number of bytes written.
|
||||
@discardableResult
|
||||
public func write(_ bytes: [UInt8]) throws(PlaydateError) -> Int {
|
||||
let result = bytes.withUnsafeBytes { buffer in
|
||||
fileAPI.pointee.write.unsafelyUnwrapped(pointer, buffer.baseAddress, UInt32(buffer.count))
|
||||
try bytes.withUnsafeBufferPointer { buffer throws(PlaydateError) in
|
||||
try write(buffer.span)
|
||||
}
|
||||
if result < 0 { throw lastFileError() }
|
||||
return Int(result)
|
||||
}
|
||||
|
||||
/// Writes the string's UTF-8 to the file. Returns the bytes written.
|
||||
|
||||
@@ -39,14 +39,42 @@ extension Graphics {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The bitmap's dimensions, row stride, and raw storage.
|
||||
/// The bitmap's dimensions and row stride.
|
||||
public var data: Data {
|
||||
let raw = rawData()
|
||||
return Data(width: raw.width, height: raw.height, rowBytes: raw.rowBytes,
|
||||
hasMask: raw.mask != nil)
|
||||
}
|
||||
|
||||
/// Calls `body` with the bitmap's pixel data: one bit per pixel,
|
||||
/// `height` rows of `rowBytes` bytes each.
|
||||
public func withPixelData<Result, Failure: Error>(
|
||||
_ body: (inout MutableSpan<UInt8>) throws(Failure) -> Result
|
||||
) throws(Failure) -> Result {
|
||||
let raw = rawData()
|
||||
var span = UnsafeMutableBufferPointer(
|
||||
start: raw.data, count: raw.data == nil ? 0 : raw.height * raw.rowBytes).mutableSpan
|
||||
return try body(&span)
|
||||
}
|
||||
|
||||
/// Calls `body` with the bitmap's mask data, laid out like the pixel
|
||||
/// data. Returns `nil` if the bitmap has no mask.
|
||||
public func withMaskData<Result, Failure: Error>(
|
||||
_ body: (inout MutableSpan<UInt8>) throws(Failure) -> Result
|
||||
) throws(Failure) -> Result? {
|
||||
let raw = rawData()
|
||||
guard let mask = raw.mask else { return nil }
|
||||
var span = UnsafeMutableBufferPointer(start: mask, count: raw.height * raw.rowBytes).mutableSpan
|
||||
return try body(&span)
|
||||
}
|
||||
|
||||
private func rawData() -> (width: Int, height: Int, rowBytes: Int,
|
||||
mask: UnsafeMutablePointer<UInt8>?, data: UnsafeMutablePointer<UInt8>?) {
|
||||
var width: Int32 = 0, height: Int32 = 0, rowBytes: Int32 = 0
|
||||
var mask: UnsafeMutablePointer<UInt8>?
|
||||
var data: UnsafeMutablePointer<UInt8>?
|
||||
gfx.pointee.getBitmapData.unsafelyUnwrapped(pointer, &width, &height, &rowBytes, &mask, &data)
|
||||
return Data(width: Int(width), height: Int(height), rowBytes: Int(rowBytes),
|
||||
mask: mask, data: data)
|
||||
return (Int(width), Int(height), Int(rowBytes), mask, data)
|
||||
}
|
||||
|
||||
/// Cached dimensions, so `width`/`height` don't pay a full
|
||||
@@ -56,8 +84,8 @@ extension Graphics {
|
||||
|
||||
private var size: (width: Int, height: Int) {
|
||||
if let cachedSize { return cachedSize }
|
||||
let data = self.data
|
||||
let size = (data.width, data.height)
|
||||
let raw = rawData()
|
||||
let size = (raw.width, raw.height)
|
||||
cachedSize = size
|
||||
return size
|
||||
}
|
||||
|
||||
@@ -23,9 +23,11 @@ extension Graphics {
|
||||
|
||||
/// Creates a font from the contents of a .pft file already in memory.
|
||||
/// The bytes are copied and retained for the font's lifetime.
|
||||
public convenience init?(data: UnsafeRawBufferPointer, wide: Bool = false) {
|
||||
public convenience init?(data: Span<UInt8>, wide: Bool = false) {
|
||||
let copy = UnsafeMutableRawPointer.allocate(byteCount: data.count, alignment: 4)
|
||||
copy.copyMemory(from: data.baseAddress.unsafelyUnwrapped, byteCount: data.count)
|
||||
data.withUnsafeBytes { bytes in
|
||||
copy.copyMemory(from: bytes.baseAddress.unsafelyUnwrapped, byteCount: bytes.count)
|
||||
}
|
||||
let fontData = OpaquePointer(copy)
|
||||
guard let pointer = gfx.pointee.makeFontFromData.unsafelyUnwrapped(
|
||||
fontData, wide ? 1 : 0, Int32(data.count)) else {
|
||||
|
||||
@@ -279,15 +279,25 @@ extension Graphics {
|
||||
|
||||
// MARK: - Framebuffer
|
||||
|
||||
/// The current working framebuffer. Rows are `rowSize` bytes.
|
||||
/// Calls `body` with the current working framebuffer: `rows` rows of
|
||||
/// `rowSize` bytes each. Returns `nil` if there is no framebuffer.
|
||||
/// Call `markUpdatedRows(from:to:)` after writing directly.
|
||||
public static var frame: UnsafeMutablePointer<UInt8>? {
|
||||
gfx.pointee.getFrame.unsafelyUnwrapped()
|
||||
public static func withFrame<Result, Failure: Error>(
|
||||
_ body: (inout MutableSpan<UInt8>) throws(Failure) -> Result
|
||||
) throws(Failure) -> Result? {
|
||||
guard let frame = gfx.pointee.getFrame.unsafelyUnwrapped() else { return nil }
|
||||
var span = UnsafeMutableBufferPointer(start: frame, count: rows * rowSize).mutableSpan
|
||||
return try body(&span)
|
||||
}
|
||||
|
||||
/// The framebuffer currently shown on the display. Rows are `rowSize` bytes.
|
||||
public static var displayFrame: UnsafeMutablePointer<UInt8>? {
|
||||
gfx.pointee.getDisplayFrame.unsafelyUnwrapped()
|
||||
/// Calls `body` with the framebuffer currently shown on the display:
|
||||
/// `rows` rows of `rowSize` bytes each. Returns `nil` if there is no
|
||||
/// framebuffer.
|
||||
public static func withDisplayFrame<Result, Failure: Error>(
|
||||
_ body: (Span<UInt8>) throws(Failure) -> Result
|
||||
) throws(Failure) -> Result? {
|
||||
guard let frame = gfx.pointee.getDisplayFrame.unsafelyUnwrapped() else { return nil }
|
||||
return try body(UnsafeBufferPointer(start: frame, count: rows * rowSize).span)
|
||||
}
|
||||
|
||||
/// A bitmap view of the display framebuffer. Simulator only; `nil` on device.
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
extension Graphics.Bitmap {
|
||||
/// The bitmap's dimensions, row stride, and raw pixel/mask storage.
|
||||
/// The pointers are owned by the bitmap.
|
||||
public struct Data {
|
||||
/// The bitmap's dimensions and row stride. Access the pixels themselves
|
||||
/// with `withPixelData(_:)` and `withMaskData(_:)`.
|
||||
public struct Data: Sendable {
|
||||
/// The bitmap's width, in pixels.
|
||||
public let width: Int
|
||||
/// The bitmap's height, in pixels.
|
||||
public let height: Int
|
||||
/// The stride of one row of pixel data, in bytes.
|
||||
/// The stride of one row of pixel (and mask) data, in bytes.
|
||||
public let rowBytes: Int
|
||||
/// The bitmap's mask data, or `nil` if it has no mask. One bit per
|
||||
/// pixel; rows are `rowBytes` wide.
|
||||
public let mask: UnsafeMutablePointer<UInt8>?
|
||||
/// The bitmap's pixel data. One bit per pixel; rows are `rowBytes`
|
||||
/// wide.
|
||||
public let data: UnsafeMutablePointer<UInt8>?
|
||||
/// Whether the bitmap has a mask.
|
||||
public let hasMask: Bool
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,9 +126,9 @@ extension JSON {
|
||||
reader.read = { userdata, buffer, size in
|
||||
guard let userdata, let buffer else { return -1 }
|
||||
let file = Unmanaged<File.Handle>.fromOpaque(userdata).takeUnretainedValue()
|
||||
let destination = UnsafeMutableRawBufferPointer(start: buffer, count: Int(size))
|
||||
var destination = UnsafeMutableBufferPointer(start: buffer, count: Int(size)).mutableSpan
|
||||
do {
|
||||
let count = try file.read(into: destination)
|
||||
let count = try file.read(into: &destination)
|
||||
return count > 0 ? Int32(count) : -1
|
||||
} catch {
|
||||
return -1
|
||||
|
||||
@@ -152,9 +152,10 @@ extension Network {
|
||||
|
||||
/// Reads up to `buffer.count` response bytes. Returns the number of
|
||||
/// bytes read.
|
||||
public func read(into buffer: UnsafeMutableRawBufferPointer) throws(NetError) -> Int {
|
||||
let result = httpAPI.pointee.read.unsafelyUnwrapped(pointer, buffer.baseAddress,
|
||||
UInt32(buffer.count))
|
||||
public func read(into buffer: inout MutableSpan<UInt8>) throws(NetError) -> Int {
|
||||
let result = buffer.withUnsafeMutableBufferPointer { buffer in
|
||||
httpAPI.pointee.read.unsafelyUnwrapped(pointer, buffer.baseAddress, UInt32(buffer.count))
|
||||
}
|
||||
if result < 0 {
|
||||
throw NetError(rawValue: result) ?? .unknown
|
||||
}
|
||||
|
||||
@@ -112,8 +112,10 @@ extension Network {
|
||||
|
||||
/// Reads up to `buffer.count` bytes, waiting up to the read timeout.
|
||||
/// Returns the number of bytes read.
|
||||
public func read(into buffer: UnsafeMutableRawBufferPointer) throws(NetError) -> Int {
|
||||
let result = tcpAPI.pointee.read.unsafelyUnwrapped(pointer, buffer.baseAddress, buffer.count)
|
||||
public func read(into buffer: inout MutableSpan<UInt8>) throws(NetError) -> Int {
|
||||
let result = buffer.withUnsafeMutableBufferPointer { buffer in
|
||||
tcpAPI.pointee.read.unsafelyUnwrapped(pointer, buffer.baseAddress, buffer.count)
|
||||
}
|
||||
if result < 0 {
|
||||
throw NetError(rawValue: result) ?? .unknown
|
||||
}
|
||||
@@ -133,11 +135,13 @@ extension Network {
|
||||
return bytes
|
||||
}
|
||||
|
||||
/// Writes the buffer to the connection. Returns the number of bytes
|
||||
/// Writes the bytes to the connection. Returns the number of bytes
|
||||
/// accepted.
|
||||
@discardableResult
|
||||
public func write(_ buffer: UnsafeRawBufferPointer) throws(NetError) -> Int {
|
||||
let result = tcpAPI.pointee.write.unsafelyUnwrapped(pointer, buffer.baseAddress, buffer.count)
|
||||
public func write(_ bytes: Span<UInt8>) throws(NetError) -> Int {
|
||||
let result = bytes.withUnsafeBufferPointer { buffer in
|
||||
tcpAPI.pointee.write.unsafelyUnwrapped(pointer, buffer.baseAddress, buffer.count)
|
||||
}
|
||||
if result < 0 {
|
||||
throw NetError(rawValue: result) ?? .unknown
|
||||
}
|
||||
@@ -148,13 +152,9 @@ extension Network {
|
||||
/// accepted.
|
||||
@discardableResult
|
||||
public func write(_ bytes: [UInt8]) throws(NetError) -> Int {
|
||||
let result = bytes.withUnsafeBytes { buffer in
|
||||
tcpAPI.pointee.write.unsafelyUnwrapped(pointer, buffer.baseAddress, buffer.count)
|
||||
try bytes.withUnsafeBufferPointer { buffer throws(NetError) in
|
||||
try write(buffer.span)
|
||||
}
|
||||
if result < 0 {
|
||||
throw NetError(rawValue: result) ?? .unknown
|
||||
}
|
||||
return Int(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
extension Sound.Effect {
|
||||
/// Processes up to `AUDIO_FRAMES_PER_CYCLE` sample frames in signed
|
||||
/// Q8.24 format. `bufferActive` is `false` when the input buffer is
|
||||
/// silent. Returns `true` if the effect produced output.
|
||||
public typealias Processor = (_ left: UnsafeMutableBufferPointer<Int32>,
|
||||
_ right: UnsafeMutableBufferPointer<Int32>?,
|
||||
/// Q8.24 format. `right` is empty when the channel is mono.
|
||||
/// `bufferActive` is `false` when the input buffer is silent. Returns
|
||||
/// `true` if the effect produced output.
|
||||
public typealias Processor = (_ left: inout MutableSpan<Int32>,
|
||||
_ right: inout MutableSpan<Int32>,
|
||||
_ bufferActive: Bool) -> Bool
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ extension Sound {
|
||||
guard let effect, let left,
|
||||
let userdata = effectAPI.pointee.getUserdata.unsafelyUnwrapped(effect) else { return 0 }
|
||||
let box = Unmanaged<ProcessorBox>.fromOpaque(userdata).takeUnretainedValue()
|
||||
let leftBuffer = UnsafeMutableBufferPointer(start: left, count: Int(nsamples))
|
||||
let rightBuffer = right.map { UnsafeMutableBufferPointer(start: $0, count: Int(nsamples)) }
|
||||
return box.processor(leftBuffer, rightBuffer, bufactive != 0) ? 1 : 0
|
||||
var leftSpan = UnsafeMutableBufferPointer(start: left, count: Int(nsamples)).mutableSpan
|
||||
var rightSpan = UnsafeMutableBufferPointer(start: right, count: right == nil ? 0 : Int(nsamples)).mutableSpan
|
||||
return box.processor(&leftSpan, &rightSpan, bufactive != 0) ? 1 : 0
|
||||
}, box.toOpaque()).unsafelyUnwrapped
|
||||
isOwned = true
|
||||
}
|
||||
|
||||
@@ -51,14 +51,14 @@ extension Sound {
|
||||
|
||||
/// Sets a callback that records microphone input. Return `false` from the
|
||||
/// callback to stop recording. Pass `nil` to stop recording immediately.
|
||||
/// The buffer contains mono 16-bit samples.
|
||||
/// The span contains mono 16-bit samples.
|
||||
@discardableResult
|
||||
public static func setMicCallback(source: MicSource = .autodetect,
|
||||
_ callback: ((UnsafeMutableBufferPointer<Int16>) -> Bool)?) -> Bool {
|
||||
_ callback: ((Span<Int16>) -> Bool)?) -> Bool {
|
||||
micCallback = callback
|
||||
if callback != nil {
|
||||
return snd.pointee.setMicCallback.unsafelyUnwrapped({ _, buffer, length in
|
||||
let samples = UnsafeMutableBufferPointer(start: buffer, count: Int(length))
|
||||
let samples = UnsafeBufferPointer(start: buffer, count: Int(length)).span
|
||||
return Sound.micCallback?(samples) == true ? 1 : 0
|
||||
}, nil, CPlaydate.MicSource(CPlaydate.MicSource.RawValue(source.rawValue))) != 0
|
||||
} else {
|
||||
@@ -66,7 +66,7 @@ extension Sound {
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated(unsafe) private static var micCallback: ((UnsafeMutableBufferPointer<Int16>) -> Bool)?
|
||||
nonisolated(unsafe) private static var micCallback: ((Span<Int16>) -> Bool)?
|
||||
|
||||
/// Asks the user for permission to record from the microphone. `purpose`
|
||||
/// is shown in the permission prompt. The completion receives whether
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
extension Sound.CallbackSource {
|
||||
/// Fills the sample buffers and returns `true` if output was
|
||||
/// produced. `right` is non-nil only for stereo sources.
|
||||
public typealias Callback = (_ left: UnsafeMutableBufferPointer<Int16>,
|
||||
_ right: UnsafeMutableBufferPointer<Int16>?) -> Bool
|
||||
/// produced. `right` is empty for mono sources.
|
||||
public typealias Callback = (_ left: inout MutableSpan<Int16>,
|
||||
_ right: inout MutableSpan<Int16>) -> Bool
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ extension Sound {
|
||||
UnsafeMutablePointer<Int16>?, Int32) -> Int32 = { context, left, right, length in
|
||||
guard let context, let left else { return 0 }
|
||||
let source = Unmanaged<CallbackSource>.fromOpaque(context).takeUnretainedValue()
|
||||
let leftBuffer = UnsafeMutableBufferPointer(start: left, count: Int(length))
|
||||
let rightBuffer = right.map { UnsafeMutableBufferPointer(start: $0, count: Int(length)) }
|
||||
return source.callback(leftBuffer, rightBuffer) ? 1 : 0
|
||||
var leftSpan = UnsafeMutableBufferPointer(start: left, count: Int(length)).mutableSpan
|
||||
var rightSpan = UnsafeMutableBufferPointer(start: right, count: right == nil ? 0 : Int(length)).mutableSpan
|
||||
return source.callback(&leftSpan, &rightSpan) ? 1 : 0
|
||||
}
|
||||
|
||||
/// Attaches the C object created for this source.
|
||||
|
||||
@@ -7,7 +7,7 @@ extension Sound {
|
||||
|
||||
var loopCallback: ((FilePlayer) -> Void)?
|
||||
var fadeCallback: ((FilePlayer) -> Void)?
|
||||
var mp3DataSource: ((UnsafeMutableBufferPointer<UInt8>) -> Int)?
|
||||
var mp3DataSource: ((inout MutableSpan<UInt8>) -> Int)?
|
||||
private var retainedRateModulator: SignalValue?
|
||||
|
||||
override init(pointer: OpaquePointer?, isOwned: Bool) {
|
||||
@@ -131,13 +131,13 @@ extension Sound {
|
||||
/// fills the buffer and returns the number of bytes written; return 0
|
||||
/// to signal the end of the stream.
|
||||
public func setMP3StreamSource(bufferLength: Float,
|
||||
_ dataSource: @escaping (UnsafeMutableBufferPointer<UInt8>) -> Int) {
|
||||
_ dataSource: @escaping (inout MutableSpan<UInt8>) -> Int) {
|
||||
mp3DataSource = dataSource
|
||||
FilePlayer.api.pointee.setMP3StreamSource.unsafelyUnwrapped(pointer, { data, bytes, userdata in
|
||||
guard let userdata, let data else { return 0 }
|
||||
let player = Unmanaged<FilePlayer>.fromOpaque(userdata).takeUnretainedValue()
|
||||
let buffer = UnsafeMutableBufferPointer(start: data, count: Int(bytes))
|
||||
return Int32(player.mp3DataSource?(buffer) ?? 0)
|
||||
var buffer = UnsafeMutableBufferPointer(start: data, count: Int(bytes)).mutableSpan
|
||||
return Int32(player.mp3DataSource?(&buffer) ?? 0)
|
||||
}, Unmanaged.passUnretained(self).toOpaque(), bufferLength)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,9 +75,9 @@ extension Sound {
|
||||
{ userdata, left, right, nsamples, rate, drate in
|
||||
guard let userdata, let left else { return 0 }
|
||||
let box = Unmanaged<GeneratorBox>.fromOpaque(userdata).takeUnretainedValue()
|
||||
let leftBuffer = UnsafeMutableBufferPointer(start: left, count: Int(nsamples))
|
||||
let rightBuffer = right.map { UnsafeMutableBufferPointer(start: $0, count: Int(nsamples)) }
|
||||
return Int32(box.generator.render(leftBuffer, rightBuffer, rate, drate))
|
||||
var leftSpan = UnsafeMutableBufferPointer(start: left, count: Int(nsamples)).mutableSpan
|
||||
var rightSpan = UnsafeMutableBufferPointer(start: right, count: right == nil ? 0 : Int(nsamples)).mutableSpan
|
||||
return Int32(box.generator.render(&leftSpan, &rightSpan, rate, drate))
|
||||
},
|
||||
{ userdata, note, velocity, length in
|
||||
guard let userdata else { return }
|
||||
|
||||
@@ -2,11 +2,11 @@ extension Sound.Synth {
|
||||
/// Custom generator callbacks. Samples are in signed Q8.24 format.
|
||||
public struct Generator {
|
||||
/// Renders up to 256 sample frames into `left` (and `right` for
|
||||
/// stereo generators). `rate` is the per-frame phase step in
|
||||
/// stereo generators; it is empty for mono ones). `rate` is the per-frame phase step in
|
||||
/// Q0.32 format and `drate` its per-frame change. Returns the
|
||||
/// number of frames rendered.
|
||||
public var render: (_ left: UnsafeMutableBufferPointer<Int32>,
|
||||
_ right: UnsafeMutableBufferPointer<Int32>?,
|
||||
public var render: (_ left: inout MutableSpan<Int32>,
|
||||
_ right: inout MutableSpan<Int32>,
|
||||
_ rate: UInt32, _ drate: Int32) -> Int
|
||||
/// Called when a note starts. `length` is -1 for indefinite notes.
|
||||
public var noteOn: ((_ note: Sound.MIDINote, _ velocity: Float, _ length: Float) -> Void)?
|
||||
@@ -17,8 +17,8 @@ extension Sound.Synth {
|
||||
/// valid.
|
||||
public var setParameter: ((_ parameter: Int, _ value: Float) -> Bool)?
|
||||
|
||||
public init(render: @escaping (_ left: UnsafeMutableBufferPointer<Int32>,
|
||||
_ right: UnsafeMutableBufferPointer<Int32>?,
|
||||
public init(render: @escaping (_ left: inout MutableSpan<Int32>,
|
||||
_ right: inout MutableSpan<Int32>,
|
||||
_ rate: UInt32, _ drate: Int32) -> Int,
|
||||
noteOn: ((_ note: Sound.MIDINote, _ velocity: Float, _ length: Float) -> Void)? = nil,
|
||||
release: ((_ stop: Bool) -> Void)? = nil,
|
||||
|
||||
@@ -307,8 +307,12 @@ extension System {
|
||||
/// Sends data over the mirror connection. Returns `false` if mirroring is
|
||||
/// not active or the send fails.
|
||||
@discardableResult
|
||||
public static func sendMirrorData(command: UInt8, data: UnsafeMutableRawBufferPointer) -> Bool {
|
||||
api.pointee.sendMirrorData.unsafelyUnwrapped(command, data.baseAddress, Int32(data.count))
|
||||
public static func sendMirrorData(command: UInt8, data: Span<UInt8>) -> Bool {
|
||||
data.withUnsafeBufferPointer { buffer in
|
||||
// The C API takes a non-const pointer but only reads the data.
|
||||
api.pointee.sendMirrorData.unsafelyUnwrapped(
|
||||
command, UnsafeMutableRawPointer(mutating: buffer.baseAddress), Int32(buffer.count))
|
||||
}
|
||||
}
|
||||
|
||||
/// OS, language, and pdx version information.
|
||||
|
||||
@@ -146,7 +146,8 @@ struct WrapperTests {
|
||||
var produced = 0
|
||||
let source = Sound.addSource(stereo: false) { left, right in
|
||||
produced += left.count
|
||||
#expect(right == nil)
|
||||
let isMono = right.isEmpty // #expect cannot capture a span
|
||||
#expect(isMono)
|
||||
return true
|
||||
}
|
||||
#expect(Sound.CallbackSource.live.count == baseline + 1)
|
||||
@@ -280,7 +281,8 @@ struct WrapperTests {
|
||||
let effect = Sound.Effect(processor: { left, right, _ in
|
||||
_ = token
|
||||
processed += left.count
|
||||
#expect(right == nil)
|
||||
let isMono = right.isEmpty // #expect cannot capture a span
|
||||
#expect(isMono)
|
||||
return true
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user