diff --git a/.gitignore b/.gitignore
index 0f48176e..1047677c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,7 @@
.cxx
/.idea/
.env
-.vscode/settings.json
\ No newline at end of file
+.vscode/settings.json
+# release / debug files
+tempus-release-key.jks
+app/tempo/
\ No newline at end of file
diff --git a/README.md b/README.md
index cf157638..00680d8d 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,8 @@ This fork is my attempt to keep development moving forward and merge in PR's tha
Moved details to [CHANGELOG.md](https://github.com/eddyizm/tempo/blob/main/CHANGELOG.md)
+Fork [**sponsorship here**](https://ko-fi.com/eddyizm).
+
## 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.
@@ -41,21 +43,11 @@ Moved details to [CHANGELOG.md](https://github.com/eddyizm/tempo/blob/main/CHANG
- **Transcoding Support**: Activate transcoding of tracks on your Subsonic server, allowing you to set a transcoding profile for optimized streaming directly from the app. This feature requires support from your Subsonic server.
- **Android Auto Support**: Enjoy your favorite music on the go with full Android Auto integration, allowing you to seamlessly control and listen to your tracks directly from your mobile device while driving.
-
-
-
-
-
-
-
-
-
-
-
## Sponsors
+Thanks to the original repo/creator [CappielloAntonio](https://github.com/CappielloAntonio) (3.9.0)
+
Tempo is an open-source project developed and maintained solely by me. I would like to express my heartfelt thanks to all the users who have shown their love and support for Tempo. Your contributions and encouragement mean a lot to me, and they help drive the development and improvement of the app.
-If you would like to sponsor the project and show your support, you can make a donation or contribution by visiting the [**sponsorship page**](https://www.buymeacoffee.com/a.cappiello). Your generosity will help cover the costs of development and further enhancements.
## Screenshot
diff --git a/app/build.gradle b/app/build.gradle
index ea649294..0aace15a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -10,8 +10,8 @@ android {
minSdkVersion 24
targetSdk 35
- versionCode 27
- versionName '3.11.2'
+ versionCode 28
+ versionName '3.12.0'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/TrackInfoDialog.java b/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/TrackInfoDialog.java
index 84afcb6a..f866c250 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/TrackInfoDialog.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/ui/dialog/TrackInfoDialog.java
@@ -15,6 +15,8 @@ import com.cappielloantonio.tempo.util.MusicUtil;
import com.cappielloantonio.tempo.util.Preferences;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import java.util.Objects;
+
public class TrackInfoDialog extends DialogFragment {
private DialogTrackInfoBinding bind;
@@ -51,7 +53,12 @@ public class TrackInfoDialog extends DialogFragment {
private void setTrackInfo() {
bind.trakTitleInfoTextView.setText(mediaMetadata.title);
- bind.trakArtistInfoTextView.setText(mediaMetadata.artist);
+ bind.trakArtistInfoTextView.setText(
+ mediaMetadata.artist != null
+ ? mediaMetadata.artist
+ : mediaMetadata.extras != null && Objects.equals(mediaMetadata.extras.getString("type"), Constants.MEDIA_TYPE_RADIO)
+ ? mediaMetadata.extras.getString("uri", getString(R.string.label_placeholder))
+ : "");
if (mediaMetadata.extras != null) {
CustomGlideRequest.Builder
@@ -62,20 +69,20 @@ public class TrackInfoDialog extends DialogFragment {
bind.titleValueSector.setText(mediaMetadata.extras.getString("title", getString(R.string.label_placeholder)));
bind.albumValueSector.setText(mediaMetadata.extras.getString("album", getString(R.string.label_placeholder)));
bind.artistValueSector.setText(mediaMetadata.extras.getString("artist", getString(R.string.label_placeholder)));
- bind.trackNumberValueSector.setText(String.valueOf(mediaMetadata.extras.getInt("track", 0)));
- bind.yearValueSector.setText(String.valueOf(mediaMetadata.extras.getInt("year", 0)));
+ bind.trackNumberValueSector.setText(mediaMetadata.extras.getInt("track", 0) != 0 ? String.valueOf(mediaMetadata.extras.getInt("track", 0)) : getString(R.string.label_placeholder));
+ bind.yearValueSector.setText(mediaMetadata.extras.getInt("year", 0) != 0 ? String.valueOf(mediaMetadata.extras.getInt("year", 0)) : getString(R.string.label_placeholder));
bind.genreValueSector.setText(mediaMetadata.extras.getString("genre", getString(R.string.label_placeholder)));
- bind.sizeValueSector.setText(MusicUtil.getReadableByteCount(mediaMetadata.extras.getLong("size", 0)));
+ bind.sizeValueSector.setText(mediaMetadata.extras.getLong("size", 0) != 0 ? MusicUtil.getReadableByteCount(mediaMetadata.extras.getLong("size", 0)) : getString(R.string.label_placeholder));
bind.contentTypeValueSector.setText(mediaMetadata.extras.getString("contentType", getString(R.string.label_placeholder)));
bind.suffixValueSector.setText(mediaMetadata.extras.getString("suffix", getString(R.string.label_placeholder)));
bind.transcodedContentTypeValueSector.setText(mediaMetadata.extras.getString("transcodedContentType", getString(R.string.label_placeholder)));
bind.transcodedSuffixValueSector.setText(mediaMetadata.extras.getString("transcodedSuffix", getString(R.string.label_placeholder)));
- bind.durationValueSector.setText(MusicUtil.getReadableDurationString(mediaMetadata.extras.getInt("duration", 0), false));
- bind.bitrateValueSector.setText(mediaMetadata.extras.getInt("bitrate", 0) + " kbps");
+ bind.durationValueSector.setText(mediaMetadata.extras.getInt("duration", 0) != 0 ? MusicUtil.getReadableDurationString(mediaMetadata.extras.getInt("duration", 0), false) : getString(R.string.label_placeholder));
+ bind.bitrateValueSector.setText(mediaMetadata.extras.getInt("bitrate", 0) != 0 ? mediaMetadata.extras.getInt("bitrate", 0) + " kbps" : getString(R.string.label_placeholder));
bind.samplingRateValueSector.setText(mediaMetadata.extras.getInt("samplingRate", 0) != 0 ? mediaMetadata.extras.getInt("samplingRate", 0) + " Hz" : getString(R.string.label_placeholder));
bind.bitDepthValueSector.setText(mediaMetadata.extras.getInt("bitDepth", 0) != 0 ? mediaMetadata.extras.getInt("bitDepth", 0) + " bits" : getString(R.string.label_placeholder));
bind.pathValueSector.setText(mediaMetadata.extras.getString("path", getString(R.string.label_placeholder)));
- bind.discNumberValueSector.setText(String.valueOf(mediaMetadata.extras.getInt("discNumber", 0)));
+ bind.discNumberValueSector.setText(mediaMetadata.extras.getInt("discNumber", 0) != 0 ? String.valueOf(mediaMetadata.extras.getInt("discNumber", 0)) : getString(R.string.label_placeholder));
}
}
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 b3755ee3..6841f247 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
@@ -174,7 +174,12 @@ public class PlayerBottomSheetFragment extends Fragment {
playerBottomSheetViewModel.setLiveDescription(mediaMetadata.extras.getString("description", null));
bind.playerHeaderLayout.playerHeaderMediaTitleLabel.setText(mediaMetadata.extras.getString("title"));
- bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setText(mediaMetadata.extras.getString("artist"));
+ bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setText(
+ mediaMetadata.artist != null
+ ? mediaMetadata.artist
+ : Objects.equals(mediaMetadata.extras.getString("type"), Constants.MEDIA_TYPE_RADIO)
+ ? mediaMetadata.extras.getString("uri", getString(R.string.label_placeholder))
+ : "");
CustomGlideRequest.Builder
.from(requireContext(), mediaMetadata.extras.getString("coverArtId"), CustomGlideRequest.ResourceType.Song)
@@ -182,7 +187,11 @@ public class PlayerBottomSheetFragment extends Fragment {
.into(bind.playerHeaderLayout.playerHeaderMediaCoverImage);
bind.playerHeaderLayout.playerHeaderMediaTitleLabel.setVisibility(mediaMetadata.extras.getString("title") != null && !Objects.equals(mediaMetadata.extras.getString("title"), "") ? View.VISIBLE : View.GONE);
- bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setVisibility(mediaMetadata.extras.getString("artist") != null && !Objects.equals(mediaMetadata.extras.getString("artist"), "") ? View.VISIBLE : View.GONE);
+ bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setVisibility(
+ (mediaMetadata.extras.getString("artist") != null && !Objects.equals(mediaMetadata.extras.getString("artist"), ""))
+ || (Objects.equals(mediaMetadata.extras.getString("type"), Constants.MEDIA_TYPE_RADIO) && mediaMetadata.extras.getString("uri") != null)
+ ? View.VISIBLE
+ : View.GONE);
}
}
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 37cd9f10..a07d58ec 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
@@ -10,6 +10,7 @@ import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.ToggleButton;
+import android.widget.RatingBar;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
@@ -36,6 +37,7 @@ import com.cappielloantonio.tempo.util.Constants;
import com.cappielloantonio.tempo.util.MusicUtil;
import com.cappielloantonio.tempo.util.Preferences;
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
+import com.cappielloantonio.tempo.viewmodel.RatingViewModel;
import com.google.android.material.chip.Chip;
import com.google.android.material.elevation.SurfaceColors;
import com.google.common.util.concurrent.ListenableFuture;
@@ -53,6 +55,8 @@ public class PlayerControllerFragment extends Fragment {
private InnerFragmentPlayerControllerBinding bind;
private ViewPager2 playerMediaCoverViewPager;
private ToggleButton buttonFavorite;
+ private RatingViewModel ratingViewModel;
+ private RatingBar songRatingBar;
private TextView playerMediaTitleLabel;
private TextView playerArtistNameLabel;
private Button playbackSpeedButton;
@@ -75,6 +79,7 @@ public class PlayerControllerFragment extends Fragment {
View view = bind.getRoot();
playerBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(PlayerBottomSheetViewModel.class);
+ ratingViewModel = new ViewModelProvider(requireActivity()).get(RatingViewModel.class);
init();
initQuickActionView();
@@ -117,6 +122,7 @@ public class PlayerControllerFragment extends Fragment {
playerQuickActionView = bind.getRoot().findViewById(R.id.player_quick_action_view);
playerOpenQueueButton = bind.getRoot().findViewById(R.id.player_open_queue_button);
playerTrackInfo = bind.getRoot().findViewById(R.id.player_info_track);
+ songRatingBar = bind.getRoot().findViewById(R.id.song_rating_bar);
}
private void initQuickActionView() {
@@ -146,7 +152,6 @@ public class PlayerControllerFragment extends Fragment {
bind.nowPlayingMediaControllerView.setPlayer(mediaBrowser);
mediaBrowser.setShuffleModeEnabled(Preferences.isShuffleModeEnabled());
mediaBrowser.setRepeatMode(Preferences.getRepeatMode());
-
setMediaControllerListener(mediaBrowser);
} catch (Exception e) {
e.printStackTrace();
@@ -181,18 +186,27 @@ public class PlayerControllerFragment extends Fragment {
private void setMetadata(MediaMetadata mediaMetadata) {
playerMediaTitleLabel.setText(String.valueOf(mediaMetadata.title));
- playerArtistNameLabel.setText(String.valueOf(mediaMetadata.artist));
+ playerArtistNameLabel.setText(
+ mediaMetadata.artist != null
+ ? String.valueOf(mediaMetadata.artist)
+ : mediaMetadata.extras != null && Objects.equals(mediaMetadata.extras.getString("type"), Constants.MEDIA_TYPE_RADIO)
+ ? mediaMetadata.extras.getString("uri", getString(R.string.label_placeholder))
+ : "");
playerMediaTitleLabel.setSelected(true);
playerArtistNameLabel.setSelected(true);
playerMediaTitleLabel.setVisibility(mediaMetadata.title != null && !Objects.equals(mediaMetadata.title, "") ? View.VISIBLE : View.GONE);
- playerArtistNameLabel.setVisibility(mediaMetadata.artist != null && !Objects.equals(mediaMetadata.artist, "") ? View.VISIBLE : View.GONE);
+ playerArtistNameLabel.setVisibility(
+ (mediaMetadata.artist != null && !Objects.equals(mediaMetadata.artist, ""))
+ || mediaMetadata.extras != null && Objects.equals(mediaMetadata.extras.getString("type"), Constants.MEDIA_TYPE_RADIO) && mediaMetadata.extras.getString("uri") != null
+ ? View.VISIBLE
+ : View.GONE);
}
private void setMediaInfo(MediaMetadata mediaMetadata) {
if (mediaMetadata.extras != null) {
- String extension = mediaMetadata.extras.getString("suffix", "Unknown format");
+ String extension = mediaMetadata.extras.getString("suffix", getString(R.string.player_unknown_format));
String bitrate = mediaMetadata.extras.getInt("bitrate", 0) != 0 ? mediaMetadata.extras.getInt("bitrate", 0) + "kbps" : "Original";
String samplingRate = mediaMetadata.extras.getInt("samplingRate", 0) != 0 ? new DecimalFormat("0.#").format(mediaMetadata.extras.getInt("samplingRate", 0) / 1000.0) + "kHz" : "";
String bitDepth = mediaMetadata.extras.getInt("bitDepth", 0) != 0 ? mediaMetadata.extras.getInt("bitDepth", 0) + "b" : "";
@@ -218,8 +232,8 @@ public class PlayerControllerFragment extends Fragment {
boolean isTranscodingBitrate = !MusicUtil.getBitratePreference().equals("0");
if (isTranscodingExtension || isTranscodingBitrate) {
- playerMediaExtension.setText("Transcoding");
- playerMediaBitrate.setText("requested");
+ playerMediaExtension.setText(MusicUtil.getTranscodingFormatPreference() + " (" + getString(R.string.player_transcoding) + ")");
+ playerMediaBitrate.setText(!MusicUtil.getBitratePreference().equals("0") ? MusicUtil.getBitratePreference() + "kbps" : getString(R.string.player_transcoding_requested));
}
playerTrackInfo.setOnClickListener(view -> {
@@ -305,6 +319,7 @@ public class PlayerControllerFragment extends Fragment {
private void initMediaListenable() {
playerBottomSheetViewModel.getLiveMedia().observe(getViewLifecycleOwner(), media -> {
if (media != null) {
+ ratingViewModel.setSong(media);
buttonFavorite.setChecked(media.getStarred() != null);
buttonFavorite.setOnClickListener(v -> playerBottomSheetViewModel.setFavorite(requireContext(), media));
buttonFavorite.setOnLongClickListener(v -> {
@@ -315,9 +330,29 @@ public class PlayerControllerFragment extends Fragment {
dialog.setArguments(bundle);
dialog.show(requireActivity().getSupportFragmentManager(), null);
+
return true;
});
+ Integer currentRating = media.getUserRating();
+
+ if (currentRating != null) {
+ songRatingBar.setRating(currentRating);
+ } else {
+ songRatingBar.setRating(0);
+ }
+
+ songRatingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
+ @Override
+ public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
+ if (fromUser) {
+ ratingViewModel.rate((int) rating);
+ media.setUserRating((int) rating);
+ }
+ }
+ });
+
+
if (getActivity() != null) {
playerBottomSheetViewModel.refreshMediaInfo(requireActivity(), media);
}
diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java b/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java
index 1b88774d..f8f15f07 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java
@@ -140,7 +140,6 @@ public class MappingUtil {
Bundle bundle = new Bundle();
bundle.putString("id", internetRadioStation.getId());
bundle.putString("title", internetRadioStation.getName());
- bundle.putString("artist", uri.toString());
bundle.putString("uri", uri.toString());
bundle.putString("type", Constants.MEDIA_TYPE_RADIO);
@@ -149,7 +148,6 @@ public class MappingUtil {
.setMediaMetadata(
new MediaMetadata.Builder()
.setTitle(internetRadioStation.getName())
- .setArtist(internetRadioStation.getStreamUrl())
.setExtras(bundle)
.setIsBrowsable(false)
.setIsPlayable(true)
diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlayerBottomSheetViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlayerBottomSheetViewModel.java
index 3e712479..bf90fa65 100644
--- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlayerBottomSheetViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/PlayerBottomSheetViewModel.java
@@ -103,7 +103,6 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
favoriteRepository.starLater(media.getId(), null, null, false);
}
});
-
media.setStarred(null);
}
@@ -131,7 +130,7 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
}
}
- public LiveData getLiveLyrics() {
+ public LiveData getLiveLyrics() {
return lyricsLiveData;
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 106500a5..01edf7f5 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -47,6 +47,8 @@
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/activity_info_offline_mode"
- android:textSize="6sp"
+ android:textSize="12sp"
+ android:textStyle="bold"
android:visibility="gone" />
+
diff --git a/app/src/main/res/layout/inner_fragment_player_controller_layout.xml b/app/src/main/res/layout/inner_fragment_player_controller_layout.xml
index ac318326..9063e242 100644
--- a/app/src/main/res/layout/inner_fragment_player_controller_layout.xml
+++ b/app/src/main/res/layout/inner_fragment_player_controller_layout.xml
@@ -104,6 +104,37 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player_media_title_label" />
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 1df280e0..c2b2a527 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -103,6 +103,9 @@
Sichern
Startseite anpassen
Die Anwendung muss neu gestartet werden, um die Änderungen auszuführen.
+ Musik
+ Podcast
+ Radio
Top Tracks Deiner Lieblingskünstler
Ein Mix von einem deiner Lieblingslieder erstellen
Radio hinzufügen
@@ -286,6 +289,7 @@
Github
Bilder Auflösung anpassen
Sprache
+ Systemsprache
Abmelden
Bitrate für Downloads
Bitrate bei mobiler Nutzung
@@ -392,6 +396,7 @@
Titel
Album
Künstler
+ Bit-Tiefe
Track Nummer
Jahr
Genre
@@ -402,6 +407,7 @@
Transkodiertes Suffix
Länge
Bitrate
+ Abtastrate
Pfad
Disk Nummer
Diese Datei wurde mit den Subsonic APIs heruntergeladen. Der Codec und die Bitrate sind unverändert zur original Datei.
diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml
index 4f7beefd..518931af 100644
--- a/app/src/main/res/values-es-rES/strings.xml
+++ b/app/src/main/res/values-es-rES/strings.xml
@@ -196,6 +196,9 @@
%1$.2fx
Limpiar la cola de reproducción
Prioridad del servidor
+ Formato desconocido
+ Transcodificando
+ solicitado
Catálogo de listas de reproducción
Explorar listas de reproducción
No hay listas de reproducción
diff --git a/app/src/main/res/values-fr/arrays.xml b/app/src/main/res/values-fr/arrays.xml
index dfc37679..7d0198c0 100644
--- a/app/src/main/res/values-fr/arrays.xml
+++ b/app/src/main/res/values-fr/arrays.xml
@@ -32,6 +32,21 @@
- 300
+
+ - Désactivé
+ - 128 MiB
+ - 256 MiB
+ - 512 MiB
+ - 1024 MiB
+
+
+ - 0
+ - 128
+ - 256
+ - 512
+ - 1024
+
+
- Original
- 32 kbps
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index aebaee19..a41b43fa 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -24,7 +24,10 @@
Albums
Similaire
Lire
+ Sorti le %1$s
+ Sorti le %1$s, initialement %2$s
Mélanger
+ %1$d titres • %2$d minutes
Tempo
Recherche…
Mix instantané
@@ -51,13 +54,16 @@
Annuler
Activer l\'économie de données
OK
- L\'accès au serveur Subsonic sur des connexions autres que le Wi-Fi ont été bloquées. Pour empêcher cette alerte de réapparaître, désactiver la vérification de la connexion dans les paramètres de l\'app.
+ L\'accès au serveur Subsonic sur des connexions autres que le Wi-Fi a été bloqué. Pour empêcher cette alerte de réapparaître, désactiver la vérification de la connexion dans les paramètres de l\'app.
Wi-Fi déconnecté
+ Mélanger
Annuler
Continuer
- Sachez que la poursuite de cette action entraînera la suppression permanente de tous les éléments sauvegardés et téléchargés à partir de tous les serveurs
+ Attention, la poursuite de cette action entraînera la suppression définitive de tous les éléments sauvegardés et téléchargés à partir de tous les serveurs
Supprimer les éléments téléchargés
Aucune description disponible
+ Disque %1$s - %2$s
+ Disque %1$s
Annuler
Télécharger
Toutes les pistes dans ce dossier seront téléchargées. Les pistes dans les sous-dossiers ne seront pas téléchargées.
@@ -66,8 +72,9 @@
Aucun téléchargement pour l\'instant
%1$s • %2$s éléments
%1$s éléments
+ Tout mélanger
Redémarrez l\'application pour appliquer les changements.
- Changer la destination des téléchargements d\'un espace de stockage à un autre résultera en la suppression immédiate de tous les fichiers précédemment téléchargés dans l\'autre espace de stockage.
+ Modifier le chemin de stockage des téléchargements entraînera la suppression immédiate de tous les fichiers précédemment téléchargés dans le nouvel espace de stockage.
Sélectionnez l\'option de stockage
Externe
Interne
@@ -84,8 +91,23 @@
Sélectionnez deux filtres ou plus
Filtrer
Filtrer par genre
+ (%1$d)
+ (+%1$d)
Catalogue des Genres
Parcourir les Genres
+ Me rappeler plus tard
+ Me soutenir
+ Télécharger maintenant
+ Une version plus récente de l\'app est disponible sur Github.
+ Mise à jour disponible
+ Annuler
+ Réinitialiser
+ Sauvegarder
+ Réorganiser l\'écran d\'accueil
+ Veuillez noter que ces changements ne s\'appliqueront qu\'après redémarrage de l\'application.
+ Musique
+ Podcast
+ Radio
Meilleurs morceaux de vos artistes préférés
Commencez le mix à partir d\'une chanson que vous aimez
Ajouter une radio
@@ -102,11 +124,14 @@
Écouté dernièrement
Voir tout
Sur la dernière semaine
+ Sur le dernier mois
+ Sur la dernière année
Faits pour vous
Les plus écoutés
Voir tout
Nouvelles sorties
Nouveau podcasts
+ Playlists
Chaînes
Voir tout
Stations radio
@@ -120,6 +145,7 @@
★ Titres favoris
Voir tout
Vos morceaux préférés
+ Réorganiser
Albums
Voir tout
Artistes
@@ -144,13 +170,23 @@
Genre
Piste
Année
- Home
- Librairie
+ Accueil
+ Sur la dernière semaine
+ Sur le dernier mois
+ Sur la dernière année
+ Bibliothèque
Rechercher
Paramètres
Artiste
Nom
Aléatoire
+ Récemment ajoutés
+ Récemment lus
+ Plus lus
+ Favoris les plus récents
+ Favoris les plus anciens
+ Ajouter à l\'écran d\'accueil
+ Retirer de l\'écran d\'accueil
Année
%1$.2fx
Vider la file d\'attente
@@ -161,8 +197,11 @@
Annuler
Créer
Ajouter à une playlist
+ Titre ajouté à la playlist
+ Échec d\'ajout du titre à la playlist
%1$d titres • %2$s
Durée • %1$s
+ Appui long pour supprimer
Nom de la playlist
Annuler
Supprimer
@@ -208,6 +247,8 @@
Artistes
Pistes
Sécurité basse
+ Appui long pour supprimer
+ URL local
Nom du serveur
Mot de passe
URL du serveur
@@ -221,8 +262,9 @@
Continuer quand même
Le serveur est injoignable. Si vous décidez de continuer, cette fenêtre n\'apparaîtra plus pendant une heure.
Serveur injoignable
- Tempo est un client open source et léger pour Subsonic, développé et build nativement pour Android.
+ Tempo est un client open source et léger pour Subsonic, développé et compilé nativement pour Android.
À propos
+ Toujours visible
Format de transcodage
Si activé, Tempo ne forcera pas le téléchargement de la piste avec les paramètres de transcodage ci-dessous.
Prioriser les paramètres du serveurs, utilisés pour le streaming, dans les téléchargements
@@ -238,6 +280,8 @@
La priorité au transcodage de la piste est donnée au serveur
Stratégie de mise en mémoire tampon
Redémarrez l\'application pour appliquer les changements.
+ Permet de prolonger la lecture après la fin d\'une playlist avec des titres similaires
+ Lecture continue
Taille du cache des illustrations
Pour réduire la consommation de données, éviter de télécharger les illustrations.
Limiter l\'utilisation des données mobiles
@@ -252,14 +296,18 @@
Définir la résolution des images
Langue
Se déconnecter
- Bitrate pour les téléchargements
- Bitrate en données mobile
- Bitrate en Wi-Fi
+ Débit binaire pour les téléchargements
+ Débit binaire en données mobile
+ Débit binaire en Wi-Fi
Taille du cache des fichiers audios
Afficher les dossiers
Si activé, rend possible la navigation dans les répertoires. À noter que pour que la navigation dans les dossiers fonctionne correctement, le serveur doit supporter cette fonctionnalité.
Voir les podcasts
Si activé, rend visible la section Podcast
+ Afficher la qualité audio
+ Le débit binaire et le format audio seront affichés pour chaque piste.
+ Afficher la note
+ Si activé, la note et le statut de mise en favori de l\'élément seront affichés.
Minuteur de synchronisation
Si activé, l\'utilisateur pourra sauvegarder sa file d\'attente et la recharger au démarrage de l\'application.
Synchroniser la file d\'attente pour cet utilisateur
@@ -272,15 +320,19 @@
Si activé, arrondi les angles des illustrations. Les modifications prendront effet au redémarrage.
Scanner la bibliothèque
Activer le scrobbling
+ Langue du système
Activer le partage de musique
+ Taille du cache de streaming
+ Emplacement du cache de streaming
À noter que le scrobbling doit être activé sur le serveur pour qu\'il puisse recevoir ces données
Lors de l\'écoute de la radio d\'un artiste, d\'un mix instantané ou de tout la bibliothèque en aléatoire, les pistes en dessous d\'une certaine note seront ignorées.
Le Replay Gain est une fonctionnalité qui vous permet d\'ajuster le volume des pistes audio pour une expérience d\'écoute cohérente. Fonctionne uniquement si la piste contient les métadonnées nécessaires.
Le scrobbling permet à votre appareil d\'envoyer des informations sur les musiques que vous écoutez au serveur afin de créer des recommendations personnalisées basées sur vos préférences musicales.
Permet à l\'utilisateur de partager de la musique via un lien. Cette fonctionnalité doit être supportée et activée sur le serveur et est limitée aux pistes, albums et playlists individuellement.
Renvoie l\'état de la file d\'attente de cet utilisateur. Cela inclut les pistes dans la file, la piste actuellement écoutée et la position dans la piste. Cette fonctionnalité doit être supportée par le serveur.
- Le mode de transcodage à prioriser. Si reglé sur \"Lecture directe\", le bitrate du fichier ne sera pas modifié.
- Télécharge les médias transcodés. Si activé, les paramètres de transcodage suivants seront utilisés pour les téléchargements.\n\n Si le format de transcodage est reglé à \"Téléchargement direct\", le bitrate du fichier ne sera pas modifé.
+ %1$s \nUtilisé actuellement : %2$s MiB
+ Le mode de transcodage à prioriser. Si réglé sur \"Lecture directe\", le débit binaire du fichier ne sera pas modifié.
+ Télécharge les médias transcodés. Si activé, les paramètres de transcodage suivants seront utilisés pour les téléchargements.\n\n Si le format de transcodage est reglé à \"Téléchargement direct\", le débit binaire du fichier ne sera pas modifé.
Quand le fichier est transcodé à la volé, en général, le client n\'affiche pas la durée de la piste. Il est possible de demander aux serveurs qui le supportent d\'estimer la durée de la piste écoutée, mais les temps de réponses peuvent être plus longs.
Si activé, les pistes favorites seront téléchargées pour l\'écoute hors-ligne
Synchronisation des pistes favorites pour écoute hors-ligne
@@ -291,7 +343,7 @@
Replay Gain
Scrobble
Ignorer des musiques selon leur note
- Musiques avec une note de:
+ Musiques avec une note de :
Partage
Synchronisation
Transcodage
@@ -336,9 +388,16 @@
Continuer et télécharger
Le téléchargement des titres favoris pourrer utiliser beaucoup de données.
Synchroniser les titres favoris
+ Veuillez redémarrer l\'app pour appliquer les changements.
+ Modifier le chemin de stockage des fichiers mis en cache risque de provoquer la suppression de tous les fichiers précédemment mis en cache dans le nouvel espace de stockage.
+ Sélectionner une option de stockage
+ Externe
+ Interne
+ https://buymeacoffee.com/a.cappiello
Album
Artiste
- Bitrate
+ Résolution audio
+ Débit binaire
Type de contenu
OK
Infos piste
@@ -346,14 +405,15 @@
Durée
Genre
Chemin
+ Fréquence d\'échantillonnage
Taille
Suffixe
- Le fichier a été téléchargé depuis les APIs Subsonic. Le codec et le bitrate du fichier demeure inchangé du fichier d\'origine.
- L\'application demandera au serveur de transcoder le fichier et de modifier son bitrate. Le codec demandé par l\'utilisateur est %1$s, avec un bitrate de %2$s. Toute modification éventuelle du codec et du bitrate du fichier dans le format choisi sera gérée par le serveur, qui peut ou non prendre en charge l\'opération.
- L\'application ne lira que le fichier original tel que fourni par le serveur. L\'application demandera explicitement au serveur le fichier non transcodé avec le bitrate de la source originale.
- La qualité du fichier à lire est laissée à l\'appréciation du serveur. L\'application n\'impose pas le choix du codec et du bitrate pour un éventuel transcodage.
- L\'application demandera au serveur de modifier le bitrate du fichier. L\'utilisateur a choisi un bitrate de %1$s, tandis que le codec du fichier restera le même. Toute modification du bitrate du fichier dans le format choisi sera effectuée par le serveur, qui peut ou non prendre en charge l\'opération.
- L\'application demandera au serveur de transcoder le fichier. Le codec choisi par l\'utilisateur est le %1$s, tandis que le bitrate sera le même que celui du fichier source. Le transcodage éventuel du fichier dans le codec choisi dépend du serveur, qui peut ou non prendre en charge l\'opération.
+ Le fichier a été téléchargé depuis les APIs Subsonic. Le codec et le débit binaire du fichier demeurent identiques à ceux du fichier d\'origine.
+ L\'application demandera au serveur de transcoder le fichier et de modifier son débit binaire. Le codec demandé par l\'utilisateur est %1$s, avec un débit binaire de %2$s. Toute modification éventuelle du codec et du débit binaire du fichier dans le format choisi sera gérée par le serveur, qui peut ou non prendre en charge l\'opération.
+ L\'application ne lira que le fichier original tel que fourni par le serveur. L\'application demandera explicitement au serveur le fichier non transcodé avec le débit binaire de la source originale.
+ La qualité du fichier à lire est laissée à l\'appréciation du serveur. L\'application n\'impose pas le choix du codec et du débit binaire pour un éventuel transcodage.
+ L\'application demandera au serveur de modifier le débit binaire du fichier. L\'utilisateur a choisi un débit binaire de %1$s, tandis que le codec du fichier restera le même. Toute modification du débit binaire du fichier dans le format choisi sera effectuée par le serveur, qui peut ou non prendre en charge l\'opération.
+ L\'application demandera au serveur de transcoder le fichier. Le codec choisi par l\'utilisateur est le %1$s, tandis que le débit binaire sera le même que celui du fichier source. Le transcodage éventuel du fichier dans le codec choisi dépend du serveur, qui peut ou non prendre en charge l\'opération.
Titre
Numéro de piste
Transcodé type de contenu
diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml
index 4725c4a3..e62f234f 100644
--- a/app/src/main/res/values-night/styles.xml
+++ b/app/src/main/res/values-night/styles.xml
@@ -41,7 +41,7 @@
\ 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
index 37f1685a..ddaca1b2 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -103,7 +103,13 @@
Reset
Zapisz
Zmień układ strony głównej
- Weź pod uwagę to że, żeby zmiany nastąpiły, musisz zrestartować aplikację.
+ Weź pod uwagę to że, żeby zmiany nastąpiły, musisz zrestartować aplikację.
+ Muzyka
+ Podcasty
+ Radio
+ Głębia bitowa
+ Częstotliwość próbkowania
+ Język systemu
Top piosenki od twoich ulubionych wykonawców
Stwórz miks z piosenki którą lubisz
Dodaj nowe radio
@@ -415,4 +421,4 @@
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/values/strings.xml b/app/src/main/res/values/strings.xml
index faea756e..dd2b066e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -193,6 +193,9 @@
%1$.2fx
Clean play queue
Server Priority
+ Unknown format
+ Transcoding
+ requested
Playlist Catalogue
Browse Playlists
No playlists created
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 b8a7179b..92c4b9b3 100644
--- a/app/src/notquitemy/java/com/cappielloantonio/tempo/service/MediaService.kt
+++ b/app/src/notquitemy/java/com/cappielloantonio/tempo/service/MediaService.kt
@@ -138,10 +138,19 @@ class MediaService : MediaLibraryService() {
controller: ControllerInfo,
mediaItems: List
): ListenableFuture> {
- val updatedMediaItems = mediaItems.map {
- it.buildUpon()
- .setUri(it.requestMetadata.mediaUri)
- .setMediaMetadata(it.mediaMetadata)
+ val updatedMediaItems = mediaItems.map { mediaItem ->
+ val mediaMetadata = mediaItem.mediaMetadata
+
+ val newMetadata = mediaMetadata.buildUpon()
+ .setArtist(
+ if (mediaMetadata.artist != null) mediaMetadata.artist
+ else mediaMetadata.extras?.getString("uri") ?: ""
+ )
+ .build()
+
+ mediaItem.buildUpon()
+ .setUri(mediaItem.requestMetadata.mediaUri)
+ .setMediaMetadata(newMetadata)
.setMimeType(MimeTypes.BASE_TYPE_AUDIO)
.build()
}