Merge pull request #1385 from prathameshmm02/dev
Playback speed and pitch fix
This commit is contained in:
commit
10367f64de
11 changed files with 86 additions and 53 deletions
|
@ -30,7 +30,6 @@ android {
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
versionNameSuffix "_" + getDate()
|
|
||||||
shrinkResources true
|
shrinkResources true
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
@ -88,10 +87,6 @@ static def getProperty(Properties properties, String name) {
|
||||||
return properties.getProperty(name) ?: "$name missing"
|
return properties.getProperty(name) ?: "$name missing"
|
||||||
}
|
}
|
||||||
|
|
||||||
static def getDate() {
|
|
||||||
new Date().format('MMddyyyyss')
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':appthemehelper')
|
implementation project(':appthemehelper')
|
||||||
implementation "androidx.gridlayout:gridlayout:1.0.0"
|
implementation "androidx.gridlayout:gridlayout:1.0.0"
|
||||||
|
|
|
@ -31,7 +31,7 @@ import java.lang.ref.WeakReference
|
||||||
* Created by Beesham Sarendranauth (Beesham)
|
* Created by Beesham Sarendranauth (Beesham)
|
||||||
*/
|
*/
|
||||||
class AutoMusicProvider(
|
class AutoMusicProvider(
|
||||||
val mContext: Context,
|
private val mContext: Context,
|
||||||
private val songsRepository: SongRepository,
|
private val songsRepository: SongRepository,
|
||||||
private val albumsRepository: AlbumRepository,
|
private val albumsRepository: AlbumRepository,
|
||||||
private val artistsRepository: ArtistRepository,
|
private val artistsRepository: ArtistRepository,
|
||||||
|
|
|
@ -60,8 +60,7 @@ class SongShareDialog : DialogFragment() {
|
||||||
0 -> {
|
0 -> {
|
||||||
startActivity(Intent.createChooser(song?.let {
|
startActivity(Intent.createChooser(song?.let {
|
||||||
MusicUtil.createShareSongFileIntent(
|
MusicUtil.createShareSongFileIntent(
|
||||||
it,
|
requireContext(), it
|
||||||
requireContext()
|
|
||||||
)
|
)
|
||||||
}, null))
|
}, null))
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ object SongMenuHelper : KoinComponent {
|
||||||
R.id.action_share -> {
|
R.id.action_share -> {
|
||||||
activity.startActivity(
|
activity.startActivity(
|
||||||
Intent.createChooser(
|
Intent.createChooser(
|
||||||
MusicUtil.createShareSongFileIntent(song, activity),
|
MusicUtil.createShareSongFileIntent(activity, song),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
package code.name.monkey.retromusic.helper.menu
|
package code.name.monkey.retromusic.helper.menu
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||||
|
@ -21,6 +22,7 @@ import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.repository.RealRepository
|
import code.name.monkey.retromusic.repository.RealRepository
|
||||||
|
import code.name.monkey.retromusic.util.MusicUtil
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -53,6 +55,15 @@ object SongsMenuHelper : KoinComponent {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.action_share -> {
|
||||||
|
activity.startActivity(
|
||||||
|
Intent.createChooser(
|
||||||
|
MusicUtil.createShareMultipleSongIntent(activity, songs),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
R.id.action_delete_from_device -> {
|
R.id.action_delete_from_device -> {
|
||||||
DeleteSongsDialog.create(songs)
|
DeleteSongsDialog.create(songs)
|
||||||
.show(activity.supportFragmentManager, "DELETE_SONGS")
|
.show(activity.supportFragmentManager, "DELETE_SONGS")
|
||||||
|
|
|
@ -7,16 +7,21 @@ import android.content.IntentFilter
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
|
import android.media.PlaybackParams
|
||||||
|
import android.os.StrictMode
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.media.AudioAttributesCompat
|
import androidx.media.AudioAttributesCompat
|
||||||
import androidx.media.AudioFocusRequestCompat
|
import androidx.media.AudioFocusRequestCompat
|
||||||
import androidx.media.AudioManagerCompat
|
import androidx.media.AudioManagerCompat
|
||||||
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.extensions.showToast
|
import code.name.monkey.retromusic.extensions.showToast
|
||||||
import code.name.monkey.retromusic.service.playback.Playback
|
import code.name.monkey.retromusic.service.playback.Playback
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.isAudioFocusEnabled
|
import code.name.monkey.retromusic.util.PreferenceUtil.isAudioFocusEnabled
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil.playbackPitch
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil.playbackSpeed
|
||||||
|
|
||||||
abstract class LocalPlayback(val context: Context) : Playback, MediaPlayer.OnErrorListener,
|
abstract class LocalPlayback(val context: Context) : Playback, MediaPlayer.OnErrorListener,
|
||||||
MediaPlayer.OnCompletionListener {
|
MediaPlayer.OnCompletionListener {
|
||||||
|
@ -121,11 +126,16 @@ abstract class LocalPlayback(val context: Context) : Playback, MediaPlayer.OnErr
|
||||||
} else {
|
} else {
|
||||||
player.setDataSource(path)
|
player.setDataSource(path)
|
||||||
}
|
}
|
||||||
player.setAudioAttributes(AudioAttributes.Builder()
|
player.setAudioAttributes(
|
||||||
|
AudioAttributes.Builder()
|
||||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
if (VersionUtils.hasMarshmallow())
|
||||||
|
player.playbackParams =
|
||||||
|
PlaybackParams().setSpeed(playbackSpeed).setPitch(playbackPitch)
|
||||||
|
|
||||||
player.setOnPreparedListener {
|
player.setOnPreparedListener {
|
||||||
player.setOnPreparedListener(null)
|
player.setOnPreparedListener(null)
|
||||||
completion(true)
|
completion(true)
|
||||||
|
|
|
@ -23,6 +23,7 @@ import code.name.monkey.retromusic.extensions.uri
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.service.playback.Playback.PlaybackCallbacks
|
import code.name.monkey.retromusic.service.playback.Playback.PlaybackCallbacks
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.isGapLessPlayback
|
import code.name.monkey.retromusic.util.PreferenceUtil.isGapLessPlayback
|
||||||
|
import code.name.monkey.retromusic.util.logE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Andrew Neal, Karim Abou Zeid (kabouzeid)
|
* @author Andrew Neal, Karim Abou Zeid (kabouzeid)
|
||||||
|
@ -141,10 +142,8 @@ class MultiPlayer(context: Context) : LocalPlayback(context) {
|
||||||
override fun release() {
|
override fun release() {
|
||||||
stop()
|
stop()
|
||||||
mCurrentMediaPlayer.release()
|
mCurrentMediaPlayer.release()
|
||||||
if (mNextMediaPlayer != null) {
|
|
||||||
mNextMediaPlayer?.release()
|
mNextMediaPlayer?.release()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pauses playback. Call start() to resume.
|
* Pauses playback. Call start() to resume.
|
||||||
|
@ -249,7 +248,7 @@ class MultiPlayer(context: Context) : LocalPlayback(context) {
|
||||||
mCurrentMediaPlayer = MediaPlayer()
|
mCurrentMediaPlayer = MediaPlayer()
|
||||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK)
|
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK)
|
||||||
context.showToast(R.string.unplayable_file)
|
context.showToast(R.string.unplayable_file)
|
||||||
Log.e(TAG, what.toString() + extra)
|
logE(what.toString() + extra)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,9 +259,9 @@ class MultiPlayer(context: Context) : LocalPlayback(context) {
|
||||||
mCurrentMediaPlayer = mNextMediaPlayer!!
|
mCurrentMediaPlayer = mNextMediaPlayer!!
|
||||||
isInitialized = true
|
isInitialized = true
|
||||||
mNextMediaPlayer = null
|
mNextMediaPlayer = null
|
||||||
if (callbacks != null) callbacks?.onTrackWentToNext()
|
callbacks?.onTrackWentToNext()
|
||||||
} else {
|
} else {
|
||||||
if (callbacks != null) callbacks?.onTrackEnded()
|
callbacks?.onTrackEnded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +269,7 @@ class MultiPlayer(context: Context) : LocalPlayback(context) {
|
||||||
|
|
||||||
override fun setPlaybackSpeedPitch(speed: Float, pitch: Float) {
|
override fun setPlaybackSpeedPitch(speed: Float, pitch: Float) {
|
||||||
mCurrentMediaPlayer.setPlaybackSpeedPitch(speed, pitch)
|
mCurrentMediaPlayer.setPlaybackSpeedPitch(speed, pitch)
|
||||||
|
mNextMediaPlayer?.setPlaybackSpeedPitch(speed, pitch)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -18,7 +18,6 @@ import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.bluetooth.BluetoothDevice
|
import android.bluetooth.BluetoothDevice
|
||||||
import android.bluetooth.BluetoothDevice.EXTRA_DEVICE
|
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
import android.content.pm.ServiceInfo
|
import android.content.pm.ServiceInfo
|
||||||
|
@ -224,14 +223,15 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
var shuffleMode = 0
|
var shuffleMode = 0
|
||||||
private val songPlayCountHelper = SongPlayCountHelper()
|
private val songPlayCountHelper = SongPlayCountHelper()
|
||||||
|
|
||||||
private val bluetoothReceiver = object : BroadcastReceiver() {
|
private val bluetoothReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||||
@SuppressLint("MissingPermission")
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val action = intent.action
|
val action = intent.action
|
||||||
val extra = intent.getParcelableExtra<BluetoothDevice>(EXTRA_DEVICE)!!
|
|
||||||
if (action != null) {
|
if (action != null) {
|
||||||
if (BluetoothDevice.ACTION_ACL_CONNECTED == action && isBluetoothSpeaker) {
|
if (BluetoothDevice.ACTION_ACL_CONNECTED == action && isBluetoothSpeaker) {
|
||||||
if (extra.type == BluetoothDevice.DEVICE_TYPE_CLASSIC) play()
|
@Suppress("Deprecation")
|
||||||
|
if (getSystemService<AudioManager>()!!.isBluetoothA2dpOn) {
|
||||||
|
play()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,16 +591,9 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
* By default return the browsable root. Treat the EXTRA_RECENT flag as a special case
|
* By default return the browsable root. Treat the EXTRA_RECENT flag as a special case
|
||||||
* and return the recent root instead.
|
* and return the recent root instead.
|
||||||
*/
|
*/
|
||||||
var isRecentRequest = false
|
val isRecentRequest = rootHints?.getBoolean(BrowserRoot.EXTRA_RECENT) ?: false
|
||||||
if (rootHints != null) {
|
val browserRootPath =
|
||||||
isRecentRequest =
|
if (isRecentRequest) AutoMediaIDHelper.RECENT_ROOT else AutoMediaIDHelper.MEDIA_ID_ROOT
|
||||||
rootHints.getBoolean(BrowserRoot.EXTRA_RECENT)
|
|
||||||
}
|
|
||||||
val browserRootPath = if (isRecentRequest) {
|
|
||||||
AutoMediaIDHelper.RECENT_ROOT
|
|
||||||
} else {
|
|
||||||
AutoMediaIDHelper.MEDIA_ID_ROOT
|
|
||||||
}
|
|
||||||
BrowserRoot(browserRootPath, null)
|
BrowserRoot(browserRootPath, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -974,6 +967,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
intent.putExtra("position", songProgressMillis.toLong())
|
intent.putExtra("position", songProgressMillis.toLong())
|
||||||
intent.putExtra("playing", isPlaying)
|
intent.putExtra("playing", isPlaying)
|
||||||
intent.putExtra("scrobbling_source", RETRO_MUSIC_PACKAGE_NAME)
|
intent.putExtra("scrobbling_source", RETRO_MUSIC_PACKAGE_NAME)
|
||||||
|
@Suppress("Deprecation")
|
||||||
sendStickyBroadcast(intent)
|
sendStickyBroadcast(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ import android.media.audiofx.AudioEffect
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.service.playback.Playback
|
import code.name.monkey.retromusic.service.playback.Playback
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.playbackPitch
|
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil.playbackSpeed
|
|
||||||
|
|
||||||
|
|
||||||
class PlaybackManager(val context: Context) {
|
class PlaybackManager(val context: Context) {
|
||||||
|
@ -35,9 +33,6 @@ class PlaybackManager(val context: Context) {
|
||||||
val isPlaying: Boolean
|
val isPlaying: Boolean
|
||||||
get() = playback != null && playback!!.isPlaying
|
get() = playback != null && playback!!.isPlaying
|
||||||
|
|
||||||
private val shouldSetSpeed: Boolean
|
|
||||||
get() = !(playbackSpeed == 1f && playbackPitch == 1f)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
playback = createLocalPlayback()
|
playback = createLocalPlayback()
|
||||||
}
|
}
|
||||||
|
@ -61,9 +56,6 @@ class PlaybackManager(val context: Context) {
|
||||||
AudioFader.startFadeAnimator(playback!!, true)
|
AudioFader.startFadeAnimator(playback!!, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shouldSetSpeed) {
|
|
||||||
playback?.setPlaybackSpeedPitch(playbackSpeed, playbackPitch)
|
|
||||||
}
|
|
||||||
playback?.start()
|
playback?.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,11 @@ import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
||||||
object MusicUtil : KoinComponent {
|
object MusicUtil : KoinComponent {
|
||||||
fun createShareSongFileIntent(song: Song, context: Context): Intent {
|
fun createShareSongFileIntent(context: Context, song: Song): Intent {
|
||||||
return Intent().apply {
|
return Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
putExtra(Intent.EXTRA_STREAM, try {
|
putExtra(
|
||||||
|
Intent.EXTRA_STREAM, try {
|
||||||
FileProvider.getUriForFile(
|
FileProvider.getUriForFile(
|
||||||
context,
|
context,
|
||||||
context.applicationContext.packageName,
|
context.applicationContext.packageName,
|
||||||
|
@ -52,12 +53,37 @@ object MusicUtil : KoinComponent {
|
||||||
)
|
)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
getSongFileUri(song.id)
|
getSongFileUri(song.id)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
type = "audio/*"
|
type = "audio/*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createShareMultipleSongIntent(context: Context, songs: List<Song>): Intent {
|
||||||
|
return Intent().apply {
|
||||||
|
action = Intent.ACTION_SEND_MULTIPLE
|
||||||
|
type = "audio/*"
|
||||||
|
|
||||||
|
val files = ArrayList<Uri>()
|
||||||
|
|
||||||
|
for (song in songs) {
|
||||||
|
files.add(
|
||||||
|
try {
|
||||||
|
FileProvider.getUriForFile(
|
||||||
|
context,
|
||||||
|
context.applicationContext.packageName,
|
||||||
|
File(song.data)
|
||||||
|
)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
getSongFileUri(song.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
putParcelableArrayListExtra(Intent.EXTRA_STREAM, files)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun buildInfoString(string1: String?, string2: String?): String {
|
fun buildInfoString(string1: String?, string2: String?): String {
|
||||||
if (string1.isNullOrEmpty()) {
|
if (string1.isNullOrEmpty()) {
|
||||||
return if (string2.isNullOrEmpty()) "" else string2
|
return if (string2.isNullOrEmpty()) "" else string2
|
||||||
|
|
|
@ -20,6 +20,12 @@
|
||||||
android:title="@string/action_add_to_playlist"
|
android:title="@string/action_add_to_playlist"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_share"
|
||||||
|
android:icon="@drawable/ic_share"
|
||||||
|
android:title="@string/action_share"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_delete_from_device"
|
android:id="@+id/action_delete_from_device"
|
||||||
android:icon="@drawable/ic_delete"
|
android:icon="@drawable/ic_delete"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue