Skip to main content

mimick/library/video_player/
tracks.rs

1use std::rc::Rc;
2
3use gst_play::prelude::*;
4use gst_play::{PlayAudioInfo, PlayMediaInfo, PlaySubtitleInfo};
5use gstreamer_play as gst_play;
6use gtk::prelude::*;
7
8use super::VideoPlayer;
9use super::controls::{popover_box, track_label, track_section};
10
11impl VideoPlayer {
12    pub(super) fn track_popover(self: &Rc<Self>, info: &PlayMediaInfo) -> gtk::Popover {
13        let content = popover_box();
14        self.add_audio_tracks(&content, &info.audio_streams());
15        self.add_subtitle_tracks(&content, &info.subtitle_streams());
16        gtk::Popover::builder().child(&content).build()
17    }
18
19    fn add_audio_tracks(self: &Rc<Self>, content: &gtk::Box, audio: &[PlayAudioInfo]) {
20        if audio.len() < 2 {
21            return;
22        }
23        let current = self.play.current_audio_track().map(|t| t.index());
24        let labels: Vec<String> = audio
25            .iter()
26            .enumerate()
27            .map(|(n, t)| track_label(n, t.language().as_deref()))
28            .collect();
29        let active = audio
30            .iter()
31            .position(|t| Some(t.index()) == current)
32            .unwrap_or(0);
33        let checks = track_section(content, "Audio", &labels, active);
34        for (check, track) in checks.iter().zip(audio) {
35            let index = track.index();
36            check.connect_toggled(self.on_picked(move |p| {
37                if let Err(err) = p.play.set_audio_track(index) {
38                    log::warn!("Audio track switch failed: {}", err);
39                }
40            }));
41        }
42    }
43
44    fn add_subtitle_tracks(self: &Rc<Self>, content: &gtk::Box, subtitles: &[PlaySubtitleInfo]) {
45        if subtitles.is_empty() {
46            return;
47        }
48        let labels: Vec<String> = std::iter::once("Off".to_string())
49            .chain(
50                subtitles
51                    .iter()
52                    .enumerate()
53                    .map(|(n, t)| track_label(n, t.language().as_deref())),
54            )
55            .collect();
56        let checks = track_section(content, "Subtitles", &labels, 0);
57        checks[0].connect_toggled(self.on_picked(|p| p.play.set_subtitle_track_enabled(false)));
58        for (check, track) in checks[1..].iter().zip(subtitles) {
59            let index = track.index();
60            check.connect_toggled(self.on_picked(move |p| {
61                if let Err(err) = p.play.set_subtitle_track(index) {
62                    log::warn!("Subtitle track switch failed: {}", err);
63                }
64                p.play.set_subtitle_track_enabled(true);
65            }));
66        }
67    }
68}