ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git), ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
63 lines
2.5 KiB
Rust
63 lines
2.5 KiB
Rust
//! The system player against a small H.264/AAC clip.
|
|
|
|
#[cfg(target_os = "macos")]
|
|
fn main() {
|
|
use std::time::{Duration, Instant};
|
|
|
|
use ely_platform::media::{Player, State};
|
|
use objc2_foundation::{NSDate, NSRunLoop};
|
|
|
|
// The player works through the main run loop.
|
|
let pump = |until: &dyn Fn() -> bool| {
|
|
let end = Instant::now() + Duration::from_secs(10);
|
|
while !until() {
|
|
assert!(Instant::now() < end, "the player never got there");
|
|
let soon = NSDate::dateWithTimeIntervalSinceNow(0.02);
|
|
NSRunLoop::currentRunLoop().runUntilDate(&soon);
|
|
}
|
|
};
|
|
let clip = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.join("../../tests/fixtures/media/clip.mp4");
|
|
let player = Player::open(&clip).expect("opens");
|
|
pump(&|| player.state() != State::Loading);
|
|
let State::Ready { seconds, video } = player.state() else {
|
|
panic!("not ready: {:?}", player.state());
|
|
};
|
|
assert!((seconds - 1.0).abs() < 0.2, "{seconds}");
|
|
assert_eq!(video, Some((160, 90)));
|
|
player.play();
|
|
let frames = std::cell::Cell::new(0);
|
|
pump(&|| {
|
|
frames.set(frames.get() + usize::from(player.frame().is_some()));
|
|
player.position() > 0.3 && frames.get() > 0
|
|
});
|
|
assert!(player.playing());
|
|
// At its end it stops; a loop starts over.
|
|
pump(&|| player.ended());
|
|
assert_eq!(player.tick(false), Ok(false), "done, nothing to draw");
|
|
assert_eq!(player.tick(true), Ok(true), "the loop goes on");
|
|
pump(&|| player.playing() && player.position() < seconds - 0.2);
|
|
// A pause near the end holds, loop or not.
|
|
player.pause();
|
|
player.seek(seconds - 0.02);
|
|
pump(&|| player.position() >= seconds - 0.05);
|
|
assert!(!player.ended());
|
|
assert_eq!(player.tick(true), Ok(false));
|
|
assert!(!player.playing(), "the pause holds");
|
|
player.play();
|
|
player.pause();
|
|
assert!(Player::open(std::path::Path::new("/no/such/clip.mp4")).is_err());
|
|
let dir = tempfile::tempdir().expect("a temp dir");
|
|
let junk = dir.path().join("junk.mp4");
|
|
std::fs::write(&junk, b"not a video at all").expect("writes");
|
|
let broken = Player::open(&junk).expect("opens the file");
|
|
pump(&|| broken.tick(false) != Ok(true));
|
|
assert!(matches!(broken.tick(false), Err(reason) if !reason.is_empty()));
|
|
println!("media: plays, shows frames, and fails with reasons");
|
|
}
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
fn main() {
|
|
println!("SKIP: no system player is built on this platform");
|
|
}
|