Skip to content

Commit

Permalink
CHANGE SamplePlayer callback implementation using userdata
Browse files Browse the repository at this point in the history
Removes the table
  • Loading branch information
ninovanhooff committed Apr 5, 2024
1 parent d91b90c commit 03ccd6b
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 19 deletions.
2 changes: 0 additions & 2 deletions src/playdate/bindings/sound.nim
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ type PlaydateSoundSampleplayer {.importc: "const struct playdate_sound_samplepla
getLength {.importc: "getLength".}: proc (player: SamplePlayerPtr): cfloat {.cdecl, raises: [].}
setRate {.importc: "setRate".}: proc (player: SamplePlayerPtr; rate: cfloat) {.cdecl, raises: [].}
getRate {.importc: "getRate".}: proc (player: SamplePlayerPtr): cfloat {.cdecl, raises: [].}
# setOffset* {.importc: "setOffset".}: proc (player: SamplePlayerPtr; offset: cfloat) {.
# cdecl.}
setPlayRange* {.importc: "setPlayRange".}: proc (player: SamplePlayerPtr;
start: cint; `end`: cint) {.cdecl, raises: [].}
setFinishCallback* {.importc: "setFinishCallback".}: proc (
Expand Down
30 changes: 13 additions & 17 deletions src/playdate/sound.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{.push raises: [].}

import std/importutils
import tables
import bindings/sound
import bindings/api
import system
Expand All @@ -19,15 +18,10 @@ type

PDSoundCallbackFunction* = proc(userData: pointer) {.raises: [].}

var
## Finish callbacks for sound sources (FilePlayer, SamplePlayer)
soundCallbackMap: Table[SoundSourcePtr, PDSoundCallbackFunction] = initTable[SoundSourcePtr, PDSoundCallbackFunction]()


proc `=destroy`(this: var AudioSampleObj) =
privateAccess(PlaydateSound)
privateAccess(PlaydateSoundSample)
soundCallbackMap.del(this.resource)
playdate.sound.sample.freeSample(this.resource)

proc newAudioSample*(this: ptr PlaydateSound, bytes: int32): AudioSample =
Expand Down Expand Up @@ -56,6 +50,7 @@ proc getLength*(this: AudioSample): float32 =
# AudioSource
type SoundSourceObj {.requiresinit.} = object of RootObj
resource: pointer
callback: PDSoundCallbackFunction
type SoundSource* = ref SoundSourceObj

# FilePlayer
Expand All @@ -71,12 +66,12 @@ proc `=destroy`(this: var FilePlayerObj) =
proc newFilePlayer*(this: ptr PlaydateSound): FilePlayer =
privateAccess(PlaydateSound)
privateAccess(PlaydateSoundFileplayer)
result = FilePlayer(resource: this.fileplayer.newPlayer())
result = FilePlayer(resource: this.fileplayer.newPlayer(), callback: nil)

proc newFilePlayer*(this: ptr PlaydateSound, path: string): FilePlayer {.raises: [IOError].} =
privateAccess(PlaydateSound)
privateAccess(PlaydateSoundFileplayer)
result = FilePlayer(resource: this.fileplayer.newPlayer())
result = FilePlayer(resource: this.fileplayer.newPlayer(), callback: nil)
if this.fileplayer.loadIntoPlayer(result.resource, path.cstring) == 0:
raise newException(IOError, fmt"file {path} not found: No such file")

Expand Down Expand Up @@ -153,7 +148,7 @@ proc `=destroy`(this: var SamplePlayerObj) =
proc newSamplePlayer*(this: ptr PlaydateSound): SamplePlayer =
privateAccess(PlaydateSound)
privateAccess(PlaydateSoundSampleplayer)
result = SamplePlayer(resource: this.sampleplayer.newPlayer())
result = SamplePlayer(resource: this.sampleplayer.newPlayer(), callback: nil)

proc sample*(this: SamplePlayer): AudioSample =
return this.sample
Expand All @@ -167,7 +162,7 @@ proc `sample=`*(this: SamplePlayer, sample: AudioSample) =
proc newSamplePlayer*(this: ptr PlaydateSound, path: string): SamplePlayer {.raises: [IOError].} =
privateAccess(PlaydateSound)
privateAccess(PlaydateSoundSampleplayer)
result = SamplePlayer(resource: this.sampleplayer.newPlayer())
result = SamplePlayer(resource: this.sampleplayer.newPlayer(), callback: nil)
result.`sample=`(this.newAudioSample(path))

proc volume*(this: SamplePlayer): tuple[left: float32, right: float32] =
Expand Down Expand Up @@ -227,22 +222,23 @@ proc rate*(this: SamplePlayer): float32 =
privateAccess(PlaydateSoundSampleplayer)
return playdate.sound.sampleplayer.getRate(this.resource).float32

proc privateFinishCallback(soundSource: SoundSourcePtr, userData: pointer) {.cdecl, raises: [].} =
try:
soundCallbackMap[soundSource](userData)
proc privateSampleFinishCallback(soundSourcePtr: SoundSourcePtr, userData: pointer) {.cdecl, raises: [].} =
try:
let soundSource = cast[SamplePlayer](userdata)[]
if soundSource.callback != nil:
soundSource.callback(userData)
except:
echo "No finish callback for sound source pointer " & repr(soundSource)
echo "Error while calling finish callback"

proc setFinishCallback*(this: SamplePlayer, callback: PDSoundCallbackFunction) =
privateAccess(PlaydateSound)
privateAccess(PlaydateSoundSampleplayer)
try:
this.callback = callback
if callback == nil:
soundCallbackMap.del(this.resource)
playdate.sound.sampleplayer.setFinishCallback(this.resource, nil, nil)
else:
soundCallbackMap[this.resource] = callback
playdate.sound.sampleplayer.setFinishCallback(this.resource, privateFinishCallback, nil)
playdate.sound.sampleplayer.setFinishCallback(this.resource, privateSampleFinishCallback, cast[pointer](this))
except:
echo "Error setting finish callback"

Expand Down

0 comments on commit 03ccd6b

Please sign in to comment.