Created
January 25, 2024 14:58
-
-
Save yandroidUA/2bf3f51329f0b480fa7555bae2e567ce to your computer and use it in GitHub Desktop.
iOS AudioPlayer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import io.github.aakira.napier.Napier | |
| import kotlinx.cinterop.* | |
| import platform.AVFAudio.AVAudioPlayer | |
| import platform.AVFAudio.AVAudioPlayerDelegateProtocol | |
| import platform.Foundation.NSError | |
| import platform.Foundation.NSURL | |
| import kotlin.time.Duration | |
| import kotlin.time.DurationUnit | |
| import kotlin.time.ExperimentalTime | |
| import kotlin.time.toDuration | |
| // this one comes as an 'actual' class, so put it here like that for simplicity | |
| class LocalUrl( | |
| val url: NSURL, | |
| ) | |
| @OptIn(ExperimentalForeignApi::class, BetaInteropApi::class) | |
| internal actual class AudioPlayer { | |
| private var player: AVAudioPlayer? = null | |
| var delegate: AVAudioPlayerDelegateProtocol? = null | |
| private inline fun createPlayer(url: NSURL): AVAudioPlayer? = memScoped { | |
| val err = allocPointerTo<ObjCObjectVar<NSError?>>() | |
| val player = AVAudioPlayer(url, err.value) | |
| val error = err.value?.pointed?.value | |
| return if (error != null) { | |
| Napier.e { "Error while creating AVAudioPlayer: ${error.code}, ${error.description}" } | |
| null | |
| } else player | |
| } | |
| actual fun play(url: LocalUrl, duration: Duration) { | |
| createPlayer(url.url)?.let { | |
| Napier.d { "Starting: $duration" } | |
| player = it | |
| it.delegate = delegate | |
| it.volume = 10.0f | |
| it.setCurrentTime(duration.toDouble(DurationUnit.SECONDS)) | |
| it.prepareToPlay() | |
| it.play() | |
| } | |
| } | |
| @OptIn(ExperimentalTime::class) | |
| actual fun duration(url: LocalUrl, unit: DurationUnit): Duration { | |
| var duration = Duration.ZERO | |
| createPlayer(url.url)?.let { player -> | |
| duration = Duration.convert( | |
| value = player.duration, | |
| sourceUnit = DurationUnit.SECONDS, | |
| targetUnit = unit | |
| ).toDuration(unit = unit) | |
| } | |
| return duration | |
| } | |
| actual fun stop() { | |
| player?.delegate = null | |
| player?.stop() | |
| player = null | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment