Merge branch 'eddyizm:development' into development

This commit is contained in:
skajmer 2025-11-09 13:06:27 +01:00 committed by GitHub
commit 51883cd82b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 177 additions and 24 deletions

View file

@ -1,6 +1,10 @@
# Changelog # Changelog
## Pending release.. ## Pending release..
* fix: reverts change causing album disc/track list to get out of order by @eddyizm in https://github.com/eddyizm/tempus/pull/237
* fix: Add listener to enable equalizer when audioSessionId changes by @jaime-grj in https://github.com/eddyizm/tempus/pull/235
**Full Changelog**: https://github.com/eddyizm/tempus/compare/v4.1.0...v4.1.2
## [4.1.0](https://github.com/eddyizm/tempo/releases/tag/v4.1.0) (2025-11-05) ## [4.1.0](https://github.com/eddyizm/tempo/releases/tag/v4.1.0) (2025-11-05)
## What's Changed ## What's Changed

View file

@ -10,8 +10,8 @@ android {
minSdkVersion 24 minSdkVersion 24
targetSdk 35 targetSdk 35
versionCode 3 versionCode 4
versionName '4.1.0' versionName '4.1.3'
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
javaCompileOptions { javaCompileOptions {

View file

@ -82,6 +82,7 @@ class MediaService : MediaLibraryService() {
private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL = private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL =
"android.media3.session.demo.REPEAT_ALL" "android.media3.session.demo.REPEAT_ALL"
const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER" const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER"
const val ACTION_EQUALIZER_UPDATED = "com.cappielloantonio.tempo.service.EQUALIZER_UPDATED"
} }
fun updateMediaItems() { fun updateMediaItems() {
@ -283,16 +284,7 @@ class MediaService : MediaLibraryService() {
private fun initializeEqualizerManager() { private fun initializeEqualizerManager() {
equalizerManager = EqualizerManager() equalizerManager = EqualizerManager()
val audioSessionId = player.audioSessionId val audioSessionId = player.audioSessionId
if (equalizerManager.attachToSession(audioSessionId)) { attachEqualizerIfPossible(audioSessionId)
val enabled = Preferences.isEqualizerEnabled()
equalizerManager.setEnabled(enabled)
val bands = equalizerManager.getNumberOfBands()
val savedLevels = Preferences.getEqualizerBandLevels(bands)
for (i in 0 until bands) {
equalizerManager.setBandLevel(i.toShort(), savedLevels[i])
}
}
} }
private fun initializeMediaLibrarySession() { private fun initializeMediaLibrarySession() {
@ -426,6 +418,10 @@ class MediaService : MediaLibraryService() {
customLayout = librarySessionCallback.buildCustomLayout(player) customLayout = librarySessionCallback.buildCustomLayout(player)
mediaLibrarySession.setCustomLayout(customLayout) mediaLibrarySession.setCustomLayout(customLayout)
} }
override fun onAudioSessionIdChanged(audioSessionId: Int) {
attachEqualizerIfPossible(audioSessionId)
}
}) })
if (player.isPlaying) { if (player.isPlaying) {
scheduleWidgetUpdates() scheduleWidgetUpdates()
@ -541,6 +537,21 @@ class MediaService : MediaLibraryService() {
widgetUpdateScheduled = false widgetUpdateScheduled = false
} }
private fun attachEqualizerIfPossible(audioSessionId: Int): Boolean {
if (audioSessionId == 0 || audioSessionId == -1) return false
val attached = equalizerManager.attachToSession(audioSessionId)
if (attached) {
val enabled = Preferences.isEqualizerEnabled()
equalizerManager.setEnabled(enabled)
val bands = equalizerManager.getNumberOfBands()
val savedLevels = Preferences.getEqualizerBandLevels(bands)
for (i in 0 until bands) {
equalizerManager.setBandLevel(i.toShort(), savedLevels[i])
}
sendBroadcast(Intent(ACTION_EQUALIZER_UPDATED))
}
return attached
}
private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false) private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false)

View file

@ -105,6 +105,16 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter<AlbumCatalogueAd
filtering.filter(currentFilter); filtering.filter(currentFilter);
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override @Override
public Filter getFilter() { public Filter getFilter() {
return filtering; return filtering;

View file

@ -66,6 +66,16 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
public class ViewHolder extends RecyclerView.ViewHolder { public class ViewHolder extends RecyclerView.ViewHolder {
ItemLibraryArtistBinding item; ItemLibraryArtistBinding item;

View file

@ -97,6 +97,16 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter<ArtistCatalogue
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override @Override
public Filter getFilter() { public Filter getFilter() {
return filtering; return filtering;

View file

@ -113,6 +113,16 @@ public class ArtistHorizontalAdapter extends RecyclerView.Adapter<ArtistHorizont
return artists.get(id); return artists.get(id);
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
public class ViewHolder extends RecyclerView.ViewHolder { public class ViewHolder extends RecyclerView.ViewHolder {
ItemHorizontalArtistBinding item; ItemHorizontalArtistBinding item;

View file

@ -60,6 +60,16 @@ public class ArtistSimilarAdapter extends RecyclerView.Adapter<ArtistSimilarAdap
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
public class ViewHolder extends RecyclerView.ViewHolder { public class ViewHolder extends RecyclerView.ViewHolder {
ItemLibrarySimilarArtistBinding item; ItemLibrarySimilarArtistBinding item;

View file

@ -96,6 +96,16 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
return shuffling; return shuffling;
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
private List<Child> groupSong(List<Child> songs) { private List<Child> groupSong(List<Child> songs) {
switch (view) { switch (view) {
case Constants.DOWNLOAD_TYPE_TRACK: case Constants.DOWNLOAD_TYPE_TRACK:

View file

@ -95,6 +95,16 @@ public class PodcastChannelCatalogueAdapter extends RecyclerView.Adapter<Podcast
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override @Override
public Filter getFilter() { public Filter getFilter() {
return filtering; return filtering;

View file

@ -71,6 +71,16 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
public class ViewHolder extends RecyclerView.ViewHolder { public class ViewHolder extends RecyclerView.ViewHolder {
ItemHomePodcastEpisodeBinding item; ItemHomePodcastEpisodeBinding item;

View file

@ -252,6 +252,16 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
public void setPlaybackState(String mediaId, boolean playing) { public void setPlaybackState(String mediaId, boolean playing) {
String oldId = this.currentPlayingId; String oldId = this.currentPlayingId;
boolean oldPlaying = this.isPlaying; boolean oldPlaying = this.isPlaying;

View file

@ -3,7 +3,9 @@ package com.cappielloantonio.tempo.ui.fragment
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.BroadcastReceiver
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.view.Gravity import android.view.Gravity
@ -12,6 +14,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.* import android.widget.*
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import com.cappielloantonio.tempo.R import com.cappielloantonio.tempo.R
@ -28,6 +31,17 @@ class EqualizerFragment : Fragment() {
private lateinit var safeSpace: Space private lateinit var safeSpace: Space
private val bandSeekBars = mutableListOf<SeekBar>() private val bandSeekBars = mutableListOf<SeekBar>()
private var receiverRegistered = false
private val equalizerUpdatedReceiver = object : BroadcastReceiver() {
@OptIn(UnstableApi::class)
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == MediaService.ACTION_EQUALIZER_UPDATED) {
initUI()
restoreEqualizerPreferences()
}
}
}
private val connection = object : ServiceConnection { private val connection = object : ServiceConnection {
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
override fun onServiceConnected(className: ComponentName, service: IBinder) { override fun onServiceConnected(className: ComponentName, service: IBinder) {
@ -49,12 +63,29 @@ class EqualizerFragment : Fragment() {
intent.action = MediaService.ACTION_BIND_EQUALIZER intent.action = MediaService.ACTION_BIND_EQUALIZER
requireActivity().bindService(intent, connection, Context.BIND_AUTO_CREATE) requireActivity().bindService(intent, connection, Context.BIND_AUTO_CREATE)
} }
if (!receiverRegistered) {
ContextCompat.registerReceiver(
requireContext(),
equalizerUpdatedReceiver,
IntentFilter(MediaService.ACTION_EQUALIZER_UPDATED),
ContextCompat.RECEIVER_NOT_EXPORTED
)
receiverRegistered = true
}
} }
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
requireActivity().unbindService(connection) requireActivity().unbindService(connection)
equalizerManager = null equalizerManager = null
if (receiverRegistered) {
try {
requireContext().unregisterReceiver(equalizerUpdatedReceiver)
} catch (_: Exception) {
// ignore if not registered
}
receiverRegistered = false
}
} }
override fun onCreateView( override fun onCreateView(

View file

@ -7,7 +7,10 @@
<ImageView <ImageView
android:id="@+id/discover_song_cover_image_view" android:id="@+id/discover_song_cover_image_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="196dp" android:layout_height="match_parent"
android:scaleType="centerCrop"
android:pivotX="50%"
android:pivotY="50%"
android:background="?attr/colorSurfaceContainerHighest" android:background="?attr/colorSurfaceContainerHighest"
android:foreground="@drawable/gradient_discover_background_image" /> android:foreground="@drawable/gradient_discover_background_image" />

View file

@ -60,6 +60,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
companion object { companion object {
const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER" const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER"
const val ACTION_EQUALIZER_UPDATED = "com.cappielloantonio.tempo.service.EQUALIZER_UPDATED"
} }
private val widgetUpdateHandler = Handler(Looper.getMainLooper()) private val widgetUpdateHandler = Handler(Looper.getMainLooper())
private var widgetUpdateScheduled = false private var widgetUpdateScheduled = false
@ -160,16 +161,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
private fun initializeEqualizerManager() { private fun initializeEqualizerManager() {
equalizerManager = EqualizerManager() equalizerManager = EqualizerManager()
val audioSessionId = player.audioSessionId val audioSessionId = player.audioSessionId
if (equalizerManager.attachToSession(audioSessionId)) { attachEqualizerIfPossible(audioSessionId)
val enabled = Preferences.isEqualizerEnabled()
equalizerManager.setEnabled(enabled)
val bands = equalizerManager.getNumberOfBands()
val savedLevels = Preferences.getEqualizerBandLevels(bands)
for (i in 0 until bands) {
equalizerManager.setBandLevel(i.toShort(), savedLevels[i])
}
}
} }
private fun initializePlayer() { private fun initializePlayer() {
@ -333,6 +325,10 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
override fun onRepeatModeChanged(repeatMode: Int) { override fun onRepeatModeChanged(repeatMode: Int) {
Preferences.setRepeatMode(repeatMode) Preferences.setRepeatMode(repeatMode)
} }
override fun onAudioSessionIdChanged(audioSessionId: Int) {
attachEqualizerIfPossible(audioSessionId)
}
}) })
if (player.isPlaying) { if (player.isPlaying) {
scheduleWidgetUpdates() scheduleWidgetUpdates()
@ -450,6 +446,22 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
player.playWhenReady = isPlaying player.playWhenReady = isPlaying
player.prepare() player.prepare()
} }
private fun attachEqualizerIfPossible(audioSessionId: Int): Boolean {
if (audioSessionId == 0 || audioSessionId == -1) return false
val attached = equalizerManager.attachToSession(audioSessionId)
if (attached) {
val enabled = Preferences.isEqualizerEnabled()
equalizerManager.setEnabled(enabled)
val bands = equalizerManager.getNumberOfBands()
val savedLevels = Preferences.getEqualizerBandLevels(bands)
for (i in 0 until bands) {
equalizerManager.setBandLevel(i.toShort(), savedLevels[i])
}
sendBroadcast(Intent(ACTION_EQUALIZER_UPDATED))
}
return attached
}
} }
private const val WIDGET_UPDATE_INTERVAL_MS = 1000L private const val WIDGET_UPDATE_INTERVAL_MS = 1000L

View file

@ -0,0 +1,2 @@
reverts change causing album disc/track list to get out of order
Add listener to enable equalizer when audioSessionId