mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-12-22 12:47:54 +01:00
Desktop FFmpeg Handling
This commit is contained in:
parent
3a93cd5f91
commit
3f4008e2be
@ -12,7 +12,7 @@ actual fun Dialog(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
AnimatedVisibility(isVisible) {
|
||||
androidx.compose.ui.window.v1.Dialog(onDismiss) {
|
||||
androidx.compose.ui.window.Dialog(onDismiss) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package com.shabinder.common.core_components.file_manager
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import co.touchlab.kermit.Kermit
|
||||
import com.github.kokorin.jaffree.JaffreeException
|
||||
import com.mpatric.mp3agic.InvalidDataException
|
||||
import com.mpatric.mp3agic.Mp3File
|
||||
import com.shabinder.common.core_components.media_converter.MediaConverter
|
||||
@ -35,6 +36,7 @@ import com.shabinder.common.models.dispatcherIO
|
||||
import com.shabinder.common.models.event.coroutines.SuspendableEvent
|
||||
import com.shabinder.common.models.event.coroutines.failure
|
||||
import com.shabinder.common.models.event.coroutines.map
|
||||
import com.shabinder.common.models.methods
|
||||
import com.shabinder.database.Database
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
@ -152,13 +154,18 @@ class DesktopFileManager(
|
||||
.setId3v2TagsAndSaveFile(trackDetails, trackDetails.outputFilePath)
|
||||
|
||||
addToLibrary(trackDetails.outputFilePath)
|
||||
}.failure {
|
||||
throw it
|
||||
}
|
||||
}.fold(
|
||||
success = {},
|
||||
failure = {
|
||||
throw it
|
||||
}
|
||||
)
|
||||
File(convertedFilePath).delete()
|
||||
} else throw e
|
||||
}
|
||||
SuspendableEvent.success(trackDetails.outputFilePath)
|
||||
} catch (e: Throwable) {
|
||||
if(e is JaffreeException) methods.value.showPopUpMessage("No FFmpeg found at path.")
|
||||
if (songFile.exists()) songFile.delete()
|
||||
logger.e { "${songFile.absolutePath} could not be created" }
|
||||
SuspendableEvent.error(e)
|
||||
|
@ -6,6 +6,7 @@ import com.github.kokorin.jaffree.ffmpeg.UrlOutput
|
||||
import com.shabinder.common.models.AudioQuality
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
import kotlin.io.path.Path
|
||||
|
||||
class DesktopMediaConverter : MediaConverter() {
|
||||
|
||||
@ -15,11 +16,14 @@ class DesktopMediaConverter : MediaConverter() {
|
||||
audioQuality: AudioQuality,
|
||||
progressCallbacks: (Long) -> Unit,
|
||||
) = executeSafelyInPool {
|
||||
val audioBitrate =
|
||||
if (audioQuality == AudioQuality.UNKNOWN) 192 else audioQuality.kbps.toIntOrNull()
|
||||
?: 192
|
||||
FFmpeg.atPath().run {
|
||||
addInput(UrlInput.fromUrl(inputFilePath))
|
||||
setOverwriteOutput(true)
|
||||
if (audioQuality != AudioQuality.UNKNOWN) {
|
||||
addArguments("-b:a", "${audioQuality.kbps}k")
|
||||
addArguments("-b:a", "${audioBitrate}k")
|
||||
}
|
||||
addArguments("-acodec", "libmp3lame")
|
||||
addArgument("-vn")
|
||||
|
@ -61,11 +61,26 @@ actual suspend fun downloadTracks(
|
||||
)
|
||||
}
|
||||
is DownloadResult.Success -> { // Todo clear map
|
||||
fileManager.saveFileWithMetadata(it.byteArray, trackDetails) {}
|
||||
DownloadProgressFlow.emit(
|
||||
DownloadProgressFlow.replayCache.getOrElse(
|
||||
0
|
||||
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloaded) }
|
||||
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Converting) }
|
||||
)
|
||||
fileManager.saveFileWithMetadata(it.byteArray, trackDetails).fold(
|
||||
failure = {
|
||||
DownloadProgressFlow.emit(
|
||||
DownloadProgressFlow.replayCache.getOrElse(
|
||||
0
|
||||
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Failed(it)) }
|
||||
)
|
||||
},
|
||||
success = {
|
||||
DownloadProgressFlow.emit(
|
||||
DownloadProgressFlow.replayCache.getOrElse(
|
||||
0
|
||||
) { hashMapOf() }.apply { set(trackDetails.title, DownloadStatus.Downloaded) }
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ kotlin {
|
||||
implementation(project(":common:compose"))
|
||||
implementation(project(":common:providers"))
|
||||
implementation(project(":common:root"))
|
||||
implementation("com.github.kokorin.jaffree:jaffree:2021.08.16")
|
||||
|
||||
// Decompose
|
||||
implementation(Decompose.decompose)
|
||||
|
@ -20,6 +20,7 @@ import androidx.compose.material.Surface
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.awt.ComposeWindow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
@ -30,6 +31,8 @@ import com.arkivanov.decompose.ExperimentalDecomposeApi
|
||||
import com.arkivanov.decompose.extensions.compose.jetbrains.lifecycle.LifecycleController
|
||||
import com.arkivanov.essenty.lifecycle.LifecycleRegistry
|
||||
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
|
||||
import com.github.kokorin.jaffree.JaffreeException
|
||||
import com.github.kokorin.jaffree.ffmpeg.FFmpeg
|
||||
import com.shabinder.common.di.*
|
||||
import com.shabinder.common.core_components.analytics.AnalyticsManager
|
||||
import com.shabinder.common.core_components.file_manager.DownloadProgressFlow
|
||||
@ -39,6 +42,7 @@ import com.shabinder.common.core_components.utils.isInternetAccessible
|
||||
import com.shabinder.common.models.Actions
|
||||
import com.shabinder.common.models.PlatformActions
|
||||
import com.shabinder.common.models.TrackDetails
|
||||
import com.shabinder.common.models.methods
|
||||
import com.shabinder.common.providers.FetchPlatformQueryResult
|
||||
import com.shabinder.common.root.SpotiFlyerRoot
|
||||
import com.shabinder.common.translations.Strings
|
||||
@ -89,10 +93,19 @@ fun main() {
|
||||
) {
|
||||
val root: SpotiFlyerRoot = SpotiFlyerRootContent(rootComponent)
|
||||
showToast = root.callBacks::showToast
|
||||
|
||||
|
||||
// FFmpeg WARNING
|
||||
try {
|
||||
FFmpeg.atPath().addArgument("-version").execute();
|
||||
} catch (e: Exception) {
|
||||
if (e is JaffreeException) methods.value.showPopUpMessage("WARNING!\nFFmpeg not found at path")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Download Tracking for Desktop Apps for Now will be measured using `GitHub Releases`
|
||||
// https://tooomm.github.io/github-release-stats/?username=Shabinder&repository=SpotiFlyer
|
||||
}
|
||||
@ -108,6 +121,8 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
|
||||
override val analyticsManager: AnalyticsManager = koin.get()
|
||||
override val preferenceManager: PreferenceManager = koin.get<PreferenceManager>().also {
|
||||
it.analyticsManager = analyticsManager
|
||||
// Allow Analytics for Desktop
|
||||
analyticsManager.giveConsent()
|
||||
}
|
||||
override val downloadProgressFlow = DownloadProgressFlow
|
||||
override val actions: Actions = object : Actions {
|
||||
|
Loading…
Reference in New Issue
Block a user