From cda71ed852f40c582dec6b9ce268903d10e1b83e Mon Sep 17 00:00:00 2001 From: daladim Date: Sat, 22 Apr 2023 22:46:27 +0200 Subject: [PATCH 1/4] [minor] typo --- .../main/java/com/simplecityapps/mediaprovider/MediaImporter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/MediaImporter.kt b/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/MediaImporter.kt index 13338cf0..d3810f9d 100644 --- a/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/MediaImporter.kt +++ b/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/MediaImporter.kt @@ -81,7 +81,7 @@ class MediaImporter( return } - Timber.v("Starting import..") + Timber.v("Starting import...") val time = System.currentTimeMillis() isImporting = true From 37372630aa28a0481514ae9ea658f6d767ca9bba Mon Sep 17 00:00:00 2001 From: daladim Date: Fri, 24 Feb 2023 17:43:54 +0100 Subject: [PATCH 2/4] m3u playlists use their path as `externalId` This will be useful when exporting update playlists to their original path --- .../local/provider/taglib/TaglibMediaProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/provider/taglib/TaglibMediaProvider.kt b/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/provider/taglib/TaglibMediaProvider.kt index f4ea48e7..16bd87d8 100644 --- a/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/provider/taglib/TaglibMediaProvider.kt +++ b/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/provider/taglib/TaglibMediaProvider.kt @@ -150,7 +150,7 @@ class TaglibMediaProvider( mediaProviderType = type, name = m3uPlaylist.name, songs = songs, - externalId = m3uPlaylist.name + externalId = m3uPlaylist.path ) updateData } else { From 69ceac8219686da21b3b1bd010b5d04c30580a81 Mon Sep 17 00:00:00 2001 From: daladim Date: Thu, 23 Feb 2023 22:09:33 +0100 Subject: [PATCH 3/4] Ability to update a playlist M3U file --- .../playlists/PlaylistRepository.kt | 3 +++ .../repository/LocalPlaylistRepository.kt | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/repository/playlists/PlaylistRepository.kt b/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/repository/playlists/PlaylistRepository.kt index eb30effb..bbba47f8 100644 --- a/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/repository/playlists/PlaylistRepository.kt +++ b/android/mediaprovider/core/src/main/java/com/simplecityapps/mediaprovider/repository/playlists/PlaylistRepository.kt @@ -6,6 +6,7 @@ import com.simplecityapps.shuttle.model.PlaylistSong import com.simplecityapps.shuttle.model.SmartPlaylist import com.simplecityapps.shuttle.model.Song import com.simplecityapps.shuttle.sorting.PlaylistSongSortOrder +import java.io.OutputStream import java.io.Serializable import kotlinx.coroutines.flow.Flow @@ -70,6 +71,8 @@ interface PlaylistRepository { playlist: Playlist, externalId: String? ) + + suspend fun updateM3uFile(playlist: Playlist) } enum class PlaylistSortOrder : Serializable { diff --git a/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt b/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt index ca848e73..fd945a46 100644 --- a/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt +++ b/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt @@ -1,6 +1,7 @@ package com.simplecityapps.localmediaprovider.local.repository import android.content.Context +import android.net.Uri import com.simplecityapps.localmediaprovider.local.data.room.dao.PlaylistDataDao import com.simplecityapps.localmediaprovider.local.data.room.dao.PlaylistSongJoinDao import com.simplecityapps.localmediaprovider.local.data.room.entity.PlaylistData @@ -159,6 +160,32 @@ class LocalPlaylistRepository( ) ) + override suspend fun updateM3uFile(playlist: Playlist) { + val outputStream = playlist.externalId?.let { path -> + context.contentResolver.openOutputStream(Uri.parse(playlist.externalId), "wt") + } + + if (outputStream == null) { + Timber.w("Unable to open M3U file at ${playlist.externalId} for playlist ${playlist.name}") + } else { + val playlistPath = Uri.decode(playlist.externalId?: "") + val playlistFolder = playlistPath.substringBeforeLast("/") + "/" + + getSongsForPlaylist(playlist) + .firstOrNull() + .orEmpty() + .forEach { plSong -> + // Quick-and-dirty way to relativize the song path to the m3u folder + // Note that paths can be content:// URIs, for which there is no proper .relativize() method + // We'll use absolute values (paths or URIs, whatever is in database) for files that are not stored in a sub-folder relative to the M3U file + val songPath = Uri.decode(plSong.song.path) + val relative = songPath.substringAfter(playlistFolder) + val line = relative.toByteArray() + /* CRLF */ 0x0d.toByte() + 0x0A.toByte() + outputStream.write(line) + } + } + } + override suspend fun updatePlaylistSortOder( playlist: Playlist, sortOrder: PlaylistSongSortOrder From 00dd108cf3065b6631ab2fd61f8904ed5bfdbb70 Mon Sep 17 00:00:00 2001 From: daladim Date: Mon, 27 Feb 2023 16:17:28 +0100 Subject: [PATCH 4/4] Automatically update M3U files --- .../repository/LocalPlaylistRepository.kt | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt b/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt index fd945a46..65656f1b 100644 --- a/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt +++ b/android/mediaprovider/local/src/main/java/com/simplecityapps/localmediaprovider/local/repository/LocalPlaylistRepository.kt @@ -110,31 +110,40 @@ class LocalPlaylistRepository( override suspend fun addToPlaylist( playlist: Playlist, songs: List - ) = playlistSongJoinDao.insert( - songs.mapIndexed { i, song -> - PlaylistSongJoin( - playlistId = playlist.id, - songId = song.id, - sortOrder = (playlist.songCount + i).toLong() - ) - } - ) + ) { + playlistSongJoinDao.insert( + songs.mapIndexed { i, song -> + PlaylistSongJoin( + playlistId = playlist.id, + songId = song.id, + sortOrder = (playlist.songCount + i).toLong() + ) + } + ) + updateM3uFile(playlist) + } override suspend fun removeFromPlaylist( playlist: Playlist, playlistSongs: List - ) = playlistSongJoinDao.delete( - playlistId = playlist.id, - playlistSongIds = playlistSongs.map { playlistSong -> playlistSong.id }.toTypedArray() - ) + ) { + playlistSongJoinDao.delete( + playlistId = playlist.id, + playlistSongIds = playlistSongs.map { playlistSong -> playlistSong.id }.toTypedArray() + ) + updateM3uFile(playlist) + } override suspend fun removeSongsFromPlaylist( playlist: Playlist, songs: List - ) = playlistSongJoinDao.deleteSongs( - playlistId = playlist.id, - songIds = songs.map { it.id }.toTypedArray() - ) + ) { + playlistSongJoinDao.deleteSongs( + playlistId = playlist.id, + songIds = songs.map { it.id }.toTypedArray() + ) + updateM3uFile(playlist) + } override fun getSongsForPlaylist(playlist: Playlist): Flow> = playlistSongJoinDao.getSongsForPlaylist(playlist.id) .map { playlistSong -> @@ -145,7 +154,10 @@ class LocalPlaylistRepository( override suspend fun deleteAll(mediaProviderType: MediaProviderType) = playlistDataDao.deleteAll(mediaProviderType) - override suspend fun clearPlaylist(playlist: Playlist) = playlistDataDao.clear(playlist.id) + override suspend fun clearPlaylist(playlist: Playlist) { + playlistDataDao.clear(playlist.id) + updateM3uFile(playlist) + } override suspend fun renamePlaylist( playlist: Playlist, @@ -216,6 +228,7 @@ class LocalPlaylistRepository( } } ) + updateM3uFile(playlist) } override suspend fun updatePlaylistMediaProviderType(