@@ -7,8 +7,10 @@ import android.graphics.BitmapFactory
7
7
import android.graphics.Canvas
8
8
import android.graphics.Paint
9
9
import android.graphics.Rect
10
+ import android.media.audiofx.Equalizer
10
11
import android.media.audiofx.LoudnessEnhancer
11
12
import android.net.Uri
13
+ import android.os.Bundle
12
14
import android.os.Handler
13
15
import android.util.Log
14
16
import androidx.annotation.ColorInt
@@ -17,6 +19,7 @@ import androidx.media3.common.AudioAttributes
17
19
import androidx.media3.common.C
18
20
import androidx.media3.common.MediaItem
19
21
import androidx.media3.common.Player
22
+ import androidx.media3.common.util.UnstableApi
20
23
import androidx.media3.database.StandaloneDatabaseProvider
21
24
import androidx.media3.datasource.DataSource
22
25
import androidx.media3.datasource.DefaultDataSource
@@ -39,7 +42,11 @@ import androidx.media3.exoplayer.source.MediaSource
39
42
import androidx.media3.session.BitmapLoader
40
43
import androidx.media3.session.MediaSession
41
44
import androidx.media3.session.MediaSessionService
45
+ import androidx.media3.session.SessionCommand
46
+ import androidx.media3.session.SessionResult
42
47
import app.suhasdissa.vibeyou.MellowMusicApplication
48
+ import app.suhasdissa.vibeyou.backend.data.EqualizerBand
49
+ import app.suhasdissa.vibeyou.backend.data.EqualizerData
43
50
import app.suhasdissa.vibeyou.backend.data.Song
44
51
import app.suhasdissa.vibeyou.utils.DynamicDataSource
45
52
import app.suhasdissa.vibeyou.utils.IS_LOCAL_KEY
@@ -58,16 +65,46 @@ import kotlinx.coroutines.launch
58
65
import kotlinx.coroutines.runBlocking
59
66
import kotlinx.coroutines.withContext
60
67
68
+ @UnstableApi
61
69
class PlayerService : MediaSessionService (), MediaSession.Callback, Player.Listener {
62
70
private var mediaSession: MediaSession ? = null
63
71
private lateinit var cache: SimpleCache
64
72
private lateinit var player: ExoPlayer
73
+ private lateinit var equalizer: Equalizer
65
74
66
75
private var loudnessEnhancer: LoudnessEnhancer ? = null
67
76
68
77
val appInstance get() = application as MellowMusicApplication
69
78
val container get() = appInstance.container
70
79
80
+ private val mediaSessionCallback = object : MediaSession .Callback {
81
+ override fun onConnect (
82
+ session : MediaSession ,
83
+ controller : MediaSession .ControllerInfo
84
+ ): MediaSession .ConnectionResult {
85
+ val sessionCommands = MediaSession .ConnectionResult .DEFAULT_SESSION_COMMANDS .buildUpon()
86
+ .add(SessionCommand (COMMAND_UPDATE_EQUALIZER , Bundle .EMPTY ))
87
+ .build()
88
+
89
+ return MediaSession .ConnectionResult .AcceptedResultBuilder (session)
90
+ .setAvailableSessionCommands(sessionCommands)
91
+ .build()
92
+ }
93
+
94
+ override fun onCustomCommand (
95
+ session : MediaSession ,
96
+ controller : MediaSession .ControllerInfo ,
97
+ customCommand : SessionCommand ,
98
+ args : Bundle
99
+ ): ListenableFuture <SessionResult > {
100
+ if (customCommand.customAction == COMMAND_UPDATE_EQUALIZER ) {
101
+ updateEqualizerSettings()
102
+ }
103
+
104
+ return super .onCustomCommand(session, controller, customCommand, args)
105
+ }
106
+ }
107
+
71
108
@androidx.annotation.OptIn (androidx.media3.common.util.UnstableApi ::class )
72
109
override fun onCreate () {
73
110
super .onCreate()
@@ -86,13 +123,15 @@ class PlayerService : MediaSessionService(), MediaSession.Callback, Player.Liste
86
123
cache = SimpleCache (directory, cacheEvictor, StandaloneDatabaseProvider (this ))
87
124
88
125
player = createPlayer()
126
+ setupEqualizer()
89
127
90
128
player.repeatMode = Player .REPEAT_MODE_OFF
91
129
player.playWhenReady = true
92
130
player.addListener(this )
93
131
94
132
mediaSession = MediaSession .Builder (this , player).setCallback(this )
95
133
.setBitmapLoader(CustomBitmapLoader (this ))
134
+ .setCallback(mediaSessionCallback)
96
135
.build()
97
136
}
98
137
@@ -304,4 +343,55 @@ class PlayerService : MediaSessionService(), MediaSession.Callback, Player.Liste
304
343
)
305
344
}
306
345
}
346
+
347
+ private fun setupEqualizer () {
348
+ equalizer = Equalizer (Integer .MAX_VALUE , player.audioSessionId)
349
+ appInstance.supportedEqualizerData = EqualizerData (
350
+ presets = (0 until equalizer.numberOfPresets).map {
351
+ equalizer.getPresetName(it.toShort())
352
+ },
353
+ bands = (0 until equalizer.numberOfBands).map { id ->
354
+ val freqRange = equalizer.bandLevelRange
355
+ EqualizerBand (
356
+ equalizer.getCenterFreq(id.toShort()),
357
+ freqRange.first(),
358
+ freqRange.last()
359
+ )
360
+ }
361
+ )
362
+
363
+ updateEqualizerSettings()
364
+ }
365
+
366
+ /* private fun useSystemEqualizer() {
367
+ val intent = Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
368
+ intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, player.audioSessionId);
369
+ intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, packageName);
370
+ sendBroadcast(intent);
371
+ }*/
372
+
373
+ private fun updateEqualizerSettings () {
374
+ if (! ::equalizer.isInitialized) return
375
+
376
+ equalizer.enabled = Pref .sharedPreferences.getBoolean(Pref .equalizerKey, false )
377
+ if (! equalizer.enabled) return
378
+
379
+ val preset = Pref .sharedPreferences.getInt(Pref .equalizerPresetKey, - 1 )
380
+ if (preset != - 1 ) {
381
+ equalizer.usePreset(preset.toShort())
382
+ return
383
+ }
384
+
385
+ val bandPrefs = Pref .sharedPreferences.getString(Pref .equalizerBandsKey, " " )
386
+ if (bandPrefs.isNullOrEmpty()) return
387
+
388
+ val bandLevels = bandPrefs.split(" ," ).map(String ::toShort)
389
+ for (i in bandLevels.indices) {
390
+ equalizer.setBandLevel(i.toShort(), bandLevels[i])
391
+ }
392
+ }
393
+
394
+ companion object {
395
+ const val COMMAND_UPDATE_EQUALIZER = " update_equalizer"
396
+ }
307
397
}
0 commit comments