From bfdeb0658b330e43de8f928312f071dbe511a0c9 Mon Sep 17 00:00:00 2001
From: Matthew Simpson
Date: Sun, 9 Mar 2025 14:15:17 +0000
Subject: [PATCH 01/26] Change `PlaylistChooserDialog`\`PlaylistEditorDialog`
to require `ArrayList` of Songs
This allows for being able to provide an entire Album's worth of songs
in one API call.
---
.../tempo/ui/dialog/PlaylistChooserDialog.java | 6 +++---
.../tempo/ui/dialog/PlaylistEditorDialog.java | 8 ++++----
.../bottomsheetdialog/SongBottomSheetDialog.java | 5 ++++-
.../tempo/viewmodel/PlaylistChooserViewModel.java | 13 +++++++------
.../tempo/viewmodel/PlaylistEditorViewModel.java | 13 +++++++------
5 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistChooserDialog.java b/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistChooserDialog.java
index f0266c84..5c0b119c 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistChooserDialog.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistChooserDialog.java
@@ -57,14 +57,14 @@ public class PlaylistChooserDialog extends DialogFragment implements ClickCallba
}
private void setSongInfo() {
- playlistChooserViewModel.setSongToAdd(requireArguments().getParcelable(Constants.TRACK_OBJECT));
+ playlistChooserViewModel.setSongsToAdd(requireArguments().getParcelableArrayList(Constants.TRACKS_OBJECT));
}
private void setButtonAction() {
androidx.appcompat.app.AlertDialog alertDialog = (androidx.appcompat.app.AlertDialog) Objects.requireNonNull(getDialog());
alertDialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_NEUTRAL).setOnClickListener(v -> {
Bundle bundle = new Bundle();
- bundle.putParcelable(Constants.TRACK_OBJECT, playlistChooserViewModel.getSongToAdd());
+ bundle.putParcelableArrayList(Constants.TRACKS_OBJECT, playlistChooserViewModel.getSongsToAdd());
PlaylistEditorDialog dialog = new PlaylistEditorDialog(null);
dialog.setArguments(bundle);
@@ -98,7 +98,7 @@ public class PlaylistChooserDialog extends DialogFragment implements ClickCallba
@Override
public void onPlaylistClick(Bundle bundle) {
Playlist playlist = bundle.getParcelable(Constants.PLAYLIST_OBJECT);
- playlistChooserViewModel.addSongToPlaylist(playlist.getId());
+ playlistChooserViewModel.addSongsToPlaylist(playlist.getId());
dismiss();
}
}
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistEditorDialog.java b/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistEditorDialog.java
index 4d265beb..dea70d7d 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistEditorDialog.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/PlaylistEditorDialog.java
@@ -74,11 +74,11 @@ public class PlaylistEditorDialog extends DialogFragment {
}
private void setParameterInfo() {
- if (requireArguments().getParcelable(Constants.TRACK_OBJECT) != null) {
- playlistEditorViewModel.setSongToAdd(requireArguments().getParcelable(Constants.TRACK_OBJECT));
+ if (requireArguments().getParcelableArrayList(Constants.TRACKS_OBJECT) != null) {
+ playlistEditorViewModel.setSongsToAdd(requireArguments().getParcelableArrayList(Constants.TRACKS_OBJECT));
playlistEditorViewModel.setPlaylistToEdit(null);
} else if (requireArguments().getParcelable(Constants.PLAYLIST_OBJECT) != null) {
- playlistEditorViewModel.setSongToAdd(null);
+ playlistEditorViewModel.setSongsToAdd(null);
playlistEditorViewModel.setPlaylistToEdit(requireArguments().getParcelable(Constants.PLAYLIST_OBJECT));
if (playlistEditorViewModel.getPlaylistToEdit() != null) {
@@ -92,7 +92,7 @@ public class PlaylistEditorDialog extends DialogFragment {
alertDialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
if (validateInput()) {
- if (playlistEditorViewModel.getSongToAdd() != null) {
+ if (playlistEditorViewModel.getSongsToAdd() != null) {
playlistEditorViewModel.createPlaylist(playlistName);
} else if (playlistEditorViewModel.getPlaylistToEdit() != null) {
playlistEditorViewModel.updatePlaylist(playlistName);
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java
index b22830eb..0d15ad2f 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/SongBottomSheetDialog.java
@@ -39,6 +39,9 @@ import com.cappielloantonio.tempo.viewmodel.SongBottomSheetViewModel;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collections;
+
@UnstableApi
public class SongBottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener {
private HomeViewModel homeViewModel;
@@ -177,7 +180,7 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
TextView addToPlaylist = view.findViewById(R.id.add_to_playlist_text_view);
addToPlaylist.setOnClickListener(v -> {
Bundle bundle = new Bundle();
- bundle.putParcelable(Constants.TRACK_OBJECT, song);
+ bundle.putParcelableArrayList(Constants.TRACKS_OBJECT, new ArrayList<>(Collections.singletonList(song)));
PlaylistChooserDialog dialog = new PlaylistChooserDialog();
dialog.setArguments(bundle);
diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistChooserViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistChooserViewModel.java
index cb8833fe..fdee85c6 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistChooserViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistChooserViewModel.java
@@ -11,6 +11,7 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.tempo.repository.PlaylistRepository;
import com.cappielloantonio.tempo.subsonic.models.Child;
import com.cappielloantonio.tempo.subsonic.models.Playlist;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
@@ -20,7 +21,7 @@ public class PlaylistChooserViewModel extends AndroidViewModel {
private final PlaylistRepository playlistRepository;
private final MutableLiveData> playlists = new MutableLiveData<>(null);
- private Child toAdd;
+ private ArrayList toAdd;
public PlaylistChooserViewModel(@NonNull Application application) {
super(application);
@@ -33,15 +34,15 @@ public class PlaylistChooserViewModel extends AndroidViewModel {
return playlists;
}
- public void addSongToPlaylist(String playlistId) {
- playlistRepository.addSongToPlaylist(playlistId, new ArrayList(Collections.singletonList(toAdd.getId())));
+ public void addSongsToPlaylist(String playlistId) {
+ playlistRepository.addSongToPlaylist(playlistId, new ArrayList<>(Lists.transform(toAdd, Child::getId)));
}
- public void setSongToAdd(Child song) {
- toAdd = song;
+ public void setSongsToAdd(ArrayList songs) {
+ toAdd = songs;
}
- public Child getSongToAdd() {
+ public ArrayList getSongsToAdd() {
return toAdd;
}
}
diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistEditorViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistEditorViewModel.java
index 8f9181a0..aceedb95 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistEditorViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlaylistEditorViewModel.java
@@ -12,6 +12,7 @@ import com.cappielloantonio.tempo.repository.SharingRepository;
import com.cappielloantonio.tempo.subsonic.models.Child;
import com.cappielloantonio.tempo.subsonic.models.Playlist;
import com.cappielloantonio.tempo.subsonic.models.Share;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
@@ -24,7 +25,7 @@ public class PlaylistEditorViewModel extends AndroidViewModel {
private final PlaylistRepository playlistRepository;
private final SharingRepository sharingRepository;
- private Child toAdd;
+ private ArrayList toAdd;
private Playlist toEdit;
private MutableLiveData> songLiveList = new MutableLiveData<>();
@@ -37,7 +38,7 @@ public class PlaylistEditorViewModel extends AndroidViewModel {
}
public void createPlaylist(String name) {
- playlistRepository.createPlaylist(null, name, new ArrayList(Collections.singletonList(toAdd.getId())));
+ playlistRepository.createPlaylist(null, name, new ArrayList(Lists.transform(toAdd, Child::getId)));
}
public void updatePlaylist(String name) {
@@ -48,12 +49,12 @@ public class PlaylistEditorViewModel extends AndroidViewModel {
if (toEdit != null) playlistRepository.deletePlaylist(toEdit.getId());
}
- public Child getSongToAdd() {
- return toAdd;
+ public void setSongsToAdd(ArrayList songs) {
+ toAdd = songs;
}
- public void setSongToAdd(Child song) {
- this.toAdd = song;
+ public ArrayList getSongsToAdd() {
+ return toAdd;
}
public Playlist getPlaylistToEdit() {
From 8ac059bb172b0b21b5c8339439c47f9a9d1eab43 Mon Sep 17 00:00:00 2001
From: Matthew Simpson
Date: Sun, 9 Mar 2025 14:34:11 +0000
Subject: [PATCH 02/26] Add "Add to playlist" option to Album bottom sheet
dialog
Resolves #349
Resolves #202
---
.../bottomsheetdialog/AlbumBottomSheetDialog.java | 15 +++++++++++++++
.../main/res/layout/bottom_sheet_album_dialog.xml | 13 +++++++++++++
app/src/main/res/values-de/strings.xml | 1 +
app/src/main/res/values-fr/strings.xml | 1 +
app/src/main/res/values-it/strings.xml | 3 ++-
app/src/main/res/values-ko/strings.xml | 1 +
app/src/main/res/values-pt/strings.xml | 1 +
app/src/main/res/values-ru/strings.xml | 1 +
app/src/main/res/values-zh/strings.xml | 1 +
app/src/main/res/values/strings.xml | 1 +
10 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java
index a498f473..cfcefe9d 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/bottomsheetdialog/AlbumBottomSheetDialog.java
@@ -31,6 +31,7 @@ import com.cappielloantonio.tempo.service.MediaService;
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
import com.cappielloantonio.tempo.subsonic.models.Child;
import com.cappielloantonio.tempo.ui.activity.MainActivity;
+import com.cappielloantonio.tempo.ui.dialog.PlaylistChooserDialog;
import com.cappielloantonio.tempo.util.Constants;
import com.cappielloantonio.tempo.util.DownloadUtil;
import com.cappielloantonio.tempo.util.MappingUtil;
@@ -167,6 +168,20 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
});
});
+ TextView addToPlaylist = view.findViewById(R.id.add_to_playlist_text_view);
+ addToPlaylist.setOnClickListener(v -> {
+ albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(Constants.TRACKS_OBJECT, new ArrayList<>(songs));
+
+ PlaylistChooserDialog dialog = new PlaylistChooserDialog();
+ dialog.setArguments(bundle);
+ dialog.show(requireActivity().getSupportFragmentManager(), null);
+
+ dismissBottomSheet();
+ });
+ });
+
TextView removeAll = view.findViewById(R.id.remove_all_text_view);
albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
List mediaItems = MappingUtil.mapDownloads(songs);
diff --git a/app/src/main/res/layout/bottom_sheet_album_dialog.xml b/app/src/main/res/layout/bottom_sheet_album_dialog.xml
index a6ed37a5..b37a5f90 100644
--- a/app/src/main/res/layout/bottom_sheet_album_dialog.xml
+++ b/app/src/main/res/layout/bottom_sheet_album_dialog.xml
@@ -146,6 +146,19 @@
android:paddingBottom="12dp"
android:text="@string/album_bottom_sheet_download_all" />
+
+
Bitte deaktiviere die Batterieoptimierung, damit die Medienwiedergabe bei ausgeschaltetem Bildschirm richtig funktioniert.
Batterie Optimierung
Offlinebetrieb
+ Zu Playliste hinzufügen
Zur Warteschlange hinzufügen
Alle herunterladen
Gehe zu Künstler
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 03a2f0db..617b6fcb 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -3,6 +3,7 @@
Veuillez désactiver les optimisations de la batterie pour permettre la lecture des médias lorsque l\'écran est éteint.
Optimisations de la batterie
Mode hors-ligne
+ Ajouter à une playlist
Ajouter à la file d\'attente
Télécharger tout
Aller à l\'artiste
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 2cc5bcb6..d402c769 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -3,7 +3,8 @@
Per favore, disabilita le ottimizzazioni della batteria per la riproduzione multimediale quando lo schermo è spento.
Ottimizzazioni della Batteria
Modalità offline
- Aggiungi alla coda
+ Aggiungi alla playlist
+ Aggiungi alla coda
Scarica tutto
Vai all\'artista
Mix istantaneo
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 679f333a..71128ca5 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -3,6 +3,7 @@
화면이 꺼진 상태에서 음악 재생을 하기 위해서는 배터리 최적화를 비활성화 해주세요.
배터리 최적화
오프라인 모드
+ 플레이리스트에 추가
재생목록에 추가
모두 다운로드
아티스트로 이동
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 12f04a31..5f688e54 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -3,6 +3,7 @@
Por favor, desative as otimizações de bateria para a reprodução de mídia enquanto a tela estiver desligada.
Otimizações de bateria
Modo offline
+ Adicionar a uma playlist
Adicionar à fila
Baixar todos
Ir para o(a) artista
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 0f893b90..684d5e8a 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -3,6 +3,7 @@
Пожалуйста, отключите оптимизацию батареи для воспроизведения мультимедиа при выключенном экране.
Оптимизация батареи
Офлайн-режим
+ Добавить в плейлист
Добавить в очередь
Скачать все
Перейти к исполнителю
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 915b33d1..1daf002e 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -3,6 +3,7 @@
请禁用针对媒体锁屏播放的电池优化。
电池优化
离线模式
+ 添加到播放列表
添加到队列
全部下载
查看该艺术家
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5fd1ac33..455701e0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,6 +3,7 @@
Please disable battery optimizations for media playback while the screen is off.
Battery Optimizations
Offline mode
+ Add to playlist
Add to queue
Download all
Go to artist
From d66f96432d2d74c3f9fd4e64f7eaa2af57d25e46 Mon Sep 17 00:00:00 2001
From: Matthew Simpson
Date: Sun, 9 Mar 2025 15:16:04 +0000
Subject: [PATCH 03/26] Add "Add to playlist" menu button to Album pages
---
.../tempo/ui/fragment/AlbumPageFragment.java | 13 +++++++++++++
app/src/main/res/menu/album_page_menu.xml | 5 +++++
app/src/main/res/values-de/strings.xml | 1 +
app/src/main/res/values-fr/strings.xml | 1 +
app/src/main/res/values-it/strings.xml | 3 ++-
app/src/main/res/values-ko/strings.xml | 1 +
app/src/main/res/values-pt/strings.xml | 1 +
app/src/main/res/values-ru/strings.xml | 1 +
app/src/main/res/values-zh/strings.xml | 1 +
app/src/main/res/values/strings.xml | 1 +
10 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/AlbumPageFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/AlbumPageFragment.java
index 8162b16b..f830888e 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/AlbumPageFragment.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/AlbumPageFragment.java
@@ -31,6 +31,7 @@ import com.cappielloantonio.tempo.service.MediaManager;
import com.cappielloantonio.tempo.service.MediaService;
import com.cappielloantonio.tempo.ui.activity.MainActivity;
import com.cappielloantonio.tempo.ui.adapter.SongHorizontalAdapter;
+import com.cappielloantonio.tempo.ui.dialog.PlaylistChooserDialog;
import com.cappielloantonio.tempo.util.Constants;
import com.cappielloantonio.tempo.util.DownloadUtil;
import com.cappielloantonio.tempo.util.MappingUtil;
@@ -38,6 +39,7 @@ import com.cappielloantonio.tempo.util.MusicUtil;
import com.cappielloantonio.tempo.viewmodel.AlbumPageViewModel;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -108,6 +110,17 @@ public class AlbumPageFragment extends Fragment implements ClickCallback {
});
return true;
}
+ if (item.getItemId() == R.id.action_add_to_playlist) {
+ albumPageViewModel.getAlbumSongLiveList().observe(getViewLifecycleOwner(), songs -> {
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(Constants.TRACKS_OBJECT, new ArrayList<>(songs));
+
+ PlaylistChooserDialog dialog = new PlaylistChooserDialog();
+ dialog.setArguments(bundle);
+ dialog.show(requireActivity().getSupportFragmentManager(), null);
+ });
+ return true;
+ }
return false;
}
diff --git a/app/src/main/res/menu/album_page_menu.xml b/app/src/main/res/menu/album_page_menu.xml
index 5a5e6f26..4524d32f 100644
--- a/app/src/main/res/menu/album_page_menu.xml
+++ b/app/src/main/res/menu/album_page_menu.xml
@@ -6,4 +6,9 @@
android:icon="@drawable/ic_file_download"
android:title="@string/menu_download_all_button"
app:showAsAction="never" />
+
\ No newline at end of file
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 8bb5f367..f14b967c 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -155,6 +155,7 @@
Subsonic Server
Cast
Hinzufügen
+ Zu Playliste hinzufügen
Alle Herunterladen
Downloads
Alle
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 617b6fcb..d62bd653 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -134,6 +134,7 @@
Serveurs Subsonic
Cast
Ajouter
+ Ajouter à une playlist
Télécharger tout
Téléchargé
Tout
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index d402c769..d531595f 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -157,7 +157,8 @@
Server Subsonic
Trasmetti
Aggiungi
- Scarica tutto
+ Aggiungi alla playlist
+ Scarica tutto
Scarica
Tutti
Scaricati
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 71128ca5..17577ec9 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -136,6 +136,7 @@
Subsonic 서버
Cast
추가
+ 플레이리스트에 추가
모두 다운로드
다운로드
모두
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 5f688e54..b2e52801 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -135,6 +135,7 @@
Servidores Subsonic
Transmitir
Adicionar
+ Adicionar a uma playlist
Baixar todos
Download
Todos
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 684d5e8a..c6d74949 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -154,6 +154,7 @@
Subsonic серверы
Cast
Добавить
+ Добавить в плейлист
Скачать все
Скачать
Все
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 1daf002e..1d0e6bdc 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -138,6 +138,7 @@
Subsonic 服务器
投送
添加
+ 添加到播放列表
全部下载
下载
全部
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 455701e0..73cf899b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -159,6 +159,7 @@
Subsonic servers
Cast
Add
+ Add to playlist
Download all
Download
All
From 44562f7d4bb9b2a9647be71491521dcfde1672ea Mon Sep 17 00:00:00 2001
From: SemvdH
Date: Wed, 26 Mar 2025 22:35:53 +0100
Subject: [PATCH 04/26] Display toast message after adding a song to a playlist
---
.../tempo/repository/PlaylistRepository.java | 7 +++++--
app/src/main/res/values-de/strings.xml | 2 ++
app/src/main/res/values-fr/strings.xml | 2 ++
app/src/main/res/values-it/strings.xml | 2 ++
app/src/main/res/values-ko/strings.xml | 2 ++
app/src/main/res/values-pt/strings.xml | 2 ++
app/src/main/res/values-ru/strings.xml | 2 ++
app/src/main/res/values-zh/strings.xml | 2 ++
app/src/main/res/values/strings.xml | 2 ++
9 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
index bcf0c732..091e846d 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
@@ -1,10 +1,13 @@
package com.cappielloantonio.tempo.repository;
+import android.widget.Toast;
+
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.tempo.App;
+import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.database.AppDatabase;
import com.cappielloantonio.tempo.database.dao.PlaylistDao;
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
@@ -80,12 +83,12 @@ public class PlaylistRepository {
.enqueue(new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
-
+ Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_success), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
-
+ Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_failure), Toast.LENGTH_SHORT).show();
}
});
}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 5c627b9a..a2b89f17 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -186,6 +186,8 @@
Abbrechen
Erstellen
Zu einer Playliste hinzufügen
+ Lied zu Playlist hinzugefügt
+ Titel kann nicht zur Playlist hinzugefügt werden
%1$d Tracks • %2$s
Länge • %1$s
Zum Löschen lange drücken
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 03a2f0db..715f8d45 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -159,6 +159,8 @@
Annuler
Créer
Ajouter à une playlist
+ Ajout d'une chanson à la playlist
+ Échec de l'ajout d'une chanson à la playlist
%1$d titres • %2$s
Durée • %1$s
Nom de la playlist
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 2cc5bcb6..493161b7 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -188,6 +188,8 @@
Annulla
Crea
Aggiungi a una playlist
+ Aggiunta di un brano alla playlist
+ Impossibile aggiungere un brano alla playlist
%1$d brani • %2$s
Durata • %1$s
Premi a lungo per eliminare
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 679f333a..59e5e39a 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -161,6 +161,8 @@
취소
생성
플레이리스트 추가
+ 재생 목록에 노래 추가
+ 재생 목록에 노래를 추가하지 못했습니다.
%1$d 트랙 • %2$s
재생시간 • %1$s
플레이리스트 이름
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 12f04a31..223093d8 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -160,6 +160,8 @@
Cancelar
Criar
Adicionar a uma playlist
+ Adicionada playlist de reprodução
+ Falha ao adicionar uma playlist de reprodução
%1$d faixas • %2$s
Duração • %1$s
Nome da playlist
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 0f893b90..259036f4 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -186,6 +186,8 @@
Отмена
Создать
Добавить в плейлист
+ Добавьте песню в плейлист
+ Не удалось добавить песню в список воспроизведения
%1$d треков • %2$s
Продолжительность • %1$s
Долгое нажатие для удаления
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 915b33d1..4564147b 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -165,6 +165,8 @@
取消
新建
添加到播放列表
+ 将歌曲添加到播放列表
+ 未能将歌曲添加到播放列表
%1$d 首曲目 • %2$s
持续时间 • %1$s
播放列表名称
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5fd1ac33..3db80974 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -194,6 +194,8 @@
Cancel
Create
Add to a playlist
+ Added song to playlist
+ Failed to add song to playlist
%1$d tracks • %2$s
Duration • %1$s
Long press to delete
From 27acf968adb4027dfe0cee53008fb21593a14868 Mon Sep 17 00:00:00 2001
From: kibirisu
Date: Wed, 23 Apr 2025 02:29:29 +0200
Subject: [PATCH 05/26] Fix redirection from album fragment to artist fragment
on artist label click
---
.../cappielloantonio/tempo/viewmodel/AlbumPageViewModel.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/AlbumPageViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/AlbumPageViewModel.java
index 6c244505..0979f408 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/AlbumPageViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/AlbumPageViewModel.java
@@ -21,6 +21,7 @@ public class AlbumPageViewModel extends AndroidViewModel {
private final AlbumRepository albumRepository;
private final ArtistRepository artistRepository;
private String albumId;
+ private String artistId;
private final MutableLiveData album = new MutableLiveData<>(null);
public AlbumPageViewModel(@NonNull Application application) {
@@ -41,6 +42,7 @@ public class AlbumPageViewModel extends AndroidViewModel {
public void setAlbum(LifecycleOwner owner, AlbumID3 album) {
this.albumId = album.getId();
this.album.postValue(album);
+ this.artistId = album.getArtistId();
albumRepository.getAlbum(album.getId()).observe(owner, albums -> {
if (albums != null) this.album.setValue(albums);
@@ -48,7 +50,7 @@ public class AlbumPageViewModel extends AndroidViewModel {
}
public LiveData getArtist() {
- return artistRepository.getArtistInfo(albumId);
+ return artistRepository.getArtistInfo(artistId);
}
public LiveData getAlbumInfo() {
From 20f5c8f295f51cc63a8ccecf90627322148c8fda Mon Sep 17 00:00:00 2001
From: observer
Date: Mon, 26 May 2025 14:06:25 +0100
Subject: [PATCH 06/26] fetch 1000 songs in discovery by default
---
.../com/cappielloantonio/tempo/viewmodel/HomeViewModel.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java
index a780d1cf..b646bcf1 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/HomeViewModel.java
@@ -94,7 +94,7 @@ public class HomeViewModel extends AndroidViewModel {
}
public LiveData> getRandomShuffleSample() {
- return songRepository.getRandomSample(100, null, null);
+ return songRepository.getRandomSample(1000, null, null);
}
public LiveData> getChronologySample(LifecycleOwner owner) {
From 8b731292a8478a3fcee448a29cf4dcd8e4d3798b Mon Sep 17 00:00:00 2001
From: observer
Date: Mon, 26 May 2025 14:08:23 +0100
Subject: [PATCH 07/26] fetch thumbnails before loading full res image
---
.../tempo/ui/adapter/PlayerSongQueueAdapter.java | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PlayerSongQueueAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PlayerSongQueueAdapter.java
index c7543f39..5747eab1 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PlayerSongQueueAdapter.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PlayerSongQueueAdapter.java
@@ -1,5 +1,6 @@
package com.cappielloantonio.tempo.ui.adapter;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -10,6 +11,7 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.media3.session.MediaBrowser;
import androidx.recyclerview.widget.RecyclerView;
+import com.bumptech.glide.RequestBuilder;
import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.databinding.ItemPlayerQueueSongBinding;
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
@@ -46,7 +48,7 @@ public class PlayerSongQueueAdapter extends RecyclerView.Adapter thumbnail = CustomGlideRequest.Builder
+ .from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
+ .build()
+ .sizeMultiplier(0.1f);
+
CustomGlideRequest.Builder
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
.build()
+ .thumbnail(thumbnail)
.into(holder.item.queueSongCoverImageView);
MediaManager.getCurrentIndex(mediaBrowserListenableFuture, new MediaIndexCallback() {
@Override
public void onRecovery(int index) {
- if (position < index) {
+ if (holder.getLayoutPosition() < index) {
holder.item.queueSongTitleTextView.setAlpha(0.2f);
holder.item.queueSongSubtitleTextView.setAlpha(0.2f);
holder.item.ratingIndicatorImageView.setAlpha(0.2f);
From b18b641c311ed90d50caaf99eb1fda86e45ab112 Mon Sep 17 00:00:00 2001
From: observer
Date: Mon, 26 May 2025 14:09:26 +0100
Subject: [PATCH 08/26] fix nestedscrollview breaking recyclerview out-of-view
culling
---
.../layout/inner_fragment_player_queue.xml | 42 +++++++------------
1 file changed, 15 insertions(+), 27 deletions(-)
diff --git a/app/src/main/res/layout/inner_fragment_player_queue.xml b/app/src/main/res/layout/inner_fragment_player_queue.xml
index c8390eba..72a70a22 100644
--- a/app/src/main/res/layout/inner_fragment_player_queue.xml
+++ b/app/src/main/res/layout/inner_fragment_player_queue.xml
@@ -4,39 +4,27 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+
-
+ android:layout_height="match_parent"
+ android:layout_marginTop="40dp"
+ android:paddingTop="8dp"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
-
-
-
-
-
-
-
-
Date: Sun, 23 Mar 2025 12:31:57 -0300
Subject: [PATCH 09/26] Removed hardcoded limit to playlist shuffle
---
.../tempo/ui/fragment/PlaylistPageFragment.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlaylistPageFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlaylistPageFragment.java
index 39c72468..55b46ff2 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlaylistPageFragment.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlaylistPageFragment.java
@@ -193,13 +193,13 @@ public class PlaylistPageFragment extends Fragment implements ClickCallback {
playlistPageViewModel.getPlaylistSongLiveList().observe(getViewLifecycleOwner(), songs -> {
if (bind != null) {
bind.playlistPagePlayButton.setOnClickListener(v -> {
- MediaManager.startQueue(mediaBrowserListenableFuture, songs.subList(0, Math.min(100, songs.size())), 0);
+ MediaManager.startQueue(mediaBrowserListenableFuture, songs, 0);
activity.setBottomSheetInPeek(true);
});
bind.playlistPageShuffleButton.setOnClickListener(v -> {
Collections.shuffle(songs);
- MediaManager.startQueue(mediaBrowserListenableFuture, songs.subList(0, Math.min(100, songs.size())), 0);
+ MediaManager.startQueue(mediaBrowserListenableFuture, songs, 0);
activity.setBottomSheetInPeek(true);
});
}
@@ -270,4 +270,4 @@ public class PlaylistPageFragment extends Fragment implements ClickCallback {
public void onMediaLongClick(Bundle bundle) {
Navigation.findNavController(requireView()).navigate(R.id.songBottomSheetDialog, bundle);
}
-}
\ No newline at end of file
+}
From 7935a9664b3800ad765ca8ba303ceb2d59ccb4b3 Mon Sep 17 00:00:00 2001
From: Robin Slot
Date: Sat, 7 Jun 2025 10:18:23 +0200
Subject: [PATCH 10/26] Fix crash when sorting albums with a null artist
---
.../tempo/ui/adapter/AlbumCatalogueAdapter.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java
index 1fc970ab..1f360c80 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java
@@ -157,7 +157,7 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter
Date: Sun, 29 Jun 2025 19:13:31 +0930
Subject: [PATCH 11/26] feat: Store and retrieve replay and shuffle states in
preferences
---
.../fragment/PlayerBottomSheetFragment.java | 13 +++++++++++
.../ui/fragment/PlayerControllerFragment.java | 12 ++++++++++
.../tempo/util/Preferences.kt | 23 +++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerBottomSheetFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerBottomSheetFragment.java
index dafd1507..b3755ee3 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerBottomSheetFragment.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerBottomSheetFragment.java
@@ -112,6 +112,9 @@ public class PlayerBottomSheetFragment extends Fragment {
try {
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
+ mediaBrowser.setShuffleModeEnabled(Preferences.isShuffleModeEnabled());
+ mediaBrowser.setRepeatMode(Preferences.getRepeatMode());
+
setMediaControllerListener(mediaBrowser);
} catch (Exception e) {
e.printStackTrace();
@@ -150,6 +153,16 @@ public class PlayerBottomSheetFragment extends Fragment {
public void onEvents(Player player, Player.Events events) {
setHeaderNextButtonState(mediaBrowser.hasNextMediaItem());
}
+
+ @Override
+ public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
+ Preferences.setShuffleModeEnabled(shuffleModeEnabled);
+ }
+
+ @Override
+ public void onRepeatModeChanged(int repeatMode) {
+ Preferences.setRepeatMode(repeatMode);
+ }
});
}
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java
index 1d474db9..d1daae9b 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java
@@ -140,6 +140,8 @@ public class PlayerControllerFragment extends Fragment {
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
bind.nowPlayingMediaControllerView.setPlayer(mediaBrowser);
+ mediaBrowser.setShuffleModeEnabled(Preferences.isShuffleModeEnabled());
+ mediaBrowser.setRepeatMode(Preferences.getRepeatMode());
setMediaControllerListener(mediaBrowser);
} catch (Exception e) {
@@ -160,6 +162,16 @@ public class PlayerControllerFragment extends Fragment {
setMetadata(mediaMetadata);
setMediaInfo(mediaMetadata);
}
+
+ @Override
+ public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
+ Preferences.setShuffleModeEnabled(shuffleModeEnabled);
+ }
+
+ @Override
+ public void onRepeatModeChanged(int repeatMode) {
+ Preferences.setRepeatMode(repeatMode);
+ }
});
}
diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt b/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt
index 5cbe9035..e7a4c459 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt
+++ b/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt
@@ -1,6 +1,7 @@
package com.cappielloantonio.tempo.util
import android.util.Log
+import androidx.media3.common.Player
import com.cappielloantonio.tempo.App
import com.cappielloantonio.tempo.model.HomeSector
import com.cappielloantonio.tempo.subsonic.models.OpenSubsonicExtension
@@ -24,6 +25,8 @@ object Preferences {
private const val NEXT_SERVER_SWITCH = "next_server_switch"
private const val PLAYBACK_SPEED = "playback_speed"
private const val SKIP_SILENCE = "skip_silence"
+ private const val SHUFFLE_MODE = "shuffle_mode"
+ private const val REPEAT_MODE = "repeat_mode"
private const val IMAGE_CACHE_SIZE = "image_cache_size"
private const val STREAMING_CACHE_SIZE = "streaming_cache_size"
private const val IMAGE_SIZE = "image_size"
@@ -226,6 +229,26 @@ object Preferences {
App.getInstance().preferences.edit().putBoolean(SKIP_SILENCE, isSkipSilenceMode).apply()
}
+ @JvmStatic
+ fun isShuffleModeEnabled(): Boolean {
+ return App.getInstance().preferences.getBoolean(SHUFFLE_MODE, false)
+ }
+
+ @JvmStatic
+ fun setShuffleModeEnabled(shuffleModeEnabled: Boolean) {
+ App.getInstance().preferences.edit().putBoolean(SHUFFLE_MODE, shuffleModeEnabled).apply()
+ }
+
+ @JvmStatic
+ fun getRepeatMode(): Int {
+ return App.getInstance().preferences.getInt(REPEAT_MODE, Player.REPEAT_MODE_OFF)
+ }
+
+ @JvmStatic
+ fun setRepeatMode(repeatMode: Int) {
+ App.getInstance().preferences.edit().putInt(REPEAT_MODE, repeatMode).apply()
+ }
+
@JvmStatic
fun getImageCacheSize(): Int {
return App.getInstance().preferences.getString(IMAGE_CACHE_SIZE, "500")!!.toInt()
From fb153d7a6cf7ff0a10fb77acd7926c2108dcbd00 Mon Sep 17 00:00:00 2001
From: le-firehawk
Date: Tue, 1 Jul 2025 09:31:36 +0930
Subject: [PATCH 12/26] feat: enhance Android media player notification window
---
.../tempo/service/MediaService.kt | 108 +++++++++++++++---
.../service/MediaLibraryServiceCallback.kt | 84 ++++++++++----
.../tempo/service/MediaService.kt | 23 +++-
.../service/MediaLibraryServiceCallback.kt | 84 ++++++++++----
.../tempo/service/MediaService.kt | 23 +++-
5 files changed, 255 insertions(+), 67 deletions(-)
diff --git a/app/src/notquitemy/java/com/cappielloantonio/tempo/service/MediaService.kt b/app/src/notquitemy/java/com/cappielloantonio/tempo/service/MediaService.kt
index 7125b9fd..b8a7179b 100644
--- a/app/src/notquitemy/java/com/cappielloantonio/tempo/service/MediaService.kt
+++ b/app/src/notquitemy/java/com/cappielloantonio/tempo/service/MediaService.kt
@@ -32,7 +32,8 @@ class MediaService : MediaLibraryService() {
private lateinit var player: ExoPlayer
private lateinit var mediaLibrarySession: MediaLibrarySession
- private lateinit var customCommands: List
+ private lateinit var shuffleCommands: List
+ private lateinit var repeatCommands: List
private var customLayout = ImmutableList.of()
@@ -41,6 +42,12 @@ class MediaService : MediaLibraryService() {
"android.media3.session.demo.SHUFFLE_ON"
private const val CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF =
"android.media3.session.demo.SHUFFLE_OFF"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF =
+ "android.media3.session.demo.REPEAT_OFF"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE =
+ "android.media3.session.demo.REPEAT_ONE"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL =
+ "android.media3.session.demo.REPEAT_ALL"
}
override fun onCreate() {
@@ -72,7 +79,7 @@ class MediaService : MediaLibraryService() {
val connectionResult = super.onConnect(session, controller)
val availableSessionCommands = connectionResult.availableSessionCommands.buildUpon()
- customCommands.forEach { commandButton ->
+ shuffleCommands.forEach { commandButton ->
// TODO: Aggiungere i comandi personalizzati
// commandButton.sessionCommand?.let { availableSessionCommands.add(it) }
}
@@ -89,22 +96,40 @@ class MediaService : MediaLibraryService() {
}
}
+ fun buildCustomLayout(player: Player): ImmutableList {
+ val shuffle = shuffleCommands[if (player.shuffleModeEnabled) 1 else 0]
+ val repeat = when (player.repeatMode) {
+ Player.REPEAT_MODE_ONE -> repeatCommands[1]
+ Player.REPEAT_MODE_ALL -> repeatCommands[2]
+ else -> repeatCommands[0]
+ }
+ return ImmutableList.of(shuffle, repeat)
+ }
+
override fun onCustomCommand(
session: MediaSession,
controller: ControllerInfo,
customCommand: SessionCommand,
args: Bundle
): ListenableFuture {
- if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON == customCommand.customAction) {
- player.shuffleModeEnabled = true
- customLayout = ImmutableList.of(customCommands[1])
- session.setCustomLayout(customLayout)
- } else if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF == customCommand.customAction) {
- player.shuffleModeEnabled = false
- customLayout = ImmutableList.of(customCommands[0])
- session.setCustomLayout(customLayout)
+ when (customCommand.customAction) {
+ CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON -> player.shuffleModeEnabled = true
+ CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF -> player.shuffleModeEnabled = false
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF,
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL,
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> {
+ val nextMode = when (player.repeatMode) {
+ Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_ALL
+ Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ONE
+ else -> Player.REPEAT_MODE_OFF
+ }
+ player.repeatMode = nextMode
+ }
}
+ customLayout = librarySessionCallback.buildCustomLayout(player)
+ session.setCustomLayout(customLayout)
+
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
@@ -125,17 +150,28 @@ class MediaService : MediaLibraryService() {
}
private fun initializeCustomCommands() {
- customCommands =
- listOf(
- getShuffleCommandButton(
- SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON, Bundle.EMPTY)
- ),
- getShuffleCommandButton(
- SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF, Bundle.EMPTY)
- )
+ shuffleCommands = listOf(
+ getShuffleCommandButton(
+ SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON, Bundle.EMPTY)
+ ),
+ getShuffleCommandButton(
+ SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF, Bundle.EMPTY)
)
+ )
- customLayout = ImmutableList.of(customCommands[0])
+ repeatCommands = listOf(
+ getRepeatCommandButton(
+ SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF, Bundle.EMPTY)
+ ),
+ getRepeatCommandButton(
+ SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE, Bundle.EMPTY)
+ ),
+ getRepeatCommandButton(
+ SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL, Bundle.EMPTY)
+ )
+ )
+
+ customLayout = ImmutableList.of(shuffleCommands[0], repeatCommands[0])
}
private fun initializePlayer() {
@@ -147,6 +183,9 @@ class MediaService : MediaLibraryService() {
.setWakeMode(C.WAKE_MODE_NETWORK)
.setLoadControl(initializeLoadControl())
.build()
+
+ player.shuffleModeEnabled = Preferences.isShuffleModeEnabled()
+ player.repeatMode = Preferences.getRepeatMode()
}
private fun initializeMediaLibrarySession() {
@@ -224,6 +263,18 @@ class MediaService : MediaLibraryService() {
}
}
}
+
+ override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
+ Preferences.setShuffleModeEnabled(shuffleModeEnabled)
+ customLayout = librarySessionCallback.buildCustomLayout(player)
+ mediaLibrarySession.setCustomLayout(customLayout)
+ }
+
+ override fun onRepeatModeChanged(repeatMode: Int) {
+ Preferences.setRepeatMode(repeatMode)
+ customLayout = librarySessionCallback.buildCustomLayout(player)
+ mediaLibrarySession.setCustomLayout(customLayout)
+ }
})
}
@@ -251,6 +302,25 @@ class MediaService : MediaLibraryService() {
.build()
}
+ @SuppressLint("PrivateResource")
+ private fun getRepeatCommandButton(sessionCommand: SessionCommand): CommandButton {
+ val icon = when (sessionCommand.customAction) {
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> R.drawable.exo_icon_repeat_one
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL -> R.drawable.exo_icon_repeat_all
+ else -> R.drawable.exo_icon_repeat_off
+ }
+ val description = when (sessionCommand.customAction) {
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> R.string.exo_controls_repeat_one_description
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL -> R.string.exo_controls_repeat_all_description
+ else -> R.string.exo_controls_repeat_off_description
+ }
+ return CommandButton.Builder()
+ .setDisplayName(getString(description))
+ .setSessionCommand(sessionCommand)
+ .setIconResId(icon)
+ .build()
+ }
+
private fun ignoreFuture(customLayout: ListenableFuture) {
/* Do nothing. */
}
diff --git a/app/src/play/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt b/app/src/play/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt
index 747a45b2..099ae672 100644
--- a/app/src/play/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt
+++ b/app/src/play/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt
@@ -4,6 +4,7 @@ import android.content.Context
import android.os.Bundle
import androidx.annotation.OptIn
import androidx.media3.common.MediaItem
+import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.CommandButton
import androidx.media3.session.LibraryResult
@@ -27,7 +28,7 @@ open class MediaLibrarySessionCallback(
MediaBrowserTree.initialize(automotiveRepository)
}
- private val customLayoutCommandButtons: List = listOf(
+ private val shuffleCommandButtons: List = listOf(
CommandButton.Builder()
.setDisplayName(context.getString(R.string.exo_controls_shuffle_on_description))
.setSessionCommand(
@@ -45,15 +46,46 @@ open class MediaLibrarySessionCallback(
).setIconResId(R.drawable.exo_icon_shuffle_on).build()
)
+ private val repeatCommandButtons: List = listOf(
+ CommandButton.Builder()
+ .setDisplayName(context.getString(R.string.exo_controls_repeat_off_description))
+ .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF, Bundle.EMPTY))
+ .setIconResId(R.drawable.exo_icon_repeat_off)
+ .build(),
+ CommandButton.Builder()
+ .setDisplayName(context.getString(R.string.exo_controls_repeat_one_description))
+ .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE, Bundle.EMPTY))
+ .setIconResId(R.drawable.exo_icon_repeat_one)
+ .build(),
+ CommandButton.Builder()
+ .setDisplayName(context.getString(R.string.exo_controls_repeat_all_description))
+ .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL, Bundle.EMPTY))
+ .setIconResId(R.drawable.exo_icon_repeat_all)
+ .build()
+ )
+
+ private val customLayoutCommandButtons: List =
+ shuffleCommandButtons + repeatCommandButtons
+
@OptIn(UnstableApi::class)
val mediaNotificationSessionCommands =
MediaSession.ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS.buildUpon()
.also { builder ->
- customLayoutCommandButtons.forEach { commandButton ->
+ (shuffleCommandButtons + repeatCommandButtons).forEach { commandButton ->
commandButton.sessionCommand?.let { builder.add(it) }
}
}.build()
+ fun buildCustomLayout(player: Player): ImmutableList {
+ val shuffle = shuffleCommandButtons[if (player.shuffleModeEnabled) 1 else 0]
+ val repeat = when (player.repeatMode) {
+ Player.REPEAT_MODE_ONE -> repeatCommandButtons[1]
+ Player.REPEAT_MODE_ALL -> repeatCommandButtons[2]
+ else -> repeatCommandButtons[0]
+ }
+ return ImmutableList.of(shuffle, repeat)
+ }
+
@OptIn(UnstableApi::class)
override fun onConnect(
session: MediaSession, controller: MediaSession.ControllerInfo
@@ -62,12 +94,11 @@ open class MediaLibrarySessionCallback(
controller
) || session.isAutoCompanionController(controller)
) {
- val customLayout =
- customLayoutCommandButtons[if (session.player.shuffleModeEnabled) 1 else 0]
+ val customLayout = buildCustomLayout(session.player)
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
.setAvailableSessionCommands(mediaNotificationSessionCommands)
- .setCustomLayout(ImmutableList.of(customLayout)).build()
+ .setCustomLayout(customLayout).build()
}
return MediaSession.ConnectionResult.AcceptedResultBuilder(session).build()
@@ -80,25 +111,28 @@ open class MediaLibrarySessionCallback(
customCommand: SessionCommand,
args: Bundle
): ListenableFuture {
- if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON == customCommand.customAction) {
- session.player.shuffleModeEnabled = true
- session.setCustomLayout(
- session.mediaNotificationControllerInfo!!,
- ImmutableList.of(customLayoutCommandButtons[1])
- )
-
- return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
- } else if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF == customCommand.customAction) {
- session.player.shuffleModeEnabled = false
- session.setCustomLayout(
- session.mediaNotificationControllerInfo!!,
- ImmutableList.of(customLayoutCommandButtons[0])
- )
-
- return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
+ when (customCommand.customAction) {
+ CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON -> session.player.shuffleModeEnabled = true
+ CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF -> session.player.shuffleModeEnabled = false
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF,
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL,
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> {
+ val nextMode = when (session.player.repeatMode) {
+ Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_ALL
+ Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ONE
+ else -> Player.REPEAT_MODE_OFF
+ }
+ session.player.repeatMode = nextMode
+ }
+ else -> return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
}
- return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
+ session.setCustomLayout(
+ session.mediaNotificationControllerInfo!!,
+ buildCustomLayout(session.player)
+ )
+
+ return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
override fun onGetLibraryRoot(
@@ -158,5 +192,11 @@ open class MediaLibrarySessionCallback(
"android.media3.session.demo.SHUFFLE_ON"
private const val CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF =
"android.media3.session.demo.SHUFFLE_OFF"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF =
+ "android.media3.session.demo.REPEAT_OFF"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE =
+ "android.media3.session.demo.REPEAT_ONE"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL =
+ "android.media3.session.demo.REPEAT_ALL"
}
}
\ No newline at end of file
diff --git a/app/src/play/java/com/cappielloantonio/tempo/service/MediaService.kt b/app/src/play/java/com/cappielloantonio/tempo/service/MediaService.kt
index b993aaba..2391a2bb 100644
--- a/app/src/play/java/com/cappielloantonio/tempo/service/MediaService.kt
+++ b/app/src/play/java/com/cappielloantonio/tempo/service/MediaService.kt
@@ -33,6 +33,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
private lateinit var player: ExoPlayer
private lateinit var castPlayer: CastPlayer
private lateinit var mediaLibrarySession: MediaLibrarySession
+ private lateinit var librarySessionCallback: MediaLibrarySessionCallback
override fun onCreate() {
super.onCreate()
@@ -79,6 +80,9 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
.setWakeMode(C.WAKE_MODE_NETWORK)
.setLoadControl(initializeLoadControl())
.build()
+
+ player.shuffleModeEnabled = Preferences.isShuffleModeEnabled()
+ player.repeatMode = Preferences.getRepeatMode()
}
private fun initializeCastPlayer() {
@@ -97,13 +101,14 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
getPendingIntent(0, FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT)
}
+ librarySessionCallback = createLibrarySessionCallback()
mediaLibrarySession =
- MediaLibrarySession.Builder(this, player, createLibrarySessionCallback())
+ MediaLibrarySession.Builder(this, player, librarySessionCallback)
.setSessionActivity(sessionActivityPendingIntent)
.build()
}
- private fun createLibrarySessionCallback(): MediaLibrarySession.Callback {
+ private fun createLibrarySessionCallback(): MediaLibrarySessionCallback {
return MediaLibrarySessionCallback(this, automotiveRepository)
}
@@ -166,6 +171,20 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
}
}
}
+
+ override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
+ Preferences.setShuffleModeEnabled(shuffleModeEnabled)
+ mediaLibrarySession.setCustomLayout(
+ librarySessionCallback.buildCustomLayout(player)
+ )
+ }
+
+ override fun onRepeatModeChanged(repeatMode: Int) {
+ Preferences.setRepeatMode(repeatMode)
+ mediaLibrarySession.setCustomLayout(
+ librarySessionCallback.buildCustomLayout(player)
+ )
+ }
})
}
diff --git a/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt b/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt
index 747a45b2..099ae672 100644
--- a/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt
+++ b/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaLibraryServiceCallback.kt
@@ -4,6 +4,7 @@ import android.content.Context
import android.os.Bundle
import androidx.annotation.OptIn
import androidx.media3.common.MediaItem
+import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.CommandButton
import androidx.media3.session.LibraryResult
@@ -27,7 +28,7 @@ open class MediaLibrarySessionCallback(
MediaBrowserTree.initialize(automotiveRepository)
}
- private val customLayoutCommandButtons: List = listOf(
+ private val shuffleCommandButtons: List = listOf(
CommandButton.Builder()
.setDisplayName(context.getString(R.string.exo_controls_shuffle_on_description))
.setSessionCommand(
@@ -45,15 +46,46 @@ open class MediaLibrarySessionCallback(
).setIconResId(R.drawable.exo_icon_shuffle_on).build()
)
+ private val repeatCommandButtons: List = listOf(
+ CommandButton.Builder()
+ .setDisplayName(context.getString(R.string.exo_controls_repeat_off_description))
+ .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF, Bundle.EMPTY))
+ .setIconResId(R.drawable.exo_icon_repeat_off)
+ .build(),
+ CommandButton.Builder()
+ .setDisplayName(context.getString(R.string.exo_controls_repeat_one_description))
+ .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE, Bundle.EMPTY))
+ .setIconResId(R.drawable.exo_icon_repeat_one)
+ .build(),
+ CommandButton.Builder()
+ .setDisplayName(context.getString(R.string.exo_controls_repeat_all_description))
+ .setSessionCommand(SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL, Bundle.EMPTY))
+ .setIconResId(R.drawable.exo_icon_repeat_all)
+ .build()
+ )
+
+ private val customLayoutCommandButtons: List =
+ shuffleCommandButtons + repeatCommandButtons
+
@OptIn(UnstableApi::class)
val mediaNotificationSessionCommands =
MediaSession.ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS.buildUpon()
.also { builder ->
- customLayoutCommandButtons.forEach { commandButton ->
+ (shuffleCommandButtons + repeatCommandButtons).forEach { commandButton ->
commandButton.sessionCommand?.let { builder.add(it) }
}
}.build()
+ fun buildCustomLayout(player: Player): ImmutableList {
+ val shuffle = shuffleCommandButtons[if (player.shuffleModeEnabled) 1 else 0]
+ val repeat = when (player.repeatMode) {
+ Player.REPEAT_MODE_ONE -> repeatCommandButtons[1]
+ Player.REPEAT_MODE_ALL -> repeatCommandButtons[2]
+ else -> repeatCommandButtons[0]
+ }
+ return ImmutableList.of(shuffle, repeat)
+ }
+
@OptIn(UnstableApi::class)
override fun onConnect(
session: MediaSession, controller: MediaSession.ControllerInfo
@@ -62,12 +94,11 @@ open class MediaLibrarySessionCallback(
controller
) || session.isAutoCompanionController(controller)
) {
- val customLayout =
- customLayoutCommandButtons[if (session.player.shuffleModeEnabled) 1 else 0]
+ val customLayout = buildCustomLayout(session.player)
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
.setAvailableSessionCommands(mediaNotificationSessionCommands)
- .setCustomLayout(ImmutableList.of(customLayout)).build()
+ .setCustomLayout(customLayout).build()
}
return MediaSession.ConnectionResult.AcceptedResultBuilder(session).build()
@@ -80,25 +111,28 @@ open class MediaLibrarySessionCallback(
customCommand: SessionCommand,
args: Bundle
): ListenableFuture {
- if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON == customCommand.customAction) {
- session.player.shuffleModeEnabled = true
- session.setCustomLayout(
- session.mediaNotificationControllerInfo!!,
- ImmutableList.of(customLayoutCommandButtons[1])
- )
-
- return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
- } else if (CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF == customCommand.customAction) {
- session.player.shuffleModeEnabled = false
- session.setCustomLayout(
- session.mediaNotificationControllerInfo!!,
- ImmutableList.of(customLayoutCommandButtons[0])
- )
-
- return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
+ when (customCommand.customAction) {
+ CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON -> session.player.shuffleModeEnabled = true
+ CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF -> session.player.shuffleModeEnabled = false
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF,
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL,
+ CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> {
+ val nextMode = when (session.player.repeatMode) {
+ Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_ALL
+ Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ONE
+ else -> Player.REPEAT_MODE_OFF
+ }
+ session.player.repeatMode = nextMode
+ }
+ else -> return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
}
- return Futures.immediateFuture(SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED))
+ session.setCustomLayout(
+ session.mediaNotificationControllerInfo!!,
+ buildCustomLayout(session.player)
+ )
+
+ return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
override fun onGetLibraryRoot(
@@ -158,5 +192,11 @@ open class MediaLibrarySessionCallback(
"android.media3.session.demo.SHUFFLE_ON"
private const val CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF =
"android.media3.session.demo.SHUFFLE_OFF"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF =
+ "android.media3.session.demo.REPEAT_OFF"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE =
+ "android.media3.session.demo.REPEAT_ONE"
+ private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL =
+ "android.media3.session.demo.REPEAT_ALL"
}
}
\ No newline at end of file
diff --git a/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaService.kt b/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaService.kt
index b993aaba..2391a2bb 100644
--- a/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaService.kt
+++ b/app/src/tempo/java/com/cappielloantonio/tempo/service/MediaService.kt
@@ -33,6 +33,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
private lateinit var player: ExoPlayer
private lateinit var castPlayer: CastPlayer
private lateinit var mediaLibrarySession: MediaLibrarySession
+ private lateinit var librarySessionCallback: MediaLibrarySessionCallback
override fun onCreate() {
super.onCreate()
@@ -79,6 +80,9 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
.setWakeMode(C.WAKE_MODE_NETWORK)
.setLoadControl(initializeLoadControl())
.build()
+
+ player.shuffleModeEnabled = Preferences.isShuffleModeEnabled()
+ player.repeatMode = Preferences.getRepeatMode()
}
private fun initializeCastPlayer() {
@@ -97,13 +101,14 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
getPendingIntent(0, FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT)
}
+ librarySessionCallback = createLibrarySessionCallback()
mediaLibrarySession =
- MediaLibrarySession.Builder(this, player, createLibrarySessionCallback())
+ MediaLibrarySession.Builder(this, player, librarySessionCallback)
.setSessionActivity(sessionActivityPendingIntent)
.build()
}
- private fun createLibrarySessionCallback(): MediaLibrarySession.Callback {
+ private fun createLibrarySessionCallback(): MediaLibrarySessionCallback {
return MediaLibrarySessionCallback(this, automotiveRepository)
}
@@ -166,6 +171,20 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
}
}
}
+
+ override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
+ Preferences.setShuffleModeEnabled(shuffleModeEnabled)
+ mediaLibrarySession.setCustomLayout(
+ librarySessionCallback.buildCustomLayout(player)
+ )
+ }
+
+ override fun onRepeatModeChanged(repeatMode: Int) {
+ Preferences.setRepeatMode(repeatMode)
+ mediaLibrarySession.setCustomLayout(
+ librarySessionCallback.buildCustomLayout(player)
+ )
+ }
})
}
From 6703704f2259e4bed34ad1df98d32452298940d4 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 18:21:24 -0700
Subject: [PATCH 13/26] fix: corrected the and updated the string message for
the toast. got the build working. It was not pretty.
---
.gitignore | 1 +
.idea/misc.xml | 1 +
app/build.gradle | 7 ++++++-
app/src/main/AndroidManifest.xml | 1 -
.../tempo/repository/PlaylistRepository.java | 12 +++++++++---
app/src/main/res/values-fr/strings.xml | 2 --
gradlew | 0
settings.gradle | 3 +++
8 files changed, 20 insertions(+), 7 deletions(-)
mode change 100644 => 100755 gradlew
diff --git a/.gitignore b/.gitignore
index 74483036..6e9024d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@
.cxx
/.idea/
.env
+.vscode/settings.json
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1d411cd3..d5950937 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -192,6 +192,7 @@
+
diff --git a/app/build.gradle b/app/build.gradle
index b6ee7b49..d26c39ed 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.0'
+ versionName '3.9.3'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
@@ -107,4 +107,9 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.14'
implementation 'com.squareup.retrofit2:converter-gson:2.11.0'
+}
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(17)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 986481bd..cc9990e7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,7 +6,6 @@
-
diff --git a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
index 091e846d..7884159f 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
@@ -1,5 +1,8 @@
package com.cappielloantonio.tempo.repository;
+import static android.provider.Settings.System.getString;
+
+import android.provider.Settings;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -23,6 +26,7 @@ import retrofit2.Callback;
import retrofit2.Response;
public class PlaylistRepository {
+ @androidx.media3.common.util.UnstableApi
private final PlaylistDao playlistDao = AppDatabase.getInstance().playlistDao();
public MutableLiveData> getPlaylists(boolean random, int size) {
MutableLiveData> listLivePlaylists = new MutableLiveData<>(new ArrayList<>());
@@ -83,12 +87,12 @@ public class PlaylistRepository {
.enqueue(new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
- Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_success), Toast.LENGTH_SHORT).show();
+ Toast.makeText(App.getContext(), App.getContext().getString(R.string.playlist_chooser_dialog_toast_add_success), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
- Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_failure), Toast.LENGTH_SHORT).show();
+ Toast.makeText(App.getContext(), App.getContext().getString(R.string.playlist_chooser_dialog_toast_add_failure), Toast.LENGTH_SHORT).show();
}
});
}
@@ -160,17 +164,19 @@ public class PlaylistRepository {
}
});
}
-
+ @androidx.media3.common.util.UnstableApi
public LiveData> getPinnedPlaylists() {
return playlistDao.getAll();
}
+ @androidx.media3.common.util.UnstableApi
public void insert(Playlist playlist) {
InsertThreadSafe insert = new InsertThreadSafe(playlistDao, playlist);
Thread thread = new Thread(insert);
thread.start();
}
+ @androidx.media3.common.util.UnstableApi
public void delete(Playlist playlist) {
DeleteThreadSafe delete = new DeleteThreadSafe(playlistDao, playlist);
Thread thread = new Thread(delete);
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 715f8d45..03a2f0db 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -159,8 +159,6 @@
Annuler
Créer
Ajouter à une playlist
- Ajout d'une chanson à la playlist
- Échec de l'ajout d'une chanson à la playlist
%1$d titres • %2$s
Durée • %1$s
Nom de la playlist
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/settings.gradle b/settings.gradle
index a7c6dd41..1cd079ae 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,5 @@
+plugins {
+ id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
+}
include ':app'
rootProject.name = "Tempo"
\ No newline at end of file
From 31ee749161c85e28e343b0fbd03573dfc5478197 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 19:07:44 -0700
Subject: [PATCH 14/26] merged and tested, bumping version
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index d26c39ed..ab1539d8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.3'
+ versionName '3.9.4'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
From 582dcc8885a7fdd6ad1797f9ea92ec8449d6447c Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Fri, 1 Aug 2025 16:09:22 -0700
Subject: [PATCH 15/26] chore: adding env for local dev
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index b1123a00..74483036 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@
.externalNativeBuild
.cxx
/.idea/
+.env
From fb8898c813292c6c0145053f33205894192c720b Mon Sep 17 00:00:00 2001
From: SemvdH
Date: Wed, 26 Mar 2025 22:35:53 +0100
Subject: [PATCH 16/26] Display toast message after adding a song to a playlist
---
.../tempo/repository/PlaylistRepository.java | 7 +++++--
app/src/main/res/values-de/strings.xml | 2 ++
app/src/main/res/values-fr/strings.xml | 2 ++
app/src/main/res/values-it/strings.xml | 2 ++
app/src/main/res/values-ko/strings.xml | 2 ++
app/src/main/res/values-pt/strings.xml | 2 ++
app/src/main/res/values-ru/strings.xml | 2 ++
app/src/main/res/values-zh/strings.xml | 2 ++
app/src/main/res/values/strings.xml | 2 ++
9 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
index bcf0c732..091e846d 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
@@ -1,10 +1,13 @@
package com.cappielloantonio.tempo.repository;
+import android.widget.Toast;
+
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.tempo.App;
+import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.database.AppDatabase;
import com.cappielloantonio.tempo.database.dao.PlaylistDao;
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
@@ -80,12 +83,12 @@ public class PlaylistRepository {
.enqueue(new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
-
+ Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_success), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
-
+ Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_failure), Toast.LENGTH_SHORT).show();
}
});
}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 5c627b9a..a2b89f17 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -186,6 +186,8 @@
Abbrechen
Erstellen
Zu einer Playliste hinzufügen
+ Lied zu Playlist hinzugefügt
+ Titel kann nicht zur Playlist hinzugefügt werden
%1$d Tracks • %2$s
Länge • %1$s
Zum Löschen lange drücken
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 03a2f0db..715f8d45 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -159,6 +159,8 @@
Annuler
Créer
Ajouter à une playlist
+ Ajout d'une chanson à la playlist
+ Échec de l'ajout d'une chanson à la playlist
%1$d titres • %2$s
Durée • %1$s
Nom de la playlist
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 2cc5bcb6..493161b7 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -188,6 +188,8 @@
Annulla
Crea
Aggiungi a una playlist
+ Aggiunta di un brano alla playlist
+ Impossibile aggiungere un brano alla playlist
%1$d brani • %2$s
Durata • %1$s
Premi a lungo per eliminare
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 679f333a..59e5e39a 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -161,6 +161,8 @@
취소
생성
플레이리스트 추가
+ 재생 목록에 노래 추가
+ 재생 목록에 노래를 추가하지 못했습니다.
%1$d 트랙 • %2$s
재생시간 • %1$s
플레이리스트 이름
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 12f04a31..223093d8 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -160,6 +160,8 @@
Cancelar
Criar
Adicionar a uma playlist
+ Adicionada playlist de reprodução
+ Falha ao adicionar uma playlist de reprodução
%1$d faixas • %2$s
Duração • %1$s
Nome da playlist
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 0f893b90..259036f4 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -186,6 +186,8 @@
Отмена
Создать
Добавить в плейлист
+ Добавьте песню в плейлист
+ Не удалось добавить песню в список воспроизведения
%1$d треков • %2$s
Продолжительность • %1$s
Долгое нажатие для удаления
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 915b33d1..4564147b 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -165,6 +165,8 @@
取消
新建
添加到播放列表
+ 将歌曲添加到播放列表
+ 未能将歌曲添加到播放列表
%1$d 首曲目 • %2$s
持续时间 • %1$s
播放列表名称
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5fd1ac33..3db80974 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -194,6 +194,8 @@
Cancel
Create
Add to a playlist
+ Added song to playlist
+ Failed to add song to playlist
%1$d tracks • %2$s
Duration • %1$s
Long press to delete
From 8f999246741639a0ec6d54a02896788d2709b85a Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 18:21:24 -0700
Subject: [PATCH 17/26] fix: corrected the and updated the string message for
the toast. got the build working. It was not pretty.
---
.gitignore | 1 +
.idea/misc.xml | 1 +
app/build.gradle | 7 ++++++-
app/src/main/AndroidManifest.xml | 1 -
.../tempo/repository/PlaylistRepository.java | 12 +++++++++---
app/src/main/res/values-fr/strings.xml | 2 --
gradlew | 0
settings.gradle | 3 +++
8 files changed, 20 insertions(+), 7 deletions(-)
mode change 100644 => 100755 gradlew
diff --git a/.gitignore b/.gitignore
index 74483036..6e9024d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@
.cxx
/.idea/
.env
+.vscode/settings.json
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1d411cd3..d5950937 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -192,6 +192,7 @@
+
diff --git a/app/build.gradle b/app/build.gradle
index b6ee7b49..d26c39ed 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.0'
+ versionName '3.9.3'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
@@ -107,4 +107,9 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.14'
implementation 'com.squareup.retrofit2:converter-gson:2.11.0'
+}
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(17)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 986481bd..cc9990e7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,7 +6,6 @@
-
diff --git a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
index 091e846d..7884159f 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/repository/PlaylistRepository.java
@@ -1,5 +1,8 @@
package com.cappielloantonio.tempo.repository;
+import static android.provider.Settings.System.getString;
+
+import android.provider.Settings;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -23,6 +26,7 @@ import retrofit2.Callback;
import retrofit2.Response;
public class PlaylistRepository {
+ @androidx.media3.common.util.UnstableApi
private final PlaylistDao playlistDao = AppDatabase.getInstance().playlistDao();
public MutableLiveData> getPlaylists(boolean random, int size) {
MutableLiveData> listLivePlaylists = new MutableLiveData<>(new ArrayList<>());
@@ -83,12 +87,12 @@ public class PlaylistRepository {
.enqueue(new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
- Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_success), Toast.LENGTH_SHORT).show();
+ Toast.makeText(App.getContext(), App.getContext().getString(R.string.playlist_chooser_dialog_toast_add_success), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
- Toast.makeText(App.getContext(), getString(R.string.playlist_chooser_dialog_toast_add_failure), Toast.LENGTH_SHORT).show();
+ Toast.makeText(App.getContext(), App.getContext().getString(R.string.playlist_chooser_dialog_toast_add_failure), Toast.LENGTH_SHORT).show();
}
});
}
@@ -160,17 +164,19 @@ public class PlaylistRepository {
}
});
}
-
+ @androidx.media3.common.util.UnstableApi
public LiveData> getPinnedPlaylists() {
return playlistDao.getAll();
}
+ @androidx.media3.common.util.UnstableApi
public void insert(Playlist playlist) {
InsertThreadSafe insert = new InsertThreadSafe(playlistDao, playlist);
Thread thread = new Thread(insert);
thread.start();
}
+ @androidx.media3.common.util.UnstableApi
public void delete(Playlist playlist) {
DeleteThreadSafe delete = new DeleteThreadSafe(playlistDao, playlist);
Thread thread = new Thread(delete);
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 715f8d45..03a2f0db 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -159,8 +159,6 @@
Annuler
Créer
Ajouter à une playlist
- Ajout d'une chanson à la playlist
- Échec de l'ajout d'une chanson à la playlist
%1$d titres • %2$s
Durée • %1$s
Nom de la playlist
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/settings.gradle b/settings.gradle
index a7c6dd41..1cd079ae 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,5 @@
+plugins {
+ id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
+}
include ':app'
rootProject.name = "Tempo"
\ No newline at end of file
From f5e10e9f9d03f6394d9688f5a6231f173cec70d2 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 19:07:44 -0700
Subject: [PATCH 18/26] merged and tested, bumping version
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index d26c39ed..ab1539d8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.3'
+ versionName '3.9.4'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
From 14dde7ae5c433b4673e16d24bf55cc80b494afcf Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 19:17:12 -0700
Subject: [PATCH 19/26] merged 374 - switched to spanish to test. build and
looked around a bit
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index ab1539d8..c13644d6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.4'
+ versionName '3.9.5'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
From e9158ee7835ddee6eb6c2ddc427205fc0c150bb1 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 19:30:35 -0700
Subject: [PATCH 20/26] merge conflicts
---
app/build.gradle | 2 +-
app/src/main/res/values-fr/strings.xml | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index c13644d6..fe03c11b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.5'
+ versionName '3.9.6'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 03a2f0db..715f8d45 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -159,6 +159,8 @@
Annuler
Créer
Ajouter à une playlist
+ Ajout d'une chanson à la playlist
+ Échec de l'ajout d'une chanson à la playlist
%1$d titres • %2$s
Durée • %1$s
Nom de la playlist
From e91ae5100071c625a338e2dbfd75f6ebc992a0a7 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sat, 2 Aug 2025 19:31:56 -0700
Subject: [PATCH 21/26] more merge conflicts
---
app/src/main/res/values-fr/strings.xml | 2 --
1 file changed, 2 deletions(-)
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 715f8d45..03a2f0db 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -159,8 +159,6 @@
Annuler
Créer
Ajouter à une playlist
- Ajout d'une chanson à la playlist
- Échec de l'ajout d'une chanson à la playlist
%1$d titres • %2$s
Durée • %1$s
Nom de la playlist
From ebe0d0bb96d0429235b149035a4cf57538b0b229 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sun, 3 Aug 2025 10:01:13 -0700
Subject: [PATCH 22/26] build successful
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index fe03c11b..a8e17311 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.6'
+ versionName '3.9.7'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
From 40b538445731287e937e5ac7c7fba88d5c2c2105 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sun, 3 Aug 2025 10:12:36 -0700
Subject: [PATCH 23/26] feat: 378-polish-translation manual merge
---
app/build.gradle | 2 +-
app/src/main/res/values-pl/arrays.xml | 257 +++++++++++++++
app/src/main/res/values-pl/strings.xml | 418 +++++++++++++++++++++++++
app/src/main/res/xml/locale_config.xml | 1 +
4 files changed, 677 insertions(+), 1 deletion(-)
create mode 100644 app/src/main/res/values-pl/arrays.xml
create mode 100644 app/src/main/res/values-pl/strings.xml
diff --git a/app/build.gradle b/app/build.gradle
index a8e17311..6562a893 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.7'
+ versionName '3.9.8'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
diff --git a/app/src/main/res/values-pl/arrays.xml b/app/src/main/res/values-pl/arrays.xml
new file mode 100644
index 00000000..f3105914
--- /dev/null
+++ b/app/src/main/res/values-pl/arrays.xml
@@ -0,0 +1,257 @@
+
+
+ - Jasny
+ - Ciemny
+ - Domyślny systemu
+
+
+ - jasny
+ - ciemny
+ - domyślny
+
+
+
+ - Duży
+ - Średni
+ - Mały
+
+
+ - 500
+ - 250
+ - 125
+
+
+
+ - Duża
+ - Średnia
+ - Mała
+
+
+ - -1
+ - 500
+ - 300
+
+
+
+ - Wyłączone
+ - 128 MiB
+ - 256 MiB
+ - 512 MiB
+ - 1024 MiB
+
+
+ - 0
+ - 128
+ - 256
+ - 512
+ - 1024
+
+
+
+ - Oryginalny
+ - 32 kbps
+ - 48 kbps
+ - 64 kbps
+ - 80 kbps
+ - 96 kbps
+ - 112 kbps
+ - 128 kbps
+ - 160 kbps
+ - 192 kbps
+ - 256 kbps
+ - 320 kbps
+
+
+ - 0
+ - 32
+ - 48
+ - 64
+ - 80
+ - 96
+ - 112
+ - 128
+ - 160
+ - 192
+ - 256
+ - 320
+
+
+
+ - Oryginalny
+ - 32 kbps
+ - 48 kbps
+ - 64 kbps
+ - 80 kbps
+ - 96 kbps
+ - 112 kbps
+ - 128 kbps
+ - 160 kbps
+ - 192 kbps
+ - 256 kbps
+ - 320 kbps
+
+
+ - 0
+ - 32
+ - 48
+ - 64
+ - 80
+ - 96
+ - 112
+ - 128
+ - 160
+ - 192
+ - 256
+ - 320
+
+
+
+ - Oryginalny
+ - 32 kbps
+ - 48 kbps
+ - 64 kbps
+ - 80 kbps
+ - 96 kbps
+ - 112 kbps
+ - 128 kbps
+ - 160 kbps
+ - 192 kbps
+ - 256 kbps
+ - 320 kbps
+
+
+ - 0
+ - 32
+ - 48
+ - 64
+ - 80
+ - 96
+ - 112
+ - 128
+ - 160
+ - 192
+ - 256
+ - 320
+
+
+
+ - Odtwarzanie bezpośrednie
+ - Opus
+ - AAC
+ - Mp3
+ - Flac
+
+
+ - raw
+ - opus
+ - aac
+ - mp3
+ - flac
+
+
+
+ - Odtwarzanie bezpośrednie
+ - Opus
+ - AAC
+ - Mp3
+ - Flac
+
+
+ - raw
+ - opus
+ - aac
+ - mp3
+ - flac
+
+
+
+ - Pobieranie bezpośrednie
+ - Opus
+ - AAC
+ - Mp3
+ - Flac
+
+
+ - raw
+ - opus
+ - aac
+ - mp3
+ - flac
+
+
+
+ - Dziesięć sekund
+ - Pięć sekund
+ - Dwie sekundy
+
+
+ - 10
+ - 5
+ - 2
+
+
+
+ - Duży
+ - Średni
+ - Mały
+
+
+ - 18
+ - 12
+ - 6
+
+
+
+ - Wyłączony
+ - Utwór
+ - Album
+ - Auto
+
+
+ - wyłączony
+ - utwór
+ - album
+ - auto
+
+
+
+ - Nie transkoduj
+ - Ustawienia serwera
+ - Format transkodowania Wi-FI
+ - Format transkodowania sieci komórkowej
+
+
+ - 0
+ - 1
+ - 2
+ - 3
+
+
+
+ - Minimalna
+ - Średnia
+ - Agresywna
+ - Ekstremalna
+
+
+ - .1
+ - 1
+ - 4
+ - 8
+
+
+
+ - Minimum 0 gwiazdek
+ - Minimum 1 gwiazdka
+ - Minimum 2 gwiazdki
+ - Minimum 3 gwiazdki
+ - Minimum 4 gwiazdki
+
+
+ - 0
+ - 1
+ - 2
+ - 3
+ - 4
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
new file mode 100644
index 00000000..89e0508d
--- /dev/null
+++ b/app/src/main/res/values-pl/strings.xml
@@ -0,0 +1,418 @@
+
+ Jeżeli masz problemy odwiedź stronę https://dontkillmyapp.com. Podaje ona dokładne instrukcje na temat tego jak wyłączyć funkcje oszczędzania energii które mogą wpływać na wydajność aplikacji.
+ Wyłącz optymalizacje baterii aby odtwarzać media przy wyłączonym ekranie.
+ Optymalizcje Baterii
+ Tryb offline
+ Dodaj do kolejki
+ Pobierz wszystkie
+ Przejdź do wykonawcy
+ Natychmiastowy mix
+ Odtwórz jako następne
+ Usuń wszystkie
+ Udostępnij
+ Odtwórz losowo
+ Albumy
+ Przeglądaj Albumy
+ Błąd podczas pobierania wykonawcy
+ Pobrane albumy
+ Najczęściej odtwarzane albumy
+ Nowe wydania
+ Albumy dodane niedawno
+ Albumy odtwarzane niedawno
+ Albumy oznaczone gwiazdką
+ Albumy
+ Więcej podobnych
+ Odtwarzaj
+ Wydane %1$s
+ Wydane %1$s, oryginalnie %2$s
+ Odtwarzaj losowo
+ %1$d utworów • %2$d minut
+ Tempo
+ Szukanie…
+ Natychmiastowy mix mix
+ Odtwórz losowo
+ Wykonawcy
+ Przeglądaj wykonawców
+ Błąd podczas pobierania radia wykonawcy
+ Błąd podczas pobierania utworów wykonawcy
+ Pobrani wykonawcy
+ Wykonawcy oznaczeni gwiazdką
+ Wykonawcy
+ Radio
+ Odtwarzanie losowe
+ Zmień układ
+ Więcej podobnych
+ Albumy
+ Więcej
+ Biografia
+ Najczęsciej słuchane utwory
+ Zobacz wszystkie
+ Ignoruj
+ Nie pytaj ponownie
+ Wyłącz
+ Anuluj
+ Włącz oszczędzanie danych
+ OK
+ Dostęp do serwera Subsonic na połaczeniach innych niż Wi-Fi został ograniczony. Aby zapobiec ponownemu pojawieniu się tej informacji, wyłącz sprawdzanie połączenia w ustawieniach aplikacji.
+ Nie połączono z Wi-Fi
+ Odtwarzanie losowe
+ Anuluj
+ Kontynuuj
+ Miej na uwadze to że kontynuowanie tej operacji spowoduje usunięcie wszystkich pobranych plików z wszystkich serwerów.
+ Usuwanie zapisanych plików
+ Brak opisu
+ Płyta %1$s - %2$s
+ Płyta %1$s
+ Anuluj
+ Pobierz
+ Wszystkie utwory w tym folderze zostaną pobrane. Utwory dostępne w subfolderach nie zostaną pobrane.
+ Pobierz utwory
+ Gdy pobierzesz piosenkę, znajdziesz ją tutaj
+ Narazie brak pobranych!
+ %1$s • %2$s elementów
+ %1$s element
+ Odtwórz losowo wszystkie
+ Aby zmiany przyniosły efekt, zrestartuj aplikację.
+ Zmiana lokalizacji pobieranych plików z jednej na drugą spowoduje natychmiastowe usunięcie wcześniej pobranych plików w drugiej lokalizacji
+ Wybieranie pamięci
+ Zewnętrzna
+ Wewnętrzna
+ Pobrane
+ Dodaj do kolejki
+ Odtwarzaj jako następne
+ Usuń
+ Usuń wszystkie
+ Odtwarzaj losowo
+
+ Wymagane
+ wymagany jest prefiks http lub https
+ Pobieranie
+ Wybierz dwa lub więcej filtrów
+ Filtry
+ Filtruj Gatunki
+ (%1$d)
+ (+%1$d)
+ Katalog Gatunków
+ Przeglądaj Gatunki
+ Przypomnij mi później
+ Wesprzyj mnie
+ Pobierz teraz
+ Nowa wersja aplikacji jest dostępna na GitHubie.
+ Dostępna aktualizacja
+ Anuluj
+ Reset
+ Zapisz
+ Zmień układ strony głównej
+ Weź pod uwagę to że, żeby zmiany nastąpiły, musisz zrestartować aplikację.
+ Top piosenki od twoich ulubionych wykonawców
+ Stwórz miks z piosenki którą lubisz
+ Dodaj nowe radio
+ Dodaj nowy kanał podcastów
+ Anuluj
+ Pobierz
+ Pobieranie tych utworów może zużyć dużo danych
+ Wygląda na to że, są utwory oznaczone gwiazdką
+ Najlepsze
+ Odkrywanie
+ Odtwórz wszystkie losowo
+ Podróż w czasie
+ Internetowe stacje radiowe
+ Ostatnio odtwarzane
+ Zobacz wszystkie
+ Ostatni tydzień
+ Ostatni miesiąc
+ Ostatni rok
+ Stworzone dla ciebie
+ Najczęściej odtwarzane
+ Zobacz wszystkie
+ Nowe wydania
+ Najnowsze podcasty
+ Playlisty
+ Kanały
+ Zobacz wszystkie
+ Stacje radiowe
+ Ostatnio dodane
+ Zobacz wszystkie
+ Udostępnienia
+ ★ Albumy oznaczone gwiazdką
+ Zobacz wszystkie
+ ★ Wykonawcy oznaczeni gwiazdką
+ Zobacz wszystkich
+ ★ Utwory oznaczone gwiazdką
+ Zobacz wszystkie
+ Twoje top piosenki
+ Zmiana układu
+ •
+ --
+ Albumy
+ Zobacz wszystkie
+ Wykonawcy
+ Zobacz wszystkich
+ Gatunki
+ Zobacz wszystkie
+ Foldery z muzyką
+ Playlisty
+ Zobacz wszystkie
+ Brak dodanych serwerów
+ Serwery Subsonic
+ Serwery Subsonic
+ Przesyłanie
+ Dodaj
+ Pobierz wszystko
+ Pobrane
+ Wszystko
+ Pobrane
+ Albumy
+ Wykonawcy
+ Gatkunki
+ Utwory
+ Rok
+ Strona główna
+ Ostatni tydzień
+ Ostatni miesiąc
+ Ostatni rok
+ Biblioteka
+ Szukaj
+ Ustawienia
+ Wykonawca
+ Nazwa
+ Losowo
+ Ostatnio dodane
+ Ostatnio odtwarzane
+ Najczęściej odtwarzane
+ Ostatnio oznaczone największą liczbą gwiazdek
+ Ostatnio oznaczone najniższą liczbą gwiazdek
+ Dodaj do ekranu głównego
+ Usuń z ekranu głównego
+ Rok
+ %1$.2fx
+ Wyczyść kolejkę odtwarzania
+ Priorytet Serwerów
+ Katalog Playlist
+ Przeglądaj Playlisty
+ Nie utworzono playlist
+ Anuluj
+ Utwórz
+ Dodaj do playlisty
+ %1$d utworów • %2$s
+ Długość • %1$s
+ Przytrzymaj aby usunąć
+ Nazwa Playlisty
+ Anuluj
+ Usuń
+ Zapisz
+ Edytuj playlistę
+ Odtwórz
+ Odtwarzaj losowo
+ Playlista • %1$d piosenek
+ Dodaj do kolejki
+ Usuń
+ Pobierz
+ Przejdź do kanału
+ Odtwórz jako następny
+ Usuń
+ Kanały
+ Przeglądaj Kanały
+ Url RSS
+ Kanał Podcastu
+ Opis
+ Odcinki
+ Brak dostępnych odcinków
+ Twoje zapytanie zostało wysłane do serwera
+ Naciśnij aby ukryć tę sekcję\nEfekty będą widoczne po restarcie
+ Gdy dodasz kanał, znajdziesz go tutaj
+ Nie znaleziono podcastów!
+ %1$s • %2$s
+ URL Strony Radia
+ Nazwa Radia
+ URL Z Strumieniem Radia
+ Anuluj
+ Usuń
+ Zapisz
+ Internetowa Stacja Radiowa
+ Naciśnij aby ukryć tę sekcję\nEfekty będą widoczne po restarcie
+ Gdy dodasz stację radiową, znajdziesz ją tutaj
+ Nie znaleziono stacji!
+ Anuluj
+ Zapisz
+ Oceń
+ Wyszukaj tytuł, wykonawców lub albumy
+ Wpisz co najmniej trzy znaki
+ Albumy
+ Wykonawcy
+ Piosenki
+ Niskie bezpieczeństwo
+ Przytrzymaj aby usunąć
+ Lokalny URL
+ Nazwa Serwera
+ Hasło
+ URL Serwera
+ Nazwa użytkownika
+ Anuluj
+ Usuń
+ Zapisz
+ Dodaj serwer
+ Anuluj
+ Przejdź do logowania
+ Kontynuuj mimo wszystko
+ Wybrany serwer jest niedostępny. Jeżeli wybierzesz żeby kontynuować ta informacja nie będzie się wyświetlać przez następną godzinę.
+ Serwer jest niedostępny
+ Tempo jest otwarto-źródłowym i lekkim klientem muzycznym dla Subsonic, stworzonym i zbudowanym natywnie dla Androida.
+ O aplikacji
+ Always on display
+ Format transkodowania
+ Jeżeli włączone, Tempo nie będzię wymuszał pobierania utworu z ustawieniami transkodowania wybranymi poniżej.
+ Priorytetyzuj ustawienia serwera używanego do strumieniowania w pobieraniach
+ Jeżeli włączone, Tempo będzie pobierał transkodowane utwory.
+ Pobieraj transkodowane utwory
+ Jeżeli włączone, serwer bedzię odpytywany o przybliżoną długość utworu.
+ Szacuj długość treści
+ Format transkodowania dla pobierania
+ Format transkodowania w sieci komórkowej
+ Format transkodowania w sieci Wi-Fi
+ Jeżeli włączone, Tempo nie będzie wymuszał strumieniowania utworu z ustawieniami transkodowania wybranymi poniżej.
+ Priorytetyzuj ustawienia transkodowania serwera
+ Priorytet przy transkodowaniu utworu danego serwerowi
+ Strategia buforowania
+ Aby zmiany przyniosły efekt, musisz ręcznie zrestartować aplikację.
+ Pozwala muzyce odtwarzać się dalej po końcu playlisty, odtwarza podobne piosenki
+ Odtwarzanie bez przerwy
+ Rozmiar cache dla okładek
+ Aby zmniejszyć zużycie danych, unikaj pobierania okładek.
+ Ogranicz zużycie danych komórkowych
+ Zatwierdzenie nieodwracalnie usunie wszystkie zapisane elementy
+ Usuń zapisane elementy
+ Pamięć do pobierania
+ Zmień ustawienia audio
+ Equalizer
+ https://github.com/CappielloAntonio/tempo
+ Śledź tworzenie aplikacji
+ GitHub
+ Rozdzielczość obrazów
+ Język
+ Wyloguj
+ Bitrate dla pobierania
+ Bitrate dla danych komórkowych
+ Bitrate dla Wi-Fi
+ Rozmiar plików cache dla mediów
+ Pokaż foldery z muzyką
+ Jeżeli włączone, widoczna będzie sekcja z folderami z muzyką. Weź pod uwagę że żeby funkcja nawigacji po folderach działała poprawnie, serwer musi wspierać tę funkcję.
+ Pokazuj podcasty
+ Jeżeli włączone, widoczna będzie sekcja z podcastami. Zrestartuj aplikację aby, zmiany przyniosły pełny efekt.
+ Pokaż jakość audio
+ Bitrate i format audio będzie pokazywany dla każdego utworu.
+ Pokaż oceny elementów
+ Jeżeli włączone, ocena elementów oraz czy jest oznaczony jako ulubiony będą pokazywane.
+ Timer synchronizacji
+ Jeżeli włączone, użytkownik będzie miał możliwość zapisania kolejki i będzie miał możliwość załadowania jej stanu przy otwarciu aplikacji.
+ Synchronizuj kolejkę odtwarzania dla tego użytkownika
+ Pokaż radio
+ Jeżeli włączone, widoczna będzie sekcja radia. Zrestartuj aplikację aby, zmiany przyniosły pełny efekt.
+ Tryb wzmocnienia głośności przy ponownym odtwarzaniu
+ Zaokrąglone rogi
+ Rozmiar rogów
+ Ustawia wielkość krzywizny kąta.
+ Jeżeli włączone, ustawia kąt krzywizny dla wszystkich renderowanych okładek. Zmiany przyniosą efekt po restarcie.
+ Skanuj bibliotekę
+ Włącz scrobbling muzyki
+ Włącz udostępnianie muzyki
+ Rozmiar cache dla strumieniowania
+ Pamięć cache dla strumieniowania
+ Ważne jest to że scrobbling polega też na byciu włączonym na serwerze aby otrzymywać te dane.
+ Podczas słuchania radia wykonawcy, natychmiastowego miksu albo podczas odtwarzania losowego, utwory poniżej określonej oceny użytkownika będą ignorowane.
+ Wzmocnienie głośności jest funkcją która pozwala tobie na ustawienia poziomu głośności dla utworów aby słuchanie brzmiało cały czas tak samo. To ustawienia działa tylko wtedy kiedy utwór zawiera potrzebne metadane.
+ Scrobbling jest funkcją która pozwala twojemu urządzeniu na wysyłanie informacji na temat piosenek których słuchasz do serwera muzyki. Te informacje pomagają tworzyć spersonalizowane rekomendacje na podstawie twojego gustu muzycznego.
+ Pozwala udostępnić użytkownikowi muzykę przez link. Ta funkcjonalność musi być wspierana i włączona na serwerze i jest ograniczona do pojedyńczych utworów, albumów i playlist.
+ Przywraca stan kolejki odtwarzania dla tego użytkownika. Zawiera utwory w kolejce, aktualnie odtwarzany utwór i pozycję w nim. Serwer musi wspierać tę funkcję.
+ %1$s \nAktualnie w użyciu: %2$s MiB
+ Priorytet dawany trybowi transkodowania. Jeżeli ustawiony na \"Odtwarzanie bezpośrednie\" bitrate pliku nie zostanie zmieniony.
+ Pobieraj transkdowane media. Jeżeli włączone, endpoint pobierania nie będzie używnany, poza następującymi ustawieniami. \n\n Jeżeli \"Format transkodowania dla pobierania\" jest ustawiony na \"Pobieranie bezpośrednie\" bitrate pliku nie zostanie zmieniony.
+ Kiedy plik jest transkodowany w locie, klient nie pokazuje zwykle długości utworu.Jest możliwe odpytanie serwera który wspiera tą funkcjonalność aby oszacował długość odtwarzanego utworu, ale czasy odpowiedzi mogą być dłuższe.
+ Jeżeli włączone, utwory oznaczone gwiazdką będą pobrane do użycia offline.
+ Zsynchronizuj utwory oznaczone gwiazdką do użycia offline
+ Motyw
+ Dane
+ Ogólne
+ Oceny
+ Wzmocnienie głośności przy ponownym odtwarzaniu
+ Scrobble
+ Ignoruj utwory na podstawie oceny
+ Piosenki z oceną:
+ Udostępnianie
+ Synchronizacja
+ Transkodowanie
+ Transkodowanie Pobrań
+ Interfejs
+ Transkodowane pobieranie
+ 3.1.0
+ Wersja
+ Pytaj o potwierdzenie od użytkownika przed strumieniowaniem przez sieć komórkową.
+ Alert o strumieniowaniu tylko przez Wi-Fi
+ Kopiuj link
+ Usuń udostępnianie
+ Zaktualizuj udostępnianie
+ Data wygaśnięcia: %1$s
+ Udostępnianie nie jest wspierane lub włączone
+ Opis
+ Data wygaśnięcia
+ Anuluj
+ Zapisz
+ Udostępnij
+ Dodaj do playlisty
+ Dodaj do kolejki
+ Pobierz
+ Błąd podczas pobierania albumu
+ Błąd podczas pobierania wykonawcy
+ Przejdź do albumu
+ Przejdź do wykonawcy
+ Natychmiastowy miks
+ Odtwarzaj jako następne
+ Oceń
+ Usuń
+ Udostępnij
+ Pobrane
+ Najczęściej odtwarzane utwory
+ Utwory dodane ostatnio
+ Utwory odtwarzane ostatnio
+ Utwory oznaczone gwiazdką
+ %1$s\ top utwory
+ Rok %1$d
+ %1$s • %2$s %3$s
+ Anuluj
+ Kontynuuj
+ Kontynuuj i pobierz
+ Pobieranie utworów oznaczonych gwiazdką może wymagać dużej ilośći danych.
+ Synchronizuj utwory oznaczone gwiazdką
+ Aby zmiany przyniosły efekt, zrestartuj aplikację.
+ Zmiana lokalizacji plików cache z jednej na drugą spowoduje natychmiastowe usunięcie wcześniej pobranych plików cache w drugiej lokalizacji.
+ Wybieranie pamięci
+ Zewnętrzna
+ Wewnętrzna
+ https://buymeacoffee.com/a.cappiello
+ Album
+ Wykonawca
+ Bitrate
+ Typ Treści
+ OK
+ Informacje o utworze
+ Numer płyty
+ Długość
+ Gatunek
+ Ścieżka
+ Rozmiar
+ Sufiks
+ Plik został pobrany przy użyciu API Subsonic. Kodek i bitrate pliku pozostaje nie zmieniony względem pliku źródłowego.
+ Aplikacja poprosi serwer żeby transkodować plik i zmienić jego bitrate. Użytkownik poprosił o kodek %1$s, z bitratem %2$s. Wszystkie potencjalne zmiany w kodeku i bitratecie pliku w wybranym formacie będą wykonywane przez serwer, który może ale nie musi obsługiwać tych operacji.
+ Aplikacja będzie tylko odczytywać oryginalne pliki jakie daje serwer. Aplikacja będzie wyłącznie prosić serwer o pliki bez transkodowania z bitratem oryginalnego źródła.
+ \Jakość odtwarzanego pliku zależy od decyzji serwera. Aplikacja nie będzie monitorować wyboru kodeku i bitrateu dla jakiegokolwiek potencjalnego transkodowania.
+ Aplikacja poprosi serwer o zmodyfikowanie bitrateu pliku. Użytkownik poprosił o bitrate %1$s, ale kodek pliku źródłowego pozostanie ten sam. Wszystkie potencjalne zmiany w bitracie pliku w wybranym formacie będą wykonywane przez serwer, który może ale nie musi obsługiwać tych operacji.
+ Aplikacja poprosi serwer żeby transkodować plik. Kodek wybrany przez użytkownika to %1$s, ale bitrate pliku źródłowego pozostanie ten sam. Wszystkie potencjalne zmiany w kodeku pliku w wybranym formacie będą wykonywane przez serwer, który może ale nie musi obsługiwać tych operacji
+ Tytuł
+ Numer utworu
+ Typ transkodowanej treści
+ Sufiks transkodowania
+ Rok
+ unDraw
+ Specjalne podziękowania dla unDraw bez którego ilustracji nie mogliśmy uczynić tej aplikacji jeszcze piękniejszą.
+ https://undraw.co/
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/locale_config.xml b/app/src/main/res/xml/locale_config.xml
index 9e9c43d1..ac6e6d0e 100644
--- a/app/src/main/res/xml/locale_config.xml
+++ b/app/src/main/res/xml/locale_config.xml
@@ -9,4 +9,5 @@
+
From 633d9218e471840f92d4690e8ace24b38032b6cd Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Sun, 3 Aug 2025 12:29:22 -0700
Subject: [PATCH 24/26] chore: alpha release for testing
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index 6562a893..17540307 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,7 +11,7 @@ android {
targetSdk 35
versionCode 26
- versionName '3.9.8'
+ versionName '3.10.0-alpha.1'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
From c5566c4fa83a45473dade36d68243bb942164b22 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Mon, 4 Aug 2025 19:50:48 -0700
Subject: [PATCH 25/26] chore: updated readme and set new url for link back to
this repo
---
README.md | 23 ++++++++++++++++++----
app/src/main/res/values-de/strings.xml | 2 +-
app/src/main/res/values-es-rES/strings.xml | 2 +-
app/src/main/res/values-fr/strings.xml | 2 +-
app/src/main/res/values-it/strings.xml | 2 +-
app/src/main/res/values-ko/strings.xml | 2 +-
app/src/main/res/values-pl/strings.xml | 2 +-
app/src/main/res/values-pt/strings.xml | 2 +-
app/src/main/res/values-ru/strings.xml | 2 +-
app/src/main/res/values-zh/strings.xml | 2 +-
app/src/main/res/values/strings.xml | 2 +-
11 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/README.md b/README.md
index 84b4b864..e9538ba2 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,12 @@
-
+
-
+
**Tempo** is an open-source and lightweight music client for Subsonic, designed and built natively for Android. It provides a seamless and intuitive music streaming experience, allowing you to access and play your Subsonic music library directly from your Android device.
@@ -22,6 +22,21 @@ Tempo does not rely on magic algorithms to decide what you should listen to. Ins
**Use the Github version of the app for full Android Auto and Chromecast support.**
+## Fork
+
+This fork is my attempt to keep development moving forward and merge in PR's that have been sitting for a while in the main repo. Thankful to @CappielloAntonio for the amazing app and hopefully we can continue to build on top of it. I will only be releasing on github and if I am not able to merge back to the main repo, I plan to rename the app to be able to publish it to fdroid and possibly google play? We will see.
+
+v3.10.0 applies the following PR's (fix/feat/chore):
+fix: [379](https://github.com/CappielloAntonio/tempo/pull/379)-Fix: redirection to artist fragment on artist label click
+fix: [385](https://github.com/CappielloAntonio/tempo/pull/385)-Player queue lag, limits
+fix: [389](https://github.com/CappielloAntonio/tempo/pull/389)-Fix crash when sorting albums with a null artist
+feat: [371](https://github.com/CappielloAntonio/tempo/pull/371)-Display toast message after adding a song to a playlist
+feat: [367](https://github.com/CappielloAntonio/tempo/pull/367)-Album add to playlist context menu item
+chore: [374](https://github.com/CappielloAntonio/tempo/pull/374)-Spanish translation
+feat: [397](https://github.com/CappielloAntonio/tempo/pull/397)-Store and retrieve replay and shuffle states in preferences
+feat:[400](https://github.com/CappielloAntonio/tempo/pull/400)- enhance Android media player notification window
+chore: [378](https://github.com/CappielloAntonio/tempo/pull/378) Polish translation
+
## Features
- **Subsonic Integration**: Tempo seamlessly integrates with your Subsonic server, providing you with easy access to your entire music collection on the go.
- **Sleek and Intuitive UI**: Enjoy a clean and user-friendly interface designed to enhance your music listening experience, tailored to your preferences and listening history.
@@ -42,7 +57,7 @@ Tempo does not rely on magic algorithms to decide what you should listen to. Ins
-
+
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index abf40990..1df280e0 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -281,7 +281,7 @@
Download storage
Audio Einstellungen anpassen
Equalizer
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Verfolge die Entwicklung
Github
Bilder Auflösung anpassen
diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml
index 693e3661..d2c21d36 100644
--- a/app/src/main/res/values-es-rES/strings.xml
+++ b/app/src/main/res/values-es-rES/strings.xml
@@ -165,7 +165,7 @@
Resolución de la imagen
Idioma
Cerrar sesión
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Siga el desarrollo
Github
Género
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index d62bd653..aebaee19 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -246,7 +246,7 @@
Stockage des téléchargements
Ajuster les paramètres audios
Égaliseur
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Suivre le développement
Github
Définir la résolution des images
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 08c9b31e..a5f3be74 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -283,7 +283,7 @@
Archivio download
Regola le impostazioni audio
Equalizzatore
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Segui lo sviluppo
Github
Imposta risoluzione delle immagini
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index d9d26d7e..1953612f 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -250,7 +250,7 @@
스토리지 다운로드
오디오 설정 적용
이퀄라이저
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Follow the development
Github
이미지 해상도 설정
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 89e0508d..37f1685a 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -285,7 +285,7 @@
Pamięć do pobierania
Zmień ustawienia audio
Equalizer
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Śledź tworzenie aplikacji
GitHub
Rozdzielczość obrazów
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 12680a11..7e4f2de7 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -250,7 +250,7 @@
Armazenamento dos downloads
Ajustar configurações de áudio
Equalizador
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Acompanhe o desenvolvimento
Github
Definir resolução da imagem
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 5c2a4a45..43448d65 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -279,7 +279,7 @@
Загрузить хранилище
Отрегулируйте настройки звука
Эквалайзер
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Следите за развитием
Github
Установить разрешение изображения
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 9ffd6877..b0933d57 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -257,7 +257,7 @@
下载存储
调整音频设置
均衡器
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
关注开发进展
Github
设置图像分辨率
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 78f6b382..8ecb78af 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -289,7 +289,7 @@
Download storage
Adjust audio settings
Equalizer
- https://github.com/CappielloAntonio/tempo
+ https://github.com/eddyizm/tempo
Follow the development
Github
Set image resolution
From 9fbae1823da8101d36a70c4fad0408ad6c3677e8 Mon Sep 17 00:00:00 2001
From: eddyizm
Date: Mon, 4 Aug 2025 19:53:07 -0700
Subject: [PATCH 26/26] chore: fixed line breaks in readme.
---
README.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index e9538ba2..79b2081d 100644
--- a/README.md
+++ b/README.md
@@ -27,15 +27,15 @@ Tempo does not rely on magic algorithms to decide what you should listen to. Ins
This fork is my attempt to keep development moving forward and merge in PR's that have been sitting for a while in the main repo. Thankful to @CappielloAntonio for the amazing app and hopefully we can continue to build on top of it. I will only be releasing on github and if I am not able to merge back to the main repo, I plan to rename the app to be able to publish it to fdroid and possibly google play? We will see.
v3.10.0 applies the following PR's (fix/feat/chore):
-fix: [379](https://github.com/CappielloAntonio/tempo/pull/379)-Fix: redirection to artist fragment on artist label click
-fix: [385](https://github.com/CappielloAntonio/tempo/pull/385)-Player queue lag, limits
-fix: [389](https://github.com/CappielloAntonio/tempo/pull/389)-Fix crash when sorting albums with a null artist
-feat: [371](https://github.com/CappielloAntonio/tempo/pull/371)-Display toast message after adding a song to a playlist
-feat: [367](https://github.com/CappielloAntonio/tempo/pull/367)-Album add to playlist context menu item
-chore: [374](https://github.com/CappielloAntonio/tempo/pull/374)-Spanish translation
-feat: [397](https://github.com/CappielloAntonio/tempo/pull/397)-Store and retrieve replay and shuffle states in preferences
-feat:[400](https://github.com/CappielloAntonio/tempo/pull/400)- enhance Android media player notification window
-chore: [378](https://github.com/CappielloAntonio/tempo/pull/378) Polish translation
+fix: [379](https://github.com/CappielloAntonio/tempo/pull/379) -Fix: redirection to artist fragment on artist label click
+fix: [385](https://github.com/CappielloAntonio/tempo/pull/385) -Player queue lag, limits
+fix: [389](https://github.com/CappielloAntonio/tempo/pull/389) -Fix crash when sorting albums with a null artist
+feat: [371](https://github.com/CappielloAntonio/tempo/pull/371) -Display toast message after adding a song to a playlist
+feat: [367](https://github.com/CappielloAntonio/tempo/pull/367) -Album add to playlist context menu item
+chore: [374](https://github.com/CappielloAntonio/tempo/pull/374) -Spanish translation
+feat: [397](https://github.com/CappielloAntonio/tempo/pull/397) -Store and retrieve replay and shuffle states in preferences
+feat:[400](https://github.com/CappielloAntonio/tempo/pull/400) - enhance Android media player notification window
+chore: [378](https://github.com/CappielloAntonio/tempo/pull/378) Polish translation
## Features
- **Subsonic Integration**: Tempo seamlessly integrates with your Subsonic server, providing you with easy access to your entire music collection on the go.