refactor: extract audio player logic into a dedicated multiplatform module
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidMultiplatformLibrary)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
iosArm64()
|
||||
iosSimulatorArm64()
|
||||
|
||||
jvm()
|
||||
|
||||
js {
|
||||
browser()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
androidLibrary {
|
||||
namespace = "fr.ajaury.gwenedeg.core.audioplayer"
|
||||
compileSdk =
|
||||
libs.versions.androidCompileSdk
|
||||
.get()
|
||||
.toInt()
|
||||
minSdk =
|
||||
libs.versions.androidMinSdk
|
||||
.get()
|
||||
.toInt()
|
||||
|
||||
compilerOptions {
|
||||
jvmTarget = JvmTarget.JVM_11
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
androidMain.dependencies {
|
||||
// Player audio
|
||||
implementation(libs.media3.exoplayer)
|
||||
implementation(libs.media3.common)
|
||||
}
|
||||
commonMain.dependencies {
|
||||
// DI
|
||||
implementation(project.dependencies.platform(libs.koin.bom))
|
||||
implementation(libs.koin.core)
|
||||
}
|
||||
commonTest.dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
import android.content.Context
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
|
||||
class AndroidAudioPlayer(
|
||||
context: Context,
|
||||
) : AudioPlayer {
|
||||
private val player = ExoPlayer.Builder(context).build()
|
||||
|
||||
override fun load(uri: String) {
|
||||
val mediaItem = MediaItem.fromUri(uri)
|
||||
player.setMediaItem(mediaItem)
|
||||
player.prepare()
|
||||
}
|
||||
|
||||
override fun play() {
|
||||
player.play()
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
player.pause()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
player.stop()
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
player.release()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
class AndroidAudioSessionManager : AudioSessionManager {
|
||||
override fun activate() {
|
||||
}
|
||||
|
||||
override fun deactivate() {
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package fr.ajaury.gwenedeg.player.di
|
||||
|
||||
import fr.ajaury.gwenedeg.player.AndroidAudioPlayer
|
||||
import fr.ajaury.gwenedeg.player.AndroidAudioSessionManager
|
||||
import fr.ajaury.gwenedeg.player.AudioPlayer
|
||||
import fr.ajaury.gwenedeg.player.AudioSessionManager
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.module
|
||||
|
||||
actual val audioPlayerModule: Module = module {
|
||||
single<AudioPlayer> { AndroidAudioPlayer(context = get()) }
|
||||
single<AudioSessionManager> { AndroidAudioSessionManager() }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
interface AudioPlayer {
|
||||
fun play()
|
||||
|
||||
fun pause()
|
||||
|
||||
fun stop()
|
||||
|
||||
fun release()
|
||||
|
||||
fun load(uri: String)
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
/**
|
||||
* An Audio Session will allow to request Audio focus and declare our audio source to the system
|
||||
*/
|
||||
interface AudioSessionManager {
|
||||
fun activate()
|
||||
|
||||
fun deactivate()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package fr.ajaury.gwenedeg.player.di
|
||||
|
||||
import org.koin.core.module.Module
|
||||
|
||||
expect val audioPlayerModule: Module
|
||||
@@ -0,0 +1,37 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import platform.AVFoundation.AVPlayer
|
||||
import platform.AVFoundation.pause
|
||||
import platform.AVFoundation.play
|
||||
import platform.AVFoundation.replaceCurrentItemWithPlayerItem
|
||||
import platform.Foundation.NSURL
|
||||
|
||||
class IosAudioPlayer : AudioPlayer {
|
||||
private var player: AVPlayer? = null
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
override fun load(uri: String) {
|
||||
val nsUrl = NSURL.URLWithString(uri) ?: error("Invalid audio URI: $uri")
|
||||
|
||||
player = AVPlayer(nsUrl)
|
||||
}
|
||||
|
||||
override fun play() {
|
||||
player?.play()
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
player?.pause()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
player?.pause()
|
||||
player?.replaceCurrentItemWithPlayerItem(null)
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
player?.pause()
|
||||
player = null
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import platform.AVFAudio.AVAudioSession
|
||||
import platform.AVFAudio.AVAudioSessionCategoryOptionDuckOthers
|
||||
import platform.AVFAudio.AVAudioSessionCategoryPlayback
|
||||
import platform.AVFAudio.AVAudioSessionModeSpokenAudio
|
||||
import platform.AVFAudio.setActive
|
||||
|
||||
class IosAudioSessionManager : AudioSessionManager {
|
||||
private val session = AVAudioSession.sharedInstance()
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
override fun activate() {
|
||||
session.setCategory(
|
||||
category = AVAudioSessionCategoryPlayback,
|
||||
mode = AVAudioSessionModeSpokenAudio,
|
||||
options = AVAudioSessionCategoryOptionDuckOthers,
|
||||
error = null,
|
||||
)
|
||||
|
||||
session.setActive(
|
||||
active = true,
|
||||
error = null,
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
override fun deactivate() {
|
||||
session.setActive(
|
||||
false,
|
||||
error = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package fr.ajaury.gwenedeg.player.di
|
||||
|
||||
import fr.ajaury.gwenedeg.player.AudioPlayer
|
||||
import fr.ajaury.gwenedeg.player.AudioSessionManager
|
||||
import fr.ajaury.gwenedeg.player.IosAudioPlayer
|
||||
import fr.ajaury.gwenedeg.player.IosAudioSessionManager
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.module
|
||||
|
||||
actual val audioPlayerModule: Module = module {
|
||||
single<AudioPlayer> { IosAudioPlayer() }
|
||||
single<AudioSessionManager> { IosAudioSessionManager() }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
class JsAudioPlayer : AudioPlayer {
|
||||
override fun play() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun load(uri: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package fr.ajaury.gwenedeg.player.di
|
||||
|
||||
import org.koin.core.module.Module
|
||||
|
||||
actual val audioPlayerModule: Module
|
||||
get() = TODO("Not yet implemented")
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
class JvmAudioPlayer : AudioPlayer {
|
||||
override fun play() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun load(uri: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package fr.ajaury.gwenedeg.player.di
|
||||
|
||||
import org.koin.core.module.Module
|
||||
|
||||
actual val audioPlayerModule: Module
|
||||
get() = TODO("Not yet implemented")
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
class WasmAudioPlayer : AudioPlayer {
|
||||
override fun play() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun load(uri: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package fr.ajaury.gwenedeg.player.di
|
||||
|
||||
import org.koin.core.module.Module
|
||||
|
||||
actual val audioPlayerModule: Module
|
||||
get() = TODO("Not yet implemented")
|
||||
Reference in New Issue
Block a user