MythTV master
mythplayereditorui.cpp
Go to the documentation of this file.
1#include <algorithm>
2
3// MythTV
6#include "tv_actions.h"
7#include "tv_play.h"
9
10#define LOC QString("Editor: ")
11
13 : MythPlayerVisualiserUI(MainWindow, Tv, Context, Flags)
14{
15 qRegisterMetaType<MythEditorState>();
16
17 // Connect incoming TV signals
21
22 // New state
24}
25
27{
28 LOG(VB_GENERAL, LOG_INFO, LOC + "Initialising editor");
30}
31
32void MythPlayerEditorUI::RefreshEditorState(bool CheckSaved /*=false*/)
33{
34 auto frame = GetFramesPlayed();
36 frame,
37 m_deleteMap.GetNearestMark(frame, false),
38 m_deleteMap.GetNearestMark(frame, true),
47 CheckSaved ? m_deleteMap.IsSaved() : false });
48}
49
51{
53
55 {
56 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot edit - no full position map");
57 SetOSDStatus(tr("No Seektable"), kOSDTimeout_Med);
58 return;
59 }
60
62 return;
63
64 QMutexLocker locker(&m_osdLock);
66
68 m_tcWrap[TC_AUDIO] = 0ms;
69
75 m_osd.HideAll();
76
77 bool loadedAutoSave = m_deleteMap.LoadAutoSaveMap();
78 if (loadedAutoSave)
79 UpdateOSDMessage(tr("Using previously auto-saved cuts"), kOSDTimeout_Short);
80
84 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
87 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
88 m_editUpdateTimer.start();
89}
90
98{
99 QMutexLocker locker(&m_osdLock);
101 if (HowToSave == 0)
103 // Unconditionally save to remove temporary marks from the DB.
104 if (HowToSave >= 0)
108 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
111 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
115
118 else
119 SetOSDStatus(tr("Paused"), kOSDTimeout_None);
120}
121
123{
124 if (qFuzzyCompare(m_deleteMap.GetSeekAmount() + 1000.0F, 1000.0F -2.0F))
125 {
126 uint64_t framenum = m_deleteMap.GetNearestMark(m_framesPlayed, Direction);
127 if (Direction && (framenum > m_framesPlayed))
129 else if (!Direction && (m_framesPlayed > framenum))
131 }
132 else
133 {
134 if (Direction)
136 else
138 }
139}
140
142{
143 bool handled = false;
144 bool refresh = true;
145 auto frame = GetFramesPlayed();
146
147 for (int i = 0; i < Actions.size() && !handled; i++)
148 {
149 static constexpr float FFREW_MULTICOUNT { 10.0F };
150 const QString& action = Actions[i];
151 handled = true;
152 float seekamount = m_deleteMap.GetSeekAmount();
153 bool seekzero = qFuzzyCompare(seekamount + 1.0F, 1.0F);
154 if (action == ACTION_LEFT)
155 {
156 if (seekzero) // 1 frame
157 {
159 }
160 else if (seekamount > 0)
161 {
162 // Use fully-accurate seeks for less than 1 second.
163 DoRewindSecs(seekamount, seekamount < 1.0F ? kInaccuracyNone :
164 kInaccuracyEditor, false);
165 }
166 else
167 {
168 HandleArbSeek(false);
169 }
170 }
171 else if (action == ACTION_RIGHT)
172 {
173 if (seekzero) // 1 frame
174 {
176 }
177 else if (seekamount > 0)
178 {
179 // Use fully-accurate seeks for less than 1 second.
180 DoFastForwardSecs(seekamount, seekamount < 1.0F ? kInaccuracyNone :
181 kInaccuracyEditor, false);
182 }
183 else
184 {
185 HandleArbSeek(true);
186 }
187 }
188 else if (action == ACTION_LOADCOMMSKIP)
189 {
191 {
192 frm_dir_map_t map;
195 }
196 }
197 else if (action == ACTION_PREVCUT)
198 {
199 float old_seekamount = m_deleteMap.GetSeekAmount();
201 HandleArbSeek(false);
202 m_deleteMap.SetSeekAmount(old_seekamount);
203 }
204 else if (action == ACTION_NEXTCUT)
205 {
206 float old_seekamount = m_deleteMap.GetSeekAmount();
208 HandleArbSeek(true);
209 m_deleteMap.SetSeekAmount(old_seekamount);
210 }
211 else if (action == ACTION_BIGJUMPREW)
212 {
213 if (seekzero)
214 DoRewind(FFREW_MULTICOUNT, kInaccuracyNone);
215 else if (seekamount > 0)
216 DoRewindSecs(seekamount * FFREW_MULTICOUNT, kInaccuracyEditor, false);
217 else
218 DoRewindSecs(FFREW_MULTICOUNT / 2, kInaccuracyNone, false);
219 }
220 else if (action == ACTION_BIGJUMPFWD)
221 {
222 if (seekzero)
223 DoFastForward(FFREW_MULTICOUNT, kInaccuracyNone);
224 else if (seekamount > 0)
225 DoFastForwardSecs(seekamount * FFREW_MULTICOUNT, kInaccuracyEditor, false);
226 else
227 DoFastForwardSecs(FFREW_MULTICOUNT / 2, kInaccuracyNone, false);
228 }
229 else if (action == ACTION_SELECT)
230 {
231 m_deleteMap.NewCut(frame);
232 UpdateOSDMessage(tr("New cut added."), kOSDTimeout_Short);
233 refresh = true;
234 }
235 else if (action == "DELETE")
236 {
237 m_deleteMap.Delete(frame, tr("Delete"));
238 refresh = true;
239 }
240 else if (action == "REVERT")
241 {
242 m_deleteMap.LoadMap(tr("Undo Changes"));
243 refresh = true;
244 }
245 else if (action == "REVERTEXIT")
246 {
247 DisableEdit(0);
248 refresh = false;
249 }
250 else if (action == ACTION_SAVEMAP)
251 {
253 refresh = true;
254 }
255 else if (action == "EDIT" || action == "SAVEEXIT")
256 {
257 DisableEdit(1);
258 refresh = false;
259 }
260 else
261 {
262 QString undoMessage = m_deleteMap.GetUndoMessage();
263 QString redoMessage = m_deleteMap.GetRedoMessage();
264 handled = m_deleteMap.HandleAction(action, frame);
265 if (handled && (action == "CUTTOBEGINNING" || action == "CUTTOEND" || action == "NEWCUT"))
266 UpdateOSDMessage(tr("New cut added."), kOSDTimeout_Short);
267 else if (handled && action == "UNDO")
268 UpdateOSDMessage(tr("Undo - %1").arg(undoMessage), kOSDTimeout_Short);
269 else if (handled && action == "REDO")
270 UpdateOSDMessage(tr("Redo - %1").arg(redoMessage), kOSDTimeout_Short);
271 }
272 }
273
274 if (handled && refresh)
275 {
276 m_osdLock.lock();
278 m_osdLock.unlock();
279 }
280
281 return handled;
282}
283
284bool MythPlayerEditorUI::DoFastForwardSecs(float Seconds, double Inaccuracy, bool UseCutlist)
285{
286 float current = ComputeSecs(m_framesPlayed, UseCutlist);
287 uint64_t targetFrame = FindFrame(current + Seconds, UseCutlist);
288 return DoFastForward(targetFrame - m_framesPlayed, Inaccuracy);
289}
290
291bool MythPlayerEditorUI::DoRewindSecs(float Seconds, double Inaccuracy, bool UseCutlist)
292{
293 float target = std::max(0.0F, ComputeSecs(m_framesPlayed, UseCutlist) - Seconds);
294 uint64_t targetFrame = FindFrame(target, UseCutlist);
295 return DoRewind(m_framesPlayed - targetFrame, Inaccuracy);
296}
bool HasMap(void) const
Definition: commbreakmap.h:25
void GetMap(frm_dir_map_t &map) const
bool HasTemporaryMark(void) const
Returns true if a temporary placeholder mark is defined.
Definition: deletemap.cpp:647
void UpdateOSD(uint64_t frame, double frame_rate, OSD *osd)
Show and update the edit mode On Screen Display.
Definition: deletemap.cpp:177
bool IsTemporaryMark(uint64_t frame) const
Returns true if the given frame is a temporary/placeholder mark.
Definition: deletemap.cpp:600
void NewCut(uint64_t frame)
Add a new cut marker (to start or end a cut region)
Definition: deletemap.cpp:397
float GetSeekAmount(void) const
Definition: deletemap.h:34
void TrackerReset(uint64_t frame)
Resets the internal state tracker.
Definition: deletemap.cpp:811
bool HandleAction(const QString &action, uint64_t frame)
Definition: deletemap.cpp:87
void SetFileEditing(bool edit)
Update the editing status in the file's ProgramInfo.
Definition: deletemap.cpp:234
void SaveMap(bool isAutoSave=false)
Saves the delete map to the database.
Definition: deletemap.cpp:778
void UpdateSeekAmount(int change)
Definition: deletemap.cpp:140
uint64_t GetNearestMark(uint64_t frame, bool right, bool *hasMark=nullptr) const
Returns the next or previous mark.
Definition: deletemap.cpp:615
bool LoadAutoSaveMap(void)
Returns true if an auto-save map was loaded.
Definition: deletemap.cpp:758
void LoadCommBreakMap(frm_dir_map_t &map)
Loads the given commercial break map into the deleteMap.
Definition: deletemap.cpp:731
QString GetRedoMessage(void) const
Definition: deletemap.cpp:81
bool IsInDelete(uint64_t frame) const
Returns true if the given frame is deemed to be within a region that should be cut.
Definition: deletemap.cpp:575
QString GetUndoMessage(void) const
Definition: deletemap.cpp:75
bool IsSaved(void) const
Compares the current cut list with the saved cut list.
Definition: deletemap.cpp:879
void Delete(uint64_t frame, const QString &undoMessage)
Remove the mark at the given frame.
Definition: deletemap.cpp:364
void SetSeekAmount(float amount)
Definition: deletemap.h:36
bool HasUndo(void) const
Definition: deletemap.h:87
void LoadMap(const QString &undoMessage="")
Loads the delete map from the database.
Definition: deletemap.cpp:742
bool IsFileEditing(void)
Determines whether the file is currently in edit mode.
Definition: deletemap.cpp:246
void SetEditing(bool edit, OSD *osd=nullptr)
Set the edit mode and optionally hide the edit mode OSD.
Definition: deletemap.cpp:226
bool HasRedo(void) const
Definition: deletemap.h:88
void SetupAudioGraph(double VideoFrameRate)
void RefreshEditorState(bool CheckSaved=false)
MythPlayerEditorUI(MythMainWindow *MainWindow, TV *Tv, PlayerContext *Context, PlayerFlags Flags)
bool HandleProgramEditorActions(const QStringList &Actions)
bool DoFastForwardSecs(float Seconds, double Inaccuracy, bool UseCutlist)
void EditorStateChanged(const MythEditorState &EditorState)
void HandleArbSeek(bool Direction)
void InitialiseState() override
QElapsedTimer m_editUpdateTimer
bool DoRewindSecs(float Seconds, double Inaccuracy, bool UseCutlist)
void DisableEdit(int HowToSave)
Leave cutlist edit mode, saving work in 1 of 3 ways.
void UpdateOSDMessage(const QString &Message)
void SetOSDStatus(const QString &Title, OSDTimeout Timeout)
QRecursiveMutex m_osdLock
void InitialiseState() override
Set initial state and update player.
uint64_t FindFrame(float offset, bool use_cutlist) const
static const double kInaccuracyFull
Definition: mythplayer.h:242
uint64_t GetTotalFrameCount(void) const
Definition: mythplayer.h:142
DeleteMap m_deleteMap
Definition: mythplayer.h:478
std::chrono::milliseconds m_savedAudioTimecodeOffset
Definition: mythplayer.h:497
static const double kInaccuracyNone
Definition: mythplayer.h:239
static const double kInaccuracyEditor
Definition: mythplayer.h:241
uint64_t m_framesPlayed
Definition: mythplayer.h:424
CommBreakMap m_commBreakMap
Definition: mythplayer.h:475
uint64_t GetFramesPlayed(void) const
Definition: mythplayer.h:144
float m_playSpeed
Definition: mythplayer.h:484
tctype_arr m_tcWrap
Definition: mythplayer.h:496
bool Pause(void)
Definition: mythplayer.cpp:153
float ComputeSecs(uint64_t position, bool use_cutlist) const
Definition: mythplayer.h:272
double m_videoFrameRate
Video (input) Frame Rate (often inaccurate)
Definition: mythplayer.h:435
bool Play(float speed=1.0, bool normal=true, bool unpauseaudio=true)
Definition: mythplayer.cpp:186
bool m_hasFullPositionMap
Definition: mythplayer.h:406
PlayerContext * m_playerCtx
Definition: mythplayer.h:366
bool DoRewind(uint64_t frames, double inaccuracy)
bool DoFastForward(uint64_t frames, double inaccuracy)
void HideAll(bool KeepSubs=true, MythScreenType *Except=nullptr, bool DropNotification=false)
Definition: osd.cpp:95
void DialogQuit()
Definition: osd.cpp:720
void LockPlayingInfo(const char *file, int line) const
void UnlockPlayingInfo(const char *file, int line) const
ProgramInfo * m_playingInfo
Currently playing info.
void SaveEditing(bool edit)
Sets "editing" field in "recorded" table to "edit".
void DisableEdit(int HowToSave)
void RefreshEditorState(bool CheckSaved=false)
void EditorStateChanged(const MythEditorState &EditorState)
Control TV playback.
Definition: tv_play.h:156
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PlayerFlags
Definition: mythplayer.h:65
@ TC_AUDIO
Definition: mythplayer.h:57
#define LOC
static constexpr const char * ACTION_LEFT
Definition: mythuiactions.h:18
static constexpr const char * ACTION_RIGHT
Definition: mythuiactions.h:19
static constexpr const char * ACTION_SELECT
Definition: mythuiactions.h:15
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
@ kOSDTimeout_Short
Definition: osd.h:59
@ kOSDTimeout_None
Definition: osd.h:58
@ kOSDTimeout_Med
Definition: osd.h:60
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:117
#define ACTION_PREVCUT
Definition: tv_actions.h:91
#define ACTION_BIGJUMPREW
Definition: tv_actions.h:92
#define ACTION_LOADCOMMSKIP
Definition: tv_actions.h:89
#define ACTION_SAVEMAP
Definition: tv_actions.h:88
#define ACTION_BIGJUMPFWD
Definition: tv_actions.h:93
#define ACTION_NEXTCUT
Definition: tv_actions.h:90