Skip to content

Commit 1d2a053

Browse files
committed
Refactor media session commands and UI scheduling
- Standardize UI update calls to use RxSchedulers.UI.ScheduleTo - Add static FavoriteSessionCommand with custom code (88) - Simplify media session layout to only include "Favorite" button - Prepend 🎙️ emoji to artist name if song has synced lyrics - Update session connection logic to expose Favorite command - Disable UpdateMediaSessionLayout with early return - Add debug code for player command inspection - Clean up and comment out unused shuffle/repeat button logic
1 parent 29a89dc commit 1d2a053

File tree

2 files changed

+63
-41
lines changed

2 files changed

+63
-41
lines changed

Dimmer/Dimmer.Droid/DimmerAudio/AudioService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public double Volume
3333
{
3434
if (Player != null)
3535
{
36-
RxSchedulers.UI.ScheduleToUI(() =>
36+
RxSchedulers.UI.ScheduleTo(() =>
3737
{
3838

3939
Player.Volume = (float)Math.Clamp(value, 0.0, 1.0);
@@ -98,8 +98,9 @@ public Task InitializeAsync(SongModelView songModel, double pos)
9898
{
9999
_currentSongModel = songModel;
100100
// Tell the native service to prepare the track.
101+
var finalArtName = songModel.HasSyncedLyrics ? "🎙️ " + songModel.OtherArtistsName : songModel.OtherArtistsName;
101102
long positionMs = (long)(pos * 1000.0);
102-
Service?.Prepare(songModel.FilePath, songModel.Title, songModel.ArtistName, songModel.AlbumName, songModel,startPositionMs: positionMs);
103+
Service?.Prepare(songModel.FilePath, songModel.Title, finalArtName, songModel.AlbumName, songModel,startPositionMs: positionMs);
103104

104105
return Task.CompletedTask;
105106
}

Dimmer/Dimmer.Droid/DimmerAudio/ExoPlayerService.cs

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class ExoPlayerService : MediaSessionService
5050
private MediaSession? mediaSession;
5151
private IExoPlayer? player;
5252
private MediaPlaybackSessionCallback? sessionCallback; // Use concrete type
53-
53+
public static SessionCommand FavoriteSessionCommand = new SessionCommand(ActionFavorite, Bundle.Empty);
5454
// --- Constants ---
5555
public const string ActionLyrics = "ACTION_LYRICS";
5656
public const string CommandPreparePlay = "com.yvanbrunel.dimmer.action.PREPARE_PLAY";
@@ -321,33 +321,28 @@ public async override void OnCreate()
321321
flags |= PendingIntentFlags.Immutable;
322322
}
323323
PendingIntent? pendingIntent = PendingIntent.GetActivity(Platform.AppContext, 0, nIntent, flags);
324+
FavoriteSessionCommand.CommandCode = 88;
324325

325326
var heartButton = new CommandButton.Builder(CommandButton.IconUndefined)
326-
.SetDisplayName("Favorite")
327-
.SetSessionCommand(new SessionCommand(ActionFavorite, Bundle.Empty))
328-
.SetCustomIconResId(Resource.Drawable.heart) // Standard resource ID
329-
.Build();
330-
331-
var shuffleButton = new CommandButton.Builder(CommandButton.IconUndefined)
332-
.SetDisplayName("Shuffle")
333-
.SetSessionCommand(new SessionCommand(ActionShuffle, Bundle.Empty))
334-
.SetCustomIconResId(Resource.Drawable.media3_icon_shuffle_off)
335-
.Build();
327+
.SetDisplayName("Favorite")
328+
.SetSessionCommand(FavoriteSessionCommand)
329+
//.SetPlayerCommand(88)
330+
//.SetSlots()
331+
332+
.SetCustomIconResId(Resource.Drawable.heart)
333+
.SetEnabled(true)
336334

337-
var repeatButton = new CommandButton.Builder(CommandButton.IconUndefined)
338-
.SetDisplayName("Repeat")
339-
.SetSessionCommand(new SessionCommand(ActionRepeat, Bundle.Empty))
340-
.SetCustomIconResId(Resource.Drawable.media3_icon_repeat_off)
341335
.Build();
342336

343337
mediaSession = new MediaSession.Builder(this, player)!
344338
.SetSessionActivity(pendingIntent)!
345339
.SetCallback(sessionCallback)!
346340
.SetId("Dimmer_MediaSession_Main")!
347-
348-
.SetCustomLayout(customLayout: new List<CommandButton> { heartButton, shuffleButton, repeatButton })
341+
.SetCommandButtonsForMediaItems(commandButtons: new List<CommandButton> { heartButton })
342+
.SetMediaButtonPreferences(mediaButtonPreferences:new List<CommandButton> { heartButton })
343+
.SetCustomLayout(customLayout: new List<CommandButton> { heartButton})
349344
.Build();
350-
345+
351346
_binder = new ExoPlayerServiceBinder(this);
352347

353348
// 2) NotificationManager
@@ -462,7 +457,7 @@ private void HandleFavoriteAction()
462457
await viewModel.AddFavoriteRatingToSong(CurrentSongContext);
463458
}
464459

465-
RxSchedulers.UI.ScheduleToUI(() => RefreshNotification());
460+
RxSchedulers.UI.ScheduleTo(() => RefreshNotification());
466461
}
467462
catch (Exception ex)
468463
{
@@ -478,7 +473,7 @@ private void HandleShuffleAction()
478473
var viewModel = MainApplication.ServiceProvider.GetService<BaseViewModel>();
479474
if (viewModel != null)
480475
{
481-
RxSchedulers.UI.ScheduleToUI(() =>
476+
RxSchedulers.UI.ScheduleTo(() =>
482477
{
483478
try
484479
{
@@ -499,7 +494,7 @@ private void HandleRepeatAction()
499494
var viewModel = MainApplication.ServiceProvider.GetService<BaseViewModel>();
500495
if (viewModel != null)
501496
{
502-
RxSchedulers.UI.ScheduleToUI(() =>
497+
RxSchedulers.UI.ScheduleTo(() =>
503498
{
504499
try
505500
{
@@ -710,6 +705,7 @@ internal static void UpdateFavoriteState(SongModelView song)
710705

711706
public void UpdateMediaSessionLayout()
712707
{
708+
return;
713709
bool isFav = CurrentSongContext?.IsFavorite ?? false;
714710

715711
var heartBtn = new CommandButton.Builder(CommandButton.IconUndefined)
@@ -978,27 +974,46 @@ public MediaSession.ConnectionResult OnConnect(
978974
{
979975

980976

981-
var sessionCommands = new SessionCommands.Builder()
982-
.Add(SessionCommand.CommandCodeSessionSetRating)!
983-
.Add(new SessionCommand(ExoPlayerService.ActionFavorite, Bundle.Empty))
984-
.Add(new SessionCommand(ExoPlayerService.ActionShuffle, Bundle.Empty))!
985-
.Add(new SessionCommand(ExoPlayerService.ActionRepeat, Bundle.Empty))!
986-
.Build();
977+
//var sessionCommands = new SessionCommands.Builder()
978+
// .Add(SessionCommand.CommandCodeSessionSetRating)!
979+
// .Add(new SessionCommand(ExoPlayerService.ActionFavorite, Bundle.Empty))
980+
// .Add(new SessionCommand(ExoPlayerService.ActionShuffle, Bundle.Empty))!
981+
// .Add(new SessionCommand(ExoPlayerService.ActionRepeat, Bundle.Empty))!
982+
// .Build();
987983

988-
989-
var playerCommands = new PlayerCommands.Builder()
990-
.Add(SessionCommand.CommandCodeSessionSetRating)
991-
992-
.AddAllCommands()!
993-
.Build();
994984

995-
return MediaSession.ConnectionResult.Accept(sessionCommands, playerCommands)!;
985+
//var playerCommands = new PlayerCommands.Builder()
986+
// .Add(SessionCommand.CommandCodeSessionSetRating)
987+
988+
// .AddAllCommands()!
989+
// .Build();
990+
var accepted = new MediaSession.ConnectionResult.AcceptedResultBuilder(session!)
991+
.SetAvailableSessionCommands(
992+
MediaSession.ConnectionResult.DefaultSessionCommands.BuildUpon()!
993+
994+
.Add(ExoPlayerService.FavoriteSessionCommand)!
995+
.Build())!;
996+
var comms = session.Player.AvailableCommands;
997+
if (comms != null)
998+
{
999+
var isAv = session.Player.IsCommandAvailable(88);
1000+
var isAvs = session.Player.AvailableCommands.Size();
1001+
//foreach (var comm in )
1002+
//{
1003+
1004+
//}
1005+
}
1006+
return accepted.
1007+
Build()!;
9961008
}
9971009
public void OnPostConnect(MediaSession? session, MediaSession.ControllerInfo? controller)
9981010
{
9991011

10001012

1001-
1013+
var commandsInSesssion = session.ConnectedControllers?.ToArray();
1014+
var commandsInSesssions = session.CustomLayout;
1015+
var commandsInSesssionsw = session.ControllerForCurrentRequest;
1016+
var commandsInSesssione = session.MediaButtonPreferences;
10021017
}
10031018

10041019
public void OnDisconnected(MediaSession? session, MediaSession.ControllerInfo? controller)
@@ -1078,10 +1093,16 @@ public SessionResult OnCustomCommand(MediaSession? session, MediaSession.Control
10781093
{
10791094
if (command == null)
10801095
{
1081-
return (SessionResult)SessionResult.ResultErrorUnknown;
1096+
return (SessionResult)SessionResult.ResultErrorBadValue;
1097+
}
1098+
if (command.CustomAction is not null && command.CustomAction.Equals(ExoPlayerService.FavoriteSessionCommand.CustomAction))
1099+
{
1100+
1101+
return (SessionResult)SessionResult.ResultSuccess;
10821102
}
10831103
switch (command.CustomAction)
10841104
{
1105+
10851106
case ExoPlayerService.ActionFavorite:
10861107
// Toggle favorite state
10871108
var currentSong = ExoPlayerService.CurrentSongContext;
@@ -1103,7 +1124,7 @@ public SessionResult OnCustomCommand(MediaSession? session, MediaSession.Control
11031124
await viewModel.AddFavoriteRatingToSong(currentSong);
11041125
}
11051126

1106-
RxSchedulers.UI.ScheduleToUI(() => service.UpdateMediaSessionLayout());
1127+
RxSchedulers.UI.ScheduleTo(() => service.UpdateMediaSessionLayout());
11071128
}
11081129
catch (Exception ex)
11091130
{
@@ -1119,7 +1140,7 @@ public SessionResult OnCustomCommand(MediaSession? session, MediaSession.Control
11191140
var vm = MainApplication.ServiceProvider.GetService<BaseViewModel>();
11201141
if (vm != null)
11211142
{
1122-
RxSchedulers.UI.ScheduleToUI(() =>
1143+
RxSchedulers.UI.ScheduleTo(() =>
11231144
{
11241145
try
11251146
{
@@ -1140,7 +1161,7 @@ public SessionResult OnCustomCommand(MediaSession? session, MediaSession.Control
11401161
var vmRepeat = MainApplication.ServiceProvider.GetService<BaseViewModel>();
11411162
if (vmRepeat != null)
11421163
{
1143-
RxSchedulers.UI.ScheduleToUI(() =>
1164+
RxSchedulers.UI.ScheduleTo(() =>
11441165
{
11451166
try
11461167
{

0 commit comments

Comments
 (0)