Compare commits

..

18 commits

Author SHA1 Message Date
6e55e68c08 chore: fige Cargo.lock (epoch-1.10.0, [patch] locaux)
Some checks are pending
Validate .desktop files / validate (push) Waiting to run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 07:02:21 +02:00
1d3445b1c3 merge: epoch-1.10.0 d'upstream
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 07:00:06 +02:00
Michael Murphy
900453787f
i18n: translation update from Hosted Weblate (#347)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pop OS/COSMIC
Player](https://hosted.weblate.org/projects/pop-os/cosmic-player/).



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pop-os/cosmic-player/matrix-auto.svg)
2026-10-06 21:40:19 +02:00
Michael Aaron Murphy
a6af9a48c2 Epoch 1.10.0 version update
[x] Generated by cosmic-epoch scripts/version-update.sh
2026-10-06 21:39:52 +02:00
Hosted Weblate
882d16513b
i18n: translation updates from weblate
Co-authored-by: Baurzhan Muftakhidinov <baurthefirst@gmail.com>
Co-authored-by: CYAXXX <85353920+CYAXXX@users.noreply.github.com>
Co-authored-by: Ettore Atalan <atalanttore@googlemail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Martin Meizoso <martinmeizoso@gmail.com>
Co-authored-by: Zahid Rizky Fakhri <zahidrizkyfakhri@gmail.com>
Co-authored-by: Димко <Dymkovych@proton.me>
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/de/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/gl/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/id/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/kk/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/kmr/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/uk/
Translation: Pop OS/COSMIC Player
2026-10-06 11:10:07 +02:00
Jeremy Soller
8923105997
feat: Keep controls and header bar visible when controls are hovered (#344)
Add a `controls_hovered` state tracked via new `ControlsHoverEnter`/
`ControlsHoverExit` messages. Previously the auto-hide timeout could
fire while the cursor was resting over the controls, since only mouse
movement/clicks reset the timer. Now, this is prevented whenever the
controls are hovered, i.e. `controls_hovered` is true.

Implementation comments:
- Controls popup is wrapped in a single `mouse_area` each to avoid
duplicate enter/exit events at internal widget boundaries.
- Double trigger of enter/exit messages in `update()` is guarded
against.

Resolves #304

- [x] I have disclosed use of any AI generated code in my commit
messages.
- If you are using an LLM, and do not fully understand the changes it is
making to the code base, do not create a PR.
- In our experience, AI generated code often results in overly complex
code that lacks enough context for a proper fix or feature inclusion.
This results in considerably longer code reviews. Due to this, AI
authored or partially authored PRs may be closed without comment.
- [x] I understand these changes in full and will be able to respond to
review comments.
- [x] My change is accurately described in the commit message.
- [x] My contribution is tested and working as described.
- [x] I have read the [Developer Certificate of
Origin](https://developercertificate.org/) and certify my contribution
under its conditions.
2026-10-01 07:12:11 -06:00
Jeremy Soller
f62353fd0a COSMIC policy update
Generated by cosmic-epoch scripts/policy-update.sh. Uses `policy_nobuild` branch to avoid package builds as it contains no code changes.
2026-09-30 09:56:07 -06:00
Lysander Treumann
8ad21891b3 feat: Keep controls and header bar visible when controls are hovered
Add a `controls_hovered` state tracked via new `ControlsHoverEnter`/
`ControlsHoverExit` messages. Previously the auto-hide timeout could
fire while the cursor was resting over the controls, since only mouse
movement/clicks reset the timer. This is now prevented whenever the
controls are hovered, i.e. `controls_hovered` is true.

Implementation comments:
- Controls popup is wrapped in a single `mouse_area` each to avoid
  duplicate enter/exit events at internal widget boundaries.
- Double trigger of enter/exit messages in `update()` is guarded
  against.

Resolves #304
2026-09-27 18:08:47 +02:00
3ee781bfc2 chore: fige Cargo.lock (epoch-1.9.0, [patch] locaux)
Some checks failed
Validate .desktop files / validate (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 21:03:54 +02:00
cfdeaa3ae1 merge: epoch-1.9.0 d'upstream 2026-09-24 20:46:53 +02:00
Michael Aaron Murphy
3b016ff126 Epoch 1.9.0 version update
Generated by cosmic-epoch scripts/version-update.sh
2026-09-24 17:24:17 +02:00
Michael Murphy
66b3f34335
i18n: translation update from Hosted Weblate (#328)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pop OS/COSMIC
Player](https://hosted.weblate.org/projects/pop-os/cosmic-player/).



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pop-os/cosmic-player/matrix-auto.svg)
2026-09-15 21:57:21 +02:00
Hosted Weblate
3d8af19ac4
i18n: translation updates from weblate
Co-authored-by: Amadɣas <massiin@proton.me>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kurt Harren Catindig <kurtharrencatindig03@gmail.com>
Co-authored-by: Quentin PAGÈS <quentinantonin@free.fr>
Co-authored-by: Satakun Utama <galaxytomostore@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/kab/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/oc/
Translate-URL: https://hosted.weblate.org/projects/pop-os/cosmic-player/th/
Translation: Pop OS/COSMIC Player
2026-09-12 11:51:35 +00:00
78b806a347 chore: fige Cargo.lock
Some checks failed
Validate .desktop files / validate (push) Has been cancelled
2026-09-10 18:11:31 +02:00
45c9b1aa19 Merge tag 'epoch-1.8.0'
Epoch 1.8.0

# Conflicts:
#	Cargo.lock
#	src/video.rs
2026-09-10 17:57:28 +02:00
Levi Portenier
a297c24a96
Epoch 1.8.0 version update (#331)
Generated by cosmic-epoch scripts/version-update.sh
2026-09-02 12:19:07 -06:00
Jeremy Soller
f0365d411b Epoch 1.8.0 version update
Generated by cosmic-epoch scripts/version-update.sh
2026-09-02 08:15:29 -06:00
krakotay
e040f7fbc7
fix: playback of malformed MP4 files with invalid framerates
- [x] I have disclosed use of any AI generated code in my commit
messages.
- If you are using an LLM, and do not fully understand the changes it is
making to the code base, do not create a PR.
- In our experience, AI generated code often results in overly complex
code that lacks enough context for a proper fix or feature inclusion.
This results in considerably longer code reviews. Due to this, AI
authored or partially authored PRs may be closed without comment.
- [x] I understand these changes in full and will be able to respond to
review comments.
- [x] My change is accurately described in the commit message.
- [x] My contribution is tested and working as described.
- [x] I have read the [Developer Certificate of
Origin](https://developercertificate.org/) and certify my contribution
under its conditions.

Some malformed MP4 files previously wouldn't play at all because they
reported a 0/1 framerate.
Other files suffered from severe audio stuttering caused by repeated
long GAP events emitted from malformed edit lists.
This patch treats invalid framerates as unknown (allowing the existing
fallback to be used) and suppresses suspicious long audio GAP events
before they reach the audio sink.
As a result, both kinds of videos now play correctly.
2026-08-29 02:31:43 +02:00
20 changed files with 593 additions and 368 deletions

View file

@ -1,8 +1,10 @@
- [ ] I have disclosed use of any AI generated code in my commit messages. Replace this text with a description of your changes, and why these changes are important. Read and acknowledge the list below. PRs without a completed checkbox will be closed.
- If you are using an LLM, and do not fully understand the changes it is making to the code base, do not create a PR.
- In our experience, AI generated code often results in overly complex code that lacks enough context for a proper fix or feature inclusion. This results in considerably longer code reviews. Due to this, AI authored or partially authored PRs may be closed without comment.
- [ ] I understand these changes in full and will be able to respond to review comments.
- [ ] My change is accurately described in the commit message.
- [ ] My contribution is tested and working as described.
- [ ] I have read the [Developer Certificate of Origin](https://developercertificate.org/) and certify my contribution under its conditions.
---
- I have not included any LLM (also known as AI) generated content in this PR, including code, comments, and descriptions.
- I understand these changes in full and will be able to respond to review comments.
- My change is accurately described in the commit message.
- My contribution is tested and working as described.
- I have read the [Developer Certificate of Origin](https://developercertificate.org/) and certify my contribution under its conditions.
- [ ] I have read and followed all of the above requirements. For more information, see our [contributor guide](https://github.com/pop-os/pop/blob/master/CONTRIBUTING.md).

14
.github/workflows/require-checklist.yml vendored Normal file
View file

@ -0,0 +1,14 @@
# From https://github.com/mheap/require-checklist-action, license MIT
name: Require Checklist
on:
pull_request:
types: [opened, edited, synchronize]
jobs:
job1:
runs-on: ubuntu-latest
steps:
- uses: mheap/require-checklist-action@v2
with:
requireChecklist: true

687
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package] [package]
name = "cosmic-player" name = "cosmic-player"
version = "1.7.0" version = "1.10.0"
edition = "2024" edition = "2024"
rust-version = "1.93" rust-version = "1.93"

70
cargo.just Normal file
View file

@ -0,0 +1,70 @@
cargo-target-dir := env('CARGO_TARGET_DIR', 'target')
# Compile with debug profile
[no-cd]
build-debug *args:
cargo build {{args}}
# Compile with release profile
[no-cd]
build-release *args: (build-debug '--release' args)
# Compile with a vendored tarball
[no-cd]
build-vendored *args: vendor-extract (build-release '--frozen --offline' args)
# Check for errors and linter warnings
[no-cd]
check *args:
cargo clippy --all-features {{args}} -- -W clippy::pedantic
# Runs a check with JSON message format for IDE integration
[no-cd]
check-json: (check '--message-format=json')
# Remove Cargo build artifacts
[no-cd]
clean:
cargo clean
# Also remove .cargo and vendored dependencies
[no-cd]
clean-dist: clean
rm -rf .cargo vendor vendor.tar target
# Run the application for testing purposes
[no-cd]
run *args:
cargo run {{args}}
# Run `cargo test`
[no-cd]
test *args:
cargo test {{args}}
# Vendor Cargo dependencies locally
[no-cd]
vendor:
#!/usr/bin/env bash
mkdir -p .cargo
cargo vendor --locked | head -n -1 > .cargo/config.toml
echo 'directory = "vendor"' >> .cargo/config.toml
echo >> .cargo/config.toml
echo '[env]' >> .cargo/config.toml
if [ -n "${SOURCE_DATE_EPOCH}" ]
then
source_date="$(date -d "@${SOURCE_DATE_EPOCH}" "+%Y-%m-%d")"
echo "VERGEN_GIT_COMMIT_DATE = \"${source_date}\"" >> .cargo/config.toml
fi
if [ -n "${SOURCE_GIT_HASH}" ]
then
echo "VERGEN_GIT_SHA = \"${SOURCE_GIT_HASH}\"" >> .cargo/config.toml
fi
tar pcf vendor.tar .cargo vendor
rm -rf .cargo vendor
# Extracts vendored dependencies
[no-cd]
vendor-extract:
rm -rf vendor
tar pxf vendor.tar

18
debian/changelog vendored
View file

@ -1,3 +1,21 @@
cosmic-player (1.10.0) noble; urgency=medium
* Epoch 1.10.0 version update
-- Michael Murphy <michael@mmurphy.dev> Mon, 05 Oct 2026 21:25:27 +0200
cosmic-player (1.9.0) noble; urgency=medium
* Epoch 1.9.0 version update
-- Michael Murphy <michael@mmurphy.dev> Mon, 14 Sep 2026 21:57:45 +0200
cosmic-player (1.8.0) noble; urgency=medium
* Epoch 1.8.0 version update
-- Jeremy Soller <jeremy@system76.com> Wed, 02 Sep 2026 08:15:23 -0600
cosmic-player (1.7.0) noble; urgency=medium cosmic-player (1.7.0) noble; urgency=medium
* Epoch 1.7.0 version update * Epoch 1.7.0 version update

View file

@ -1,4 +1,6 @@
tar-ignore=.github tar-ignore=.github
tar-ignore=.vscode tar-ignore=target/.rustc_info.json
tar-ignore=target/CACHEDIR.TAG
tar-ignore=target/debug
tar-ignore=target/release
tar-ignore=vendor tar-ignore=vendor
tar-ignore=target

View file

@ -46,6 +46,6 @@ ab-repeat = A-B-Wiederholung
ab-repeat-set-a = A-B-Wiederholung (A) ab-repeat-set-a = A-B-Wiederholung (A)
ab-repeat-set-b = A-B-Wiederholung (B) ab-repeat-set-b = A-B-Wiederholung (B)
ab-repeat-clear = A-B-Wiederholung löschen ab-repeat-clear = A-B-Wiederholung löschen
xdg-keywords = Audio;Film;Musik;Ton;Video; xdg-keywords = Audio;Film;Musik;Klang;Ton;Video;
xdg-name = COSMIC Mediaplayer xdg-name = COSMIC Mediaplayer
xdg-comment = Mediaplayer für den COSMIC-Desktop xdg-comment = Mediaplayer für den COSMIC-Desktop

View file

View file

@ -1,7 +1,7 @@
settings = Axustes settings = Axustes
appearance = Apariencia appearance = Apariencia
theme = Tema theme = Tema
match-desktop = Axustar ao escritorio match-desktop = Emparexar co escritorio
dark = Escuro dark = Escuro
light = Claro light = Claro
file = Ficheiro file = Ficheiro

View file

@ -11,7 +11,7 @@ settings = Pengaturan
untitled = Tidak Berjudul untitled = Tidak Berjudul
appearance = Tampilan appearance = Tampilan
theme = Tema theme = Tema
match-desktop = Cocok desktop match-desktop = Sesuaikan desktop
dark = Gelap dark = Gelap
light = Terang light = Terang
file = Berkas file = Berkas

View file

@ -2,13 +2,13 @@ open-file = Ldi afaylu
open-folder = Ldi akaram open-folder = Ldi akaram
repeat-disabled = Allus yensa repeat-disabled = Allus yensa
repeat-track = Ales tazribt repeat-track = Ales tazribt
quit = Tuffɣa quit = Ffeɣ
settings = Iɣewwaṛen settings = Iɣewwaṛen
appearance = Timeẓri appearance = Timeẓri
theme = Asentel theme = Asentel
dark = Aɣmayan dark = Aɣmayan
light = Aceɛlal light = Aceɛlal
match-desktop = Amṣada d tnarit match-desktop = Semṣada akked tnarit
file = Afaylu file = Afaylu
close-file = Mdel afaylu close-file = Mdel afaylu
album = Album: { $album } album = Album: { $album }

View file

@ -3,8 +3,8 @@ open-folder = Буманы ашу
settings = Баптаулар settings = Баптаулар
appearance = Сыртқы көрініс appearance = Сыртқы көрініс
theme = Тема theme = Тема
match-desktop = Жұмыс үстеліне сәйкес болу match-desktop = Жұмыс үстеліне сәйкес
dark = Қою dark = Қараңғы
light = Ашық light = Ашық
file = Файл file = Файл
quit = Шығу quit = Шығу

View file

@ -6,7 +6,7 @@ light = Ronî
quit = Biqedîne quit = Biqedîne
open-file = Pelê veke open-file = Pelê veke
open-folder = Peldankê veke open-folder = Peldankê veke
match-desktop = Bi sermaseyê re li hev bîne match-desktop = Bi sermaseyê re guncav bike
album = Elbum: { $album } album = Elbum: { $album }
audio = Deng audio = Deng
no-video-or-audio-file-open = Tu pelê vîdiyo yan jî dengê vekirî tune ne no-video-or-audio-file-open = Tu pelê vîdiyo yan jî dengê vekirî tune ne

View file

@ -1,4 +1,4 @@
settings = Paramètres settings = Configuracion
album = Album : { $album } album = Album : { $album }
audio = Àudio audio = Àudio
no-video-or-audio-file-open = Cap de fichièr vidèo o àudio pas dobèrt no-video-or-audio-file-open = Cap de fichièr vidèo o àudio pas dobèrt
@ -9,7 +9,7 @@ untitled = Sens títol
appearance = Aparéncia appearance = Aparéncia
theme = Tèma theme = Tèma
match-desktop = Assortir al burèu match-desktop = Assortir al burèu
dark = Fosc dark = Escur
light = Clar light = Clar
file = Fichièr file = Fichièr
open-media = Dorbir mèdia... open-media = Dorbir mèdia...
@ -31,3 +31,4 @@ ab-repeat-clear = Escafar la repeticion A-B
xdg-name = Lector multimèdia COSMIC xdg-name = Lector multimèdia COSMIC
xdg-comment = Lector multimèdia pel burèu COSMIC xdg-comment = Lector multimèdia pel burèu COSMIC
xdg-keywords = Àudio;Musica;Vidèo;Film;Son; xdg-keywords = Àudio;Musica;Vidèo;Film;Son;
quit = Quitar

View file

@ -0,0 +1,4 @@
settings = การตั้งค่า
dark = มืด
light = สว่าง
appearance = ลักษณะ

View file

@ -9,7 +9,7 @@ untitled = Без назви
settings = Налаштування settings = Налаштування
appearance = Вигляд appearance = Вигляд
theme = Тема theme = Тема
match-desktop = Системна match-desktop = Підігнати під стільницю
dark = Темна dark = Темна
light = Світла light = Світла
file = Файл file = Файл

View file

@ -82,7 +82,32 @@ fn get_framerate(video: &Video) -> Option<f64> {
let caps = pad.current_caps()?; let caps = pad.current_caps()?;
let structure = caps.structure(0)?; let structure = caps.structure(0)?;
let framerate = structure.get::<gst::Fraction>("framerate").ok()?; let framerate = structure.get::<gst::Fraction>("framerate").ok()?;
Some(framerate.numer() as f64 / framerate.denom() as f64) positive_framerate(framerate)
}
fn positive_framerate(framerate: gst::Fraction) -> Option<f64> {
if framerate.numer() <= 0 || framerate.denom() <= 0 {
return None;
}
let fps = framerate.numer() as f64 / framerate.denom() as f64;
fps.is_finite().then_some(fps)
}
#[cfg(test)]
mod tests {
use super::positive_framerate;
use iced_video_player::gst;
#[test]
fn variable_framerate_uses_fallback() {
assert_eq!(positive_framerate(gst::Fraction::new(0, 1)), None);
}
#[test]
fn fixed_framerate_is_preserved() {
assert_eq!(positive_framerate(gst::Fraction::new(30, 1)), Some(30.0));
}
} }
/// Runs application with these settings /// Runs application with these settings
@ -325,6 +350,8 @@ pub enum Message {
VideoAreaClick, VideoAreaClick,
PlaybackSpeed(f64), PlaybackSpeed(f64),
ShowControls, ShowControls,
ControlsHoverEnter,
ControlsHoverExit,
SystemThemeModeChange(cosmic_theme::ThemeMode), SystemThemeModeChange(cosmic_theme::ThemeMode),
ToggleAbout, ToggleAbout,
WindowClose, WindowClose,
@ -338,6 +365,7 @@ pub struct App {
album_art_opt: Option<tempfile::NamedTempFile>, album_art_opt: Option<tempfile::NamedTempFile>,
controls: bool, controls: bool,
controls_time: Instant, controls_time: Instant,
controls_hovered: bool,
dropdown_opt: Option<DropdownKind>, dropdown_opt: Option<DropdownKind>,
fullscreen: bool, fullscreen: bool,
key_binds: HashMap<KeyBind, Action>, key_binds: HashMap<KeyBind, Action>,
@ -636,6 +664,7 @@ impl App {
fn update_controls(&mut self, in_use: bool) { fn update_controls(&mut self, in_use: bool) {
if in_use if in_use
|| self.controls_hovered
|| !self || !self
.video_opt .video_opt
.as_ref() .as_ref()
@ -934,6 +963,7 @@ impl Application for App {
album_art_opt: None, album_art_opt: None,
controls: true, controls: true,
controls_time: Instant::now(), controls_time: Instant::now(),
controls_hovered: false,
dropdown_opt: None, dropdown_opt: None,
fullscreen: false, fullscreen: false,
key_binds: key_binds(), key_binds: key_binds(),
@ -1671,6 +1701,18 @@ impl Application for App {
Message::ShowControls => { Message::ShowControls => {
self.update_controls(true); self.update_controls(true);
} }
Message::ControlsHoverEnter => {
if !self.controls_hovered {
self.controls_hovered = true;
self.update_controls(true);
}
}
Message::ControlsHoverExit => {
if self.controls_hovered {
self.controls_hovered = false;
self.update_controls(false);
}
}
Message::SystemThemeModeChange(_theme_mode) => { Message::SystemThemeModeChange(_theme_mode) => {
return self.update_config(); return self.update_config();
} }
@ -2140,7 +2182,11 @@ impl Application for App {
} }
} }
if !popup_items.is_empty() { if !popup_items.is_empty() {
popover = popover.popup(widget::column::with_children(popup_items)); popover = popover.popup(
widget::mouse_area(widget::column::with_children(popup_items))
.on_enter(Message::ControlsHoverEnter)
.on_exit(Message::ControlsHoverExit),
);
} }
widget::container(popover) widget::container(popover)

View file

@ -4,6 +4,40 @@ use iced_video_player::{Video, gst, gst_app, gst_pbutils};
use cosmic::action; use cosmic::action;
use cosmic::app::Task; use cosmic::app::Task;
const SUSPICIOUS_AUDIO_GAP_DURATION: gst::ClockTime = gst::ClockTime::SECOND;
fn is_suspicious_audio_gap(duration: Option<gst::ClockTime>) -> bool {
duration.is_some_and(|duration| duration >= SUSPICIOUS_AUDIO_GAP_DURATION)
}
fn suppress_suspicious_audio_gaps(audio_filter: &gst::Element) {
let Some(src_pad) = audio_filter.static_pad("src") else {
log::warn!("audio filter has no source pad; malformed audio gaps will not be suppressed");
return;
};
let _ = src_pad.add_probe(gst::PadProbeType::EVENT_DOWNSTREAM, |_, info| {
let Some(event) = info.event() else {
return gst::PadProbeReturn::Ok;
};
let gst::EventView::Gap(gap) = event.view() else {
return gst::PadProbeReturn::Ok;
};
let (timestamp, duration) = gap.get();
if !is_suspicious_audio_gap(duration) {
return gst::PadProbeReturn::Ok;
}
// Some malformed MP4 edit lists cause streamsynchronizer to emit a
// long GAP before almost every audio buffer. The next buffer's PTS is
// still continuous, so forwarding those events makes audio sinks
// repeatedly wait or resynchronise and produces choppy playback.
log::debug!("suppressing audio GAP at {timestamp} with duration {duration:?}");
drop(info.take_event());
gst::PadProbeReturn::Handled
});
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct VideoSettings { pub struct VideoSettings {
pub mute: bool, pub mute: bool,
@ -33,11 +67,14 @@ pub fn new_video(
.downcast::<gst::Pipeline>() .downcast::<gst::Pipeline>()
.map_err(|_| iced_video_player::Error::Cast) .map_err(|_| iced_video_player::Error::Cast)
.unwrap(); .unwrap();
if let Ok(scaletempo) = gst::ElementFactory::make("scaletempo").build() { let audio_filter = gst::ElementFactory::make("scaletempo")
pipeline.set_property("audio-filter", &scaletempo); .build()
} else { .unwrap_or_else(|_| {
log::warn!("scaletempo element not available; speed changes will affect pitch"); log::warn!("scaletempo element not available; speed changes will affect pitch");
} gst::ElementFactory::make("identity").build().unwrap()
});
suppress_suspicious_audio_gaps(&audio_filter);
pipeline.set_property("audio-filter", &audio_filter);
pipeline.connect("element-setup", false, |vals| { pipeline.connect("element-setup", false, |vals| {
let Ok(elem) = vals[1].get::<gst::Element>() else { let Ok(elem) = vals[1].get::<gst::Element>() else {
return None; return None;
@ -111,3 +148,25 @@ fn disable_broken_hardware_decoders() {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::is_suspicious_audio_gap;
use iced_video_player::gst;
#[test]
fn long_audio_gap_is_suspicious() {
assert!(is_suspicious_audio_gap(Some(gst::ClockTime::SECOND)));
assert!(is_suspicious_audio_gap(Some(
gst::ClockTime::from_seconds(3)
)));
}
#[test]
fn short_or_unknown_audio_gap_is_preserved() {
assert!(!is_suspicious_audio_gap(Some(
gst::ClockTime::from_mseconds(999)
)));
assert!(!is_suspicious_audio_gap(None));
}
}