Generalized the song and podcastEpisode field to Media

This commit is contained in:
CappielloAntonio 2022-02-07 17:34:46 +01:00
parent ae941ad769
commit bf09a581b9
13 changed files with 154 additions and 136 deletions

View file

@ -15,7 +15,8 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.cappielloantonio.play.R; import com.cappielloantonio.play.R;
import com.cappielloantonio.play.glide.CustomGlideRequest; import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.PodcastEpisode; import com.cappielloantonio.play.model.Media;
import com.cappielloantonio.play.service.MediaManager;
import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.util.MusicUtil; import com.cappielloantonio.play.util.MusicUtil;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -32,7 +33,7 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
private final MainActivity activity; private final MainActivity activity;
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture; private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
private List<PodcastEpisode> podcastEpisodes; private List<Media> podcastEpisodes;
public PodcastEpisodeAdapter(MainActivity activity, Context context) { public PodcastEpisodeAdapter(MainActivity activity, Context context) {
this.activity = activity; this.activity = activity;
@ -50,11 +51,11 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
@Override @Override
public void onBindViewHolder(ViewHolder holder, int position) { public void onBindViewHolder(ViewHolder holder, int position) {
PodcastEpisode podcastEpisode = podcastEpisodes.get(position); Media podcastEpisode = podcastEpisodes.get(position);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM d"); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM d");
holder.textTitle.setText(MusicUtil.getReadableString(podcastEpisode.getTitle())); holder.textTitle.setText(MusicUtil.getReadableString(podcastEpisode.getTitle()));
holder.textSubtitle.setText(MusicUtil.getReadableString(podcastEpisode.getArtist())); holder.textSubtitle.setText(MusicUtil.getReadableString(podcastEpisode.getArtistName()));
holder.textReleaseAndDuration.setText(context.getString(R.string.podcast_release_date_duration_formatter, simpleDateFormat.format(podcastEpisode.getPublishDate()), MusicUtil.getReadablePodcastDurationString(podcastEpisode.getDuration()))); holder.textReleaseAndDuration.setText(context.getString(R.string.podcast_release_date_duration_formatter, simpleDateFormat.format(podcastEpisode.getPublishDate()), MusicUtil.getReadablePodcastDurationString(podcastEpisode.getDuration())));
holder.textDescription.setText(MusicUtil.getReadableString(podcastEpisode.getDescription())); holder.textDescription.setText(MusicUtil.getReadableString(podcastEpisode.getDescription()));
@ -70,7 +71,7 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
return podcastEpisodes.size(); return podcastEpisodes.size();
} }
public void setItems(List<PodcastEpisode> podcastEpisodes) { public void setItems(List<Media> podcastEpisodes) {
this.podcastEpisodes = podcastEpisodes; this.podcastEpisodes = podcastEpisodes;
notifyDataSetChanged(); notifyDataSetChanged();
} }
@ -104,8 +105,8 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
@Override @Override
public void onClick(View view) { public void onClick(View view) {
// MediaManager.startQueue(mediaBrowserListenableFuture, context, podcastEpisodes.get(getBindingAdapterPosition())); MediaManager.startQueue(mediaBrowserListenableFuture, context, podcastEpisodes.get(getBindingAdapterPosition()));
// activity.setBottomSheetInPeek(true); activity.setBottomSheetInPeek(true);
} }
} }
} }

View file

@ -21,9 +21,9 @@ import com.cappielloantonio.play.model.Server;
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
@Database( @Database(
version = 33, version = 36,
entities = {Queue.class, Server.class, RecentSearch.class, Download.class, Playlist.class}, entities = {Queue.class, Server.class, RecentSearch.class, Download.class, Playlist.class},
autoMigrations = { @AutoMigration(from = 32, to = 33) } autoMigrations = { @AutoMigration(from = 35, to = 36) }
) )
public abstract class AppDatabase extends RoomDatabase { public abstract class AppDatabase extends RoomDatabase {
private static final String TAG = "AppDatabase"; private static final String TAG = "AppDatabase";

View file

@ -13,7 +13,7 @@ public class PodcastChannel {
protected String originalImageUrl; protected String originalImageUrl;
protected String status; protected String status;
protected String errorMessage; protected String errorMessage;
protected List<PodcastEpisode> episodes; protected List<Media> episodes;
public PodcastChannel(com.cappielloantonio.play.subsonic.models.PodcastChannel podcastChannel) { public PodcastChannel(com.cappielloantonio.play.subsonic.models.PodcastChannel podcastChannel) {
this.id = podcastChannel.getId(); this.id = podcastChannel.getId();
@ -27,7 +27,7 @@ public class PodcastChannel {
this.episodes = MappingUtil.mapPodcastEpisode(podcastChannel.getEpisodes()); this.episodes = MappingUtil.mapPodcastEpisode(podcastChannel.getEpisodes());
} }
public PodcastChannel(String id, String url, String title, String description, String coverArtId, String originalImageUrl, String status, String errorMessage, List<PodcastEpisode> episodes) { public PodcastChannel(String id, String url, String title, String description, String coverArtId, String originalImageUrl, String status, String errorMessage, List<Media> episodes) {
this.id = id; this.id = id;
this.url = url; this.url = url;
this.title = title; this.title = title;
@ -103,11 +103,11 @@ public class PodcastChannel {
this.errorMessage = errorMessage; this.errorMessage = errorMessage;
} }
public List<PodcastEpisode> getEpisodes() { public List<Media> getEpisodes() {
return episodes; return episodes;
} }
public void setEpisodes(List<PodcastEpisode> episodes) { public void setEpisodes(List<Media> episodes) {
this.episodes = episodes; this.episodes = episodes;
} }
} }

View file

@ -7,8 +7,8 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.model.Media;
import com.cappielloantonio.play.model.PodcastChannel; import com.cappielloantonio.play.model.PodcastChannel;
import com.cappielloantonio.play.model.PodcastEpisode;
import com.cappielloantonio.play.subsonic.models.SubsonicResponse; import com.cappielloantonio.play.subsonic.models.SubsonicResponse;
import com.cappielloantonio.play.util.MappingUtil; import com.cappielloantonio.play.util.MappingUtil;
@ -50,8 +50,8 @@ public class PodcastRepository {
return livePodcastChannel; return livePodcastChannel;
} }
public MutableLiveData<List<PodcastEpisode>> getNewestPodcastEpisodes(int count) { public MutableLiveData<List<Media>> getNewestPodcastEpisodes(int count) {
MutableLiveData<List<PodcastEpisode>> liveNewestPodcastEpisodes = new MutableLiveData<>(); MutableLiveData<List<Media>> liveNewestPodcastEpisodes = new MutableLiveData<>();
App.getSubsonicClientInstance(application, false) App.getSubsonicClientInstance(application, false)
.getPodcastClient() .getPodcastClient()

View file

@ -28,43 +28,43 @@ public class QueueRepository {
return queueDao.getAll(); return queueDao.getAll();
} }
public List<Media> getSongs() { public List<Media> getMedia() {
List<Media> songs = new ArrayList<>(); List<Media> media = new ArrayList<>();
GetSongsThreadSafe getSongs = new GetSongsThreadSafe(queueDao); GetMediaThreadSafe getMedia = new GetMediaThreadSafe(queueDao);
Thread thread = new Thread(getSongs); Thread thread = new Thread(getMedia);
thread.start(); thread.start();
try { try {
thread.join(); thread.join();
songs = getSongs.getSongs(); media = getMedia.getMedia();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
return songs; return media;
} }
public void insert(Media song, boolean reset, int afterIndex) { public void insert(Media media, boolean reset, int afterIndex) {
try { try {
List<Media> songs = new ArrayList<>(); List<Media> mediaList = new ArrayList<>();
if (!reset) { if (!reset) {
GetSongsThreadSafe getSongsThreadSafe = new GetSongsThreadSafe(queueDao); GetMediaThreadSafe getMediaThreadSafe = new GetMediaThreadSafe(queueDao);
Thread getSongsThread = new Thread(getSongsThreadSafe); Thread getMediaThread = new Thread(getMediaThreadSafe);
getSongsThread.start(); getMediaThread.start();
getSongsThread.join(); getMediaThread.join();
songs = getSongsThreadSafe.getSongs(); mediaList = getMediaThreadSafe.getMedia();
} }
songs.add(afterIndex, song); mediaList.add(afterIndex, media);
Thread delete = new Thread(new DeleteAllThreadSafe(queueDao)); Thread delete = new Thread(new DeleteAllThreadSafe(queueDao));
delete.start(); delete.start();
delete.join(); delete.join();
Thread insertAll = new Thread(new InsertAllThreadSafe(queueDao, songs)); Thread insertAll = new Thread(new InsertAllThreadSafe(queueDao, mediaList));
insertAll.start(); insertAll.start();
insertAll.join(); insertAll.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -74,24 +74,24 @@ public class QueueRepository {
public void insertAll(List<Media> toAdd, boolean reset, int afterIndex) { public void insertAll(List<Media> toAdd, boolean reset, int afterIndex) {
try { try {
List<Media> songs = new ArrayList<>(); List<Media> media = new ArrayList<>();
if (!reset) { if (!reset) {
GetSongsThreadSafe getSongsThreadSafe = new GetSongsThreadSafe(queueDao); GetMediaThreadSafe getMediaThreadSafe = new GetMediaThreadSafe(queueDao);
Thread getSongsThread = new Thread(getSongsThreadSafe); Thread getMediaThread = new Thread(getMediaThreadSafe);
getSongsThread.start(); getMediaThread.start();
getSongsThread.join(); getMediaThread.join();
songs = getSongsThreadSafe.getSongs(); media = getMediaThreadSafe.getMedia();
} }
songs.addAll(afterIndex, toAdd); media.addAll(afterIndex, toAdd);
Thread delete = new Thread(new DeleteAllThreadSafe(queueDao)); Thread delete = new Thread(new DeleteAllThreadSafe(queueDao));
delete.start(); delete.start();
delete.join(); delete.join();
Thread insertAll = new Thread(new InsertAllThreadSafe(queueDao, songs)); Thread insertAll = new Thread(new InsertAllThreadSafe(queueDao, media));
insertAll.start(); insertAll.start();
insertAll.join(); insertAll.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -140,16 +140,16 @@ public class QueueRepository {
thread.start(); thread.start();
} }
public int getLastPlayedSongIndex() { public int getLastPlayedMediaIndex() {
int index = 0; int index = 0;
GetLastPlayedSongThreadSafe getLastPlayedSongThreadSafe = new GetLastPlayedSongThreadSafe(queueDao); GetLastPlayedMediaThreadSafe getLastPlayedMediaThreadSafe = new GetLastPlayedMediaThreadSafe(queueDao);
Thread thread = new Thread(getLastPlayedSongThreadSafe); Thread thread = new Thread(getLastPlayedMediaThreadSafe);
thread.start(); thread.start();
try { try {
thread.join(); thread.join();
index = getLastPlayedSongThreadSafe.getIndex(); index = getLastPlayedMediaThreadSafe.getIndex();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -157,16 +157,16 @@ public class QueueRepository {
return index; return index;
} }
public long getLastPlayedSongTimestamp() { public long getLastPlayedMediaTimestamp() {
long timestamp = 0; long timestamp = 0;
GetLastPlayedSongTimestampThreadSafe getLastPlayedSongTimestampThreadSafe = new GetLastPlayedSongTimestampThreadSafe(queueDao); GetLastPlayedMediaTimestampThreadSafe getLastPlayedMediaTimestampThreadSafe = new GetLastPlayedMediaTimestampThreadSafe(queueDao);
Thread thread = new Thread(getLastPlayedSongTimestampThreadSafe); Thread thread = new Thread(getLastPlayedMediaTimestampThreadSafe);
thread.start(); thread.start();
try { try {
thread.join(); thread.join();
timestamp = getLastPlayedSongTimestampThreadSafe.getTimestamp(); timestamp = getLastPlayedMediaTimestampThreadSafe.getTimestamp();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -174,36 +174,36 @@ public class QueueRepository {
return timestamp; return timestamp;
} }
private static class GetSongsThreadSafe implements Runnable { private static class GetMediaThreadSafe implements Runnable {
private final QueueDao queueDao; private final QueueDao queueDao;
private List<Media> songs; private List<Media> media;
public GetSongsThreadSafe(QueueDao queueDao) { public GetMediaThreadSafe(QueueDao queueDao) {
this.queueDao = queueDao; this.queueDao = queueDao;
} }
@Override @Override
public void run() { public void run() {
songs = MappingUtil.mapQueue(queueDao.getAllSimple()); media = MappingUtil.mapQueue(queueDao.getAllSimple());
} }
public List<Media> getSongs() { public List<Media> getMedia() {
return songs; return media;
} }
} }
private static class InsertAllThreadSafe implements Runnable { private static class InsertAllThreadSafe implements Runnable {
private final QueueDao queueDao; private final QueueDao queueDao;
private final List<Media> songs; private final List<Media> media;
public InsertAllThreadSafe(QueueDao queueDao, List<Media> songs) { public InsertAllThreadSafe(QueueDao queueDao, List<Media> media) {
this.queueDao = queueDao; this.queueDao = queueDao;
this.songs = songs; this.media = media;
} }
@Override @Override
public void run() { public void run() {
queueDao.insertAll(MappingUtil.mapSongsToQueue(songs)); queueDao.insertAll(MappingUtil.mapMediaToQueue(media));
} }
} }
@ -255,41 +255,41 @@ public class QueueRepository {
private static class SetLastPlayedTimestampThreadSafe implements Runnable { private static class SetLastPlayedTimestampThreadSafe implements Runnable {
private final QueueDao queueDao; private final QueueDao queueDao;
private final String songId; private final String mediaId;
public SetLastPlayedTimestampThreadSafe(QueueDao queueDao, String songId) { public SetLastPlayedTimestampThreadSafe(QueueDao queueDao, String mediaId) {
this.queueDao = queueDao; this.queueDao = queueDao;
this.songId = songId; this.mediaId = mediaId;
} }
@Override @Override
public void run() { public void run() {
queueDao.setLastPlay(songId, Instant.now().toEpochMilli()); queueDao.setLastPlay(mediaId, Instant.now().toEpochMilli());
} }
} }
private static class SetPlayingPausedTimestampThreadSafe implements Runnable { private static class SetPlayingPausedTimestampThreadSafe implements Runnable {
private final QueueDao queueDao; private final QueueDao queueDao;
private final String songId; private final String mediaId;
private final long ms; private final long ms;
public SetPlayingPausedTimestampThreadSafe(QueueDao queueDao, String songId, long ms) { public SetPlayingPausedTimestampThreadSafe(QueueDao queueDao, String mediaId, long ms) {
this.queueDao = queueDao; this.queueDao = queueDao;
this.songId = songId; this.mediaId = mediaId;
this.ms = ms; this.ms = ms;
} }
@Override @Override
public void run() { public void run() {
queueDao.setPlayingChanged(songId, ms); queueDao.setPlayingChanged(mediaId, ms);
} }
} }
private static class GetLastPlayedSongThreadSafe implements Runnable { private static class GetLastPlayedMediaThreadSafe implements Runnable {
private final QueueDao queueDao; private final QueueDao queueDao;
private int index; private int index;
public GetLastPlayedSongThreadSafe(QueueDao queueDao) { public GetLastPlayedMediaThreadSafe(QueueDao queueDao) {
this.queueDao = queueDao; this.queueDao = queueDao;
} }
@ -303,11 +303,11 @@ public class QueueRepository {
} }
} }
private static class GetLastPlayedSongTimestampThreadSafe implements Runnable { private static class GetLastPlayedMediaTimestampThreadSafe implements Runnable {
private final QueueDao queueDao; private final QueueDao queueDao;
private long timestamp; private long timestamp;
public GetLastPlayedSongTimestampThreadSafe(QueueDao queueDao) { public GetLastPlayedMediaTimestampThreadSafe(QueueDao queueDao) {
this.queueDao = queueDao; this.queueDao = queueDao;
} }

View file

@ -133,18 +133,19 @@ public class PlayerBottomSheetFragment extends Fragment {
}); });
} }
@SuppressLint("UnsafeOptInUsageError")
private void setMetadata(MediaMetadata mediaMetadata) { private void setMetadata(MediaMetadata mediaMetadata) {
if (mediaMetadata.extras != null) playerBottomSheetViewModel.setLiveSong(requireActivity(), mediaMetadata.extras.getString("id")); if (mediaMetadata.extras != null) playerBottomSheetViewModel.setLiveMedia(requireActivity(), mediaMetadata.extras.getString("mediaType"), mediaMetadata.extras.getString("id"));
if (mediaMetadata.extras != null) playerBottomSheetViewModel.setLiveArtist(requireActivity(), mediaMetadata.extras.getString("artistId")); if (mediaMetadata.extras != null) playerBottomSheetViewModel.setLiveArtist(requireActivity(), mediaMetadata.extras.getString("mediaType"), mediaMetadata.extras.getString("artistId"));
bind.playerHeaderLayout.playerHeaderSongTitleLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.title))); bind.playerHeaderLayout.playerHeaderMediaTitleLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.title)));
bind.playerHeaderLayout.playerHeaderSongArtistLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.artist))); bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.artist)));
if (mediaMetadata.extras != null) CustomGlideRequest.Builder if (mediaMetadata.extras != null) CustomGlideRequest.Builder
.from(requireContext(), mediaMetadata.extras.getString("id"), CustomGlideRequest.SONG_PIC, null) .from(requireContext(), mediaMetadata.extras.getString("id"), CustomGlideRequest.SONG_PIC, null)
.build() .build()
.transform(new RoundedCorners(CustomGlideRequest.CORNER_RADIUS)) .transform(new RoundedCorners(CustomGlideRequest.CORNER_RADIUS))
.into(bind.playerHeaderLayout.playerHeaderSongCoverImage); .into(bind.playerHeaderLayout.playerHeaderMediaCoverImage);
} }
private void setContentDuration(long duration) { private void setContentDuration(long duration) {
@ -165,12 +166,12 @@ public class PlayerBottomSheetFragment extends Fragment {
} }
}); });
bind.playerHeaderLayout.playerHeaderNextSongButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_next).performClick()); bind.playerHeaderLayout.playerHeaderNextMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_next).performClick());
} }
private void setHeaderNextButtonState(boolean isEnabled) { private void setHeaderNextButtonState(boolean isEnabled) {
bind.playerHeaderLayout.playerHeaderNextSongButton.setEnabled(isEnabled); bind.playerHeaderLayout.playerHeaderNextMediaButton.setEnabled(isEnabled);
bind.playerHeaderLayout.playerHeaderNextSongButton.setAlpha(isEnabled ? (float) 1.0 : (float) 0.3); bind.playerHeaderLayout.playerHeaderNextMediaButton.setAlpha(isEnabled ? (float) 1.0 : (float) 0.3);
} }
public View getPlayerHeader() { public View getPlayerHeader() {

View file

@ -7,7 +7,6 @@ import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.ToggleButton; import android.widget.ToggleButton;
@ -38,9 +37,9 @@ public class PlayerControllerFragment extends Fragment {
private InnerFragmentPlayerControllerBinding bind; private InnerFragmentPlayerControllerBinding bind;
private ImageView playerMoveDownBottomSheet; private ImageView playerMoveDownBottomSheet;
private ViewPager2 playerSongCoverViewPager; private ViewPager2 playerMediaCoverViewPager;
private ToggleButton buttonFavorite; private ToggleButton buttonFavorite;
private TextView playerSongTitleLabel; private TextView playerMediaTitleLabel;
private TextView playerArtistNameLabel; private TextView playerArtistNameLabel;
private MainActivity activity; private MainActivity activity;
@ -87,9 +86,9 @@ public class PlayerControllerFragment extends Fragment {
@SuppressLint("UnsafeOptInUsageError") @SuppressLint("UnsafeOptInUsageError")
private void init() { private void init() {
playerMoveDownBottomSheet = bind.getRoot().findViewById(R.id.player_move_down_bottom_sheet); playerMoveDownBottomSheet = bind.getRoot().findViewById(R.id.player_move_down_bottom_sheet);
playerSongCoverViewPager = bind.getRoot().findViewById(R.id.player_song_cover_view_pager); playerMediaCoverViewPager = bind.getRoot().findViewById(R.id.player_media_cover_view_pager);
buttonFavorite = bind.getRoot().findViewById(R.id.button_favorite); buttonFavorite = bind.getRoot().findViewById(R.id.button_favorite);
playerSongTitleLabel = bind.getRoot().findViewById(R.id.player_song_title_label); playerMediaTitleLabel = bind.getRoot().findViewById(R.id.player_media_title_label);
playerArtistNameLabel = bind.getRoot().findViewById(R.id.player_artist_name_label); playerArtistNameLabel = bind.getRoot().findViewById(R.id.player_artist_name_label);
playerMoveDownBottomSheet.setOnClickListener(view -> activity.collapseBottomSheet()); playerMoveDownBottomSheet.setOnClickListener(view -> activity.collapseBottomSheet());
@ -110,7 +109,7 @@ public class PlayerControllerFragment extends Fragment {
try { try {
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get(); MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
bind.nowPlayingSongControllerView.setPlayer(mediaBrowser); bind.nowPlayingMediaControllerView.setPlayer(mediaBrowser);
setMediaControllerListener(mediaBrowser); setMediaControllerListener(mediaBrowser);
} catch (Exception e) { } catch (Exception e) {
@ -131,19 +130,20 @@ public class PlayerControllerFragment extends Fragment {
}); });
} }
@SuppressLint("UnsafeOptInUsageError")
private void setMetadata(MediaMetadata mediaMetadata) { private void setMetadata(MediaMetadata mediaMetadata) {
playerSongTitleLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.title))); playerMediaTitleLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.title)));
playerArtistNameLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.artist))); playerArtistNameLabel.setText(MusicUtil.getReadableString(String.valueOf(mediaMetadata.artist)));
playerSongTitleLabel.setSelected(true); playerMediaTitleLabel.setSelected(true);
playerArtistNameLabel.setSelected(true); playerArtistNameLabel.setSelected(true);
} }
private void initCoverLyricsSlideView() { private void initCoverLyricsSlideView() {
playerSongCoverViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL); playerMediaCoverViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
playerSongCoverViewPager.setAdapter(new PlayerControllerHorizontalPager(this)); playerMediaCoverViewPager.setAdapter(new PlayerControllerHorizontalPager(this));
playerSongCoverViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { playerMediaCoverViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override @Override
public void onPageSelected(int position) { public void onPageSelected(int position) {
super.onPageSelected(position); super.onPageSelected(position);
@ -158,15 +158,15 @@ public class PlayerControllerFragment extends Fragment {
} }
private void initMediaListenable() { private void initMediaListenable() {
playerBottomSheetViewModel.getLiveSong().observe(requireActivity(), song -> { playerBottomSheetViewModel.getLiveMedia().observe(requireActivity(), media -> {
if (song != null) { if (media != null) {
buttonFavorite.setChecked(song.isFavorite()); buttonFavorite.setChecked(media.isStarred());
buttonFavorite.setOnClickListener(v -> playerBottomSheetViewModel.setFavorite(requireContext(), song)); buttonFavorite.setOnClickListener(v -> playerBottomSheetViewModel.setFavorite(requireContext(), media));
buttonFavorite.setOnLongClickListener(v -> { buttonFavorite.setOnLongClickListener(v -> {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable("song_object", song); bundle.putParcelable("song_object", media);
RatingDialog dialog = new RatingDialog(); RatingDialog dialog = new RatingDialog();
dialog.setArguments(bundle); dialog.setArguments(bundle);
@ -176,7 +176,7 @@ public class PlayerControllerFragment extends Fragment {
}); });
if (getActivity() != null) { if (getActivity() != null) {
playerBottomSheetViewModel.refreshSongInfo(requireActivity(), song); playerBottomSheetViewModel.refreshMediaInfo(requireActivity(), media);
} }
} }
}); });
@ -196,10 +196,10 @@ public class PlayerControllerFragment extends Fragment {
} }
public void goToControllerPage() { public void goToControllerPage() {
playerSongCoverViewPager.setCurrentItem(0, false); playerMediaCoverViewPager.setCurrentItem(0, false);
} }
public void goToLyricsPage() { public void goToLyricsPage() {
playerSongCoverViewPager.setCurrentItem(1, true); playerMediaCoverViewPager.setCurrentItem(1, true);
} }
} }

View file

@ -92,7 +92,7 @@ public class PlayerCoverFragment extends Fragment {
} }
private void initInnerButton() { private void initInnerButton() {
playerBottomSheetViewModel.getLiveSong().observe(requireActivity(), song -> { playerBottomSheetViewModel.getLiveMedia().observe(requireActivity(), song -> {
if (song != null && bind != null) { if (song != null && bind != null) {
bind.innerButtonTopLeft.setOnClickListener(view -> { bind.innerButtonTopLeft.setOnClickListener(view -> {
DownloadUtil.getDownloadTracker(requireContext()).download( DownloadUtil.getDownloadTracker(requireContext()).download(
@ -172,6 +172,7 @@ public class PlayerCoverFragment extends Fragment {
}); });
} }
@SuppressLint("UnsafeOptInUsageError")
private void setCover(MediaMetadata mediaMetadata) { private void setCover(MediaMetadata mediaMetadata) {
CustomGlideRequest.Builder CustomGlideRequest.Builder
.from(requireContext(), mediaMetadata.extras != null ? mediaMetadata.extras.getString("id") : null, CustomGlideRequest.SONG_PIC, null) .from(requireContext(), mediaMetadata.extras != null ? mediaMetadata.extras.getString("id") : null, CustomGlideRequest.SONG_PIC, null)

View file

@ -11,9 +11,8 @@ import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.App; import com.cappielloantonio.play.App;
import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Artist;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.model.PodcastEpisode;
import com.cappielloantonio.play.model.Media; import com.cappielloantonio.play.model.Media;
import com.cappielloantonio.play.model.Playlist;
import com.cappielloantonio.play.repository.AlbumRepository; import com.cappielloantonio.play.repository.AlbumRepository;
import com.cappielloantonio.play.repository.ArtistRepository; import com.cappielloantonio.play.repository.ArtistRepository;
import com.cappielloantonio.play.repository.PlaylistRepository; import com.cappielloantonio.play.repository.PlaylistRepository;
@ -47,7 +46,7 @@ public class HomeViewModel extends AndroidViewModel {
private final MutableLiveData<List<Integer>> years = new MutableLiveData<>(null); private final MutableLiveData<List<Integer>> years = new MutableLiveData<>(null);
private final MutableLiveData<List<Album>> recentlyAddedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData<List<Album>> recentlyAddedAlbumSample = new MutableLiveData<>(null);
private final MutableLiveData<List<Playlist>> pinnedPlaylists = new MutableLiveData<>(null); private final MutableLiveData<List<Playlist>> pinnedPlaylists = new MutableLiveData<>(null);
private final MutableLiveData<List<PodcastEpisode>> newestPodcastEpisodes = new MutableLiveData<>(null); private final MutableLiveData<List<Media>> newestPodcastEpisodes = new MutableLiveData<>(null);
public HomeViewModel(@NonNull Application application) { public HomeViewModel(@NonNull Application application) {
super(application); super(application);
@ -134,7 +133,7 @@ public class HomeViewModel extends AndroidViewModel {
return playlistRepository.getPlaylistSongs(playlistId); return playlistRepository.getPlaylistSongs(playlistId);
} }
public LiveData<List<PodcastEpisode>> getNewestPodcastEpisodes(LifecycleOwner owner) { public LiveData<List<Media>> getNewestPodcastEpisodes(LifecycleOwner owner) {
podcastRepository.getNewestPodcastEpisodes(20).observe(owner, newestPodcastEpisodes::postValue); podcastRepository.getNewestPodcastEpisodes(20).observe(owner, newestPodcastEpisodes::postValue);
return newestPodcastEpisodes; return newestPodcastEpisodes;
} }

View file

@ -9,7 +9,6 @@ import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.play.model.Album;
import com.cappielloantonio.play.model.Artist; import com.cappielloantonio.play.model.Artist;
import com.cappielloantonio.play.model.Queue; import com.cappielloantonio.play.model.Queue;
import com.cappielloantonio.play.model.Media; import com.cappielloantonio.play.model.Media;
@ -31,8 +30,7 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
private final MutableLiveData<String> lyricsLiveData = new MutableLiveData<>(null); private final MutableLiveData<String> lyricsLiveData = new MutableLiveData<>(null);
private final MutableLiveData<Media> liveSong = new MutableLiveData<>(null); private final MutableLiveData<Media> liveMedia = new MutableLiveData<>(null);
private final MutableLiveData<Album> liveAlbum = new MutableLiveData<>(null);
private final MutableLiveData<Artist> liveArtist = new MutableLiveData<>(null); private final MutableLiveData<Artist> liveArtist = new MutableLiveData<>(null);
public PlayerBottomSheetViewModel(@NonNull Application application) { public PlayerBottomSheetViewModel(@NonNull Application application) {
@ -47,19 +45,19 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
return queueRepository.getLiveQueue(); return queueRepository.getLiveQueue();
} }
public void setFavorite(Context context, Media song) { public void setFavorite(Context context, Media media) {
if (song != null) { if (media != null) {
if (song.isFavorite()) { if (media.isStarred()) {
songRepository.unstar(song.getId()); songRepository.unstar(media.getId());
song.setFavorite(false); media.setStarred(false);
} else { } else {
songRepository.star(song.getId()); songRepository.star(media.getId());
song.setFavorite(true); media.setStarred(true);
if (PreferenceUtil.getInstance(context).isStarredSyncEnabled()) { if (PreferenceUtil.getInstance(context).isStarredSyncEnabled()) {
DownloadUtil.getDownloadTracker(context).download( DownloadUtil.getDownloadTracker(context).download(
MappingUtil.mapMediaItem(context, song, false), MappingUtil.mapMediaItem(context, media, false),
MappingUtil.mapDownload(song, null, null) MappingUtil.mapDownload(media, null, null)
); );
} }
} }
@ -70,23 +68,41 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
return lyricsLiveData; return lyricsLiveData;
} }
public void refreshSongInfo(LifecycleOwner owner, Media song) { public void refreshMediaInfo(LifecycleOwner owner, Media media) {
songRepository.getSongLyrics(song).observe(owner, lyricsLiveData::postValue); songRepository.getSongLyrics(media).observe(owner, lyricsLiveData::postValue);
} }
public LiveData<Media> getLiveSong() { public LiveData<Media> getLiveMedia() {
return liveSong; return liveMedia;
} }
public void setLiveSong(LifecycleOwner owner, String songId) { public void setLiveMedia(LifecycleOwner owner, String mediaType, String mediaId) {
songRepository.getSong(songId).observe(owner, liveSong::postValue); if(mediaType != null) {
switch (mediaType) {
case Media.MEDIA_TYPE_MUSIC:
songRepository.getSong(mediaId).observe(owner, liveMedia::postValue);
break;
case Media.MEDIA_TYPE_PODCAST:
liveMedia.postValue(null);
break;
}
}
} }
public LiveData<Artist> getLiveArtist() { public LiveData<Artist> getLiveArtist() {
return liveArtist; return liveArtist;
} }
public void setLiveArtist(LifecycleOwner owner, String ArtistId) { public void setLiveArtist(LifecycleOwner owner, String mediaType, String ArtistId) {
artistRepository.getArtist(ArtistId).observe(owner, liveArtist::postValue); if(mediaType != null) {
switch (mediaType) {
case Media.MEDIA_TYPE_MUSIC:
artistRepository.getArtist(ArtistId).observe(owner, liveArtist::postValue);
break;
case Media.MEDIA_TYPE_PODCAST:
liveArtist.postValue(null);
break;
}
}
} }
} }

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.media3.ui.PlayerControlView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.media3.ui.PlayerControlView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/now_playing_song_controller_view" android:id="@+id/now_playing_media_controller_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:controller_layout_id="@layout/inner_fragment_player_controller_layout" app:controller_layout_id="@layout/inner_fragment_player_controller_layout"

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/now_playing_song_controller_layout" android:id="@+id/now_playing_media_controller_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -44,7 +44,7 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/player_song_cover_view_pager" android:id="@+id/player_media_cover_view_pager"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/guideline" app:layout_constraintBottom_toTopOf="@id/guideline"
@ -60,7 +60,7 @@
app:layout_constraintGuide_percent="0.60" /> app:layout_constraintGuide_percent="0.60" />
<TextView <TextView
android:id="@+id/player_song_title_label" android:id="@+id/player_media_title_label"
style="@style/HeadlineLarge" style="@style/HeadlineLarge"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -84,9 +84,9 @@
android:text="" android:text=""
android:textOff="" android:textOff=""
android:textOn="" android:textOn=""
app:layout_constraintBottom_toBottomOf="@+id/player_song_title_label" app:layout_constraintBottom_toBottomOf="@+id/player_media_title_label"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/player_song_title_label" /> app:layout_constraintTop_toTopOf="@+id/player_media_title_label" />
<TextView <TextView
android:id="@+id/player_artist_name_label" android:id="@+id/player_artist_name_label"
@ -99,7 +99,7 @@
android:maxLines="2" android:maxLines="2"
android:text="@string/label_placeholder" android:text="@string/label_placeholder"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player_song_title_label" /> app:layout_constraintTop_toBottomOf="@+id/player_media_title_label" />
<TextView <TextView
android:id="@+id/exo_position" android:id="@+id/exo_position"

View file

@ -7,7 +7,7 @@
android:clipChildren="false"> android:clipChildren="false">
<ImageView <ImageView
android:id="@+id/player_header_song_cover_image" android:id="@+id/player_header_media_cover_image"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="42dp" android:layout_height="42dp"
android:layout_gravity="center" android:layout_gravity="center"
@ -17,7 +17,7 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/player_header_song_title_label" android:id="@+id/player_header_media_title_label"
style="@style/LabelMedium" style="@style/LabelMedium"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -27,11 +27,11 @@
android:paddingStart="8dp" android:paddingStart="8dp"
android:paddingEnd="8dp" android:paddingEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/player_header_button" app:layout_constraintEnd_toStartOf="@+id/player_header_button"
app:layout_constraintStart_toEndOf="@+id/player_header_song_cover_image" app:layout_constraintStart_toEndOf="@+id/player_header_media_cover_image"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/player_header_song_artist_label" android:id="@+id/player_header_media_artist_label"
style="@style/LabelSmall" style="@style/LabelSmall"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -40,8 +40,8 @@
android:paddingStart="8dp" android:paddingStart="8dp"
android:paddingEnd="8dp" android:paddingEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/player_header_button" app:layout_constraintEnd_toStartOf="@+id/player_header_button"
app:layout_constraintStart_toEndOf="@+id/player_header_song_cover_image" app:layout_constraintStart_toEndOf="@+id/player_header_media_cover_image"
app:layout_constraintTop_toBottomOf="@+id/player_header_song_title_label" /> app:layout_constraintTop_toBottomOf="@+id/player_header_media_title_label" />
<ToggleButton <ToggleButton
android:id="@+id/player_header_button" android:id="@+id/player_header_button"
@ -56,11 +56,11 @@
android:textOff="" android:textOff=""
android:textOn="" android:textOn=""
app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar" app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar"
app:layout_constraintEnd_toStartOf="@+id/player_header_next_song_button" app:layout_constraintEnd_toStartOf="@+id/player_header_next_media_button"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageButton <ImageButton
android:id="@+id/player_header_next_song_button" android:id="@+id/player_header_next_media_button"
android:layout_width="28dp" android:layout_width="28dp"
android:layout_height="28dp" android:layout_height="28dp"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"