From c376adf2d95a581b9dd62b5f9598e44f84a72765 Mon Sep 17 00:00:00 2001 From: CappielloAntonio Date: Tue, 8 Feb 2022 17:46:13 +0100 Subject: [PATCH] Implemented the logic of podcast controllers --- .idea/misc.xml | 8 +- .../cappielloantonio/play/model/Media.java | 7 ++ .../fragment/PlayerBottomSheetFragment.java | 25 ++++ .../ui/fragment/PlayerControllerFragment.java | 101 ++++++++++++++++ .../inner_fragment_player_controller.xml | 2 + ...nner_fragment_player_controller_layout.xml | 111 ++++++++++++++++-- .../res/layout/player_header_bottom_sheet.xml | 52 +++++++- app/src/main/res/values/strings.xml | 1 + 8 files changed, 295 insertions(+), 12 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 04b54c4d..00ed8c15 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -18,6 +18,7 @@ + @@ -34,6 +35,7 @@ + @@ -60,6 +62,7 @@ + @@ -68,6 +71,9 @@ + + + @@ -110,7 +116,7 @@ - + diff --git a/app/src/main/java/com/cappielloantonio/play/model/Media.java b/app/src/main/java/com/cappielloantonio/play/model/Media.java index 46a62a25..fdfac521 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Media.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Media.java @@ -16,6 +16,13 @@ public class Media implements Parcelable { public static final String MEDIA_TYPE_AUDIOBOOK = "audiobook"; public static final String MEDIA_TYPE_VIDEO = "video"; + public static final float MEDIA_PLAYBACK_SPEED_080 = 0.8f; + public static final float MEDIA_PLAYBACK_SPEED_100 = 1.0f; + public static final float MEDIA_PLAYBACK_SPEED_125 = 1.25f; + public static final float MEDIA_PLAYBACK_SPEED_150 = 1.50f; + public static final float MEDIA_PLAYBACK_SPEED_175 = 1.75f; + public static final float MEDIA_PLAYBACK_SPEED_200 = 2.0f; + public static final String RECENTLY_PLAYED = "RECENTLY_PLAYED"; public static final String MOST_PLAYED = "MOST_PLAYED"; public static final String RECENTLY_ADDED = "RECENTLY_ADDED"; diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java index a4fbb9c6..d37ca206 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerBottomSheetFragment.java @@ -14,6 +14,7 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.media3.common.MediaMetadata; import androidx.media3.common.Player; +import androidx.media3.common.util.RepeatModeUtil; import androidx.media3.session.MediaBrowser; import androidx.media3.session.MediaController; import androidx.media3.session.SessionToken; @@ -23,6 +24,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.cappielloantonio.play.R; import com.cappielloantonio.play.databinding.FragmentPlayerBottomSheetBinding; import com.cappielloantonio.play.glide.CustomGlideRequest; +import com.cappielloantonio.play.model.Media; import com.cappielloantonio.play.service.MediaService; import com.cappielloantonio.play.ui.fragment.pager.PlayerControllerVerticalPager; import com.cappielloantonio.play.util.MusicUtil; @@ -108,6 +110,7 @@ public class PlayerBottomSheetFragment extends Fragment { @SuppressLint("UnsafeOptInUsageError") private void setMediaControllerListener(MediaBrowser mediaBrowser) { + setMediaControllerUI(mediaBrowser); setMetadata(mediaBrowser.getMediaMetadata()); setContentDuration(mediaBrowser.getContentDuration()); setPlayingState(mediaBrowser.isPlaying()); @@ -117,6 +120,7 @@ public class PlayerBottomSheetFragment extends Fragment { mediaBrowser.addListener(new Player.Listener() { @Override public void onMediaMetadataChanged(@NonNull MediaMetadata mediaMetadata) { + setMediaControllerUI(mediaBrowser); setMetadata(mediaMetadata); setContentDuration(mediaBrowser.getContentDuration()); } @@ -150,6 +154,25 @@ public class PlayerBottomSheetFragment extends Fragment { .into(bind.playerHeaderLayout.playerHeaderMediaCoverImage); } + @SuppressLint("UnsafeOptInUsageError") + private void setMediaControllerUI(MediaBrowser mediaBrowser) { + if (mediaBrowser.getMediaMetadata().extras != null) { + switch (mediaBrowser.getMediaMetadata().extras.getString("mediaType", Media.MEDIA_TYPE_MUSIC)) { + case Media.MEDIA_TYPE_PODCAST: + bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setVisibility(View.VISIBLE); + bind.playerHeaderLayout.playerHeaderRewindMediaButton.setVisibility(View.VISIBLE); + bind.playerHeaderLayout.playerHeaderNextMediaButton.setVisibility(View.GONE); + break; + case Media.MEDIA_TYPE_MUSIC: + default: + bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setVisibility(View.GONE); + bind.playerHeaderLayout.playerHeaderRewindMediaButton.setVisibility(View.GONE); + bind.playerHeaderLayout.playerHeaderNextMediaButton.setVisibility(View.VISIBLE); + break; + } + } + } + private void setContentDuration(long duration) { bind.playerHeaderLayout.playerHeaderSeekBar.setMax((int) (duration / 1000)); } @@ -169,6 +192,8 @@ public class PlayerBottomSheetFragment extends Fragment { }); bind.playerHeaderLayout.playerHeaderNextMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_next).performClick()); + bind.playerHeaderLayout.playerHeaderRewindMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_rew).performClick()); + bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_ffwd).performClick()); } private void setHeaderNextButtonState(boolean isEnabled) { diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerControllerFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerControllerFragment.java index 753e7e91..e9308a8c 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerControllerFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerControllerFragment.java @@ -7,6 +7,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.ToggleButton; @@ -15,7 +16,9 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.media3.common.MediaMetadata; +import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Player; +import androidx.media3.common.util.RepeatModeUtil; import androidx.media3.session.MediaBrowser; import androidx.media3.session.SessionToken; import androidx.navigation.fragment.NavHostFragment; @@ -23,11 +26,13 @@ import androidx.viewpager2.widget.ViewPager2; import com.cappielloantonio.play.R; import com.cappielloantonio.play.databinding.InnerFragmentPlayerControllerBinding; +import com.cappielloantonio.play.model.Media; import com.cappielloantonio.play.service.MediaService; import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.ui.dialog.RatingDialog; import com.cappielloantonio.play.ui.fragment.pager.PlayerControllerHorizontalPager; import com.cappielloantonio.play.util.MusicUtil; +import com.cappielloantonio.play.util.PreferenceUtil; import com.cappielloantonio.play.viewmodel.PlayerBottomSheetViewModel; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; @@ -41,6 +46,8 @@ public class PlayerControllerFragment extends Fragment { private ToggleButton buttonFavorite; private TextView playerMediaTitleLabel; private TextView playerArtistNameLabel; + private Button playbackSpeedButton; + private ToggleButton skipSilenceToggleButton; private MainActivity activity; private PlayerBottomSheetViewModel playerBottomSheetViewModel; @@ -60,6 +67,7 @@ public class PlayerControllerFragment extends Fragment { initMediaListenable(); initArtistLabelButton(); + return view; } @@ -90,6 +98,8 @@ public class PlayerControllerFragment extends Fragment { buttonFavorite = bind.getRoot().findViewById(R.id.button_favorite); playerMediaTitleLabel = bind.getRoot().findViewById(R.id.player_media_title_label); playerArtistNameLabel = bind.getRoot().findViewById(R.id.player_artist_name_label); + playbackSpeedButton = bind.getRoot().findViewById(R.id.player_playback_speed_button); + skipSilenceToggleButton = bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button); playerMoveDownBottomSheet.setOnClickListener(view -> activity.collapseBottomSheet()); } @@ -120,11 +130,13 @@ public class PlayerControllerFragment extends Fragment { @SuppressLint("UnsafeOptInUsageError") private void setMediaControllerListener(MediaBrowser mediaBrowser) { + setMediaControllerUI(mediaBrowser); setMetadata(mediaBrowser.getMediaMetadata()); mediaBrowser.addListener(new Player.Listener() { @Override public void onMediaMetadataChanged(@NonNull MediaMetadata mediaMetadata) { + setMediaControllerUI(mediaBrowser); setMetadata(mediaMetadata); } }); @@ -139,6 +151,39 @@ public class PlayerControllerFragment extends Fragment { playerArtistNameLabel.setSelected(true); } + @SuppressLint("UnsafeOptInUsageError") + private void setMediaControllerUI(MediaBrowser mediaBrowser) { + initPlaybackSpeedButton(mediaBrowser); + + if (mediaBrowser.getMediaMetadata().extras != null) { + switch (mediaBrowser.getMediaMetadata().extras.getString("mediaType", Media.MEDIA_TYPE_MUSIC)) { + case Media.MEDIA_TYPE_PODCAST: + bind.getRoot().setShowShuffleButton(false); + bind.getRoot().setShowRewindButton(true); + bind.getRoot().setShowPreviousButton(false); + bind.getRoot().setShowNextButton(false); + bind.getRoot().setShowFastForwardButton(true); + bind.getRoot().setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE); + bind.getRoot().findViewById(R.id.player_playback_speed_button).setVisibility(View.VISIBLE); + bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button).setVisibility(View.VISIBLE); + setPlaybackParameters(mediaBrowser); + break; + case Media.MEDIA_TYPE_MUSIC: + default: + bind.getRoot().setShowShuffleButton(true); + bind.getRoot().setShowRewindButton(false); + bind.getRoot().setShowPreviousButton(true); + bind.getRoot().setShowNextButton(true); + bind.getRoot().setShowFastForwardButton(false); + bind.getRoot().setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL | RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE); + bind.getRoot().findViewById(R.id.player_playback_speed_button).setVisibility(View.GONE); + bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button).setVisibility(View.GONE); + resetPlaybackParameters(mediaBrowser); + break; + } + } + } + private void initCoverLyricsSlideView() { playerMediaCoverViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL); playerMediaCoverViewPager.setAdapter(new PlayerControllerHorizontalPager(this)); @@ -195,6 +240,43 @@ public class PlayerControllerFragment extends Fragment { }); } + @SuppressLint("UnsafeOptInUsageError") + private void initPlaybackSpeedButton(MediaBrowser mediaBrowser) { + playbackSpeedButton.setOnClickListener(view -> { + float currentSpeed = PreferenceUtil.getInstance(requireContext()).getPlaybackSpeed(); + + if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_080) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_100)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_100)); + PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_100); + } else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_100) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_125)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_125)); + PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_125); + } else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_125) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_150)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_150)); + PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_150); + } else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_150) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_175)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_175)); + PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_175); + } else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_175) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_200)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_200)); + PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_200); + } else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_200) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_080)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_080)); + PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_080); + } + }); + + skipSilenceToggleButton.setOnClickListener(view -> { + PreferenceUtil.getInstance(requireContext()).setSkipSilenceMode(!skipSilenceToggleButton.isChecked()); + }); + } + public void goToControllerPage() { playerMediaCoverViewPager.setCurrentItem(0, false); } @@ -202,4 +284,23 @@ public class PlayerControllerFragment extends Fragment { public void goToLyricsPage() { playerMediaCoverViewPager.setCurrentItem(1, true); } + + @SuppressLint("UnsafeOptInUsageError") + private void setPlaybackParameters(MediaBrowser mediaBrowser) { + Button playbackSpeedButton = bind.getRoot().findViewById(R.id.player_playback_speed_button); + float currentSpeed = PreferenceUtil.getInstance(requireContext()).getPlaybackSpeed(); + boolean skipSilence = PreferenceUtil.getInstance(requireContext()).isSkipSilenceMode(); + + mediaBrowser.setPlaybackParameters(new PlaybackParameters(currentSpeed)); + playbackSpeedButton.setText(getString(R.string.player_playback_speed, currentSpeed)); + + // TODO Skippare il silenzio + skipSilenceToggleButton.setChecked(skipSilence); + } + + @SuppressLint("UnsafeOptInUsageError") + private void resetPlaybackParameters(MediaBrowser mediaBrowser) { + mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_100)); + // TODO Resettare lo skip del silenzio + } } \ No newline at end of file diff --git a/app/src/main/res/layout/inner_fragment_player_controller.xml b/app/src/main/res/layout/inner_fragment_player_controller.xml index 8e7214fd..9499e90d 100644 --- a/app/src/main/res/layout/inner_fragment_player_controller.xml +++ b/app/src/main/res/layout/inner_fragment_player_controller.xml @@ -7,4 +7,6 @@ app:controller_layout_id="@layout/inner_fragment_player_controller_layout" app:repeat_toggle_modes="all|one" app:show_shuffle_button="true" + app:show_rewind_button="false" + app:show_fastforward_button="false" app:show_timeout="0" /> \ No newline at end of file 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 21faf51c..3b56be26 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 @@ -145,6 +145,25 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/exo_progress" /> + + + + + + + + +