Skip to content

Commit

Permalink
Merge branch 'fast4x:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
KyNarec authored Oct 9, 2024
2 parents c504e14 + 3e7f606 commit cb191db
Show file tree
Hide file tree
Showing 135 changed files with 2,817 additions and 1,799 deletions.
3 changes: 2 additions & 1 deletion composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ kotlin {
configurations.commonMainApi {
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-android")
}
*/
*/



}
Expand Down
Binary file modified composeApp/src/androidMain/ic_launcher-playstore.webp
Binary file not shown.
Binary file modified composeApp/src/androidMain/ic_logo-playstore.webp
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package it.fast4x.rimusic.enums

import androidx.navigation.NavController

enum class NavRoutes {
home,
album,
Expand All @@ -21,5 +23,14 @@ enum class NavRoutes {
statistics,
newAlbums,
moodsPage,
podcast
podcast;

companion object {

fun current( navController: NavController ) = navController.currentBackStackEntry?.destination?.route
}

fun isHere( navController: NavController ) = current( navController ) == this.name

fun isNotHere( navController: NavController ) = !isHere( navController )
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.media3.datasource.okhttp.OkHttpDataSource
import androidx.media3.exoplayer.offline.Download
import androidx.media3.exoplayer.offline.DownloadManager
import androidx.media3.exoplayer.offline.DownloadNotificationHelper
import androidx.media3.exoplayer.scheduler.Requirements
import it.fast4x.innertube.Innertube
import it.fast4x.innertube.models.bodies.PlayerBody
import it.fast4x.innertube.requests.player
Expand Down Expand Up @@ -144,9 +145,10 @@ object DownloadUtil {
?.maxByOrNull {
(it.bitrate?.times(
when (audioQualityFormat) {
AudioQualityFormat.Auto -> if (connectivityManager.isActiveNetworkMetered) -1 else 1
AudioQualityFormat.Auto -> if (connectivityManager.isActiveNetworkMetered) -2 else 1
AudioQualityFormat.High -> 1
AudioQualityFormat.Low, AudioQualityFormat.Medium -> -1
AudioQualityFormat.Medium -> -1
AudioQualityFormat.Low -> -2
}
) ?: -1) + (if (it.mimeType.startsWith("audio/webm")) 10240 else 0)
}
Expand Down Expand Up @@ -343,7 +345,9 @@ object DownloadUtil {
getResolvingDataSourceFactory(context),
Executors.newFixedThreadPool(6)
).apply {
maxParallelDownloads = 2
maxParallelDownloads = 3
minRetryCount = 1
requirements = Requirements(Requirements.NETWORK)
}

//downloadTracker =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ import androidx.media3.common.audio.SonicAudioProcessor
import androidx.media3.common.util.Log
import androidx.media3.common.util.UnstableApi
import androidx.media3.database.StandaloneDatabaseProvider
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DataSpec
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.HttpDataSource.InvalidResponseCodeException
import androidx.media3.datasource.ResolvingDataSource
import androidx.media3.datasource.cache.Cache
import androidx.media3.datasource.cache.CacheDataSource
Expand All @@ -81,6 +83,7 @@ import androidx.media3.exoplayer.audio.SilenceSkippingAudioProcessor
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector
import androidx.media3.exoplayer.offline.Download
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.upstream.DefaultLoadErrorHandlingPolicy
import androidx.media3.extractor.DefaultExtractorsFactory
import androidx.media3.extractor.ExtractorsFactory
import androidx.media3.extractor.mkv.MatroskaExtractor
Expand Down Expand Up @@ -126,6 +129,7 @@ import it.fast4x.rimusic.utils.asSong
import it.fast4x.rimusic.utils.broadCastPendingIntent
import it.fast4x.rimusic.cleanPrefix
import it.fast4x.rimusic.enums.AudioQualityFormat
import it.fast4x.rimusic.enums.PopupType
import it.fast4x.rimusic.utils.audioQualityFormatKey
import it.fast4x.rimusic.utils.closebackgroundPlayerKey
import it.fast4x.rimusic.utils.discordPersonalAccessTokenKey
Expand All @@ -140,6 +144,8 @@ import it.fast4x.rimusic.utils.forcePlayFromBeginning
import it.fast4x.rimusic.utils.forceSeekToNext
import it.fast4x.rimusic.utils.forceSeekToPrevious
import it.fast4x.rimusic.utils.getEnum
import it.fast4x.rimusic.utils.handleCatchingErrors
import it.fast4x.rimusic.utils.handleRangeErrors
import it.fast4x.rimusic.utils.intent
import it.fast4x.rimusic.utils.isAtLeastAndroid10
import it.fast4x.rimusic.utils.isAtLeastAndroid12
Expand All @@ -164,6 +170,7 @@ import it.fast4x.rimusic.utils.resumePlaybackWhenDeviceConnectedKey
import it.fast4x.rimusic.utils.shouldBePlaying
import it.fast4x.rimusic.utils.showDownloadButtonBackgroundPlayerKey
import it.fast4x.rimusic.utils.showLikeButtonBackgroundPlayerKey
import it.fast4x.rimusic.utils.skipMediaOnErrorKey
import it.fast4x.rimusic.utils.skipSilenceKey
import it.fast4x.rimusic.utils.startFadeAnimator
import it.fast4x.rimusic.utils.thumbnail
Expand Down Expand Up @@ -202,6 +209,7 @@ import kotlinx.coroutines.withContext
import me.knighthat.appContext
import okhttp3.OkHttpClient
import timber.log.Timber
import java.io.IOException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.net.ConnectException
Expand Down Expand Up @@ -543,7 +551,7 @@ class PlayerService : InvincibleService(),
downloadCache = DownloadUtil.getDownloadSimpleCache(applicationContext) as SimpleCache

player = ExoPlayer.Builder(this, createRendersFactory(), createMediaSourceFactory())
.setRenderersFactory(DefaultRenderersFactory(this).setEnableDecoderFallback(true))
//.setRenderersFactory(DefaultRenderersFactory(this).setEnableDecoderFallback(true))
.setAudioAttributes(
AudioAttributes.Builder()
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
Expand All @@ -556,19 +564,19 @@ class PlayerService : InvincibleService(),
.setHandleAudioBecomingNoisy(true)
//.setSeekForwardIncrementMs(5000)
//.setSeekBackIncrementMs(5000)
//.setUsePlatformDiagnostics(false)
.setUsePlatformDiagnostics(false)
.build()

player.skipSilenceEnabled = preferences.getBoolean(skipSilenceKey, false)
player.addListener(this@PlayerService)
player.addAnalyticsListener(PlaybackStatsListener(false, this@PlayerService))

player.repeatMode = when {
preferences.getBoolean(trackLoopEnabledKey, false) -> Player.REPEAT_MODE_ONE
preferences.getBoolean(queueLoopEnabledKey, false) -> Player.REPEAT_MODE_ALL
else -> Player.REPEAT_MODE_OFF
}

player.skipSilenceEnabled = preferences.getBoolean(skipSilenceKey, false)
player.addListener(this)
player.addAnalyticsListener(PlaybackStatsListener(false, this))

// Build a PendingIntent that can be used to launch the UI.
val sessionActivityPendingIntent =
packageManager?.getLaunchIntentForPackage(packageName)?.let { sessionIntent ->
Expand Down Expand Up @@ -1521,24 +1529,57 @@ class PlayerService : InvincibleService(),
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
Timber.e("PlayerService onPlayerError ${error.stackTraceToString()}")
//this.stopService(this.intent<MyDownloadService>())
//this.stopService(this.intent<PlayerService>())
//Log.d("mediaItem","onPlayerError ${error.errorCodeName}")
//println("mediaItem onPlayerError errorCode ${error.errorCode} errorCodeName ${error.errorCodeName}")
if (error.errorCode in arrayOf(416,2000)) {
//println("mediaItem onPlayerError recovered occurred errorCodeName ${error.errorCodeName}")
player.pause()
player.prepare()
player.play()
return
}

if (!preferences.getBoolean(skipMediaOnErrorKey, false)
|| !player.hasNextMediaItem())
return

val prev = player.currentMediaItem ?: return
player.seekToNextMediaItem()

coroutineScope.launch(Dispatchers.Main) {
withContext(Dispatchers.Main) {
SmartMessage(
getString(
R.string.skip_media_on_error_message,
prev.mediaMetadata.title
), type = PopupType.Success, durationLong = true ,context = this@PlayerService
)
}
}


}

/*
override fun onPlayerErrorChanged(error: PlaybackException?) {
super.onPlayerErrorChanged(error)
Timber.e("PlayerService onPlayerErrorChanged ${error?.stackTraceToString()}")
//this.stopService(this.intent<MyDownloadService>())
//this.stopService(this.intent<PlayerService>())
//Log.d("mediaItem","onPlayerErrorChanged ${error?.errorCodeName}")
//onPlayerError(error!!)
}
*/



/*
override fun onPlaybackSuppressionReasonChanged(playbackSuppressionReason: Int) {
super.onPlaybackSuppressionReasonChanged(playbackSuppressionReason)
//Timber.e("PlayerService onPlaybackSuppressionReasonChanged $playbackSuppressionReason")
//Log.d("mediaItem","onPlaybackSuppressionReasonChanged $playbackSuppressionReason")
}
*/

@UnstableApi
override fun onIsPlayingChanged(isPlaying: Boolean) {
Expand Down Expand Up @@ -1805,6 +1846,10 @@ class PlayerService : InvincibleService(),
),
DefaultExtractorsFactory()
//getExtractorsFactory()
).setLoadErrorHandlingPolicy(
object : DefaultLoadErrorHandlingPolicy() {
override fun isEligibleForFallback(exception: IOException) = true
}
)

private fun getExtractorsFactory(): ExtractorsFactory = ExtractorsFactory {
Expand All @@ -1821,16 +1866,52 @@ class PlayerService : InvincibleService(),
)
}

private fun createRendersFactory() = object : DefaultRenderersFactory(this) {
override fun buildAudioSink(
context: Context,
enableFloatOutput: Boolean,
enableAudioTrackPlaybackParams: Boolean
): AudioSink {
val minimumSilenceDuration = preferences.getLong(
minimumSilenceDurationKey, 2_000_000L).coerceIn(1000L..2_000_000L)

return DefaultAudioSink.Builder(applicationContext)
.setEnableFloatOutput(enableFloatOutput)
.setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams)
.setAudioOffloadSupportProvider(
DefaultAudioOffloadSupportProvider(applicationContext)
)
.setAudioProcessorChain(
DefaultAudioProcessorChain(
arrayOf(),
SilenceSkippingAudioProcessor(
/* minimumSilenceDurationUs = */ minimumSilenceDuration,
/* silenceRetentionRatio = */ 0.01f,
/* maxSilenceToKeepDurationUs = */ minimumSilenceDuration,
/* minVolumeToKeepPercentageWhenMuting = */ 0,
/* silenceThresholdLevel = */ 256
),
SonicAudioProcessor()
)
)
.build()
.apply {
if (isAtLeastAndroid10) setOffloadMode(AudioSink.OFFLOAD_MODE_DISABLED)
}
}
}

/*
private fun createRendersFactory(): RenderersFactory {
val minimumSilenceDuration = preferences.getLong(
minimumSilenceDurationKey, 2_000_000L) //PlayerPreferences.minimumSilence.coerceIn(1000L..2_000_000L)
minimumSilenceDurationKey, 2_000_000L).coerceIn(1000L..2_000_000L)
val audioSink = DefaultAudioSink.Builder(applicationContext)
.setEnableFloatOutput(false)
.setEnableAudioTrackPlaybackParams(false)
.setAudioOffloadSupportProvider(DefaultAudioOffloadSupportProvider(applicationContext))
.setAudioProcessorChain(
DefaultAudioProcessorChain(
emptyArray(),
arrayOf(),
SilenceSkippingAudioProcessor(
/* minimumSilenceDurationUs = */ minimumSilenceDuration,
/* silenceRetentionRatio = */ 0.01f,
Expand Down Expand Up @@ -1865,11 +1946,13 @@ class PlayerService : InvincibleService(),
)
}
}

*/

private fun createDataSourceResolverFactory(
mediaItemToPlay: (videoId: String) -> MediaItem?
): ResolvingDataSource.Factory {
): //ResolvingDataSource.Factory { // not required for handlers
DataSource.Factory { // required for handlers

val ringBuffer = RingBuffer<Pair<String, Uri>?>(2) { null }
val chunkLength = 512 * 1024L

Expand Down Expand Up @@ -1975,9 +2058,10 @@ class PlayerService : InvincibleService(),
?.maxByOrNull {
(it.bitrate?.times(
when (audioQualityFormat) {
AudioQualityFormat.Auto -> if (connectivityManager.isActiveNetworkMetered) -1 else 1
AudioQualityFormat.Auto -> if (connectivityManager.isActiveNetworkMetered) -2 else 1
AudioQualityFormat.High -> 1
AudioQualityFormat.Low, AudioQualityFormat.Medium -> -1
AudioQualityFormat.Medium -> -1
AudioQualityFormat.Low -> -2
}
) ?: -1) + (if (it.mimeType.startsWith("audio/webm")) 10240 else 0)
}
Expand Down Expand Up @@ -2091,6 +2175,8 @@ class PlayerService : InvincibleService(),
}
}
}
.handleCatchingErrors() // required for Datasource.Factory
.handleRangeErrors() // required for Datasource.Factory
}


Expand Down
Loading

0 comments on commit cb191db

Please sign in to comment.