diff --git a/app/src/main/java/com/maxrave/simpmusic/common/Config.kt b/app/src/main/java/com/maxrave/simpmusic/common/Config.kt index 5245d6bd..bc79042b 100644 --- a/app/src/main/java/com/maxrave/simpmusic/common/Config.kt +++ b/app/src/main/java/com/maxrave/simpmusic/common/Config.kt @@ -202,8 +202,8 @@ object QUALITY { } object VIDEO_QUALITY { - val items: Array = arrayOf("720p", "360p") - val itags: Array = arrayOf(22, 18) + val items: Array = arrayOf("1080p", "720p", "360p") + val itags: Array = arrayOf(137, 136, 134) } object LYRICS_PROVIDER { diff --git a/app/src/main/java/com/maxrave/simpmusic/data/db/DatabaseDao.kt b/app/src/main/java/com/maxrave/simpmusic/data/db/DatabaseDao.kt index 0c893560..1000f58a 100644 --- a/app/src/main/java/com/maxrave/simpmusic/data/db/DatabaseDao.kt +++ b/app/src/main/java/com/maxrave/simpmusic/data/db/DatabaseDao.kt @@ -370,6 +370,9 @@ interface DatabaseDao { @Query("SELECT * FROM new_format WHERE videoId = :videoId") suspend fun getNewFormat(videoId: String): NewFormatEntity? + @Query("SELECT * FROM new_format WHERE videoId = :videoId") + fun getNewFormatAsFlow(videoId: String): Flow + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertSongInfo(songInfo: SongInfoEntity) diff --git a/app/src/main/java/com/maxrave/simpmusic/data/db/LocalDataSource.kt b/app/src/main/java/com/maxrave/simpmusic/data/db/LocalDataSource.kt index 56a8d89e..6178ea73 100644 --- a/app/src/main/java/com/maxrave/simpmusic/data/db/LocalDataSource.kt +++ b/app/src/main/java/com/maxrave/simpmusic/data/db/LocalDataSource.kt @@ -212,6 +212,8 @@ class LocalDataSource suspend fun getNewFormat(videoId: String) = databaseDao.getNewFormat(videoId) + suspend fun getNewFormatAsFlow(videoId: String) = databaseDao.getNewFormatAsFlow(videoId) + suspend fun insertSongInfo(songInfo: SongInfoEntity) = databaseDao.insertSongInfo(songInfo) suspend fun getSongInfo(videoId: String) = databaseDao.getSongInfo(videoId) diff --git a/app/src/main/java/com/maxrave/simpmusic/data/repository/MainRepository.kt b/app/src/main/java/com/maxrave/simpmusic/data/repository/MainRepository.kt index 419fddf8..9dde32d2 100644 --- a/app/src/main/java/com/maxrave/simpmusic/data/repository/MainRepository.kt +++ b/app/src/main/java/com/maxrave/simpmusic/data/repository/MainRepository.kt @@ -2,6 +2,7 @@ package com.maxrave.simpmusic.data.repository import android.content.Context import android.util.Log +import androidx.media3.common.util.UnstableApi import com.maxrave.kotlinytmusicscraper.YouTube import com.maxrave.kotlinytmusicscraper.models.AccountInfo import com.maxrave.kotlinytmusicscraper.models.MediaType @@ -21,6 +22,7 @@ import com.maxrave.kotlinytmusicscraper.pages.BrowseResult import com.maxrave.kotlinytmusicscraper.pages.PlaylistPage import com.maxrave.kotlinytmusicscraper.pages.SearchPage import com.maxrave.simpmusic.R +import com.maxrave.simpmusic.common.QUALITY import com.maxrave.simpmusic.common.VIDEO_QUALITY import com.maxrave.simpmusic.data.dataStore.DataStoreManager import com.maxrave.simpmusic.data.db.LocalDataSource @@ -84,6 +86,7 @@ import com.maxrave.simpmusic.extension.bestMatchingIndex import com.maxrave.simpmusic.extension.toListTrack import com.maxrave.simpmusic.extension.toLyrics import com.maxrave.simpmusic.extension.toTrack +import com.maxrave.simpmusic.service.test.source.MergingMediaSourceFactory import com.maxrave.simpmusic.utils.Resource import com.maxrave.simpmusic.viewModel.FilterState import dagger.hilt.android.qualifiers.ApplicationContext @@ -420,6 +423,8 @@ class MainRepository suspend fun getNewFormat(videoId: String): Flow = flow { emit(localDataSource.getNewFormat(videoId)) }.flowOn(Dispatchers.Main) + suspend fun getFormatFlow(videoId: String) = localDataSource.getNewFormatAsFlow(videoId) + suspend fun insertSongInfo(songInfo: SongInfoEntity) = withContext(Dispatchers.IO) { localDataSource.insertSongInfo(songInfo) @@ -2146,10 +2151,14 @@ class MainRepository } }.flowOn(Dispatchers.IO) + @UnstableApi suspend fun getSongInfo(videoId: String): Flow = flow { runCatching { - YouTube.getSongInfo(videoId).onSuccess { songInfo -> + val id = if (videoId.contains(MergingMediaSourceFactory.isVideo)) + videoId.removePrefix(MergingMediaSourceFactory.isVideo) + else videoId + YouTube.getSongInfo(id).onSuccess { songInfo -> val song = SongInfoEntity( videoId = songInfo.videoId, @@ -2174,19 +2183,20 @@ class MainRepository } }.flowOn(Dispatchers.IO) + @UnstableApi suspend fun getStream( videoId: String, - itag: Int, + isVideo: Boolean, ): Flow = flow { + //134, 136, 137 YouTube.player(videoId).onSuccess { data -> - val acceptToPlayVideo = - runBlocking { dataStoreManager.watchVideoInsteadOfPlayingAudio.first() == DataStoreManager.TRUE } + val itag = QUALITY.itags.getOrNull(QUALITY.items.indexOf(dataStoreManager.quality.first())) val videoItag = VIDEO_QUALITY.itags.getOrNull( VIDEO_QUALITY.items.indexOf(dataStoreManager.videoQuality.first()), ) - ?: 22 + ?: 134 val response = data.second if (data.third == MediaType.Song) { Log.w( @@ -2196,18 +2206,14 @@ class MainRepository } else { Log.w("Stream", "response: is VIDEO") } - Log.w("Stream: ", data.toString()) + Log.w("Stream", response.streamingData?.formats?.map { it.itag }.toString() + " " + + response.streamingData?.adaptiveFormats?.map { it.itag }.toString()) + + Log.w("Stream", "Get stream for video $isVideo") var format = - if (acceptToPlayVideo) { - if (data.third == MediaType.Song) { - if (response.streamingData?.adaptiveFormats?.find { it.itag == 141 } != null) { - response.streamingData?.adaptiveFormats?.find { it.itag == 141 } - } else { - response.streamingData?.adaptiveFormats?.find { it.itag == itag } - } - } else { - response.streamingData?.formats?.find { it.itag == videoItag } - } + if (isVideo) { + response.streamingData?.formats?.find { it.itag == videoItag } + ?: response.streamingData?.adaptiveFormats?.find { it.itag == videoItag } } else { if (response.streamingData?.adaptiveFormats?.find { it.itag == 141 } != null) { response.streamingData?.adaptiveFormats?.find { it.itag == 141 } @@ -2222,8 +2228,8 @@ class MainRepository runBlocking { insertNewFormat( NewFormatEntity( - videoId = videoId, - itag = format?.itag ?: itag, + videoId = if(VIDEO_QUALITY.itags.contains(format?.itag)) "${MergingMediaSourceFactory.isVideo}$videoId" else videoId, + itag = format?.itag ?: itag ?: 141, mimeType = Regex("""([^;]+);\s*codecs=["']([^"']+)["']""").find( format?.mimeType ?: "", diff --git a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt index 04de32a3..aa4d7b56 100644 --- a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt +++ b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaService.kt @@ -37,18 +37,17 @@ import androidx.media3.session.SessionToken import com.google.common.util.concurrent.MoreExecutors import com.maxrave.simpmusic.R import com.maxrave.simpmusic.common.MEDIA_NOTIFICATION -import com.maxrave.simpmusic.common.QUALITY import com.maxrave.simpmusic.data.dataStore.DataStoreManager import com.maxrave.simpmusic.data.repository.MainRepository import com.maxrave.simpmusic.di.DownloadCache import com.maxrave.simpmusic.di.PlayerCache import com.maxrave.simpmusic.service.test.CoilBitmapLoader +import com.maxrave.simpmusic.service.test.source.MergingMediaSourceFactory import com.maxrave.simpmusic.ui.MainActivity import com.maxrave.simpmusic.ui.widget.BasicWidget import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.cancellable -import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import javax.inject.Inject @@ -100,7 +99,7 @@ class SimpleMediaService : MediaLibraryService() { .setHandleAudioBecomingNoisy(true) .setSeekForwardIncrementMs(5000) .setSeekBackIncrementMs(5000) - .setMediaSourceFactory(provideMediaSourceFactory()) + .setMediaSourceFactory(provideMergingMediaSource()) .setRenderersFactory(provideRendererFactory(this)) .build() @@ -230,11 +229,12 @@ class SimpleMediaService : MediaLibraryService() { cacheDataSourceFactory: CacheDataSource.Factory, @DownloadCache downloadCache: SimpleCache, @PlayerCache playerCache: SimpleCache, - mainRepository: MainRepository, - dataStoreManager: DataStoreManager + mainRepository: MainRepository ): DataSource.Factory { return ResolvingDataSource.Factory(cacheDataSourceFactory) { dataSpec -> - val mediaId = dataSpec.key ?: error("No media id") + var mediaId = dataSpec.key ?: error("No media id") + Log.w("Stream", mediaId) + Log.w("Stream", mediaId.startsWith(MergingMediaSourceFactory.isVideo).toString()) val CHUNK_LENGTH = 512 * 1024L if (downloadCache.isCached( mediaId, @@ -246,14 +246,23 @@ class SimpleMediaService : MediaLibraryService() { } var dataSpecReturn: DataSpec = dataSpec runBlocking(Dispatchers.IO) { - val itag = dataStoreManager.quality.first() - - mainRepository.getStream( - mediaId, - if (itag == QUALITY.items[0].toString()) QUALITY.itags[0] else QUALITY.itags[1] - ).cancellable().collect { - if (it != null) { - dataSpecReturn = dataSpec.withUri(it.toUri()) + if (mediaId.contains(MergingMediaSourceFactory.isVideo)) { + val id = mediaId.removePrefix(MergingMediaSourceFactory.isVideo) + mainRepository.getStream( + id, true + ).cancellable().collect { + if (it != null) { + dataSpecReturn = dataSpec.withUri(it.toUri()) + } + } + } + else { + mainRepository.getStream( + mediaId, isVideo = false + ).cancellable().collect { + if (it != null) { + dataSpecReturn = dataSpec.withUri(it.toUri()) + } } } } @@ -277,12 +286,16 @@ class SimpleMediaService : MediaLibraryService() { provideCacheDataSource(downloadCache, playerCache), downloadCache, playerCache, - mainRepository, - dataStoreManager + mainRepository ), provideExtractorFactory() ) + private fun provideMergingMediaSource(): MergingMediaSourceFactory = MergingMediaSourceFactory( + provideMediaSourceFactory(), + dataStoreManager + ) + @UnstableApi fun provideRendererFactory(context: Context): DefaultRenderersFactory = object : DefaultRenderersFactory(context) { diff --git a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaServiceHandler.kt b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaServiceHandler.kt index edac63fd..216a23b6 100644 --- a/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaServiceHandler.kt +++ b/app/src/main/java/com/maxrave/simpmusic/service/SimpleMediaServiceHandler.kt @@ -837,6 +837,8 @@ class SimpleMediaServiceHandler( thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544") } val artistName: String = track.artists.toListName().connectArtists() + val isSong = (track.thumbnails?.last()?.height != 0 && track.thumbnails?.last()?.height == track.thumbnails?.last()?.width + && track.thumbnails?.last()?.height != null) if (track.artists.isNullOrEmpty()) { mainRepository.getSongInfo(track.videoId).singleOrNull() .let { songInfo -> @@ -862,6 +864,7 @@ class SimpleMediaServiceHandler( .setArtist(songInfo.author) .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build(), @@ -878,6 +881,7 @@ class SimpleMediaServiceHandler( .setAlbumTitle(track.album?.name) .setTitle(track.title) .setArtist("Various Artists") + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build() @@ -900,6 +904,7 @@ class SimpleMediaServiceHandler( .setArtist(artistName) .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build(), @@ -929,6 +934,8 @@ class SimpleMediaServiceHandler( if (thumbUrl.contains("w120")) { thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544") } + val isSong = (track.thumbnails?.last()?.height != 0 && track.thumbnails?.last()?.height == track.thumbnails?.last()?.width && + track.thumbnails?.last()?.height != null) if (downloaded == 1) { if (track.artists.isNullOrEmpty()) { mainRepository.getSongInfo(track.videoId).singleOrNull() @@ -945,6 +952,7 @@ class SimpleMediaServiceHandler( .setAlbumTitle(track.album?.name) .setTitle(track.title) .setArtist(songInfo.author) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build() @@ -972,6 +980,7 @@ class SimpleMediaServiceHandler( .setAlbumTitle(track.album?.name) .setTitle(track.title) .setArtist("Various Artists") + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build() @@ -995,6 +1004,7 @@ class SimpleMediaServiceHandler( .setAlbumTitle(track.album?.name) .setTitle(track.title) .setArtist(track.artists.toListName().connectArtists()) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build() @@ -1029,6 +1039,7 @@ class SimpleMediaServiceHandler( .setTitle(track.title) .setArtist(songInfo.author) .setArtworkUri(thumbUrl.toUri()) + .setDescription(if (isSong) "Song" else "Video") .setAlbumTitle(track.album?.name) .build(), ) @@ -1045,6 +1056,7 @@ class SimpleMediaServiceHandler( .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) .setTitle(track.title) + .setDescription(if (isSong) "Song" else "Video") .setArtist("Various Artists") .build(), ) @@ -1068,6 +1080,7 @@ class SimpleMediaServiceHandler( .setArtist(artistName) .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build(), @@ -1136,6 +1149,8 @@ class SimpleMediaServiceHandler( thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544") } val artistName: String = track.artists.toListName().connectArtists() + val isSong = (track.thumbnails?.last()?.height != 0 && track.thumbnails?.last()?.height == track.thumbnails?.last()?.width && + track.thumbnails?.last()?.height != null) if ((currentIndex() + 1 in 0..catalogMetadata.size)) { if (track.artists.isNullOrEmpty()) { mainRepository.getSongInfo(track.videoId).cancellable().first().let { songInfo -> @@ -1162,6 +1177,7 @@ class SimpleMediaServiceHandler( .setArtist(songInfo.author) .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build(), @@ -1179,6 +1195,7 @@ class SimpleMediaServiceHandler( .setAlbumTitle(track.album?.name) .setTitle(track.title) .setArtist("Various Artists") + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build() @@ -1202,6 +1219,7 @@ class SimpleMediaServiceHandler( .setArtist(artistName) .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build(), diff --git a/app/src/main/java/com/maxrave/simpmusic/service/test/download/DownloadUtils.kt b/app/src/main/java/com/maxrave/simpmusic/service/test/download/DownloadUtils.kt index 45830346..ded81c4e 100644 --- a/app/src/main/java/com/maxrave/simpmusic/service/test/download/DownloadUtils.kt +++ b/app/src/main/java/com/maxrave/simpmusic/service/test/download/DownloadUtils.kt @@ -17,6 +17,7 @@ import com.maxrave.simpmusic.data.repository.MainRepository import com.maxrave.simpmusic.di.DownloadCache import com.maxrave.simpmusic.di.PlayerCache import com.maxrave.simpmusic.service.test.download.MusicDownloadService.Companion.CHANNEL_ID +import com.maxrave.simpmusic.service.test.source.MergingMediaSourceFactory import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -62,13 +63,25 @@ class DownloadUtils @Inject constructor( runBlocking(Dispatchers.IO) { Log.w("DownloadUtils", "Not cached: $mediaId") var extract: DataSpec? = null - mainRepository.getStream(mediaId, 251).cancellable().collect { values -> - if (values != null) { - extract = dataSpec.withUri((values).toUri()) + if (mediaId.startsWith(MergingMediaSourceFactory.isVideo)) { + mainRepository.getStream(mediaId.removePrefix(MergingMediaSourceFactory.isVideo), true).cancellable().collect { values -> + if (values != null) { + extract = dataSpec.withUri((values).toUri()) + } } + Log.d("DownloadUtils", "extract: ${extract.toString()}") + return@runBlocking extract!! } - Log.d("DownloadUtils", "extract: ${extract.toString()}") - return@runBlocking extract!! + else { + mainRepository.getStream(mediaId, false).cancellable().collect { values -> + if (values != null) { + extract = dataSpec.withUri((values).toUri()) + } + } + Log.d("DownloadUtils", "extract: ${extract.toString()}") + return@runBlocking dataSpec + } + } } } diff --git a/app/src/main/java/com/maxrave/simpmusic/service/test/source/MergingMediaSourceFactory.kt b/app/src/main/java/com/maxrave/simpmusic/service/test/source/MergingMediaSourceFactory.kt new file mode 100644 index 00000000..c485ac05 --- /dev/null +++ b/app/src/main/java/com/maxrave/simpmusic/service/test/source/MergingMediaSourceFactory.kt @@ -0,0 +1,59 @@ +package com.maxrave.simpmusic.service.test.source + +import android.util.Log +import androidx.media3.common.MediaItem +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.drm.DrmSessionManagerProvider +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory +import androidx.media3.exoplayer.source.MediaSource +import androidx.media3.exoplayer.source.MergingMediaSource +import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy +import com.maxrave.simpmusic.data.dataStore.DataStoreManager +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking + +@UnstableApi +class MergingMediaSourceFactory(private val defaultMediaSourceFactory: DefaultMediaSourceFactory, private val dataStoreManager: DataStoreManager) : MediaSource.Factory { + + override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory { + defaultMediaSourceFactory.setDrmSessionManagerProvider(drmSessionManagerProvider) + return this; + } + + override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory { + defaultMediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy) + return this + } + + override fun getSupportedTypes(): IntArray { + return defaultMediaSourceFactory.supportedTypes + } + + override fun createMediaSource(mediaItem: MediaItem): MediaSource { + + Log.w("Merging Media Source", mediaItem.mediaMetadata.description.toString()) + val getVideo = runBlocking(Dispatchers.IO){ dataStoreManager.watchVideoInsteadOfPlayingAudio.first() } == DataStoreManager.TRUE + Log.w("Merging Media Source", getVideo.toString()) + if (mediaItem.mediaMetadata.description == isVideo && getVideo) { + val videoItem = mediaItem.buildUpon().setMediaId("$isVideo${mediaItem.mediaId}").setCustomCacheKey("$isVideo${mediaItem.mediaId}").build() + Log.w("Stream", "Video Item " +videoItem.mediaId) + val videoSource = defaultMediaSourceFactory.createMediaSource( + videoItem + ) + Log.w("Stream", "VideoSource " +videoSource.mediaItem.mediaId) + val audioSource = defaultMediaSourceFactory.createMediaSource(mediaItem) + Log.w("Stream", "AudioSource " +audioSource.mediaItem.mediaId) + return MergingMediaSource(videoSource, audioSource) + } else { + return defaultMediaSourceFactory.createMediaSource(mediaItem) + } + +// val default = defaultMediaSourceFactory.createMediaSource(mediaItem.buildUpon().setMediaId("AUDIO-${mediaItem.mediaId}").build()) + } + + companion object { + const val isVideo = "Video" + const val isSong = "Song" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/NowPlayingFragment.kt b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/NowPlayingFragment.kt index 43bc2eac..6fa422a4 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/NowPlayingFragment.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/fragment/player/NowPlayingFragment.kt @@ -66,6 +66,7 @@ import com.maxrave.simpmusic.common.Config.VIDEO_CLICK import com.maxrave.simpmusic.common.DownloadState import com.maxrave.simpmusic.common.LYRICS_PROVIDER import com.maxrave.simpmusic.common.STATUS_DONE +import com.maxrave.simpmusic.common.VIDEO_QUALITY import com.maxrave.simpmusic.data.dataStore.DataStoreManager import com.maxrave.simpmusic.data.db.entities.LocalPlaylistEntity import com.maxrave.simpmusic.data.db.entities.PairSongLocalPlaylist @@ -930,7 +931,7 @@ class NowPlayingFragment : Fragment() { launch { viewModel.format.collect { f -> if (f != null) { - if (f.itag == 22 || f.itag == 18) { + if (VIDEO_QUALITY.itags.contains(f.itag)) { binding.playerLayout.visibility = View.VISIBLE binding.playerView.visibility = View.VISIBLE binding.ivArt.visibility = View.INVISIBLE diff --git a/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt b/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt index 3845a5c2..01712a77 100644 --- a/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt +++ b/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt @@ -85,6 +85,7 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first @@ -218,6 +219,8 @@ class SharedViewModel private var jobWatchtime: Job? = null + private var getFormatFlowJob: Job? = null + var playlistId: MutableStateFlow = MutableStateFlow(null) private var initJob: Job? = null @@ -435,9 +438,12 @@ class SharedViewModel launch { duration.collect { if (it > 0) { - getFormat( - simpleMediaServiceHandler!!.nowPlaying.first()?.mediaId, - ) + simpleMediaServiceHandler!!.nowPlaying.first()?.mediaId?.let { mediaId -> + getFormat( + mediaId, + ) + } + } } } @@ -915,6 +921,8 @@ class SharedViewModel if (thumbUrl.contains("w120")) { thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544") } + val isSong = (track.thumbnails.last().height != 0 &&track.thumbnails.last().height == track.thumbnails.last().width + && track.thumbnails.lastOrNull()?.height != null) simpleMediaServiceHandler?.addMediaItem( MediaItem.Builder() .setUri(track.videoId) @@ -925,6 +933,7 @@ class SharedViewModel .setTitle(track.title) .setArtist(track.artists.toListName().connectArtists()) .setArtworkUri(thumbUrl.toUri()) + .setDescription(if (isSong) "Song" else "Video") .setAlbumTitle(track.album?.name) .build(), ) @@ -946,6 +955,8 @@ class SharedViewModel thumbUrl = Regex("([wh])120").replace(thumbUrl, "$1544") } Log.d("Check URI", uri) + val isSong = (track.thumbnails.last().height != 0 &&track.thumbnails.last().height == track.thumbnails.last().width + && track.thumbnails.lastOrNull()?.height != null) simpleMediaServiceHandler?.addMediaItem( MediaItem.Builder() .setUri(track.videoId) @@ -957,6 +968,7 @@ class SharedViewModel .setArtist(artistName) .setArtworkUri(thumbUrl.toUri()) .setAlbumTitle(track.album?.name) + .setDescription(if (isSong) "Song" else "Video") .build(), ) .build(), @@ -1415,9 +1427,11 @@ class SharedViewModel } fun getFormat(mediaId: String?) { - viewModelScope.launch { + getFormatFlowJob?.cancel() + getFormatFlowJob = viewModelScope.launch { if (mediaId != null) { - mainRepository.getNewFormat(mediaId).collect { f -> + mainRepository.getFormatFlow(mediaId).cancellable().collectLatest { f -> + Log.w("Format", mediaId.toString() + " " +f.toString()) if (f != null) { _format.emit(f) } else { diff --git a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt index 7185384f..b8324f96 100644 --- a/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt +++ b/kotlinYtmusicScraper/src/main/java/com/maxrave/kotlinytmusicscraper/YouTube.kt @@ -779,7 +779,8 @@ object YouTube { val firstThumb = playerResponse.videoDetails?.thumbnail?.thumbnails?.firstOrNull() val thumbnails = if (firstThumb?.height == firstThumb?.width && firstThumb != null) MediaType.Song else MediaType.Video - println("Player Response " + playerResponse.streamingData) + println("Player Response " + playerResponse.streamingData?.formats?.map { Pair(it.itag, it.isAudio) }) + println("Player Response " + playerResponse.streamingData?.adaptiveFormats?.map { Pair(it.itag, it.isAudio) }) // println( playerResponse.streamingData?.adaptiveFormats?.findLast { it.itag == 251 }?.mimeType.toString()) if (playerResponse.playabilityStatus.status == "OK") {