void VideoContext::Reload() { if (IsLoaded()) { int frame = frame_n; SetVideo(videoFile.Clone()); JumpToFrame(frame); } }
void VideoContext::PrevFrame() { if (!videoProvider || IsPlaying() || frame_n == 0) return; JumpToFrame(frame_n - 1); // Start playing audio if (playAudioOnStep->GetBool()) { context->audioController->PlayRange(TimeRange(TimeAtFrame(frame_n), TimeAtFrame(frame_n + 1))); } }
void VideoContext::PlayLine() { Stop(); AssDialogue *curline = context->selectionController->GetActiveLine(); if (!curline) return; // Start playing audio context->audioController->PlayRange(TimeRange(curline->Start, curline->End)); // Round-trip conversion to convert start to exact int startFrame = FrameAtTime(context->selectionController->GetActiveLine()->Start,agi::vfr::START); startMS = TimeAtFrame(startFrame); endFrame = FrameAtTime(context->selectionController->GetActiveLine()->End,agi::vfr::END) + 1; // Jump to start JumpToFrame(startFrame); // Start timer playTime.Start(); playback.Start(10); }
void Project::LoadUnloadFiles(ProjectProperties properties) { auto load_linked = OPT_GET("App/Auto/Load Linked Files")->GetInt(); if (!load_linked) return; auto audio = context->path->MakeAbsolute(properties.audio_file, "?script"); auto video = context->path->MakeAbsolute(properties.video_file, "?script"); auto timecodes = context->path->MakeAbsolute(properties.timecodes_file, "?script"); auto keyframes = context->path->MakeAbsolute(properties.keyframes_file, "?script"); if (video == video_file && audio == audio_file && keyframes == keyframes_file && timecodes == timecodes_file) return; if (load_linked == 2) { wxString str = _("Do you want to load/unload the associated files?"); str += "\n"; auto append_file = [&](agi::fs::path const& p, wxString const& unload, wxString const& load) { if (p.empty()) str += "\n" + unload; else str += "\n" + agi::wxformat(load, p); }; if (audio != audio_file) append_file(audio, _("Unload audio"), _("Load audio file: %s")); if (video != video_file) append_file(video, _("Unload video"), _("Load video file: %s")); if (timecodes != timecodes_file) append_file(timecodes, _("Unload timecodes"), _("Load timecodes file: %s")); if (keyframes != keyframes_file) append_file(keyframes, _("Unload keyframes"), _("Load keyframes file: %s")); if (wxMessageBox(str, _("(Un)Load files?"), wxYES_NO | wxCENTRE, context->parent) != wxYES) return; } bool loaded_video = false; if (video != video_file) { if (video.empty()) CloseVideo(); else if ((loaded_video = DoLoadVideo(video))) { auto vc = context->videoController.get(); vc->JumpToFrame(properties.video_position); auto ar_mode = static_cast<AspectRatio>(properties.ar_mode); if (ar_mode == AspectRatio::Custom) vc->SetAspectRatio(properties.ar_value); else vc->SetAspectRatio(ar_mode); context->videoDisplay->SetZoom(properties.video_zoom); } } if (!timecodes.empty()) LoadTimecodes(timecodes); if (!keyframes.empty()) LoadKeyframes(keyframes); if (audio != audio_file) { if (audio.empty()) CloseAudio(); else DoLoadAudio(audio, false); } else if (loaded_video && OPT_GET("Video/Open Audio")->GetBool() && audio_file != video_file && video_provider->HasAudio()) DoLoadAudio(video, true); }
void VideoContext::JumpToTime(int ms, agi::vfr::Time end) { JumpToFrame(FrameAtTime(ms, end)); }
void VideoContext::SetVideo(const wxString &filename) { Reset(); if (filename.empty()) { VideoOpen(); return; } bool commit_subs = false; try { provider.reset(new ThreadedFrameSource(filename, this)); videoProvider = provider->GetVideoProvider(); videoFile = filename; // Check that the script resolution matches the video resolution int sx = context->ass->GetScriptInfoAsInt("PlayResX"); int sy = context->ass->GetScriptInfoAsInt("PlayResY"); int vx = GetWidth(); int vy = GetHeight(); // If the script resolution hasn't been set at all just force it to the // video resolution if (sx == 0 && sy == 0) { context->ass->SetScriptInfo("PlayResX", wxString::Format("%d", vx)); context->ass->SetScriptInfo("PlayResY", wxString::Format("%d", vy)); commit_subs = true; } // If it has been set to something other than a multiple of the video // resolution, ask the user if they want it to be fixed else if (sx % vx != 0 || sy % vy != 0) { switch (OPT_GET("Video/Check Script Res")->GetInt()) { case 1: // Ask to change on mismatch if (wxYES != wxMessageBox( wxString::Format(_("The resolution of the loaded video and the resolution specified for the subtitles don't match.\n\nVideo resolution:\t%d x %d\nScript resolution:\t%d x %d\n\nChange subtitles resolution to match video?"), vx, vy, sx, sy), _("Resolution mismatch"), wxYES_NO | wxCENTER, context->parent)) break; // Fallthrough to case 2 case 2: // Always change script res context->ass->SetScriptInfo("PlayResX", wxString::Format("%d", vx)); context->ass->SetScriptInfo("PlayResY", wxString::Format("%d", vy)); commit_subs = true; break; default: // Never change break; } } keyFrames = videoProvider->GetKeyFrames(); // Set frame rate videoFPS = videoProvider->GetFPS(); if (ovrFPS.IsLoaded()) { int ovr = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION); if (ovr == wxYES) { ovrFPS = agi::vfr::Framerate(); ovrTimecodeFile.clear(); } } // Set aspect ratio double dar = videoProvider->GetDAR(); if (dar > 0) SetAspectRatio(4, dar); // Set filename config::mru->Add("Video", STD_STR(filename)); StandardPaths::SetPathValue("?video", wxFileName(filename).GetPath()); // Show warning wxString warning = videoProvider->GetWarning(); if (!warning.empty()) wxMessageBox(warning, "Warning", wxICON_WARNING | wxOK); hasSubtitles = false; if (filename.Right(4).Lower() == ".mkv") { hasSubtitles = MatroskaWrapper::HasSubtitles(filename); } provider->LoadSubtitles(context->ass); VideoOpen(); KeyframesOpen(keyFrames); TimecodesOpen(FPS()); } catch (agi::UserCancelException const&) { } catch (agi::FileNotAccessibleError const& err) { config::mru->Remove("Video", STD_STR(filename)); wxMessageBox(lagi_wxString(err.GetMessage()), "Error setting video", wxOK | wxICON_ERROR | wxCENTER); } catch (VideoProviderError const& err) { wxMessageBox(lagi_wxString(err.GetMessage()), "Error setting video", wxOK | wxICON_ERROR | wxCENTER); } if (commit_subs) context->ass->Commit(_("change script resolution"), AssFile::COMMIT_SCRIPTINFO); else JumpToFrame(0); }
void FrameMain::OnSubtitlesOpen() { UpdateTitle(); auto vc = context->videoController; /// @todo figure out how to move this to the relevant controllers without /// prompting for each file loaded/unloaded // Load stuff from the new script auto video = config::path->MakeAbsolute(context->ass->GetScriptInfo("Video File"), "?script"); auto vfr = config::path->MakeAbsolute(context->ass->GetScriptInfo("VFR File"), "?script"); auto keyframes = config::path->MakeAbsolute(context->ass->GetScriptInfo("Keyframes File"), "?script"); auto audio = config::path->MakeAbsolute(context->ass->GetScriptInfo("Audio URI"), "?script"); bool videoChanged = !blockVideoLoad && video != vc->GetVideoName(); bool timecodesChanged = vfr != vc->GetTimecodesName(); bool keyframesChanged = keyframes != vc->GetKeyFramesName(); bool audioChanged = !blockAudioLoad && audio != context->audioController->GetAudioURL(); // Check if there is anything to change int autoLoadMode = OPT_GET("App/Auto/Load Linked Files")->GetInt(); if (autoLoadMode == 0 || (!videoChanged && !timecodesChanged && !keyframesChanged && !audioChanged)) { SetDisplayMode(1, 1); return; } if (autoLoadMode == 2) { if (wxMessageBox(_("Do you want to load/unload the associated files?"), _("(Un)Load files?"), wxYES_NO | wxCENTRE, this) != wxYES) { SetDisplayMode(1, 1); if (vc->IsLoaded() && vc->GetProvider()->GetColorSpace() != context->ass->GetScriptInfo("YCbCr Matrix")) vc->Reload(); return; } } if (audioChanged) blockAudioLoad = true; // Video if (videoChanged) { vc->SetVideo(video); if (vc->IsLoaded()) { vc->JumpToFrame(context->ass->GetUIStateAsInt("Video Position")); std::string arString = context->ass->GetUIState("Video Aspect Ratio"); if (boost::starts_with(arString, "c")) { double ar = 0.; agi::util::try_parse(arString.substr(1), &ar); vc->SetAspectRatio(ar); } else { int ar = 0; if (agi::util::try_parse(arString, &ar) && ar >= 0 && ar < 4) vc->SetAspectRatio((AspectRatio)ar); } double videoZoom = 0.; if (agi::util::try_parse(context->ass->GetUIState("Video Zoom Percent"), &videoZoom)) context->videoDisplay->SetZoom(videoZoom); } } else if (vc->IsLoaded() && vc->GetProvider()->GetColorSpace() != context->ass->GetScriptInfo("YCbCr Matrix")) vc->Reload(); vc->LoadTimecodes(vfr); vc->LoadKeyframes(keyframes); // Audio if (audioChanged) { blockAudioLoad = false; try { if (audio.empty()) context->audioController->CloseAudio(); else context->audioController->OpenAudio(audio); } catch (agi::UserCancelException const&) { } catch (agi::fs::FileSystemError const& err) { wxMessageBox(to_wx(err.GetMessage()), "Error opening audio", wxOK | wxICON_ERROR | wxCENTER, this); } } SetDisplayMode(1, 1); }