using MediaBrowser.UI.Controller; using MediaBrowser.UI.Playback; using MediaBrowser.UI.Playback.InternalPlayer; using System; using System.Threading; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Input; namespace MediaBrowser.UI.Controls { /// /// Interaction logic for NavigationBar.xaml /// public partial class NavigationBar : BaseUserControl { /// /// Gets or sets the current player. /// /// The current player. private BaseMediaPlayer CurrentPlayer { get; set; } /// /// Gets or sets the current position timer. /// /// The current position timer. private Timer CurrentPositionTimer { get; set; } /// /// Initializes a new instance of the class. /// public NavigationBar() { InitializeComponent(); Loaded += NavigationBar_Loaded; } /// /// Handles the Loaded event of the NavigationBar control. /// /// The source of the event. /// The instance containing the event data. void NavigationBar_Loaded(object sender, RoutedEventArgs e) { BackButton.Click += BtnApplicationBackClick; MuteButton.Click += MuteButton_Click; VolumeDownButton.PreviewMouseDown += VolumeDownButton_Click; VolumeUpButton.PreviewMouseDown += VolumeUpButton_Click; StopButton.Click += StopButton_Click; PlayButton.Click += PlayButton_Click; PauseButton.Click += PauseButton_Click; NextChapterButton.Click += NextChapterButton_Click; PreviousChapterButton.Click += PreviousChapterButton_Click; UIKernel.Instance.PlaybackManager.PlaybackStarted += PlaybackManager_PlaybackStarted; UIKernel.Instance.PlaybackManager.PlaybackCompleted += PlaybackManager_PlaybackCompleted; CurrentPositionSlider.PreviewMouseUp += CurrentPositionSlider_PreviewMouseUp; } /// /// Handles the Click event of the PreviousChapterButton control. /// /// The source of the event. /// The instance containing the event data. async void PreviousChapterButton_Click(object sender, RoutedEventArgs e) { await CurrentPlayer.GoToPreviousChapter(); } /// /// Handles the Click event of the NextChapterButton control. /// /// The source of the event. /// The instance containing the event data. async void NextChapterButton_Click(object sender, RoutedEventArgs e) { await CurrentPlayer.GoToNextChapter(); } /// /// Handles the Click event of the PauseButton control. /// /// The source of the event. /// The instance containing the event data. async void PauseButton_Click(object sender, RoutedEventArgs e) { await CurrentPlayer.Pause(); } /// /// Handles the Click event of the PlayButton control. /// /// The source of the event. /// The instance containing the event data. async void PlayButton_Click(object sender, RoutedEventArgs e) { await CurrentPlayer.UnPause(); } /// /// Handles the Click event of the StopButton control. /// /// The source of the event. /// The instance containing the event data. async void StopButton_Click(object sender, RoutedEventArgs e) { await CurrentPlayer.Stop(); } /// /// Handles the PlaybackCompleted event of the PlaybackManager control. /// /// The source of the event. /// The instance containing the event data. void PlaybackManager_PlaybackCompleted(object sender, PlaybackStopEventArgs e) { if (e.Player == CurrentPlayer) { if (CurrentPositionTimer != null) { CurrentPositionTimer.Dispose(); } CurrentPlayer.PlayStateChanged -= CurrentPlayer_PlayStateChanged; CurrentPlayer = null; ResetButtonVisibilities(null); Dispatcher.InvokeAsync(() => TxtCurrentPosition.Text = string.Empty); } } /// /// Handles the Click event of the VolumeUpButton control. /// /// The source of the event. /// The instance containing the event data. void VolumeUpButton_Click(object sender, RoutedEventArgs e) { CurrentPlayer.Volume += 3; } /// /// Handles the Click event of the VolumeDownButton control. /// /// The source of the event. /// The instance containing the event data. void VolumeDownButton_Click(object sender, RoutedEventArgs e) { CurrentPlayer.Volume -= 3; } /// /// Handles the Click event of the MuteButton control. /// /// The source of the event. /// The instance containing the event data. void MuteButton_Click(object sender, RoutedEventArgs e) { if (CurrentPlayer.CanMute) { CurrentPlayer.Mute = !CurrentPlayer.Mute; } } /// /// Handles the PlaybackStarted event of the PlaybackManager control. /// /// The source of the event. /// The instance containing the event data. void PlaybackManager_PlaybackStarted(object sender, PlaybackEventArgs e) { if (e.Player is BaseInternalMediaPlayer) { CurrentPlayer = e.Player; CurrentPlayer.PlayStateChanged += CurrentPlayer_PlayStateChanged; ResetButtonVisibilities(e.Player); Dispatcher.InvokeAsync(() => { var runtime = e.Player.CurrentMedia.RunTimeTicks ?? 0; CurrentPositionSlider.Maximum = runtime; TxtDuration.Text = GetTimeString(runtime); }); CurrentPositionTimer = new Timer(CurrentPositionTimerCallback, null, 250, 250); } } /// /// Currents the position timer callback. /// /// The state. private void CurrentPositionTimerCallback(object state) { var time = string.Empty; var ticks = CurrentPlayer.CurrentPositionTicks; if (ticks.HasValue) { time = GetTimeString(ticks.Value); } Dispatcher.InvokeAsync(() => { TxtCurrentPosition.Text = time; if (!_isPositionSliderDragging) { CurrentPositionSlider.Value = ticks ?? 0; } }); } /// /// Gets the time string. /// /// The ticks. /// System.String. private string GetTimeString(long ticks) { var timespan = TimeSpan.FromTicks(ticks); return timespan.TotalHours >= 1 ? timespan.ToString("hh':'mm':'ss") : timespan.ToString("mm':'ss"); } /// /// Handles the PlayStateChanged event of the CurrentPlayer control. /// /// The source of the event. /// The instance containing the event data. void CurrentPlayer_PlayStateChanged(object sender, EventArgs e) { ResetButtonVisibilities(CurrentPlayer); } /// /// Resets the button visibilities. /// /// The player. private void ResetButtonVisibilities(BaseMediaPlayer player) { Dispatcher.Invoke(() => { PlayButton.Visibility = player != null && player.PlayState == PlayState.Paused ? Visibility.Visible : Visibility.Collapsed; PauseButton.Visibility = player != null && player.CanPause && player.PlayState == PlayState.Playing ? Visibility.Visible : Visibility.Collapsed; StopButton.Visibility = player != null ? Visibility.Visible : Visibility.Collapsed; MuteButton.Visibility = player != null && player.CanMute ? Visibility.Visible : Visibility.Collapsed; VolumeUpButton.Visibility = player != null && player.CanControlVolume ? Visibility.Visible : Visibility.Collapsed; VolumeDownButton.Visibility = player != null && player.CanControlVolume ? Visibility.Visible : Visibility.Collapsed; var isSeekabke = player != null && player.CanSeek && player.CurrentMedia != null; SeekGrid.Visibility = isSeekabke ? Visibility.Visible : Visibility.Collapsed; var canSeekChapters = isSeekabke && player.CurrentMedia.Chapters != null && player.CurrentMedia.Chapters.Count > 1; NextChapterButton.Visibility = canSeekChapters ? Visibility.Visible : Visibility.Collapsed; PreviousChapterButton.Visibility = canSeekChapters ? Visibility.Visible : Visibility.Collapsed; }); } /// /// BTNs the application back click. /// /// The sender. /// The instance containing the event data. void BtnApplicationBackClick(object sender, RoutedEventArgs e) { App.Instance.ApplicationWindow.NavigateBack(); } /// /// The is position slider dragging /// private bool _isPositionSliderDragging; /// /// Handles the DragStarted event of the CurrentPositionSlider control. /// /// The source of the event. /// The instance containing the event data. private void CurrentPositionSlider_DragStarted(object sender, DragStartedEventArgs e) { _isPositionSliderDragging = true; } /// /// Handles the DragCompleted event of the CurrentPositionSlider control. /// /// The source of the event. /// The instance containing the event data. private void CurrentPositionSlider_DragCompleted(object sender, DragCompletedEventArgs e) { _isPositionSliderDragging = false; //await CurrentPlayer.Seek(Convert.ToInt64(CurrentPositionSlider.Value)); } /// /// Handles the PreviewMouseUp event of the CurrentPositionSlider control. /// /// The source of the event. /// The instance containing the event data. async void CurrentPositionSlider_PreviewMouseUp(object sender, MouseButtonEventArgs e) { await CurrentPlayer.Seek(Convert.ToInt64(CurrentPositionSlider.Value)); } } }