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)
92 else if (action == ACTION_DOWN)
94 else if (action == ACTION_CLEARMAP)
95 Clear(tr("Clear Cuts"));
96 else if (action == ACTION_INVERTMAP)
97 ReverseAll();
98 else if (action == "MOVEPREV")
99 MoveRelative(frame, false);
100 else if (action == "MOVENEXT")
101 MoveRelative(frame, true);
102 else if (action == "CUTTOBEGINNING")
103 {
104 Push(tr("Cut to Beginning"));
105 AddMark(frame, MARK_CUT_END);
106 }
107 else if (action == "CUTTOEND")
108 {
109 Push(tr("Cut to End"));
110 AddMark(frame, MARK_CUT_START);
111 // If the recording is still in progress, add an explicit end
112 // mark at the end.
115 }
116 else if (action == "NEWCUT")
117 {
118 NewCut(frame);
119 }
120 else if (action == "DELETE")
121 {
122 //: Delete the current cut or preserved region
123 Delete(frame, tr("Delete"));
124 }
125 else if (action == "UNDO")
126 {
127 Undo();
128 }
129 else if (action == "REDO")
130 {
131 Redo();
132 }
133 else
134 {
135 handled = false;
136 }
137 return handled;
138}
139
141{
142 m_seekamountpos += change;
144
145 m_seekText = "";
146 switch (m_seekamountpos)
147 {
148 case 0: m_seekText = tr("cut point"); m_seekamount = -2; break;
149 case 1: m_seekText = tr("keyframe"); m_seekamount = -1; break;
150 case 2: m_seekText = tr("1 frame"); m_seekamount = 0; break;
151 case 3: m_seekText = tr("0.5 seconds"); m_seekamount = 0.5; break;
152 case 4: m_seekText = tr("%n second(s)", "", 1); m_seekamount = 1; break;
153 case 5: m_seekText = tr("%n second(s)", "", 5); m_seekamount = 5; break;
154 case 6: m_seekText = tr("%n second(s)", "", 20); m_seekamount = 20; break;
155 case 7: m_seekText = tr("%n minute(s)", "", 1); m_seekamount = 60; break;
156 case 8: m_seekText = tr("%n minute(s)", "", 5); m_seekamount = 300; break;
157 case 9: m_seekText = tr("%n minute(s)", "", 10); m_seekamount = 600; break;
158 default: m_seekText = tr("error"); m_seekamount = 1; break;
159 }
160}
161
162QString DeleteMap::CreateTimeString(uint64_t frame, bool use_cutlist,
163 double frame_rate, bool full_resolution)
164 const
165{
166 std::chrono::milliseconds ms = TranslatePositionFrameToMs(frame, frame_rate, use_cutlist);
167 QString fmt = (ms >= 1h) ? "H:mm:ss" : "mm:ss";
168 if (full_resolution)
169 fmt += ".zzz";
170 return MythDate::formatTime(ms, fmt);
171}
172
177void DeleteMap::UpdateOSD(uint64_t frame, double frame_rate, OSD *osd)
178{
179 if (!osd || !m_ctx)
180 return;
181 CleanMap();
182
183 InfoMap infoMap;
184 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
185 if (m_ctx->m_playingInfo)
186 m_ctx->m_playingInfo->ToMap(infoMap);
187 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
188
189 QString cutmarker = " ";
190 if (IsInDelete(frame))
191 cutmarker = tr("cut");
192
193 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
194 QString timestr = CreateTimeString(frame, false, frame_rate, true);
195 QString relTimeDisplay;
196 relTimeDisplay = CreateTimeString(frame, true, frame_rate, false);
197 QString relLengthDisplay;
198 relLengthDisplay = CreateTimeString(total, true, frame_rate, false);
199 infoMap["timedisplay"] = timestr;
200 infoMap["framedisplay"] = QString::number(frame);
201 infoMap["cutindicator"] = cutmarker;
202 infoMap["title"] = tr("Edit");
203 infoMap["seekamount"] = m_seekText;;
204 infoMap["reltimedisplay"] = relTimeDisplay;
205 infoMap["rellengthdisplay"] = relLengthDisplay;
206 //: example: "13:24 (10:23 of 24:37)"
207 infoMap["fulltimedisplay"] = tr("%3 (%1 of %2)")
208 .arg(relTimeDisplay, relLengthDisplay, timestr);
209
210 QHash<QString,float> posMap;
211 posMap.insert("position", (float)((double)frame/(double)total));
214 if (m_changed || total != m_cachedTotalForOSD)
216 m_changed = false;
217 m_cachedTotalForOSD = total;
218}
219
220void DeleteMap::UpdateOSD(std::chrono::milliseconds timecode, OSD *osd)
221{
222 osd->SetGraph(OSD_WIN_PROGEDIT, "audiograph", timecode);
223}
224
226void DeleteMap::SetEditing(bool edit, OSD *osd)
227{
228 if (osd && !edit)
230 m_editing = edit;
231}
232
235{
236 if (m_ctx)
237 {
238 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
239 if (m_ctx->m_playingInfo)
241 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
242 }
243}
244
247{
248 bool result = false;
249 if (m_ctx)
250 {
251 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
252 if (m_ctx->m_playingInfo)
254 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
255 }
256 return result;
257}
258
259bool DeleteMap::IsEmpty(void) const
260{
261 return m_deleteMap.empty();
262}
263
265void DeleteMap::Clear(const QString& undoMessage)
266{
267 if (!undoMessage.isEmpty())
268 Push(undoMessage);
269 m_deleteMap.clear();
270 m_changed = true;
271}
272
275{
277 Push(tr("Reverse Cuts"));
278 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
279 Add(it.key(), it.value() == MARK_CUT_END ? MARK_CUT_START :
281 CleanMap();
282}
283
289void DeleteMap::AddMark(uint64_t frame, MarkTypes type)
290{
292 if ((MARK_CUT_START != type) && (MARK_CUT_END != type) &&
294 return;
295
296 frm_dir_map_t::Iterator find_temporary = m_deleteMap.find(frame);
297 if (find_temporary != m_deleteMap.end())
298 {
299 if (MARK_PLACEHOLDER == find_temporary.value())
300 {
301 // Delete the temporary mark before putting a real mark at its
302 // location
303 Delete(frame, "");
304 }
305 else
306 {
307 // Don't add a mark on top of a mark
308 return;
309 }
310 }
311
312 int lasttype = MARK_UNSET;
313 long long lastframe = -1;
314 long long remove = -1;
315
316 if (type == MARK_CUT_END)
317 {
318 // remove curent end marker if it exists
319 for (auto it = m_deleteMap.cbegin(); it != m_deleteMap.cend(); ++it)
320 {
321 if (it.key() > frame)
322 {
323 if ((lasttype == MARK_CUT_END) && (lastframe > -1))
324 remove = lastframe;
325 break;
326 }
327 lasttype = it.value();
328 lastframe = it.key();
329 }
330 if ((remove < 0) && (lasttype == MARK_CUT_END) &&
331 (lastframe > -1) && (lastframe < (int64_t)frame))
332 remove = lastframe;
333 }
334 else if ((type == MARK_CUT_START) && !m_deleteMap.empty())
335 {
336 // remove curent start marker if it exists
337 for (auto it = m_deleteMap.cend(); it != m_deleteMap.cbegin(); )
338 {
339 --it;
340 if (it.key() <= frame)
341 {
342 if (lasttype == MARK_CUT_START && (lastframe > -1))
343 remove = lastframe;
344 break;
345 }
346 lasttype = it.value();
347 lastframe = it.key();
348 }
349 if ((remove < 0) && (lasttype == MARK_CUT_START) &&
350 (lastframe > -1) && (lastframe > (int64_t)frame))
351 remove = lastframe;
352 }
353
354 if (remove > -1)
355 Delete((uint64_t)remove);
356 Add(frame, type);
357 CleanMap();
358}
359
361void DeleteMap::Delete(uint64_t frame, const QString& undoMessage)
362{
364 if (m_deleteMap.isEmpty())
365 return;
366
367 if (!undoMessage.isEmpty())
368 Push(undoMessage);
369
370 uint64_t prev = GetNearestMark(frame, false);
371 uint64_t next = GetNearestMark(frame, true);
372
373 // If frame is a cut point, GetNearestMark() would return the previous/next
374 // mark (not this frame), so check to see if we need to use frame, instead
375 frm_dir_map_t::Iterator it = m_deleteMap.find(frame);
376 if (it != m_deleteMap.end())
377 {
378 int type = it.value();
379 if (MARK_PLACEHOLDER == type)
380 next = prev = frame;
381 else if (MARK_CUT_END == type)
382 next = frame;
383 else if (MARK_CUT_START == type)
384 prev = frame;
385 }
386
387 Delete(prev);
388 if (prev != next)
389 Delete(next);
390 CleanMap();
391}
392
394void DeleteMap::NewCut(uint64_t frame)
395{
397
398 // Defer pushing the undo entry until the end, when we're sure a
399 // change has been made.
400 frm_dir_map_t initialDeleteMap = m_deleteMap;
401
402 // find any existing temporary marker to determine cut range
403 int64_t existing = -1;
404 for (auto it = m_deleteMap.begin() ; it != m_deleteMap.end(); ++it)
405 {
406 if (MARK_PLACEHOLDER == it.value())
407 {
408 existing = it.key();
409 break;
410 }
411 }
412
413 if (existing > -1)
414 {
415 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
416 auto otherframe = static_cast<uint64_t>(existing);
417 if (otherframe == frame)
418 Delete(otherframe);
419 else
420 {
421 uint64_t startframe = 0;
422 uint64_t endframe = 0;
423 int64_t cut_start = -1;
424 int64_t cut_end = -1;
425 if (IsInDelete(frame))
426 {
428 cut_start = GetNearestMark(frame, false);
429 cut_end = GetNearestMark(frame, true);
430 frm_dir_map_t::Iterator it2 = m_deleteMap.find(frame);
431 if (it2 != m_deleteMap.end())
432 type = it2.value();
433 if (MARK_CUT_START == type)
434 {
435 cut_start = frame;
436 }
437 else if (MARK_CUT_END == type)
438 {
439 cut_end = frame;
440 }
441 }
442
443 if (otherframe < frame)
444 {
445 startframe = otherframe;
446 endframe = cut_end != -1 ? static_cast<uint64_t>(cut_end)
447 : frame;
448 }
449 else
450 {
451 startframe = cut_start != -1 ? static_cast<uint64_t>(cut_start)
452 : frame;
453 endframe = otherframe;
454 }
455
456 // Don't place a cut marker on first or last frame; instead cut
457 // to beginning or end
458 if (startframe == 1)
459 startframe = 0;
460 if (endframe >= total - 1)
461 endframe = total;
462
463 // Don't cut the entire recording
464 if ((startframe == 0) && (endframe == total))
465 {
466 LOG(VB_GENERAL, LOG_CRIT, LOC +
467 "Refusing to cut entire recording.");
468 return;
469 }
470
471 Delete(otherframe);
472 Add(startframe, MARK_CUT_START);
473 Add(endframe, MARK_CUT_END);
474 // Clear out any markers between the start and end frames
475 otherframe = 0;
476 frm_dir_map_t::Iterator it = m_deleteMap.find(startframe);
477 for ( ; it != m_deleteMap.end() && otherframe < endframe; ++it)
478 {
479 otherframe = it.key();
480 if ((startframe < otherframe) && (endframe > otherframe))
481 {
482 LOG(VB_PLAYBACK, LOG_INFO, LOC +
483 QString("Deleting bounded marker: %1").arg(otherframe));
484 it = m_deleteMap.erase(it);
485 m_changed = true;
486 }
487 }
488 }
489 }
490 else
491 {
492 Add(frame, MARK_PLACEHOLDER);
493 }
494
495 CleanMap();
496 PushDeferred(initialDeleteMap, tr("New Cut"));
497}
498
500void DeleteMap::MoveRelative(uint64_t frame, bool right)
501{
502 frm_dir_map_t::Iterator it = m_deleteMap.find(frame);
503 if (it != m_deleteMap.end())
504 {
505 int type = it.value();
506 if (((MARK_CUT_START == type) && !right) ||
507 ((MARK_CUT_END == type) && right))
508 {
509 // If on a mark, don't move a mark from a different cut region;
510 // instead, "move" this mark onto itself
511 return;
512 }
513 if (((MARK_CUT_START == type) && right) ||
514 ((MARK_CUT_END == type) && !right))
515 {
516 // If on a mark, don't collapse a cut region to 0;
517 // instead, delete the region
518 //: Delete the current cut or preserved region
519 Delete(frame, tr("Delete"));
520 return;
521 }
522 if (MARK_PLACEHOLDER == type)
523 {
524 // Delete the temporary mark before putting a real mark at its
525 // location
526 Delete(frame, "");
527 }
528 }
529
530 uint64_t from = GetNearestMark(frame, right);
531 Move(from, frame);
532}
533
535void DeleteMap::Move(uint64_t frame, uint64_t to)
536{
538 Push(tr("Move Mark"));
539 MarkTypes type = Delete(frame);
540 if (MARK_UNSET == type)
541 {
542 if (frame == 0)
544 else if (frame == m_ctx->m_player->GetTotalFrameCount())
546 }
547 AddMark(to, type);
548}
549
551void DeleteMap::Add(uint64_t frame, MarkTypes type)
552{
553 m_deleteMap[frame] = type;
554 m_changed = true;
555}
556
559{
560 if (m_deleteMap.contains(frame))
561 {
562 m_changed = true;
563 return m_deleteMap.take(frame);
564 }
565 return MARK_UNSET;
566}
567
572bool DeleteMap::IsInDelete(uint64_t frame) const
573{
574 if (m_deleteMap.isEmpty())
575 return false;
576
577 frm_dir_map_t::const_iterator it = m_deleteMap.find(frame);
578 if (it != m_deleteMap.end())
579 return true;
580
581 int lasttype = MARK_UNSET;
582 uint64_t lastframe = UINT64_MAX;
583 for (it = m_deleteMap.begin() ; it != m_deleteMap.end(); ++it)
584 {
585 if (it.key() > frame)
586 return MARK_CUT_END == it.value();
587 lasttype = it.value();
588 lastframe = it.key();
589 }
590
591 return lasttype == MARK_CUT_START && lastframe <= frame;
592}
593
597bool DeleteMap::IsTemporaryMark(uint64_t frame) const
598{
599 if (m_deleteMap.isEmpty())
600 return false;
601
602 frm_dir_map_t::const_iterator it = m_deleteMap.find(frame);
603 return (it != m_deleteMap.end()) && (MARK_PLACEHOLDER == it.value());
604}
605
612uint64_t DeleteMap::GetNearestMark(uint64_t frame, bool right, bool *hasMark)
613 const
614{
615 uint64_t result = 0;
616 if (hasMark)
617 *hasMark = true;
618 frm_dir_map_t::const_iterator it = m_deleteMap.begin();
619 if (right)
620 {
621 result = m_ctx->m_player->GetTotalFrameCount();
622 for (; it != m_deleteMap.end(); ++it)
623 if (it.key() > frame)
624 return it.key();
625 if (hasMark)
626 *hasMark = false;
627 }
628 else
629 {
630 result = 0;
631 for (; it != m_deleteMap.end(); ++it)
632 {
633 if (it.key() >= frame)
634 return result;
635 result = it.key();
636 }
637 }
638 return result;
639}
640
645{
646 if (!m_deleteMap.isEmpty())
647 {
648 for (auto it = m_deleteMap.cbegin(); it != m_deleteMap.cend(); ++it)
649 if (MARK_PLACEHOLDER == it.value())
650 return true;
651 }
652
653 return false;
654}
655
662{
663 if (IsEmpty())
664 return;
665
666 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
667 Delete(0);
668 Delete(total);
669
670 bool clear = false;
671 while (!IsEmpty() && !clear)
672 {
673 clear = true;
674 int lasttype = MARK_UNSET;
675 int64_t lastframe = -1;
676 int64_t tempframe = -1;
677 QList<int64_t> deleteList;
678 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
679 {
680 int thistype = it.value();
681 uint64_t thisframe = it.key();
682 if (thisframe >= total)
683 {
684 deleteList.append(thisframe);
685 }
686 else if (lasttype == thistype)
687 {
688 deleteList.append(thistype == MARK_CUT_END ? thisframe :
689 (uint64_t)lastframe);
690 clear = false;
691 break;
692 }
693 if (MARK_PLACEHOLDER == thistype)
694 {
695 if (tempframe > 0)
696 deleteList.append(tempframe);
697 tempframe = thisframe;
698 }
699 else
700 {
701 lasttype = thistype;
702 lastframe = thisframe;
703 }
704 }
705
706 // Delete the unwanted frame marks safely, and not while iterating over
707 // the map which would lead to a crash
708 for (const int64_t & dit : std::as_const(deleteList))
709 {
710 Delete(dit);
711 }
712 deleteList.clear();
713 }
714}
715
718{
719 // Can't save an undo point for SetMap() or transcodes fail.
720 // Leaving as a marker for refactor.
721 //Push(tr("Set New Cut List"));
722
723 Clear();
724 m_deleteMap = map;
725}
726
729{
730 Push(tr("Load Detected Commercials"));
731 Clear();
732 for (auto it = map.begin(); it != map.end(); ++it)
733 Add(it.key(), it.value() == MARK_COMM_START ?
735 CleanMap();
736}
737
739void DeleteMap::LoadMap(const QString& undoMessage)
740{
742 return;
743
744 if (!undoMessage.isEmpty())
745 Push(undoMessage);
746 Clear();
747 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
749 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
750 CleanMap();
751}
752
756{
758 return false;
759
760 frm_dir_map_t tmpDeleteMap = m_deleteMap;
761 Clear();
762 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
763 bool result = m_ctx->m_playingInfo->QueryCutList(m_deleteMap, true);
764 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
765 CleanMap();
766 if (result)
767 PushDeferred(tmpDeleteMap, tr("Load Auto-saved Cuts"));
768 else
769 m_deleteMap = tmpDeleteMap;
770
771 return result;
772}
773
775void DeleteMap::SaveMap(bool isAutoSave)
776{
778 return;
779
780 if (!isAutoSave)
781 {
782 // Remove temporary placeholder marks
783 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); /*no inc*/)
784 {
785 if (MARK_PLACEHOLDER == it.value())
786 {
787 it = m_deleteMap.erase(it);
788 m_changed = true;
789 }
790 else
791 {
792 ++it;
793 }
794 }
795
796 CleanMap();
797 }
798 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
801 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
802}
803
810void DeleteMap::TrackerReset(uint64_t frame)
811{
812 m_nextCutStart = 0;
813 m_nextCutStartIsValid = false;
814 if (IsEmpty())
815 return;
816
817 frm_dir_map_t::iterator cutpoint = m_deleteMap.find(frame);
818 if (cutpoint != m_deleteMap.end())
819 {
820 if (cutpoint.value() == MARK_CUT_START)
821 {
823 m_nextCutStart = cutpoint.key();
824 }
825 else
826 {
827 ++cutpoint;
828 m_nextCutStartIsValid = (cutpoint != m_deleteMap.end());
829 m_nextCutStart = m_nextCutStartIsValid ? cutpoint.key() :
831 }
832 }
833 else
834 {
837 }
838 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Tracker next CUT_START: %1")
839 .arg(m_nextCutStart));
840}
841
846bool DeleteMap::TrackerWantsToJump(uint64_t frame, uint64_t &to) const
847{
848 if (IsEmpty() || !m_nextCutStartIsValid || frame < m_nextCutStart)
849 return false;
850
851 to = GetNearestMark(m_nextCutStart, true);
852 LOG(VB_PLAYBACK, LOG_INFO, LOC +
853 QString("Tracker wants to jump to: %1").arg(to));
854 return true;
855}
856
861uint64_t DeleteMap::GetLastFrame(void) const
862{
863 uint64_t result = m_ctx->m_player->GetCurrentFrameCount();
864 if (IsEmpty())
865 return result;
866
867 frm_dir_map_t::const_iterator it = m_deleteMap.end();
868 --it;
869
870 if (it.value() == MARK_CUT_START)
871 result = it.key();
872 return result;
873}
874
878bool DeleteMap::IsSaved(void) const
879{
881 return true;
882
883 frm_dir_map_t currentMap(m_deleteMap);
884 frm_dir_map_t savedMap;
885 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
886 m_ctx->m_playingInfo->QueryCutList(savedMap);
887 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
888
889 // Remove temporary placeholder marks from currentMap
890 for (auto it = currentMap.begin(); it != currentMap.end(); /* no inc */)
891 {
892 if (MARK_PLACEHOLDER == it.value())
893 it = currentMap.erase(it);
894 else
895 ++it;
896 }
897
898 return currentMap == savedMap;
899}
900
901std::chrono::milliseconds DeleteMap::TranslatePositionFrameToMs(uint64_t position,
902 float fallback_framerate,
903 bool use_cutlist) const
904{
905 return m_ctx->m_player->GetDecoder()
906 ->TranslatePositionFrameToMs(position, fallback_framerate,
907 use_cutlist ? m_deleteMap :
908 frm_dir_map_t());
909}
910uint64_t DeleteMap::TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms,
911 float fallback_framerate,
912 bool use_cutlist) const
913{
914 return m_ctx->m_player->GetDecoder()
915 ->TranslatePositionMsToFrame(dur_ms, fallback_framerate,
916 use_cutlist ? m_deleteMap :
917 frm_dir_map_t());
918}
919
920uint64_t DeleteMap::TranslatePositionAbsToRel(uint64_t position) const
921{
923}
924
925uint64_t DeleteMap::TranslatePositionRelToAbs(uint64_t position) const
926{
928}
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:644
QString CreateTimeString(uint64_t frame, bool use_cutlist, double frame_rate, bool full_resolution) const
Definition: deletemap.cpp:162
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:597
void NewCut(uint64_t frame)
Add a new cut marker (to start or end a cut region)
Definition: deletemap.cpp:394
void SetMap(const frm_dir_map_t &map)
Use the given map.
Definition: deletemap.cpp:717
void CleanMap(void)
Removes redundant marks and ensures the markup sequence is valid.
Definition: deletemap.cpp:661
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:810
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:234
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:775
int m_seekamountpos
Definition: deletemap.h:111
void UpdateSeekAmount(int change)
Definition: deletemap.cpp:140
void Add(uint64_t frame, MarkTypes type)
Private addition to the deleteMap.
Definition: deletemap.cpp:551
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:861
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:846
void AddMark(uint64_t frame, MarkTypes type)
Add a new mark of the given type.
Definition: deletemap.cpp:289
uint64_t GetNearestMark(uint64_t frame, bool right, bool *hasMark=nullptr) const
Returns the next or previous mark.
Definition: deletemap.cpp:612
bool LoadAutoSaveMap(void)
Returns true if an auto-save map was loaded.
Definition: deletemap.cpp:755
void MoveRelative(uint64_t frame, bool right)
Move the previous (!right) or next (right) cut to frame.
Definition: deletemap.cpp:500
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:535
void LoadCommBreakMap(frm_dir_map_t &map)
Loads the given commercial break map into the deleteMap.
Definition: deletemap.cpp:728
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:572
std::chrono::milliseconds TranslatePositionFrameToMs(uint64_t position, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:901
uint64_t TranslatePositionRelToAbs(uint64_t position) const
Definition: deletemap.cpp:925
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:878
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:361
bool IsEmpty(void) const
Definition: deletemap.cpp:259
bool HasUndo(void) const
Definition: deletemap.h:87
void LoadMap(const QString &undoMessage="")
Loads the delete map from the database.
Definition: deletemap.cpp:739
bool IsFileEditing(void)
Determines whether the file is currently in edit mode.
Definition: deletemap.cpp:246
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:910
void SetEditing(bool edit, OSD *osd=nullptr)
Set the edit mode and optionally hide the edit mode OSD.
Definition: deletemap.cpp:226
void Clear(const QString &undoMessage="")
Clears the deleteMap.
Definition: deletemap.cpp:265
uint64_t TranslatePositionAbsToRel(uint64_t position) const
Definition: deletemap.cpp:920
PlayerContext * m_ctx
Definition: deletemap.h:113
void ReverseAll(void)
Reverses the direction of each mark in the map.
Definition: deletemap.cpp:274
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:149
void SetRegions(const QString &Window, frm_dir_map_t &Map, long long Total)
Definition: osd.cpp:374
void HideWindow(const QString &Window) override
Definition: osd.cpp:689
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:207
void SetGraph(const QString &Window, const QString &Graph, std::chrono::milliseconds Timecode)
Definition: osd.cpp:438
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:206
#define ACTION_CLEARMAP
Definition: tv_actions.h:86
#define ACTION_INVERTMAP
Definition: tv_actions.h:87