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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! A hardware-accelerated video widget for `egui`, backed by [`libmpv2`].
//!
//! This crate provides an immediate-mode video player for `eframe`
//! applications.
//!
//! # Overview
//!
//! - [`PlayerState`]: Manages the `libmpv` context, media properties, and
//! playback state. This requires access to the graphics context and must be
//! initialized once using the [`eframe::CreationContext`].
//!
//! A single [`PlayerState`] maps to a single video stream. Displaying
//! multiple videos simultaneously requires independent state instances.
//!
//! - [`SharkPlayer`]: The actual UI widget. This is what you create in your
//! `ui` method.
//!
//! The video player works best with the `glow` backend because libmpv2's render
//! API only supports OpenGL. When using the `wgpu` feature, instead of a direct
//! VRAM copy, image data has to roundtrip through main system memory. If at all
//! possible, use `glow` and disable the `wgpu` feature.
//!
//! 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.
//!
//! # Features
//!
//! - Integrated contol overlays (play/pause, volume, seekbar, info overlay,
//! etc.)
//! - Fullscreening support
//!
//! # Quick Start
//!
//! ```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 time, 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 axes 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 necessary it's fine to leak VRAM, like if the process
//! stops when the UI closes.
pub use ;
pub use ;