Skip to content

Commit

Permalink
Implemented switch of playback mode
Browse files Browse the repository at this point in the history
aidewoode committed Mar 7, 2024
1 parent e31db54 commit cfca458
Showing 10 changed files with 131 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -37,15 +37,18 @@ fun MiniPlayer(viewModel: MiniPlayerViewModel = koinViewModel()) {
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier =
Modifier
.padding(vertical = dimensionResource(R.dimen.padding_narrow))
.padding(start = dimensionResource(R.dimen.padding_small)),
) {
if (musicState.hasCurrentSong) {
AsyncImage(
model = musicState.currentSong!!.albumImageUrl.small,
contentDescription = stringResource(R.string.album_cover),
modifier =
Modifier
.clip(RoundedCornerShape(dimensionResource(R.dimen.corner_radius_small)))
.padding(vertical = dimensionResource(R.dimen.padding_narrow)),
.clip(RoundedCornerShape(dimensionResource(R.dimen.corner_radius_small))),
)
}

Original file line number Diff line number Diff line change
@@ -3,34 +3,56 @@ package org.blackcandy.android.compose.player
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconToggleButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import org.blackcandy.android.R
import org.blackcandy.android.models.PlaybackMode

@Composable
fun PlayerActions(modifier: Modifier = Modifier) {
fun PlayerActions(
modifier: Modifier = Modifier,
playbackMode: PlaybackMode,
onModeSwitchButtonClicked: () -> Unit,
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier =
modifier
.fillMaxWidth(),
) {
Icon(
painter = painterResource(R.drawable.baseline_repeat_24),
contentDescription = stringResource(R.string.repeat_mode),
)
FilledIconToggleButton(
checked = playbackMode != PlaybackMode.NO_REPEAT,
onCheckedChange = { _ -> onModeSwitchButtonClicked() },
) {
Icon(
painter = painterResource(playbackMode.iconResourceId),
contentDescription = stringResource(playbackMode.titleResourceId),
)
}

Icon(
painter = painterResource(R.drawable.baseline_favorite_border_24),
contentDescription = stringResource(R.string.unfavorited),
)
IconToggleButton(
checked = false,
onCheckedChange = {},
) {
Icon(
painter = painterResource(R.drawable.baseline_favorite_border_24),
contentDescription = stringResource(R.string.unfavorited),
)
}

Icon(
painter = painterResource(R.drawable.baseline_format_list_bulleted_24),
contentDescription = stringResource(R.string.playlist),
)
FilledIconToggleButton(
checked = false,
onCheckedChange = {},
) {
Icon(
painter = painterResource(R.drawable.baseline_format_list_bulleted_24),
contentDescription = stringResource(R.string.playlist),
)
}
}
}
Original file line number Diff line number Diff line change
@@ -53,6 +53,8 @@ fun PlayerScreen(viewModel: PlayerViewModel = koinViewModel()) {
Modifier
.padding(top = dimensionResource(R.dimen.padding_medium))
.padding(horizontal = dimensionResource(R.dimen.padding_small)),
playbackMode = uiState.musicState.playbackMode,
onModeSwitchButtonClicked = { viewModel.nextMode() },
)
}
}
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import org.blackcandy.android.models.MusicState
import org.blackcandy.android.models.PlaybackMode
import org.blackcandy.android.models.Song
import kotlin.time.Duration.Companion.milliseconds

@@ -150,4 +152,38 @@ class MusicServiceController(
fun seekTo(seconds: Double) {
controller?.seekTo((seconds * 1000).toLong())
}

fun setPlaybackMode(playbackMode: PlaybackMode) {
when (playbackMode) {
PlaybackMode.NO_REPEAT -> {
controller?.run {
setRepeatMode(Player.REPEAT_MODE_OFF)
setShuffleModeEnabled(false)
}
}

PlaybackMode.REPEAT -> {
controller?.run {
setRepeatMode(Player.REPEAT_MODE_ALL)
setShuffleModeEnabled(false)
}
}

PlaybackMode.REPEAT_ONE -> {
controller?.run {
setRepeatMode(Player.REPEAT_MODE_ONE)
setShuffleModeEnabled(false)
}
}

PlaybackMode.SHUFFLE -> {
controller?.run {
setRepeatMode(Player.REPEAT_MODE_OFF)
setShuffleModeEnabled(true)
}
}
}

_musicState.update { it.copy(playbackMode = playbackMode) }
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package org.blackcandy.android.media
package org.blackcandy.android.models

import androidx.media3.common.Player
import org.blackcandy.android.models.Song

data class MusicState(
val playlist: List<Song> = emptyList(),
val playbackState: Int = Player.STATE_IDLE,
val currentSong: Song? = null,
val isPlaying: Boolean = false,
val playbackMode: PlaybackMode = PlaybackMode.NO_REPEAT,
) {
val hasCurrentSong: Boolean get() = currentSong != null
}
33 changes: 33 additions & 0 deletions app/src/main/java/org/blackcandy/android/models/PlaybackMode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.blackcandy.android.models

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import org.blackcandy.android.R

enum class PlaybackMode {
NO_REPEAT,
REPEAT,
REPEAT_ONE,
SHUFFLE,
;

@get:DrawableRes
val iconResourceId get() =
when (this) {
NO_REPEAT -> R.drawable.baseline_repeat_24
REPEAT -> R.drawable.baseline_repeat_24
REPEAT_ONE -> R.drawable.baseline_repeat_one_24
SHUFFLE -> R.drawable.baseline_shuffle_24
}

@get:StringRes
val titleResourceId get() =
when (this) {
NO_REPEAT -> R.string.no_repeat_mode
REPEAT -> R.string.repeat_mode
REPEAT_ONE -> R.string.repeat_one_mode
SHUFFLE -> R.string.shuffle_mode
}

val next get() = PlaybackMode.values()[(this.ordinal + 1) % PlaybackMode.values().size]
}
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import org.blackcandy.android.media.MusicServiceController
import org.blackcandy.android.media.MusicState
import org.blackcandy.android.models.MusicState

data class PlayerUiState(
val musicState: MusicState = MusicState(),
@@ -54,4 +54,8 @@ class PlayerViewModel(
fun seekTo(seconds: Double) {
musicServiceController.seekTo(seconds)
}

fun nextMode() {
musicServiceController.setPlaybackMode(uiState.value.musicState.playbackMode.next)
}
}
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/baseline_repeat_one_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M7,7h10v3l4,-4 -4,-4v3L5,5v6h2L7,7zM17,17L7,17v-3l-4,4 4,4v-3h12v-6h-2v4zM13,15L13,9h-1l-2,1v1h1.5v4L13,15z"/>

</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/baseline_shuffle_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z"/>

</vector>
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -25,7 +25,10 @@
<string name="next">Next Track</string>
<string name="previous">Previous Track</string>
<string name="album_cover">Album Cover</string>
<string name="no_repeat_mode">No Repeat Mode</string>
<string name="repeat_mode">Repeat Mode</string>
<string name="repeat_one_mode">Repeat One Mode</string>
<string name="shuffle_mode">Shuffle Mode</string>
<string name="favorited">Favorited</string>
<string name="unfavorited">Unfavorited</string>
<string name="playlist">Playlist</string>

0 comments on commit cfca458

Please sign in to comment.