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 android.content.Context
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer 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.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
class AndroidAudioPlayer( internal class AndroidAudioPlayer(
context: Context, context: Context,
) : AudioPlayer { ) : AudioPlayer {
private val player = ExoPlayer.Builder(context).build() 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 package fr.ajaury.gwenedeg.player.di
import fr.ajaury.gwenedeg.player.AndroidAudioPlayer import fr.ajaury.gwenedeg.player.data.AndroidAudioPlayer
import fr.ajaury.gwenedeg.player.AndroidAudioSessionManager import fr.ajaury.gwenedeg.player.data.AndroidAudioSessionManager
import fr.ajaury.gwenedeg.player.AudioPlayer import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.dsl.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 kotlinx.coroutines.flow.StateFlow
import kotlin.time.Duration 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 * 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 { enum class PlaybackState {
IDLE, 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.cinterop.ExperimentalForeignApi
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@@ -24,7 +26,7 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
class IosAudioPlayer : AudioPlayer { internal class IosAudioPlayer : AudioPlayer {
private var player: AVPlayer? = null private var player: AVPlayer? = null
private var endObserver: NSObjectProtocol? = 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 kotlinx.cinterop.ExperimentalForeignApi
import platform.AVFAudio.AVAudioSession import platform.AVFAudio.AVAudioSession
import platform.AVFAudio.AVAudioSessionCategoryOptionDuckOthers import platform.AVFAudio.AVAudioSessionCategoryOptionDuckOthers
@@ -7,7 +8,7 @@ import platform.AVFAudio.AVAudioSessionCategoryPlayback
import platform.AVFAudio.AVAudioSessionModeSpokenAudio import platform.AVFAudio.AVAudioSessionModeSpokenAudio
import platform.AVFAudio.setActive import platform.AVFAudio.setActive
class IosAudioSessionManager : AudioSessionManager { internal class IosAudioSessionManager : AudioSessionManager {
private val session = AVAudioSession.sharedInstance() private val session = AVAudioSession.sharedInstance()
@OptIn(ExperimentalForeignApi::class) @OptIn(ExperimentalForeignApi::class)
@@ -1,9 +1,9 @@
package fr.ajaury.gwenedeg.player.di package fr.ajaury.gwenedeg.player.di
import fr.ajaury.gwenedeg.player.AudioPlayer import fr.ajaury.gwenedeg.player.data.IosAudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager import fr.ajaury.gwenedeg.player.data.IosAudioSessionManager
import fr.ajaury.gwenedeg.player.IosAudioPlayer import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.IosAudioSessionManager import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.dsl.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.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow 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 * the JDK [AudioSystem] discovers automatically, so loading works the same as any natively
* supported format. * supported format.
*/ */
class JvmAudioPlayer : AudioPlayer { internal class JvmAudioPlayer : AudioPlayer {
private var clip: Clip? = null private var clip: Clip? = null
private var stoppedByUser = false 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. * 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() { override fun activate() {
} }
@@ -1,9 +1,9 @@
package fr.ajaury.gwenedeg.player.di package fr.ajaury.gwenedeg.player.di
import fr.ajaury.gwenedeg.player.AudioPlayer import fr.ajaury.gwenedeg.player.data.JvmAudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager import fr.ajaury.gwenedeg.player.data.JvmAudioSessionManager
import fr.ajaury.gwenedeg.player.JvmAudioPlayer import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.JvmAudioSessionManager import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.dsl.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.browser.document
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@@ -8,7 +10,7 @@ import org.w3c.dom.HTMLAudioElement
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
class WebAudioPlayer : AudioPlayer { internal class WebAudioPlayer : AudioPlayer {
private var audio: HTMLAudioElement? = null private var audio: HTMLAudioElement? = null
private val _playbackState = MutableStateFlow(PlaybackState.IDLE) 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 package fr.ajaury.gwenedeg.player.di
import fr.ajaury.gwenedeg.player.AudioPlayer import fr.ajaury.gwenedeg.player.data.WebAudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager import fr.ajaury.gwenedeg.player.data.WebAudioSessionManager
import fr.ajaury.gwenedeg.player.WebAudioPlayer import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.WebAudioSessionManager import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.dsl.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.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle 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.PlayerUiState
import fr.ajaury.gwenedeg.player.ui.viewmodel.PlayerViewModel import fr.ajaury.gwenedeg.player.ui.viewmodel.PlayerViewModel
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleLine import fr.ajaury.gwenedeg.subtitle.domain.SubtitleLine
@@ -1,6 +1,6 @@
package fr.ajaury.gwenedeg.player.ui.viewmodel 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 import fr.ajaury.gwenedeg.subtitle.domain.SubtitleLine
data class PlayerUiState( data class PlayerUiState(
@@ -3,9 +3,9 @@ package fr.ajaury.gwenedeg.player.ui.viewmodel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import fr.ajaury.gwenedeg.core.logging.Logger import fr.ajaury.gwenedeg.core.logging.Logger
import fr.ajaury.gwenedeg.player.AudioPlayer import fr.ajaury.gwenedeg.player.domain.AudioPlayer
import fr.ajaury.gwenedeg.player.AudioSessionManager import fr.ajaury.gwenedeg.player.domain.AudioSessionManager
import fr.ajaury.gwenedeg.player.PlaybackState import fr.ajaury.gwenedeg.player.model.PlaybackState
import fr.ajaury.gwenedeg.subtitle.domain.GetCurrentSubtitleIndexUseCase import fr.ajaury.gwenedeg.subtitle.domain.GetCurrentSubtitleIndexUseCase
import fr.ajaury.gwenedeg.subtitle.domain.Subtitle import fr.ajaury.gwenedeg.subtitle.domain.Subtitle
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleRepository import fr.ajaury.gwenedeg.subtitle.domain.SubtitleRepository