Skip to content

Commit 9d3a824

Browse files
committed
syncplay improvements
1 parent cf24221 commit 9d3a824

File tree

6 files changed

+60
-32
lines changed

6 files changed

+60
-32
lines changed

FluentFin/Controls/MediaPlayerHost.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
HorizontalAlignment="Stretch"
1919
VerticalAlignment="Stretch"
2020
IsSkipButtonVisible="{x:Bind IsSkipButtonVisible, Mode=OneWay}"
21+
JellyfinClient="{x:Bind JellyfinClient, Mode=OneWay}"
2122
Player="{x:Bind Player, Mode=TwoWay}"
2223
Playlist="{x:Bind Playlist, Mode=OneWay}"
2324
SkipCommand="{x:Bind SkipCommand, Mode=OneWay}"

FluentFin/Controls/MediaPlayerHost.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public sealed partial class MediaPlayerHost : UserControl
3737
[GeneratedDependencyProperty]
3838
public partial MediaPlayerType? MediaPlayerType { get; set; }
3939

40+
[GeneratedDependencyProperty]
41+
public partial IJellyfinClient? JellyfinClient { get; set; }
42+
4043
public IMediaPlayerController? Player
4144
{
4245
get

FluentFin/Controls/TransportControls.xaml.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public sealed partial class TransportControls : UserControl
3434
[GeneratedDependencyProperty]
3535
public partial TrickplayViewModel Trickplay { get; set; }
3636

37+
[GeneratedDependencyProperty]
38+
public partial IJellyfinClient JellyfinClient { get; set; }
39+
3740
public IMediaPlayerController Player
3841
{
3942
get
@@ -156,14 +159,26 @@ private async void SkipBackwardButton_Click(object sender, RoutedEventArgs e)
156159
{
157160
var ts = Player.Position - TimeSpan.FromSeconds(10);
158161
Player.SeekTo(ts);
159-
await App.GetService<IJellyfinClient>().SignalSeekForSyncPlay(ts);
162+
163+
if (JellyfinClient is null)
164+
{
165+
return;
166+
}
167+
168+
await JellyfinClient.SignalSeekForSyncPlay(ts);
160169
}
161170

162171
private async void SkipForwardButton_Click(object sender, RoutedEventArgs e)
163172
{
164173
var ts = Player.Position + TimeSpan.FromSeconds(30);
165174
Player.SeekTo(ts);
166-
await App.GetService<IJellyfinClient>().SignalSeekForSyncPlay(ts);
175+
176+
if(JellyfinClient is null)
177+
{
178+
return;
179+
}
180+
181+
await JellyfinClient.SignalSeekForSyncPlay(ts);
167182
}
168183

169184
private void TimeSlider_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
@@ -195,21 +210,30 @@ private async void PlayPauseButton_Click(object sender, RoutedEventArgs e)
195210
{
196211
Player.TogglePlayPlause();
197212

198-
var client = App.GetService<IJellyfinClient>();
213+
if(JellyfinClient is null)
214+
{
215+
return;
216+
}
217+
218+
199219
if (Player.State == MediaPlayerState.Playing)
200220
{
201-
await client.SignalUnpauseForSyncPlay();
221+
await JellyfinClient.SignalUnpauseForSyncPlay();
202222
}
203223
else
204224
{
205-
await client.SignalPauseForSyncPlay();
225+
await JellyfinClient.SignalPauseForSyncPlay();
206226
}
207227
}
208228

209229
private async void CastButton_Click(object sender, RoutedEventArgs e)
210230
{
211-
var jellyfinClient = App.GetService<IJellyfinClient>();
212-
var sessions = await jellyfinClient.GetControllableSessions();
231+
if(JellyfinClient is null)
232+
{
233+
return;
234+
}
235+
236+
var sessions = await JellyfinClient.GetControllableSessions();
213237

214238
if(sessions.FirstOrDefault(x => x.Id == SessionInfo.SessionId) is { } session && session.NowPlayingItem is { } dto)
215239
{

FluentFin/Services/WebSocketMessageHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public Task StartAsync(CancellationToken cancellationToken)
3030
gcm.Data.Arguments["Text"],
3131
TimeSpan.FromMilliseconds(double.Parse(gcm.Data.Arguments["TimeoutMs"])));
3232
break;
33-
case PlayQueueUpdateMessage { Data: not null } playMessage:
33+
case PlayQueueUpdateMessage { Data.Data.PlayingItemIndex: >= 0 } playMessage:
3434
navigationService.NavigateTo<VideoPlayerViewModel>(playMessage.Data.Data);
3535
break;
3636
case GroupJoinedUpdateMessage groupJoined:

FluentFin/ViewModels/VideoPlayerViewModel.cs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public partial class VideoPlayerViewModel(IJellyfinClient jellyfinClient,
4040

4141

4242
public TrickplayViewModel TrickplayViewModel { get; } = trickplayViewModel;
43+
public IJellyfinClient JellyfinClient { get; } = jellyfinClient;
4344

4445

4546
[ObservableProperty]
@@ -78,15 +79,14 @@ public async Task OnNavigatedFrom()
7879
NativeMethods.AllowSleep();
7980

8081
taskBarProgress.Clear();
81-
await jellyfinClient.Stop();
82+
await JellyfinClient.Stop();
8283

8384
if(MediaPlayer is null)
8485
{
8586
return;
8687
}
8788

88-
MediaPlayer.Pause();
89-
MediaPlayer.Dispose();
89+
MediaPlayer.Stop();
9090
}
9191

9292
public async Task OnNavigatedTo(object parameter)
@@ -121,7 +121,7 @@ public async Task OnNavigatedTo(object parameter)
121121
.Subscribe(async mp =>
122122
{
123123
_keyboardController?.UnsubscribeEvents();
124-
_keyboardController = new KeyboardMediaPlayerController(mp, jellyfinClient, Skip, ToggleFullScreen);
124+
_keyboardController = new KeyboardMediaPlayerController(mp, JellyfinClient, Skip, ToggleFullScreen);
125125

126126
if(_playQueueUpdate is null)
127127
{
@@ -132,7 +132,7 @@ public async Task OnNavigatedTo(object parameter)
132132
Playlist.SelectedItem = Playlist.Items.FirstOrDefault();
133133
}
134134

135-
await jellyfinClient.Playing(Dto);
135+
await JellyfinClient.Playing(Dto);
136136
});
137137

138138
Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(20))
@@ -149,7 +149,7 @@ private async Task Initialize(Guid? id)
149149
return;
150150
}
151151

152-
Dto = await jellyfinClient.GetItem(id.Value);
152+
Dto = await JellyfinClient.GetItem(id.Value);
153153

154154
if(Dto is null)
155155
{
@@ -159,9 +159,9 @@ private async Task Initialize(Guid? id)
159159
Playlist = Dto.Type switch
160160
{
161161
BaseItemDto_Type.Movie => PlaylistViewModel.FromMovie(Dto),
162-
BaseItemDto_Type.Episode => await PlaylistViewModel.FromEpisode(jellyfinClient, Dto),
163-
BaseItemDto_Type.Series => await PlaylistViewModel.FromSeries(jellyfinClient, Dto),
164-
BaseItemDto_Type.Season => await PlaylistViewModel.FromSeason(jellyfinClient, Dto),
162+
BaseItemDto_Type.Episode => await PlaylistViewModel.FromEpisode(JellyfinClient, Dto),
163+
BaseItemDto_Type.Series => await PlaylistViewModel.FromSeries(JellyfinClient, Dto),
164+
BaseItemDto_Type.Season => await PlaylistViewModel.FromSeason(JellyfinClient, Dto),
165165
_ => new PlaylistViewModel()
166166
};
167167
}
@@ -174,7 +174,7 @@ private async Task InitializeForSyncPlay(PlayQueueUpdate pqu)
174174
}
175175

176176
var id = pqu.Playlist[pqu.PlayingItemIndex].ItemId;
177-
Dto = await jellyfinClient.GetItem(id);
177+
Dto = await JellyfinClient.GetItem(id);
178178
Playlist = PlaylistViewModel.FromSyncPlay(pqu.Playlist);
179179
}
180180

@@ -198,7 +198,7 @@ private async Task Skip()
198198

199199
if (_playQueueUpdate is not null)
200200
{
201-
await jellyfinClient.SignalSeekForSyncPlay(endPosition);
201+
await JellyfinClient.SignalSeekForSyncPlay(endPosition);
202202
}
203203

204204
MediaPlayer.SeekTo(endPosition);
@@ -223,7 +223,7 @@ private async void OnPlaylistPropertyChanged(object? sender, System.ComponentMod
223223

224224
MediaPlayer.Stop();
225225

226-
var full = await jellyfinClient.GetItem(selectedItem.Dto.Id ?? Guid.Empty);
226+
var full = await JellyfinClient.GetItem(selectedItem.Dto.Id ?? Guid.Empty);
227227

228228
if (full is null)
229229
{
@@ -238,7 +238,7 @@ private async void OnPlaylistPropertyChanged(object? sender, System.ComponentMod
238238
}
239239

240240

241-
await jellyfinClient.Stop();
241+
await JellyfinClient.Stop();
242242
TrickplayViewModel.SetItem(full);
243243

244244
var defaultSubtitleIndex = mediaResponse.MediaSourceInfo.DefaultSubtitleStreamIndex;
@@ -277,7 +277,7 @@ private void OpenSubtitles(IMediaPlayerController mp, MediaResponse response, Me
277277
{
278278
if (stream.IsExternal == true)
279279
{
280-
var url = HttpUtility.UrlDecode(jellyfinClient.BaseUrl.AppendPathSegment(stream.DeliveryUrl).ToString());
280+
var url = HttpUtility.UrlDecode(JellyfinClient.BaseUrl.AppendPathSegment(stream.DeliveryUrl).ToString());
281281
mp.OpenExternalSubtitleTrack(url);
282282
}
283283
else
@@ -297,14 +297,14 @@ private void OpenSubtitles(IMediaPlayerController mp, MediaResponse response, Me
297297

298298
private async Task<MediaResponse?> GetMediaUrl(BaseItemDto dto)
299299
{
300-
var segments = await jellyfinClient.GetMediaSegments(dto, [MediaSegmentType.Intro, MediaSegmentType.Outro]);
300+
var segments = await JellyfinClient.GetMediaSegments(dto, [MediaSegmentType.Intro, MediaSegmentType.Outro]);
301301

302302
if (segments is { Items: not null })
303303
{
304304
Segments = segments.Items;
305305
}
306306

307-
return await jellyfinClient.GetMediaUrl(dto);
307+
return await JellyfinClient.GetMediaUrl(dto);
308308
}
309309

310310
private async Task UpdateStatus()
@@ -348,7 +348,7 @@ private async Task UpdateStatus()
348348

349349
taskBarProgress.SetProgressPercent((int)((MediaPlayer.Position.TotalSeconds / _duration.TotalSeconds) * 100));
350350

351-
await jellyfinClient.Progress(_playbackProgressInfo);
351+
await JellyfinClient.Progress(_playbackProgressInfo);
352352
}
353353

354354
private void SubscribeEvents(IMediaPlayerController mp)
@@ -359,11 +359,11 @@ private void SubscribeEvents(IMediaPlayerController mp)
359359
taskBarProgress.Clear();
360360
Playlist.SelectNext();
361361
});
362-
mp.Stopped.Subscribe(async _ => await jellyfinClient.Stop());
362+
mp.Stopped.Subscribe(async _ => await JellyfinClient.Stop());
363363
mp.Errored.Subscribe(async _ =>
364364
{
365365
logger.LogError("An error occurred while playing media");
366-
await jellyfinClient.Stop();
366+
await JellyfinClient.Stop();
367367
});
368368
mp.PositionChanged
369369
.Where(_ => MediaPlayer?.State == MediaPlayerState.Playing)
@@ -376,7 +376,7 @@ private void SubscribeEvents(IMediaPlayerController mp)
376376

377377
mp.MediaLoaded
378378
.Where(_ => _playQueueUpdate is not null)
379-
.SelectMany(_ => jellyfinClient.SignalReadyForSyncPlay(new ReadyRequestDto
379+
.SelectMany(_ => JellyfinClient.SignalReadyForSyncPlay(new ReadyRequestDto
380380
{
381381
When = TimeProvider.System.GetUtcNow(),
382382
IsPlaying = mp.IsPlaying,
@@ -397,7 +397,6 @@ private void SubscribeWebsocketMessage()
397397
return;
398398
}
399399

400-
401400
switch (message)
402401
{
403402
case PlayStateMessage { Data.Command: PlaystateCommand.PlayPause }:
@@ -406,7 +405,7 @@ private void SubscribeWebsocketMessage()
406405
break;
407406
case PlayStateMessage { Data.Command: PlaystateCommand.Stop }:
408407
MediaPlayer.Stop();
409-
await jellyfinClient.Stop();
408+
await JellyfinClient.Stop();
410409
navigationService.NavigateTo<HomeViewModel>(new());
411410
break;
412411
case SyncPlayCommandMessage { Data: not null } syncPlay:
@@ -445,7 +444,7 @@ private async Task SchedulePause(SyncPlaySendCommand command, IMediaPlayerContro
445444
return;
446445
}
447446

448-
var currentTime = await jellyfinClient.SyncTime();
447+
var currentTime = await JellyfinClient.SyncTime();
449448
var commandTime = command.When;
450449

451450
mp.SeekTo(new TimeSpan(command.PositionTicks));
@@ -467,7 +466,7 @@ private async Task SchedulePlay(SyncPlaySendCommand command, IMediaPlayerControl
467466
return;
468467
}
469468

470-
var currentTime = await jellyfinClient.SyncTime();
469+
var currentTime = await JellyfinClient.SyncTime();
471470
var commandTime = command.When;
472471

473472
if (commandTime > currentTime)

FluentFin/Views/VideoPlayerPage.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<controls:MediaPlayerHost
1515
x:Name="MediaPlayerHost"
1616
IsSkipButtonVisible="{x:Bind ViewModel.IsSkipButtonVisible, Mode=OneWay}"
17+
JellyfinClient="{x:Bind ViewModel.JellyfinClient}"
1718
MediaPlayerType="{x:Bind ViewModel.MediaPlayerType, Mode=OneWay}"
1819
Player="{x:Bind ViewModel.MediaPlayer, Mode=TwoWay}"
1920
Playlist="{x:Bind ViewModel.Playlist, Mode=OneWay}"

0 commit comments

Comments
 (0)