refactor: restructure player package, separate data, domain, and model modules

This commit is contained in:
2026-06-19 17:40:08 +02:00
parent 77a8ee645f
commit 2938fc7fa8
20 changed files with 70 additions and 54 deletions
@@ -1,9 +0,0 @@
package fr.ajaury.gwenedeg.player
class AndroidAudioSessionManager : AudioSessionManager {
override fun activate() {
}
override fun deactivate() {
}
}
@@ -1,17 +1,19 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.data
import android.content.Context
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.model.PlaybackState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
class AndroidAudioPlayer(
internal class AndroidAudioPlayer(
context: Context,
) : AudioPlayer {
private val player = ExoPlayer.Builder(context).build()
@@ -0,0 +1,11 @@
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
internal class AndroidAudioSessionManager : AudioSessionManager {
override fun activate() {
}
override fun deactivate() {
}
}
@@ -1,9 +1,9 @@
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 fr.ajaury.gwenedeg.player.data.AndroidAudioPlayer
import fr.ajaury.gwenedeg.player.data.AndroidAudioSessionManager
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module
import org.koin.dsl.module
@@ -1,5 +1,6 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.domain
import fr.ajaury.gwenedeg.player.model.PlaybackState
import kotlinx.coroutines.flow.StateFlow
import kotlin.time.Duration
@@ -1,4 +1,4 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.domain
/**
* An Audio Session will allow to request Audio focus and declare our audio source to the system
@@ -1,4 +1,4 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.model
enum class PlaybackState {
IDLE,
@@ -1,5 +1,7 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.model.PlaybackState
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -24,7 +26,7 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
class IosAudioPlayer : AudioPlayer {
internal class IosAudioPlayer : AudioPlayer {
private var player: AVPlayer? = null
private var endObserver: NSObjectProtocol? = null
@@ -1,5 +1,6 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import kotlinx.cinterop.ExperimentalForeignApi
import platform.AVFAudio.AVAudioSession
import platform.AVFAudio.AVAudioSessionCategoryOptionDuckOthers
@@ -7,7 +8,7 @@ import platform.AVFAudio.AVAudioSessionCategoryPlayback
import platform.AVFAudio.AVAudioSessionModeSpokenAudio
import platform.AVFAudio.setActive
class IosAudioSessionManager : AudioSessionManager {
internal class IosAudioSessionManager : AudioSessionManager {
private val session = AVAudioSession.sharedInstance()
@OptIn(ExperimentalForeignApi::class)
@@ -1,9 +1,9 @@
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 fr.ajaury.gwenedeg.player.data.IosAudioPlayer
import fr.ajaury.gwenedeg.player.data.IosAudioSessionManager
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module
import org.koin.dsl.module
@@ -1,5 +1,7 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.model.PlaybackState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -19,7 +21,7 @@ import kotlin.time.Duration.Companion.microseconds
* the JDK [AudioSystem] discovers automatically, so loading works the same as any natively
* supported format.
*/
class JvmAudioPlayer : AudioPlayer {
internal class JvmAudioPlayer : AudioPlayer {
private var clip: Clip? = null
private var stoppedByUser = false
@@ -1,9 +1,11 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
/**
* Desktop has no system audio focus model to honour, so activation is a no-op.
*/
class JvmAudioSessionManager : AudioSessionManager {
internal class JvmAudioSessionManager : AudioSessionManager {
override fun activate() {
}
@@ -1,9 +1,9 @@
package fr.ajaury.gwenedeg.player.di
import fr.ajaury.gwenedeg.player.AudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager
import fr.ajaury.gwenedeg.player.JvmAudioPlayer
import fr.ajaury.gwenedeg.player.JvmAudioSessionManager
import fr.ajaury.gwenedeg.player.data.JvmAudioPlayer
import fr.ajaury.gwenedeg.player.data.JvmAudioSessionManager
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module
import org.koin.dsl.module
@@ -1,9 +0,0 @@
package fr.ajaury.gwenedeg.player
class WebAudioSessionManager : AudioSessionManager {
override fun activate() {
}
override fun deactivate() {
}
}
@@ -1,5 +1,7 @@
package fr.ajaury.gwenedeg.player
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.model.PlaybackState
import kotlinx.browser.document
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -8,7 +10,7 @@ import org.w3c.dom.HTMLAudioElement
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
class WebAudioPlayer : AudioPlayer {
internal class WebAudioPlayer : AudioPlayer {
private var audio: HTMLAudioElement? = null
private val _playbackState = MutableStateFlow(PlaybackState.IDLE)
@@ -0,0 +1,11 @@
package fr.ajaury.gwenedeg.player.data
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
internal class WebAudioSessionManager : AudioSessionManager {
override fun activate() {
}
override fun deactivate() {
}
}
@@ -1,9 +1,9 @@
package fr.ajaury.gwenedeg.player.di
import fr.ajaury.gwenedeg.player.AudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager
import fr.ajaury.gwenedeg.player.WebAudioPlayer
import fr.ajaury.gwenedeg.player.WebAudioSessionManager
import fr.ajaury.gwenedeg.player.data.WebAudioPlayer
import fr.ajaury.gwenedeg.player.data.WebAudioSessionManager
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module
import org.koin.dsl.module
@@ -45,7 +45,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import fr.ajaury.gwenedeg.player.PlaybackState
import fr.ajaury.gwenedeg.player.model.PlaybackState
import fr.ajaury.gwenedeg.player.ui.viewmodel.PlayerUiState
import fr.ajaury.gwenedeg.player.ui.viewmodel.PlayerViewModel
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleLine
@@ -1,6 +1,6 @@
package fr.ajaury.gwenedeg.player.ui.viewmodel
import fr.ajaury.gwenedeg.player.PlaybackState
import fr.ajaury.gwenedeg.player.model.PlaybackState
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleLine
data class PlayerUiState(
@@ -3,9 +3,9 @@ package fr.ajaury.gwenedeg.player.ui.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import fr.ajaury.gwenedeg.core.logging.Logger
import fr.ajaury.gwenedeg.player.AudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager
import fr.ajaury.gwenedeg.player.PlaybackState
import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import fr.ajaury.gwenedeg.player.model.PlaybackState
import fr.ajaury.gwenedeg.subtitle.domain.GetCurrentSubtitleIndexUseCase
import fr.ajaury.gwenedeg.subtitle.domain.Subtitle
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleRepository