1 // Copyright (c) 2005-2007, Rodrigo Braz Monteiro 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of the Aegisub Group nor the names of its contributors 13 // may be used to endorse or promote products derived from this software 14 // without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 // POSSIBILITY OF SUCH DAMAGE. 27 // 28 // Aegisub Project http://www.aegisub.org/ 29 30 #include <libaegisub/signal.h> 31 #include <libaegisub/vfr.h> 32 33 #include <chrono> 34 #include <set> 35 36 #include <wx/timer.h> 37 38 class AssDialogue; 39 class AsyncVideoProvider; 40 struct SubtitlesProviderErrorEvent; 41 struct VideoProviderErrorEvent; 42 43 namespace agi { 44 struct Context; 45 class OptionValue; 46 } 47 48 enum class AspectRatio { 49 Default = 0, 50 Fullscreen, 51 Widescreen, 52 Cinematic, 53 Custom 54 }; 55 56 /// Manage stuff related to video playback 57 class VideoController final : public wxEvtHandler { 58 /// Current frame number changed (new frame number) 59 agi::signal::Signal<int> Seek; 60 /// Aspect ratio was changed (type, value) 61 agi::signal::Signal<AspectRatio, double> ARChange; 62 63 agi::Context *context; 64 65 /// The video provider owned by the threaded frame source, or nullptr if no 66 /// video is open 67 AsyncVideoProvider *provider = nullptr; 68 69 /// Last seen script color matrix 70 std::string color_matrix; 71 72 /// Playback timer used to periodically check if we should go to the next 73 /// frame while playing video 74 wxTimer playback; 75 76 /// Time when playback was last started 77 std::chrono::steady_clock::time_point playback_start_time; 78 79 /// The start time of the first frame of the current playback; undefined if 80 /// video is not currently playing 81 int start_ms = 0; 82 83 /// The last frame to play if video is currently playing 84 int end_frame = 0; 85 86 /// The frame number which was last requested from the video provider, 87 /// which may not be the same thing as the currently displayed frame 88 int frame_n = 0; 89 90 /// The picture aspect ratio of the video if the aspect ratio has been 91 /// overridden by the user 92 double ar_value = 1.; 93 94 /// The current AR type 95 AspectRatio ar_type = AspectRatio::Default; 96 97 /// Cached option for audio playing when frame stepping 98 const agi::OptionValue* playAudioOnStep; 99 100 std::vector<agi::signal::Connection> connections; 101 102 void OnPlayTimer(wxTimerEvent &event); 103 104 void OnVideoError(VideoProviderErrorEvent const& err); 105 void OnSubtitlesError(SubtitlesProviderErrorEvent const& err); 106 107 void OnSubtitlesCommit(int type, std::set<const AssDialogue *> const& changed); 108 void OnNewVideoProvider(AsyncVideoProvider *provider); 109 void OnActiveLineChanged(AssDialogue *line); 110 111 void RequestFrame(); 112 113 public: 114 VideoController(agi::Context *context); 115 116 /// Is the video currently playing? IsPlaying()117 bool IsPlaying() const { return playback.IsRunning(); } 118 119 /// Get the current frame number GetFrameN()120 int GetFrameN() const { return frame_n; } 121 122 /// Get the actual aspect ratio from a predefined AR type 123 double GetARFromType(AspectRatio type) const; 124 125 /// Override the aspect ratio of the currently loaded video 126 void SetAspectRatio(double value); 127 128 /// Override the aspect ratio of the currently loaded video 129 /// @param type Predefined type to set the AR to. Must not be Custom. 130 void SetAspectRatio(AspectRatio type); 131 132 /// Get the current AR type GetAspectRatioType()133 AspectRatio GetAspectRatioType() const { return ar_type; } 134 135 /// Get the current aspect ratio of the video GetAspectRatioValue()136 double GetAspectRatioValue() const { return ar_value; } 137 138 /// @brief Jump to the beginning of a frame 139 /// @param n Frame number to jump to 140 void JumpToFrame(int n); 141 /// @brief Jump to a time 142 /// @param ms Time to jump to in milliseconds 143 /// @param end Type of time 144 void JumpToTime(int ms, agi::vfr::Time end = agi::vfr::START); 145 146 /// Starting playing the video 147 void Play(); 148 /// Play the next frame then stop 149 void NextFrame(); 150 /// Play the previous frame then stop 151 void PrevFrame(); 152 /// Seek to the beginning of the current line, then play to the end of it 153 void PlayLine(); 154 /// Stop playing 155 void Stop(); 156 157 DEFINE_SIGNAL_ADDERS(Seek, AddSeekListener) 158 DEFINE_SIGNAL_ADDERS(ARChange, AddARChangeListener) 159 160 int TimeAtFrame(int frame, agi::vfr::Time type = agi::vfr::EXACT) const; 161 int FrameAtTime(int time, agi::vfr::Time type = agi::vfr::EXACT) const; 162 }; 163