void RefreshItems() { if (Playlist is LocalPlaylist localPlaylist) { var localPlaylistItems = new ObservableCollection<IVideoContent>(localPlaylist.GetPlaylistItems().ToList()); PlaylistItems = localPlaylistItems; // キューと「あとで見る」はHohoemaPlaylistがリスト内容を管理しているが // ローカルプレイリストは内部DBが書き換えられるだけなので // 表示向けの更新をVMで引き受ける必要がある Observable.FromEventPattern<LocalPlaylistItemRemovedEventArgs>( h => localPlaylist.ItemRemoved += h, h => localPlaylist.ItemRemoved -= h ) .Subscribe(e => { var args = e.EventArgs; foreach (var itemId in args.RemovedItems) { var removedItem = PlaylistItems.FirstOrDefault(x => x.Id == itemId); if (removedItem != null) { localPlaylistItems.Remove(removedItem); } } }) .AddTo(_NavigatingCompositeDisposable); _localMylistManager.LocalPlaylists.ObserveRemoveChanged() .Subscribe(removed => { if (Playlist.Id == removed.Id) { _pageManager.ForgetLastPage(); _pageManager.OpenPage(HohoemaPageType.UserMylist); } }) .AddTo(_NavigatingCompositeDisposable); } else if (Playlist is PlaylistObservableCollection collection) { PlaylistItems = collection; } }
private async Task InitiatePlayback(bool isResume, int?subtitleIndex = null) { Messenger.Default.Send(new NotificationMessage(Constants.Messages.ClearNowPlayingMsg)); EndTime = TimeSpan.Zero; var streamInfo = new StreamInfo(); switch (PlayerSourceType) { case PlayerSourceType.Playlist: case PlayerSourceType.Video: if (SelectedItem.VideoType != VideoType.VideoFile) { var result = MessageBox.Show(AppResources.MessageExperimentalVideo, AppResources.MessageExperimentalTitle, MessageBoxButton.OKCancel); if (result == MessageBoxResult.Cancel) { NavigationService.GoBack(); return; } } if (SelectedItem.UserData != null && isResume) { _startPositionTicks = SelectedItem.UserData.PlaybackPositionTicks; } if (_startPositionTicks == 0) { // Although the API will return 0 items if the user doesn't have cinema mode enabled, // that's still precious time on a slow connection needlessly wasted. So let's make sure // the user actually has it enabled first. if (AuthenticationService.Current.LoggedInUser.Configuration.EnableCinemaMode) { try { var items = await ApiClient.GetIntrosAsync(SelectedItem.Id, AuthenticationService.Current.LoggedInUserId); if (items != null && !items.Items.IsNullOrEmpty()) { if (PlaylistItems == null) { PlaylistItems = new List <BaseItemDto>(items.Items) { SelectedItem }; } else { var list = items.Items.ToList(); list.AddRange(PlaylistItems); PlaylistItems = list; } var firstItem = PlaylistItems.FirstOrDefault(); if (firstItem != null) { SelectedItem = firstItem; } } } catch (HttpException ex) { Log.ErrorException("GetIntros (Cinema Mode)", ex); } } } streamInfo = await CreateVideoStream(SelectedItem.Id, _startPositionTicks, SelectedItem.MediaSources, SelectedItem.Type.ToLower().Equals("channelvideoitem")); if (SelectedItem.RunTimeTicks.HasValue) { EndTime = TimeSpan.FromTicks(SelectedItem.RunTimeTicks.Value); } Log.Info("Playing {0} [{1}] ({2})", SelectedItem.Type, SelectedItem.Name, SelectedItem.Id); break; case PlayerSourceType.Recording: streamInfo = await CreateVideoStream(RecordingItem.Id, _startPositionTicks); if (RecordingItem.RunTimeTicks.HasValue) { EndTime = TimeSpan.FromTicks(RecordingItem.RunTimeTicks.Value); } Log.Info("Playing {0} [{1}] ({2})", RecordingItem.Type, RecordingItem.Name, RecordingItem.Id); break; case PlayerSourceType.Programme: try { var channel = await ApiClient.GetItemAsync(ProgrammeItem.ChannelId, AuthenticationService.Current.LoggedInUserId); streamInfo = await CreateVideoStream(ProgrammeItem.ChannelId, _startPositionTicks, channel.MediaSources, useHls : true); } catch (HttpException ex) { Utils.HandleHttpException(ex, "GetVideoChannel", NavigationService, Log); NavigationService.GoBack(); return; } if (ProgrammeItem.RunTimeTicks.HasValue) { EndTime = TimeSpan.FromTicks(ProgrammeItem.RunTimeTicks.Value); } Log.Info("Playing {0} [{1}] ({2})", ProgrammeItem.Type, ProgrammeItem.Name, ProgrammeItem.Id); break; } if (streamInfo == null) { NavigationService.GoBack(); return; } if (subtitleIndex.HasValue) { streamInfo.SubtitleStreamIndex = subtitleIndex.Value; } var url = streamInfo.ToUrl(ApiClient.GetApiUrl("/"), ApiClient.AccessToken); _streamInfo = streamInfo; //Captions = GetSubtitles(SelectedItem); var isSyncedVideo = url.StartsWith("AnyTime", StringComparison.InvariantCultureIgnoreCase); if (EndTime.Ticks > 0 && !IsDirectStream) { EndTime = TimeSpan.FromTicks(EndTime.Ticks - _startPositionTicks); } StopAudioPlayback(); _streamInfo = streamInfo; if (_isResume && IsDirectStream) { StartFrom = TimeSpan.FromTicks(_startPositionTicks); } RaisePropertyChanged(() => IsDirectStream); if (isSyncedVideo) { SetVideoUrl(string.Empty); if (VideoStream == null || _storageUrl != url) { _storageUrl = url; using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) { var stream = storage.OpenFile(url, FileMode.Open); VideoStream = stream; } } } else { VideoStream = null; SetVideoUrl(url); _storageUrl = string.Empty; } Debug.WriteLine(VideoUrl); Log.Debug(VideoUrl); try { Log.Info("Sending playback started message to the server."); _itemId = streamInfo.ItemId; var info = new PlaybackStartInfo { ItemId = _itemId, CanSeek = false, QueueableMediaTypes = new List <string>() }; await ApiClient.ReportPlaybackStartAsync(info); } catch (HttpException ex) { Utils.HandleHttpException("VideoPageLoaded", ex, NavigationService, Log); } }