1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! A hardware-accelerated video widget for `egui`, backed by [`libmpv2`].
//!
//! Because playback is driven with mpv, and video frames are rendered straight
//! into an OpenGL framebuffer, this only works when using `eframe`'s `glow`
//! rendering backend; wgpu` is not supported.
//!
//! # Quick Start
//!
//! There are two components to the video player, the state ([`PlayerState`]),
//! and the egui widget ([`SharkPlayer`]). [`PlayerState`] is built once during
//! application startup using [`eframe::CreationContext`].
//!
//! ```no_run
//! use eframe::egui;
//! use egui_sharkplayer::{PlayerState, SharkPlayer};
//!
//! struct App {
//! player: PlayerState,
//! }
//!
//! impl App {
//! fn new(cc: &eframe::CreationContext<'_>) -> Self {
//! let player = PlayerState::new(cc).expect("failed to initialize player");
//! player.load_file("video.mp4").expect("failed to load video.mp4");
//! Self { player }
//! }
//! }
//!
//! impl eframe::App for App {
//! fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {
//! // Required: see "Cleaning up".
//! self.player.destroy_gl_resources();
//! }
//!
//! fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
//! egui::CentralPanel::default().show_inside(ui, |ui| {
//! ui.add(SharkPlayer::new(&mut self.player));
//! });
//! }
//! }
//!
//! fn main() {
//! eframe::run_native(
//! "Sharkplayer",
//! eframe::NativeOptions::default(),
//! Box::new(|cc| Ok(Box::new(App::new(cc)))),
//! )
//! .unwrap();
//! }
//! ```
//!
//! If you want to play multiple videos at the same tie, you'll need to have
//! multiple [`PlayerState`]s.
//!
//! # Player Size
//!
//! By default, the widget claims all the space available in its panel. However,
//! it's possible to contrain one of the axies using [`SharkPlayer::sizing`] to
//! pin one axis instead — the other is derived from the video's aspect ratio,
//! so the player doesn't letterbox.
//!
//! ```no_run
//! # use eframe::egui;
//! # use egui_sharkplayer::{PlayerState, SharkPlayer, Sizing};
//! # fn ui(ui: &mut egui::Ui, player: &mut PlayerState) {
//! ui.add(SharkPlayer::new(player).sizing(Sizing::Width(640.0)));
//! # }
//! ```
//!
//! # Styling Controls
//!
//! For the most part, the controls use standard egui styling, but some
//! components have special styling options.
//!
//! ## Bar Height
//! The player bar has a default height, but it can be overridden with
//! [`SharkPlayer::bar_height`].
//!
//! ```no_run
//! # use eframe::egui;
//! # use egui_sharkplayer::{PlayerState, SharkPlayer, Sizing};
//! # fn ui(ui: &mut egui::Ui, player: &mut PlayerState) {
//! ui.add(
//! SharkPlayer::new(player)
//! .sizing(Sizing::Height(360.0))
//! .bar_height(32.0),
//! );
//! # }
//! ```
//!
//! ## Custom icons
//!
//! To customize which icons are used for the controls, you need a
//! [`ControlsIconProvider`].
//!
//! ```no_run
//! # use eframe::egui;
//! use egui_sharkplayer::{ControlsIconProvider, PlayerState, SharkPlayer};
//!
//! struct Icons;
//!
//! impl ControlsIconProvider for Icons {
//! fn play(&self) -> egui::WidgetText { "Play".into() }
//! fn pause(&self) -> egui::WidgetText { "Pause".into() }
//! }
//!
//! # fn ui(ui: &mut egui::Ui, player: &mut PlayerState) {
//! ui.add(SharkPlayer::new_with_icons(player, Icons));
//! # }
//! ```
//!
//!
//! # Cleaning Up
//!
//! To clean up the player's OpenGL resources, call
//! [`PlayerState::destroy_gl_resources`] from [`eframe::App::on_exit`].
//!
//! This isn't strictly neccesary if it's fine to leak VRAM, like if the process
//! stops when the UI closes.
pub use ;
pub use ;