1 // Copyright (c) 2010, Niels Martin Hansen
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 /// @file audio_timing.h
31 /// @brief Construction-functions for timing controller objects
32 /// @ingroup audio_ui
33 
34 class AssDialogue;
35 class AssFile;
36 class AssKaraoke;
37 class AudioRenderingStyleRanges;
38 namespace agi { struct Context; }
39 
40 #include "audio_marker.h"
41 
42 /// @class AudioTimingController
43 /// @brief Base class for objects controlling audio timing
44 ///
45 /// There is just one active audio timing controller at a time per audio
46 /// controller. The timing controller manages the timing mode and supplies
47 /// markers that can be manipulated to the audio display, as well as the
48 /// current selection.
49 ///
50 /// The timing controller must then be sent the marker drag events as well as
51 /// clicks in empty areas of the audio display.
52 class AudioTimingController : public AudioMarkerProvider, public AudioLabelProvider {
53 protected:
54 	/// The primary playback range has changed, usually as a result of user interaction.
55 	agi::signal::Signal<> AnnounceUpdatedPrimaryRange;
56 
57 	/// One or more rendering style ranges have changed in the timing controller.
58 	agi::signal::Signal<> AnnounceUpdatedStyleRanges;
59 
60 public:
61 	/// @brief Get any warning message to show in the audio display
62 	/// @return The warning message to show, may be empty if there is none
63 	virtual wxString GetWarningMessage() const = 0;
64 
65 	/// @brief Get the time range the user is most likely to want to see for the current state
66 	/// @return A time range
67 	///
68 	/// This is used for "bring working area into view" operations.
69 	virtual TimeRange GetIdealVisibleTimeRange() const = 0;
70 
71 	/// @brief Get the primary playback range
72 	/// @return A time range
73 	///
74 	/// Get the time range the user is most likely to want to play back
75 	/// currently.
76 	virtual TimeRange GetPrimaryPlaybackRange() const = 0;
77 
78 	/// @brief Get the active line's time
79 	/// @return A time range
80 	///
81 	/// Get the time range which the active line would have if any pending
82 	/// modifications were committed.
83 	virtual TimeRange GetActiveLineRange() const = 0;
84 
85 	/// @brief Get all rendering style ranges
86 	/// @param[out] ranges Rendering ranges will be added to this
87 	virtual void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const = 0;
88 
89 	enum NextMode {
90 		/// Advance to the next timing unit, whether it's a line or a sub-part
91 		/// of a line such as a karaoke syllable
92 		TIMING_UNIT = 0,
93 
94 		/// @brief Advance to the next line
95 		///
96 		/// This may create a new line if there are no more lines in the file,
97 		/// but should never modify existing lines
98 		LINE,
99 
100 		/// @brief Advance to the next line using default timing
101 		///
102 		/// This may create new lines when needed, and should discard any
103 		/// existing timing data in favor of the defaults
104 		LINE_RESET_DEFAULT
105 	};
106 
107 	/// @brief Go to next timing unit
108 	/// @param mode What sort of timing unit should be advanced to
109 	virtual void Next(NextMode mode) = 0;
110 
111 	/// @brief Go to the previous timing unit
112 	///
113 	/// Rewinds the timing controller to the previous timing unit.
114 	virtual void Prev() = 0;
115 
116 	/// @brief Commit all changes
117 	///
118 	/// Stores all changes permanently.
119 	virtual void Commit() = 0;
120 
121 	/// @brief Revert all changes
122 	///
123 	/// Revert all changes to the last committed state.
124 	virtual void Revert() = 0;
125 
126 	/// Add lead-in time to the current timing unit
127 	virtual void AddLeadIn() = 0;
128 
129 	/// Add lead-out time to the current timing unit
130 	virtual void AddLeadOut() = 0;
131 
132 	/// Modify the length of the current and possibly following timing units
133 	/// @param delta Amount to add in centiseconds
134 	/// @param shift_following Should the following things be shifted by delta?
135 	virtual void ModifyLength(int delta, bool shift_following) = 0;
136 
137 	/// Modify the start time of the current timing unit
138 	/// @param delta Amount to add in centiseconds
139 	virtual void ModifyStart(int delta) = 0;
140 
141 	/// @brief Determine if a position is close to a draggable marker
142 	/// @param ms          The time in milliseconds to test
143 	/// @param sensitivity Distance in milliseconds to consider markers as nearby
144 	/// @return True if a marker is close by the given time, as defined by sensitivity
145 	///
146 	/// This is solely for hit-testing against draggable markers, for
147 	/// controlling the mouse cursor.
148 	virtual bool IsNearbyMarker(int ms, int sensitivity, bool alt_down) const = 0;
149 
150 	/// @brief The user pressed the left mouse button on the audio
151 	/// @param ms          The time in milliseconds the user clicked
152 	/// @param ctrl_down   Is the user currently holding the ctrl key down?
153 	/// @param sensitivity Distance in milliseconds to consider existing markers
154 	/// @param snap_range  Maximum snapping range in milliseconds
155 	/// @return All audio markers at the clicked position which are eligible
156 	///         to be dragged, if any.
157 	virtual std::vector<AudioMarker*> OnLeftClick(int ms, bool ctrl_down, bool alt_down, int sensitivity, int snap_range) = 0;
158 
159 	/// @brief The user pressed the right mouse button on the audio
160 	/// @param ms          The time in milliseconds the user clicked
161 	/// @param ctrl_down   Is the user currently holding the ctrl key down?
162 	/// @param sensitivity Distance in milliseconds to consider existing markers
163 	/// @param snap_range  Maximum snapping range in milliseconds
164 	/// @return All audio markers at the clicked position which are eligible
165 	///         to be dragged, if any.
166 	virtual std::vector<AudioMarker*> OnRightClick(int ms, bool ctrl_down, int sensitivity, int snap_range) = 0;
167 
168 	/// @brief The user dragged one or more timing markers
169 	/// @param marker       The markers being dragged. This is guaranteed to be
170 	///                     a vector returned from OnLeftClick or OnRightClick.
171 	/// @param new_position Time position the marker was dragged to
172 	/// @param snap_range   Maximum snapping range in milliseconds
173 	virtual void OnMarkerDrag(std::vector<AudioMarker*> const& marker, int new_position, int snap_range) = 0;
174 
175 	/// @brief Destructor
176 	virtual ~AudioTimingController() = default;
177 
178 	DEFINE_SIGNAL_ADDERS(AnnounceUpdatedPrimaryRange, AddUpdatedPrimaryRangeListener)
179 	DEFINE_SIGNAL_ADDERS(AnnounceUpdatedStyleRanges, AddUpdatedStyleRangesListener)
180 };
181 
182 /// @brief Create a standard dialogue audio timing controller
183 /// @param c Project context
184 std::unique_ptr<AudioTimingController> CreateDialogueTimingController(agi::Context *c);
185 
186 /// @brief Create a karaoke audio timing controller
187 /// @param c Project context
188 /// @param kara Karaoke model
189 std::unique_ptr<AudioTimingController> CreateKaraokeTimingController(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed);
190