using Gtk; using Adw; namespace Publicate.Video { public class VideoProcessor : Adw.Window { private ProgressBar progress_bar; private Label label; private Button cancel_button; public VideoProcessor() { this.resizable = false; var hbox = new Box(Orientation.HORIZONTAL, 8); hbox.margin_bottom = 18; hbox.margin_top = 18; hbox.margin_start = 18; hbox.margin_end = 18; var vbox = new Box(Orientation.VERTICAL, 8); hbox.append (vbox); content = hbox; label = new Label("Reading Video…"); progress_bar = new ProgressBar (); cancel_button = new Button.from_icon_name ("process-stop-symbolic"); // hbox.append(cancel_button); vbox.append (label); vbox.append(progress_bar); } public async VideoProcessResult? process_video(string path, ViewerWindow window) { this.modal = true; this.transient_for = window; present(); var video_file = File.new_for_path(path); var video_info = new VideoInfo(video_file); yield video_info.read_info(); var profiles = construct_vp9_profiles().concat(construct_theora_profiles()); var use_profiles = profiles.where(p => p.suitable_for(video_info)); use_profiles.iterate(p => p.setup_for(video_info)); var encoders = use_profiles.select(p => new Encoder(video_file, "/tmp/", p)).to_sequence(); foreach (var encoder in encoders) { encoder.progress_changed.connect((frac, done) => { var amount = frac; amount = amount / (double)encoders.count(); Idle.add(() => { progress_bar.fraction += amount; return false; }); }); } progress_bar.fraction = 0.0; label.label = "Encoding Video…"; yield encode_video(encoders); progress_bar.fraction = 1; label.label = "Writing PPUB…"; var manifest = new Ppub.VideoManifest(); manifest.streams = encoders.select(e => e.get_video_description()).to_sequence(); manifest.duration = video_info.duration; var ratio_parts = video_info.aspect_ratio.split(":"); manifest.ratio = new double[] { double.parse(ratio_parts[0]), double.parse(ratio_parts[1]) }; return new VideoProcessResult(manifest, encoders.select(e => e.get_output_file()).to_sequence()); } private async void encode_video(Invercargill.Enumerable encoders) { SourceFunc callback = encode_video.callback; ThreadFunc run = () => { encoders.parallel_iterate(e => e.encode()); Idle.add((owned) callback); return true; }; new Thread("encoder thread", run); yield; } public void complete() { close(); } } public class VideoProcessResult { public Ppub.VideoManifest manifest { get; private set; } public Invercargill.Enumerable video_files { get; private set; } public VideoProcessResult(Ppub.VideoManifest manifest, Invercargill.Enumerable videos) { this.manifest = manifest; video_files = videos; } } }