diff --git a/app/src/main/java/code/name/monkey/retromusic/Constants.kt b/app/src/main/java/code/name/monkey/retromusic/Constants.kt
index 3e95ef631..23e9bf40c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/Constants.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/Constants.kt
@@ -155,3 +155,5 @@ const val WHITELIST_MUSIC = "whitelist_music"
const val MATERIAL_YOU = "material_you"
const val SNOWFALL = "snowfall"
const val LYRICS_TYPE = "lyrics_type"
+const val PLAYBACK_SPEED = "playback_speed"
+const val PLAYBACK_PITCH = "playback_pitch"
diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/PlaybackSpeedDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/PlaybackSpeedDialog.kt
new file mode 100644
index 000000000..114915fa0
--- /dev/null
+++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/PlaybackSpeedDialog.kt
@@ -0,0 +1,52 @@
+package code.name.monkey.retromusic.dialogs
+
+import android.app.Dialog
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import code.name.monkey.retromusic.R
+import code.name.monkey.retromusic.databinding.DialogPlaybackSpeedBinding
+import code.name.monkey.retromusic.extensions.accent
+import code.name.monkey.retromusic.extensions.colorButtons
+import code.name.monkey.retromusic.extensions.materialDialog
+import code.name.monkey.retromusic.util.PreferenceUtil
+import com.google.android.material.slider.Slider
+
+class PlaybackSpeedDialog : DialogFragment() {
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val binding = DialogPlaybackSpeedBinding.inflate(layoutInflater)
+ binding.playbackSpeedSlider.accent()
+ binding.playbackPitchSlider.accent()
+ binding.playbackSpeedSlider.addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
+ binding.speedValue.text = "$value"
+ })
+ binding.playbackPitchSlider.addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
+ binding.pitchValue.text = "$value"
+ })
+ binding.playbackSpeedSlider.value = PreferenceUtil.playbackSpeed
+ binding.playbackPitchSlider.value = PreferenceUtil.playbackPitch
+
+ return materialDialog(R.string.playback_settings)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(R.string.save) { _, _ ->
+ updatePlaybackAndPitch(
+ binding.playbackSpeedSlider.value,
+ binding.playbackPitchSlider.value
+ )
+ }
+ .setView(binding.root)
+ .create()
+ .colorButtons()
+ }
+
+ private fun updatePlaybackAndPitch(speed: Float, pitch: Float) {
+ PreferenceUtil.playbackSpeed = speed
+ PreferenceUtil.playbackPitch = pitch
+ }
+
+ companion object {
+ fun newInstance(): PlaybackSpeedDialog {
+ return PlaybackSpeedDialog()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/extensions/ColorExtensions.kt b/app/src/main/java/code/name/monkey/retromusic/extensions/ColorExtensions.kt
index 41c4f70de..6463070d7 100644
--- a/app/src/main/java/code/name/monkey/retromusic/extensions/ColorExtensions.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/extensions/ColorExtensions.kt
@@ -43,6 +43,7 @@ import com.google.android.material.button.MaterialButton
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.CircularProgressIndicator
+import com.google.android.material.slider.Slider
import com.google.android.material.textfield.TextInputLayout
fun Int.ripAlpha(): Int {
@@ -112,6 +113,12 @@ fun SeekBar.addAccentColor() {
thumbTintList = colorState
}
+fun Slider.accent() {
+ if (materialYou) return
+ trackActiveTintList = context.accentColor().colorStateList
+ trackInactiveTintList = context.accentColorVariant().colorStateList
+}
+
fun Button.accentTextColor() {
if (materialYou) return
setTextColor(ThemeStore.accentColor(App.getContext()))
@@ -269,6 +276,15 @@ fun Context.darkAccentColorVariant(): Int {
)
}
+@ColorInt
+fun Context.accentColorVariant(): Int {
+ return if (surfaceColor().isColorLight) {
+ accentColor().darkerColor
+ } else {
+ accentColor().lighterColor
+ }
+}
+
inline val @receiver:ColorInt Int.isColorLight
get() = ColorUtil.isColorLight(this)
@@ -276,4 +292,7 @@ inline val @receiver:ColorInt Int.lighterColor
get() = ColorUtil.lightenColor(this)
inline val @receiver:ColorInt Int.darkerColor
- get() = ColorUtil.darkenColor(this)
\ No newline at end of file
+ get() = ColorUtil.darkenColor(this)
+
+inline val Int.colorStateList : ColorStateList
+ get() = ColorStateList.valueOf(this)
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt
index bbbc8dd2a..eba65a37a 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt
@@ -42,6 +42,7 @@ import androidx.viewpager.widget.ViewPager
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.EXTRA_ARTIST_ID
+import code.name.monkey.retromusic.PLAYBACK_SPEED
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.MainActivity
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
@@ -79,6 +80,10 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
): Boolean {
val song = MusicPlayerRemote.currentSong
when (item.itemId) {
+ R.id.action_playback_speed -> {
+ PlaybackSpeedDialog.newInstance().show(childFragmentManager, "PLAYBACK_SETTINGS")
+ return true
+ }
R.id.action_toggle_lyrics -> {
PreferenceUtil.showLyrics = !item.isChecked
item.isChecked = !item.isChecked
diff --git a/app/src/main/java/code/name/monkey/retromusic/preferences/DurationPreference.kt b/app/src/main/java/code/name/monkey/retromusic/preferences/DurationPreference.kt
index c9b5e5d2b..e0581896c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/preferences/DurationPreference.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/preferences/DurationPreference.kt
@@ -1,17 +1,3 @@
-/*
- * Copyright (c) 2019 Hemanth Savarala.
- *
- * Licensed under the GNU General Public License v3
- *
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- */
-
package code.name.monkey.retromusic.preferences
import android.app.Dialog
diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java b/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java
index a861543d3..c3768dc17 100644
--- a/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java
+++ b/app/src/main/java/code/name/monkey/retromusic/service/MultiPlayer.java
@@ -16,8 +16,10 @@ package code.name.monkey.retromusic.service;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
+import android.media.PlaybackParams;
import android.media.audiofx.AudioEffect;
import android.net.Uri;
import android.os.PowerManager;
@@ -26,7 +28,10 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.preference.PreferenceManager;
+import code.name.monkey.appthemehelper.util.VersionUtils;
+import code.name.monkey.retromusic.ConstantsKt;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.service.playback.Playback;
import code.name.monkey.retromusic.util.PreferenceUtil;
@@ -35,7 +40,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil;
* @author Andrew Neal, Karim Abou Zeid (kabouzeid)
*/
public class MultiPlayer
- implements Playback, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
+ implements Playback, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, SharedPreferences.OnSharedPreferenceChangeListener {
public static final String TAG = MultiPlayer.class.getSimpleName();
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
@@ -53,6 +58,7 @@ public class MultiPlayer
MultiPlayer(final Context context) {
this.context = context;
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
+ PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this);
}
/**
@@ -86,6 +92,7 @@ public class MultiPlayer
} else {
player.setDataSource(path);
}
+ setPlaybackSpeedPitch(player);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.prepare();
} catch (Exception e) {
@@ -199,6 +206,7 @@ public class MultiPlayer
if (mNextMediaPlayer != null) {
mNextMediaPlayer.release();
}
+ PreferenceManager.getDefaultSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(this);
}
/**
@@ -346,4 +354,23 @@ public class MultiPlayer
@Override
public void setCrossFadeDuration(int duration) {
}
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key.equals(ConstantsKt.PLAYBACK_SPEED) || key.equals(ConstantsKt.PLAYBACK_PITCH)) {
+ setPlaybackSpeedPitch(mCurrentMediaPlayer);
+ }
+ }
+
+ public void setPlaybackSpeedPitch(MediaPlayer mp) {
+ if (VersionUtils.INSTANCE.hasMarshmallow()) {
+ boolean wasPlaying = mp.isPlaying();
+ mp.setPlaybackParams(new PlaybackParams()
+ .setSpeed(PreferenceUtil.INSTANCE.getPlaybackSpeed())
+ .setPitch(PreferenceUtil.INSTANCE.getPlaybackPitch()));
+ if (!wasPlaying) {
+ if (mp.isPlaying()) mp.pause();
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java
index d6add80cc..9cd954f80 100644
--- a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java
+++ b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java
@@ -22,6 +22,7 @@ import static code.name.monkey.retromusic.ConstantsKt.BLURRED_ALBUM_ART;
import static code.name.monkey.retromusic.ConstantsKt.CLASSIC_NOTIFICATION;
import static code.name.monkey.retromusic.ConstantsKt.COLORED_NOTIFICATION;
import static code.name.monkey.retromusic.ConstantsKt.CROSS_FADE_DURATION;
+import static code.name.monkey.retromusic.ConstantsKt.PLAYBACK_SPEED;
import static code.name.monkey.retromusic.ConstantsKt.TOGGLE_HEADSET;
import static code.name.monkey.retromusic.service.AudioFader.startFadeAnimator;
@@ -940,6 +941,9 @@ public class MusicService extends MediaBrowserServiceCompat
playingNotification.setPlaying(isPlaying());
playingNotification.updateMetadata(getCurrentSong(), this::startForegroundOrNotify);
break;
+ case PLAYBACK_SPEED:
+ updateMediaSessionPlaybackState();
+ break;
case TOGGLE_HEADSET:
registerHeadsetEvents();
break;
@@ -1334,7 +1338,7 @@ public class MusicService extends MediaBrowserServiceCompat
.setState(
isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
getSongProgressMillis(),
- 1);
+ PreferenceUtil.INSTANCE.getPlaybackSpeed());
setCustomAction(stateBuilder);
diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt
index f310bb9cc..7a92d61a6 100644
--- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt
@@ -674,6 +674,16 @@ object PreferenceUtil {
} else {
LyricsType.OVER_LYRICS
}
+
+ var playbackSpeed
+ get() = sharedPreferences
+ .getFloat(PLAYBACK_SPEED, 1F)
+ set(value) = sharedPreferences.edit { putFloat(PLAYBACK_SPEED, value) }
+
+ var playbackPitch
+ get() = sharedPreferences
+ .getFloat(PLAYBACK_PITCH, 1F)
+ set(value) = sharedPreferences.edit { putFloat(PLAYBACK_PITCH, value) }
}
enum class LyricsType {
REPLACE_LYRICS, OVER_LYRICS
diff --git a/app/src/main/res/drawable/ic_playback_speed.xml b/app/src/main/res/drawable/ic_playback_speed.xml
new file mode 100644
index 000000000..39b481679
--- /dev/null
+++ b/app/src/main/res/drawable/ic_playback_speed.xml
@@ -0,0 +1,12 @@
+