Skip to content

Commit

Permalink
[feature|build] Support add external audio track (#44); update depend…
Browse files Browse the repository at this point in the history
…encies
  • Loading branch information
SkyD666 committed May 31, 2024
1 parent dc7955b commit ff6d4bb
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 32 deletions.
8 changes: 4 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ android {
minSdk = 24
targetSdk = 34
versionCode = 16
versionName = "1.1-beta39"
versionName = "1.1-beta40"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -152,17 +152,17 @@ tasks.withType(KotlinCompile::class.java).configureEach {
dependencies {

implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.0")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.1")
implementation("androidx.compose.ui:ui:1.7.0-beta01")
implementation("androidx.compose.material:material:1.7.0-beta01")
implementation("androidx.compose.material3:material3:1.3.0-beta01")
implementation("androidx.compose.material3:material3-window-size-class:1.2.1")
implementation("androidx.compose.material3:material3-window-size-class:1.3.0-beta01")
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-beta01")
implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-beta01")
implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-beta01")
Expand Down
14 changes: 11 additions & 3 deletions app/src/main/java/com/skyd/anivu/ui/mpv/MPVView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,11 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att
}
}

fun loadSubtitleTrack() {
tracks["sub"]!!.apply {
fun loadSubtitleTrack() = loadTrack("sub")
fun loadAudioTrack() = loadTrack("audio")

private fun loadTrack(trackType: String) {
tracks[trackType]!!.apply {
clear()
add(Track(-1, context.getString(R.string.track_off)))
}
Expand All @@ -266,7 +269,7 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att
// so use ?: continue instead of !!
for (i in 0 until count) {
val type = MPVLib.getPropertyString("track-list/$i/type") ?: continue
if (type == "sub") {
if (type == trackType) {
val mpvId = MPVLib.getPropertyInt("track-list/$i/id") ?: continue
val lang = MPVLib.getPropertyString("track-list/$i/lang")
val title = MPVLib.getPropertyString("track-list/$i/title")
Expand Down Expand Up @@ -538,6 +541,11 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att
loadSubtitleTrack()
}

fun addAudio(filePath: String) {
MPVLib.command(arrayOf("audio-add", filePath, "cached"))
loadAudioTrack()
}

companion object {
private const val TAG = "mpv"
}
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/skyd/anivu/ui/mpv/PlayerCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ sealed interface PlayerCommand {
data class SetAudioTrack(val trackId: Int) : PlayerCommand
data object Screenshot : PlayerCommand
data class AddSubtitle(val filePath: String) : PlayerCommand
data class AddAudio(val filePath: String) : PlayerCommand
data object GetBuffer : PlayerCommand
}
34 changes: 17 additions & 17 deletions app/src/main/java/com/skyd/anivu/ui/mpv/PlayerUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ internal fun Uri.resolveUri(context: Context): String? {
return filepath
}

private fun Uri.openContentFd(context: Context): String? =
context.contentResolver.openFileDescriptor(this, "r")!!.use { fileDescriptor ->
val fd = try {
fileDescriptor.detachFd()
} catch (e: Exception) {
Log.e("openContentFd", "Failed to open content fd: $e")
return@use null
}
// See if we skip the indirection and read the real file directly
val path = findRealPath(fd)
if (path != null) {
Log.v("openContentFd", "Found real file path: $path")
ParcelFileDescriptor.adoptFd(fd).close() // we don't need that anymore
return@use path
}
// Else, pass the fd to mpv
return@use "fd://${fd}"
private fun Uri.openContentFd(context: Context): String? {
val resolver = context.contentResolver
val fd = try {
resolver.openFileDescriptor(this, "r")!!.detachFd()
} catch (e: Exception) {
Log.e("openContentFd", "Failed to open content fd: $e")
return null
}
// See if we skip the indirection and read the real file directly
val path = findRealPath(fd)
if (path != null) {
Log.v("openContentFd", "Found real file path: $path")
ParcelFileDescriptor.adoptFd(fd).close() // we don't need that anymore
return path
}
// Else, pass the fd to mpv
return "fd://${fd}"
}

fun findRealPath(fd: Int): String? {
var ins: InputStream? = null
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/java/com/skyd/anivu/ui/mpv/PlayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ private fun MPVView.solveCommand(
onSubtitleTrack(subtitleTrack)
}

is PlayerCommand.AddAudio -> {
addAudio(command.filePath)
onAudioTrack(audioTrack)
}

PlayerCommand.GetBuffer -> onCacheBufferStateChanged(demuxerCacheDuration.toFloat())
}
}
Expand Down Expand Up @@ -183,10 +188,11 @@ fun PlayerView(
),
audioTrackDialogCallback = AudioTrackDialogCallback(
onAudioTrackChanged = { commandQueue.trySend(PlayerCommand.SetAudioTrack(it.trackId)) },
onAddAudioTrack = { commandQueue.trySend(PlayerCommand.AddAudio(it)) },
),
subtitleTrackDialogCallback = SubtitleTrackDialogCallback(
onAddSubtitle = { commandQueue.trySend(PlayerCommand.AddSubtitle(it)) },
onSubtitleTrackChanged = { commandQueue.trySend(PlayerCommand.SetSubtitleTrack(it.trackId)) },
onAddSubtitle = { commandQueue.trySend(PlayerCommand.AddSubtitle(it)) },
)
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package com.skyd.anivu.ui.mpv.controller.dialog

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.Check
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.skyd.anivu.R
import com.skyd.anivu.ui.component.AniVuIconButton
import com.skyd.anivu.ui.mpv.controller.state.dialog.track.AudioTrackDialogCallback
import com.skyd.anivu.ui.mpv.controller.state.dialog.track.AudioTrackDialogState
import com.skyd.anivu.ui.mpv.resolveUri


@Composable
Expand All @@ -25,6 +33,14 @@ internal fun AudioTrackDialog(
audioTrackDialogCallback: AudioTrackDialogCallback,
) {
val state = audioTrackDialogState()
val context = LocalContext.current
val pickAudioFileLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.GetContent()
) { subtitleUri ->
subtitleUri?.resolveUri(context)?.let { filePath ->
audioTrackDialogCallback.onAddAudioTrack(filePath)
}
}

if (state.show) {
BasicPlayerDialog(onDismissRequest = onDismissRequest) {
Expand All @@ -33,13 +49,20 @@ internal fun AudioTrackDialog(
.padding(PaddingValues(16.dp))
.verticalScroll(rememberScrollState())
) {
Text(
modifier = Modifier
.padding(horizontal = 16.dp)
.padding(bottom = 6.dp),
text = stringResource(id = R.string.player_audio_track),
style = MaterialTheme.typography.headlineSmall,
)
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
modifier = Modifier
.weight(1f)
.padding(start = 16.dp, bottom = 6.dp),
text = stringResource(id = R.string.player_audio_track),
style = MaterialTheme.typography.headlineSmall,
)
AniVuIconButton(
onClick = { pickAudioFileLauncher.launch("*/*") },
imageVector = Icons.Rounded.Add,
contentDescription = stringResource(id = R.string.player_add_external_audio),
)
}
repeat(state.audioTrack.size) { index ->
val track = state.audioTrack[index]
TrackDialogListItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ data class AudioTrackDialogState(
@Immutable
data class AudioTrackDialogCallback(
val onAudioTrackChanged: (MPVView.Track) -> Unit,
val onAddAudioTrack: (String) -> Unit,
)
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
<string name="data_fragment_sync_category">Sync</string>
<string name="import_export_screen_description">Import and Export RSS data via OPML files</string>
<string name="player_speed">Speed</string>
<string name="player_add_external_audio">Add audio file</string>
<plurals name="import_opml_result">
<item quantity="one">Imported %d item, takes %.2f seconds</item>
<item quantity="other">Imported %d items, takes %.2f seconds</item>
Expand Down

0 comments on commit ff6d4bb

Please sign in to comment.