MythTV master
deletemap.cpp
Go to the documentation of this file.
1
2#include "deletemap.h"
3
4#include <algorithm>
5#include <cstdint>
6
7#include "libmythbase/mythcorecontext.h" // for MythCoreContext, etc
10#include "libmythbase/mythtypes.h" // for InfoMap
11#include "libmythui/mythuiactions.h" // for ACTION_DOWN, ACTION_UP
12#include "mythplayer.h"
13#include "osd.h"
14#include "playercontext.h" // for PlayerContext
15#include "programinfo.h"
16#include "tv_actions.h" // for ACTION_CLEARMAP, etc
17
18#define LOC QString("DelMap: ")
19#define EDIT_CHECK do { \
20 if(!m_editing) { \
21 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot edit outside edit mode."); \
22 return; \
23 } \
24} while(false)
25
26void DeleteMap::Push(const QString &undoMessage)
27{
28 DeleteMapUndoEntry entry(m_deleteMap, undoMessage);
29 // Remove all "redo" entries
30 while (m_undoStack.size() > m_undoStackPointer)
31 m_undoStack.pop_back();
32 m_undoStack.append(entry);
34 SaveMap(true);
35}
36
38 const QString &undoMessage)
39{
40 // Temporarily roll back to the initial state, push the undo
41 // entry, then restore the correct state.
43 m_deleteMap = savedMap;
44 Push(undoMessage);
45 m_deleteMap = tmp;
46 SaveMap(true);
47}
48
50{
51 if (!HasUndo())
52 return false;
56 m_undoStack[m_undoStackPointer].m_deleteMap = tmp;
57 m_changed = true;
58 SaveMap(true);
59 return true;
60}
61
63{
64 if (!HasRedo())
65 return false;
68 m_undoStack[m_undoStackPointer].m_deleteMap = tmp;
70 m_changed = true;
71 SaveMap(true);
72 return true;
73}
74
75QString DeleteMap::GetUndoMessage(void) const
76{
77 return (HasUndo() ? m_undoStack[m_undoStackPointer - 1].m_message :
78 tr("(Nothing to undo)"));
79}
80
81QString DeleteMap::GetRedoMessage(void) const
82{
83 return (HasRedo() ? m_undoStack[m_undoStackPointer].m_message :
84 tr("(Nothing to redo)"));
85}
86
87bool DeleteMap::HandleAction(const QString &action, uint64_t frame)
88{
89 bool handled = true;
90 if (action == ACTION_UP)
91 {
93 }
94 else if (action == ACTION_DOWN)
95 {
97 }
98 else if (action == ACTION_CLEARMAP)
99 {
100 Clear(tr("Clear Cuts"));
101 }
102 else if (action == ACTION_INVERTMAP)
103 {
104 ReverseAll();
105 }
106 else if (action == "MOVEPREV")
107 {
108 MoveRelative(frame, false);
109 }
110 else if (action == "MOVENEXT")
111 {
112 MoveRelative(frame, true);
113 }
114 else if (action == "CUTTOBEGINNING")
115 {
116 Push(tr("Cut to Beginning"));
117 AddMark(frame, MARK_CUT_END);
118 }
119 else if (action == "CUTTOEND")
120 {
121 Push(tr("Cut to End"));
122 AddMark(frame, MARK_CUT_START);
123 // If the recording is still in progress, add an explicit end
124 // mark at the end.
127 }
128 else if (action == "NEWCUT")
129 {
130 NewCut(frame);
131 }
132 else if (action == "DELETE")
133 {
134 //: Delete the current cut or preserved region
135 Delete(frame, tr("Delete"));
136 }
137 else if (action == "UNDO")
138 {
139 Undo();
140 }
141 else if (action == "REDO")
142 {
143 Redo();
144 }
145 else
146 {
147 handled = false;
148 }
149 return handled;
150}
151
153{
154 m_seekamountpos += change;
156
157 m_seekText = "";
158 switch (m_seekamountpos)
159 {
160 case 0: m_seekText = tr("cut point"); m_seekamount = -2; break;
161 case 1: m_seekText = tr("keyframe"); m_seekamount = -1; break;
162 case 2: m_seekText = tr("1 frame"); m_seekamount = 0; break;
163 case 3: m_seekText = tr("0.5 seconds"); m_seekamount = 0.5; break;
164 case 4: m_seekText = tr("%n second(s)", "", 1); m_seekamount = 1; break;
165 case 5: m_seekText = tr("%n second(s)", "", 5); m_seekamount = 5; break;
166 case 6: m_seekText = tr("%n second(s)", "", 20); m_seekamount = 20; break;
167 case 7: m_seekText = tr("%n minute(s)", "", 1); m_seekamount = 60; break;
168 case 8: m_seekText = tr("%n minute(s)", "", 5); m_seekamount = 300; break;
169 case 9: m_seekText = tr("%n minute(s)", "", 10); m_seekamount = 600; break;
170 default: m_seekText = tr("error"); m_seekamount = 1; break;
171 }
172}
173
174QString DeleteMap::CreateTimeString(uint64_t frame, bool use_cutlist,
175 double frame_rate, bool full_resolution)
176 const
177{
178 std::chrono::milliseconds ms = TranslatePositionFrameToMs(frame, frame_rate, use_cutlist);
179 QString fmt = (ms >= 1h) ? "H:mm:ss" : "mm:ss";
180 if (full_resolution)
181 fmt += ".zzz";
182 return MythDate::formatTime(ms, fmt);
183}
184
189void DeleteMap::UpdateOSD(uint64_t frame, double frame_rate, OSD *osd)
190{
191 if (!osd || !m_ctx)
192 return;
193 CleanMap();
194
195 InfoMap infoMap;
196 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
197 if (m_ctx->m_playingInfo)
198 m_ctx->m_playingInfo->ToMap(infoMap);
199 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
200
201 QString cutmarker = " ";
202 if (IsInDelete(frame))
203 cutmarker = tr("cut");
204
205 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
206 QString timestr = CreateTimeString(frame, false, frame_rate, true);
207 QString relTimeDisplay;
208 relTimeDisplay = CreateTimeString(frame, true, frame_rate, false);
209 QString relLengthDisplay;
210 relLengthDisplay = CreateTimeString(total, true, frame_rate, false);
211 infoMap["timedisplay"] = timestr;
212 infoMap["framedisplay"] = QString::number(frame);
213 infoMap["cutindicator"] = cutmarker;
214 infoMap["title"] = tr("Edit");
215 infoMap["seekamount"] = m_seekText;;
216 infoMap["reltimedisplay"] = relTimeDisplay;
217 infoMap["rellengthdisplay"] = relLengthDisplay;
218 //: example: "13:24 (10:23 of 24:37)"
219 infoMap["fulltimedisplay"] = tr("%3 (%1 of %2)")
220 .arg(relTimeDisplay, relLengthDisplay, timestr);
221
222 QHash<QString,float> posMap;
223 posMap.insert("position", (float)((double)frame/(double)total));
226 if (m_changed || total != m_cachedTotalForOSD)
228 m_changed = false;
229 m_cachedTotalForOSD = total;
230}
231
232void DeleteMap::UpdateOSD(std::chrono::milliseconds timecode, OSD *osd)
233{
234 osd->SetGraph(OSD_WIN_PROGEDIT, "audiograph", timecode);
235}
236
238void DeleteMap::SetEditing(bool edit, OSD *osd)
239{
240 if (osd && !edit)
242 m_editing = edit;
243}
244
247{
248 if (m_ctx)
249 {
250 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
251 if (m_ctx->m_playingInfo)
253 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
254 }
255}
256
259{
260 bool result = false;
261 if (m_ctx)
262 {
263 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
264 if (m_ctx->m_playingInfo)
266 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
267 }
268 return result;
269}
270
271bool DeleteMap::IsEmpty(void) const
272{
273 return m_deleteMap.empty();
274}
275
277void DeleteMap::Clear(const QString& undoMessage)
278{
279 if (!undoMessage.isEmpty())
280 Push(undoMessage);
281 m_deleteMap.clear();
282 m_changed = true;
283}
284
287{
289 Push(tr("Reverse Cuts"));
290 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
291 Add(it.key(), it.value() == MARK_CUT_END ? MARK_CUT_START :
293 CleanMap();
294}
295
301void DeleteMap::AddMark(uint64_t frame, MarkTypes type)
302{
304 if ((MARK_CUT_START != type) && (MARK_CUT_END != type) &&
306 return;
307
308 frm_dir_map_t::Iterator find_temporary = m_deleteMap.find(frame);
309 if (find_temporary != m_deleteMap.end())
310 {
311 if (MARK_PLACEHOLDER == find_temporary.value())
312 {
313 // Delete the temporary mark before putting a real mark at its
314 // location
315 Delete(frame, "");
316 }
317 else
318 {
319 // Don't add a mark on top of a mark
320 return;
321 }
322 }
323
324 int lasttype = MARK_UNSET;
325 long long lastframe = -1;
326 long long remove = -1;
327
328 if (type == MARK_CUT_END)
329 {
330 // remove curent end marker if it exists
331 for (auto it = m_deleteMap.cbegin(); it != m_deleteMap.cend(); ++it)
332 {
333 if (it.key() > frame)
334 {
335 if ((lasttype == MARK_CUT_END) && (lastframe > -1))
336 remove = lastframe;
337 break;
338 }
339 lasttype = it.value();
340 lastframe = it.key();
341 }
342 if ((remove < 0) && (lasttype == MARK_CUT_END) &&
343 (lastframe > -1) && (lastframe < (int64_t)frame))
344 remove = lastframe;
345 }
346 else if ((type == MARK_CUT_START) && !m_deleteMap.empty())
347 {
348 // remove curent start marker if it exists
349 for (auto it = m_deleteMap.cend(); it != m_deleteMap.cbegin(); )
350 {
351 --it;
352 if (it.key() <= frame)
353 {
354 if (lasttype == MARK_CUT_START && (lastframe > -1))
355 remove = lastframe;
356 break;
357 }
358 lasttype = it.value();
359 lastframe = it.key();
360 }
361 if ((remove < 0) && (lasttype == MARK_CUT_START) &&
362 (lastframe > -1) && (lastframe > (int64_t)frame))
363 remove = lastframe;
364 }
365
366 if (remove > -1)
367 Delete((uint64_t)remove);
368 Add(frame, type);
369 CleanMap();
370}
371
373void DeleteMap::Delete(uint64_t frame, const QString& undoMessage)
374{
376 if (m_deleteMap.isEmpty())
377 return;
378
379 if (!undoMessage.isEmpty())
380 Push(undoMessage);
381
382 uint64_t prev = GetNearestMark(frame, false);
383 uint64_t next = GetNearestMark(frame, true);
384
385 // If frame is a cut point, GetNearestMark() would return the previous/next
386 // mark (not this frame), so check to see if we need to use frame, instead
387 frm_dir_map_t::Iterator it = m_deleteMap.find(frame);
388 if (it != m_deleteMap.end())
389 {
390 int type = it.value();
391 if (MARK_PLACEHOLDER == type)
392 next = prev = frame;
393 else if (MARK_CUT_END == type)
394 next = frame;
395 else if (MARK_CUT_START == type)
396 prev = frame;
397 }
398
399 Delete(prev);
400 if (prev != next)
401 Delete(next);
402 CleanMap();
403}
404
406void DeleteMap::NewCut(uint64_t frame)
407{
409
410 // Defer pushing the undo entry until the end, when we're sure a
411 // change has been made.
412 frm_dir_map_t initialDeleteMap = m_deleteMap;
413
414 // find any existing temporary marker to determine cut range
415 int64_t existing = -1;
416 for (auto it = m_deleteMap.begin() ; it != m_deleteMap.end(); ++it)
417 {
418 if (MARK_PLACEHOLDER == it.value())
419 {
420 existing = it.key();
421 break;
422 }
423 }
424
425 if (existing > -1)
426 {
427 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
428 auto otherframe = static_cast<uint64_t>(existing);
429 if (otherframe == frame)
430 {
431 Delete(otherframe);
432 }
433 else
434 {
435 uint64_t startframe = 0;
436 uint64_t endframe = 0;
437 int64_t cut_start = -1;
438 int64_t cut_end = -1;
439 if (IsInDelete(frame))
440 {
442 cut_start = GetNearestMark(frame, false);
443 cut_end = GetNearestMark(frame, true);
444 frm_dir_map_t::Iterator it2 = m_deleteMap.find(frame);
445 if (it2 != m_deleteMap.end())
446 type = it2.value();
447 if (MARK_CUT_START == type)
448 {
449 cut_start = frame;
450 }
451 else if (MARK_CUT_END == type)
452 {
453 cut_end = frame;
454 }
455 }
456
457 if (otherframe < frame)
458 {
459 startframe = otherframe;
460 endframe = cut_end != -1 ? static_cast<uint64_t>(cut_end)
461 : frame;
462 }
463 else
464 {
465 startframe = cut_start != -1 ? static_cast<uint64_t>(cut_start)
466 : frame;
467 endframe = otherframe;
468 }
469
470 // Don't place a cut marker on first or last frame; instead cut
471 // to beginning or end
472 if (startframe == 1)
473 startframe = 0;
474 if (endframe >= total - 1)
475 endframe = total;
476
477 // Don't cut the entire recording
478 if ((startframe == 0) && (endframe == total))
479 {
480 LOG(VB_GENERAL, LOG_CRIT, LOC +
481 "Refusing to cut entire recording.");
482 return;
483 }
484
485 Delete(otherframe);
486 Add(startframe, MARK_CUT_START);
487 Add(endframe, MARK_CUT_END);
488 // Clear out any markers between the start and end frames
489 otherframe = 0;
490 frm_dir_map_t::Iterator it = m_deleteMap.find(startframe);
491 for ( ; it != m_deleteMap.end() && otherframe < endframe; ++it)
492 {
493 otherframe = it.key();
494 if ((startframe < otherframe) && (endframe > otherframe))
495 {
496 LOG(VB_PLAYBACK, LOG_INFO, LOC +
497 QString("Deleting bounded marker: %1").arg(otherframe));
498 it = m_deleteMap.erase(it);
499 m_changed = true;
500 }
501 }
502 }
503 }
504 else
505 {
506 Add(frame, MARK_PLACEHOLDER);
507 }
508
509 CleanMap();
510 PushDeferred(initialDeleteMap, tr("New Cut"));
511}
512
514void DeleteMap::MoveRelative(uint64_t frame, bool right)
515{
516 frm_dir_map_t::Iterator it = m_deleteMap.find(frame);
517 if (it != m_deleteMap.end())
518 {
519 int type = it.value();
520 if (((MARK_CUT_START == type) && !right) ||
521 ((MARK_CUT_END == type) && right))
522 {
523 // If on a mark, don't move a mark from a different cut region;
524 // instead, "move" this mark onto itself
525 return;
526 }
527 if (((MARK_CUT_START == type) && right) ||
528 ((MARK_CUT_END == type) && !right))
529 {
530 // If on a mark, don't collapse a cut region to 0;
531 // instead, delete the region
532 //: Delete the current cut or preserved region
533 Delete(frame, tr("Delete"));
534 return;
535 }
536 if (MARK_PLACEHOLDER == type)
537 {
538 // Delete the temporary mark before putting a real mark at its
539 // location
540 Delete(frame, "");
541 }
542 }
543
544 uint64_t from = GetNearestMark(frame, right);
545 Move(from, frame);
546}
547
549void DeleteMap::Move(uint64_t frame, uint64_t to)
550{
552 Push(tr("Move Mark"));
553 MarkTypes type = Delete(frame);
554 if (MARK_UNSET == type)
555 {
556 if (frame == 0)
558 else if (frame == m_ctx->m_player->GetTotalFrameCount())
560 }
561 AddMark(to, type);
562}
563
565void DeleteMap::Add(uint64_t frame, MarkTypes type)
566{
567 m_deleteMap[frame] = type;
568 m_changed = true;
569}
570
573{
574 if (m_deleteMap.contains(frame))
575 {
576 m_changed = true;
577 return m_deleteMap.take(frame);
578 }
579 return MARK_UNSET;
580}
581
586bool DeleteMap::IsInDelete(uint64_t frame) const
587{
588 if (m_deleteMap.isEmpty())
589 return false;
590
591 frm_dir_map_t::const_iterator it = m_deleteMap.find(frame);
592 if (it != m_deleteMap.end())
593 return true;
594
595 int lasttype = MARK_UNSET;
596 uint64_t lastframe = UINT64_MAX;
597 for (it = m_deleteMap.begin() ; it != m_deleteMap.end(); ++it)
598 {
599 if (it.key() > frame)
600 return MARK_CUT_END == it.value();
601 lasttype = it.value();
602 lastframe = it.key();
603 }
604
605 return lasttype == MARK_CUT_START && lastframe <= frame;
606}
607
611bool DeleteMap::IsTemporaryMark(uint64_t frame) const
612{
613 if (m_deleteMap.isEmpty())
614 return false;
615
616 frm_dir_map_t::const_iterator it = m_deleteMap.find(frame);
617 return (it != m_deleteMap.end()) && (MARK_PLACEHOLDER == it.value());
618}
619
626uint64_t DeleteMap::GetNearestMark(uint64_t frame, bool right, bool *hasMark)
627 const
628{
629 uint64_t result = 0;
630 if (hasMark)
631 *hasMark = true;
632 frm_dir_map_t::const_iterator it = m_deleteMap.begin();
633 if (right)
634 {
635 result = m_ctx->m_player->GetTotalFrameCount();
636 for (; it != m_deleteMap.end(); ++it)
637 if (it.key() > frame)
638 return it.key();
639 if (hasMark)
640 *hasMark = false;
641 }
642 else
643 {
644 result = 0;
645 for (; it != m_deleteMap.end(); ++it)
646 {
647 if (it.key() >= frame)
648 return result;
649 result = it.key();
650 }
651 }
652 return result;
653}
654
659{
660 if (!m_deleteMap.isEmpty())
661 {
662 for (auto it = m_deleteMap.cbegin(); it != m_deleteMap.cend(); ++it)
663 if (MARK_PLACEHOLDER == it.value())
664 return true;
665 }
666
667 return false;
668}
669
676{
677 if (IsEmpty())
678 return;
679
680 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
681 Delete(0);
682 Delete(total);
683
684 bool clear = false;
685 while (!IsEmpty() && !clear)
686 {
687 clear = true;
688 int lasttype = MARK_UNSET;
689 int64_t lastframe = -1;
690 int64_t tempframe = -1;
691 QList<int64_t> deleteList;
692 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
693 {
694 int thistype = it.value();
695 uint64_t thisframe = it.key();
696 if (thisframe >= total)
697 {
698 deleteList.append(thisframe);
699 }
700 else if (lasttype == thistype)
701 {
702 deleteList.append(thistype == MARK_CUT_END ? thisframe :
703 (uint64_t)lastframe);
704 clear = false;
705 break;
706 }
707 if (MARK_PLACEHOLDER == thistype)
708 {
709 if (tempframe > 0)
710 deleteList.append(tempframe);
711 tempframe = thisframe;
712 }
713 else
714 {
715 lasttype = thistype;
716 lastframe = thisframe;
717 }
718 }
719
720 // Delete the unwanted frame marks safely, and not while iterating over
721 // the map which would lead to a crash
722 for (const int64_t & dit : std::as_const(deleteList))
723 {
724 Delete(dit);
725 }
726 deleteList.clear();
727 }
728}
729
732{
733 // Can't save an undo point for SetMap() or transcodes fail.
734 // Leaving as a marker for refactor.
735 //Push(tr("Set New Cut List"));
736
737 Clear();
738 m_deleteMap = map;
739}
740
743{
744 Push(tr("Load Detected Commercials"));
745 Clear();
746 for (auto it = map.begin(); it != map.end(); ++it)
747 Add(it.key(), it.value() == MARK_COMM_START ?
749 CleanMap();
750}
751
753void DeleteMap::LoadMap(const QString& undoMessage)
754{
756 return;
757
758 if (!undoMessage.isEmpty())
759 Push(undoMessage);
760 Clear();
761 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
763 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
764 CleanMap();
765}
766
770{
772 return false;
773
774 frm_dir_map_t tmpDeleteMap = m_deleteMap;
775 Clear();
776 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
777 bool result = m_ctx->m_playingInfo->QueryCutList(m_deleteMap, true);
778 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
779 CleanMap();
780 if (result)
781 PushDeferred(tmpDeleteMap, tr("Load Auto-saved Cuts"));
782 else
783 m_deleteMap = tmpDeleteMap;
784
785 return result;
786}
787
789void DeleteMap::SaveMap(bool isAutoSave)
790{
792 return;
793
794 if (!isAutoSave)
795 {
796 // Remove temporary placeholder marks
797 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); /*no inc*/)
798 {
799 if (MARK_PLACEHOLDER == it.value())
800 {
801 it = m_deleteMap.erase(it);
802 m_changed = true;
803 }
804 else
805 {
806 ++it;
807 }
808 }
809
810 CleanMap();
811 }
812 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
815 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
816}
817
824void DeleteMap::TrackerReset(uint64_t frame)
825{
826 m_nextCutStart = 0;
827 m_nextCutStartIsValid = false;
828 if (IsEmpty())
829 return;
830
831 frm_dir_map_t::iterator cutpoint = m_deleteMap.find(frame);
832 if (cutpoint != m_deleteMap.end())
833 {
834 if (cutpoint.value() == MARK_CUT_START)
835 {
837 m_nextCutStart = cutpoint.key();
838 }
839 else
840 {
841 ++cutpoint;
842 m_nextCutStartIsValid = (cutpoint != m_deleteMap.end());
843 m_nextCutStart = m_nextCutStartIsValid ? cutpoint.key() :
845 }
846 }
847 else
848 {
851 }
852 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Tracker next CUT_START: %1")
853 .arg(m_nextCutStart));
854}
855
860bool DeleteMap::TrackerWantsToJump(uint64_t frame, uint64_t &to) const
861{
862 if (IsEmpty() || !m_nextCutStartIsValid || frame < m_nextCutStart)
863 return false;
864
865 to = GetNearestMark(m_nextCutStart, true);
866 LOG(VB_PLAYBACK, LOG_INFO, LOC +
867 QString("Tracker wants to jump to: %1").arg(to));
868 return true;
869}
870
875uint64_t DeleteMap::GetLastFrame(void) const
876{
877 uint64_t result = m_ctx->m_player->GetCurrentFrameCount();
878 if (IsEmpty())
879 return result;
880
881 frm_dir_map_t::const_iterator it = m_deleteMap.end();
882 --it;
883
884 if (it.value() == MARK_CUT_START)
885 result = it.key();
886 return result;
887}
888
892bool DeleteMap::IsSaved(void) const
893{
895 return true;
896
897 frm_dir_map_t currentMap(m_deleteMap);
898 frm_dir_map_t savedMap;
899 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
900 m_ctx->m_playingInfo->QueryCutList(savedMap);
901 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
902
903 // Remove temporary placeholder marks from currentMap
904 for (auto it = currentMap.begin(); it != currentMap.end(); /* no inc */)
905 {
906 if (MARK_PLACEHOLDER == it.value())
907 it = currentMap.erase(it);
908 else
909 ++it;
910 }
911
912 return currentMap == savedMap;
913}
914
915std::chrono::milliseconds DeleteMap::TranslatePositionFrameToMs(uint64_t position,
916 float fallback_framerate,
917 bool use_cutlist) const
918{
919 return m_ctx->m_player->GetDecoder()
920 ->TranslatePositionFrameToMs(position, fallback_framerate,
921 use_cutlist ? m_deleteMap :
922 frm_dir_map_t());
923}
924uint64_t DeleteMap::TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms,
925 float fallback_framerate,
926 bool use_cutlist) const
927{
928 return m_ctx->m_player->GetDecoder()
929 ->TranslatePositionMsToFrame(dur_ms, fallback_framerate,
930 use_cutlist ? m_deleteMap :
931 frm_dir_map_t());
932}
933
934uint64_t DeleteMap::TranslatePositionAbsToRel(uint64_t position) const
935{
937}
938
939uint64_t DeleteMap::TranslatePositionRelToAbs(uint64_t position) const
940{
942}
static uint64_t TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap, uint64_t absPosition, const frm_pos_map_t &map=frm_pos_map_t(), float fallback_ratio=1.0)
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms, float fallback_framerate, const frm_dir_map_t &cutlist)
static uint64_t TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap, uint64_t relPosition, const frm_pos_map_t &map=frm_pos_map_t(), float fallback_ratio=1.0)
std::chrono::milliseconds TranslatePositionFrameToMs(long long position, float fallback_framerate, const frm_dir_map_t &cutlist)
bool m_changed
Definition: deletemap.h:110
bool HasTemporaryMark(void) const
Returns true if a temporary placeholder mark is defined.
Definition: deletemap.cpp:658
QString CreateTimeString(uint64_t frame, bool use_cutlist, double frame_rate, bool full_resolution) const
Definition: deletemap.cpp:174
void UpdateOSD(uint64_t frame, double frame_rate, OSD *osd)
Show and update the edit mode On Screen Display.
Definition: deletemap.cpp:189
bool IsTemporaryMark(uint64_t frame) const
Returns true if the given frame is a temporary/placeholder mark.
Definition: deletemap.cpp:611
void NewCut(uint64_t frame)
Add a new cut marker (to start or end a cut region)
Definition: deletemap.cpp:406
void SetMap(const frm_dir_map_t &map)
Use the given map.
Definition: deletemap.cpp:731
void CleanMap(void)
Removes redundant marks and ensures the markup sequence is valid.
Definition: deletemap.cpp:675
float m_seekamount
Definition: deletemap.h:112
bool Redo(void)
Definition: deletemap.cpp:62
void TrackerReset(uint64_t frame)
Resets the internal state tracker.
Definition: deletemap.cpp:824
QString m_seekText
Definition: deletemap.h:109
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:246
frm_dir_map_t m_deleteMap
Definition: deletemap.h:108
bool m_editing
Definition: deletemap.h:105
void SaveMap(bool isAutoSave=false)
Saves the delete map to the database.
Definition: deletemap.cpp:789
int m_seekamountpos
Definition: deletemap.h:111
void UpdateSeekAmount(int change)
Definition: deletemap.cpp:152
void Add(uint64_t frame, MarkTypes type)
Private addition to the deleteMap.
Definition: deletemap.cpp:565
uint64_t GetLastFrame(void) const
Returns the number of the last frame in the video that is not in a cut sequence.
Definition: deletemap.cpp:875
bool TrackerWantsToJump(uint64_t frame, uint64_t &to) const
Returns true if the given frame has passed the last cut point start and provides the frame number of ...
Definition: deletemap.cpp:860
void AddMark(uint64_t frame, MarkTypes type)
Add a new mark of the given type.
Definition: deletemap.cpp:301
uint64_t GetNearestMark(uint64_t frame, bool right, bool *hasMark=nullptr) const
Returns the next or previous mark.
Definition: deletemap.cpp:626
bool LoadAutoSaveMap(void)
Returns true if an auto-save map was loaded.
Definition: deletemap.cpp:769
void MoveRelative(uint64_t frame, bool right)
Move the previous (!right) or next (right) cut to frame.
Definition: deletemap.cpp:514
QVector< DeleteMapUndoEntry > m_undoStack
Definition: deletemap.h:116
void Push(const QString &undoMessage)
Definition: deletemap.cpp:26
uint64_t m_cachedTotalForOSD
Definition: deletemap.h:114
void Move(uint64_t frame, uint64_t to)
Move an existing mark to a new frame.
Definition: deletemap.cpp:549
void LoadCommBreakMap(frm_dir_map_t &map)
Loads the given commercial break map into the deleteMap.
Definition: deletemap.cpp:742
QString GetRedoMessage(void) const
Definition: deletemap.cpp:81
bool Undo(void)
Definition: deletemap.cpp:49
void PushDeferred(const frm_dir_map_t &savedMap, const QString &undoMessage)
Definition: deletemap.cpp:37
uint64_t m_nextCutStart
Definition: deletemap.h:107
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:586
std::chrono::milliseconds TranslatePositionFrameToMs(uint64_t position, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:915
uint64_t TranslatePositionRelToAbs(uint64_t position) const
Definition: deletemap.cpp:939
bool m_nextCutStartIsValid
Definition: deletemap.h:106
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:892
int m_undoStackPointer
Definition: deletemap.h:117
void Delete(uint64_t frame, const QString &undoMessage)
Remove the mark at the given frame.
Definition: deletemap.cpp:373
bool IsEmpty(void) const
Definition: deletemap.cpp:271
bool HasUndo(void) const
Definition: deletemap.h:87
void LoadMap(const QString &undoMessage="")
Loads the delete map from the database.
Definition: deletemap.cpp:753
bool IsFileEditing(void)
Determines whether the file is currently in edit mode.
Definition: deletemap.cpp:258
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:924
void SetEditing(bool edit, OSD *osd=nullptr)
Set the edit mode and optionally hide the edit mode OSD.
Definition: deletemap.cpp:238
void Clear(const QString &undoMessage="")
Clears the deleteMap.
Definition: deletemap.cpp:277
uint64_t TranslatePositionAbsToRel(uint64_t position) const
Definition: deletemap.cpp:934
PlayerContext * m_ctx
Definition: deletemap.h:113
void ReverseAll(void)
Reverses the direction of each mark in the map.
Definition: deletemap.cpp:286
bool HasRedo(void) const
Definition: deletemap.h:88
bool IsDatabaseIgnored(void) const
/brief Returns true if database is being ignored.
DecoderBase * GetDecoder(void)
Returns the stream decoder currently in use.
Definition: mythplayer.h:183
uint64_t GetTotalFrameCount(void) const
Definition: mythplayer.h:141
uint64_t GetCurrentFrameCount(void) const
bool IsWatchingInprogress(void) const
Definition: mythplayer.cpp:124
Definition: osd.h:94
void SetValues(const QString &Window, const QHash< QString, int > &Map, OSDTimeout Timeout)
Definition: osd.cpp:150
void SetRegions(const QString &Window, frm_dir_map_t &Map, long long Total)
Definition: osd.cpp:375
void HideWindow(const QString &Window) override
Definition: osd.cpp:690
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:208
void SetGraph(const QString &Window, const QString &Graph, std::chrono::milliseconds Timecode)
Definition: osd.cpp:439
MythPlayer * m_player
void LockPlayingInfo(const char *file, int line) const
void UnlockPlayingInfo(const char *file, int line) const
ProgramInfo * m_playingInfo
Currently playing info.
void SetEditing(bool editing)
Definition: programinfo.h:558
bool QueryIsEditing(void) const
Queries "recorded" table for its "editing" field and returns true if it is set to true.
bool QueryCutList(frm_dir_map_t &delMap, bool loadAutosave=false) const
void SaveCutList(frm_dir_map_t &delMap, bool isAutoSave=false) const
void SaveMarkupFlag(MarkTypes type) const
Clears the specified flag, then if sets it.
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10, uint date_format=0) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
#define LOC
Definition: deletemap.cpp:18
#define EDIT_CHECK
Definition: deletemap.cpp:19
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:948
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
static constexpr const char * ACTION_DOWN
Definition: mythuiactions.h:17
static constexpr const char * ACTION_UP
Definition: mythuiactions.h:16
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:242
static constexpr const char * OSD_WIN_PROGEDIT
Definition: osd.h:35
@ kOSDTimeout_None
Definition: osd.h:58
MarkTypes
Definition: programtypes.h:46
@ MARK_CUT_START
Definition: programtypes.h:55
@ MARK_CUT_END
Definition: programtypes.h:54
@ MARK_UNSET
Definition: programtypes.h:49
@ MARK_UPDATED_CUT
Definition: programtypes.h:52
@ MARK_PLACEHOLDER
Definition: programtypes.h:53
@ MARK_COMM_START
Definition: programtypes.h:58
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:117
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:204
#define ACTION_CLEARMAP
Definition: tv_actions.h:86
#define ACTION_INVERTMAP
Definition: tv_actions.h:87