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
12#include "libmythui/mythuiactions.h" // for ACTION_DOWN, ACTION_UP
13#include "mythplayer.h"
14#include "osd.h"
15#include "playercontext.h" // for PlayerContext
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);
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 QMutableMapIterator<uint64_t, MarkTypes> it(m_deleteMap);
316
317 if (type == MARK_CUT_END)
318 {
319 // remove curent end marker if it exists
320 while (it.hasNext())
321 {
322 it.next();
323 if (it.key() > frame)
324 {
325 if ((lasttype == MARK_CUT_END) && (lastframe > -1))
326 remove = lastframe;
327 break;
328 }
329 lasttype = it.value();
330 lastframe = it.key();
331 }
332 if ((remove < 0) && (lasttype == MARK_CUT_END) &&
333 (lastframe > -1) && (lastframe < (int64_t)frame))
334 remove = lastframe;
335 }
336 else if (type == MARK_CUT_START)
337 {
338 // remove curent start marker if it exists
339 it.toBack();
340 while (it.hasPrevious())
341 {
342 it.previous();
343 if (it.key() <= frame)
344 {
345 if (lasttype == MARK_CUT_START && (lastframe > -1))
346 remove = lastframe;
347 break;
348 }
349 lasttype = it.value();
350 lastframe = it.key();
351 }
352 if ((remove < 0) && (lasttype == MARK_CUT_START) &&
353 (lastframe > -1) && (lastframe > (int64_t)frame))
354 remove = lastframe;
355 }
356
357 if (remove > -1)
358 Delete((uint64_t)remove);
359 Add(frame, type);
360 CleanMap();
361}
362
364void DeleteMap::Delete(uint64_t frame, const QString& undoMessage)
365{
367 if (m_deleteMap.isEmpty())
368 return;
369
370 if (!undoMessage.isEmpty())
371 Push(undoMessage);
372
373 uint64_t prev = GetNearestMark(frame, false);
374 uint64_t next = GetNearestMark(frame, true);
375
376 // If frame is a cut point, GetNearestMark() would return the previous/next
377 // mark (not this frame), so check to see if we need to use frame, instead
378 frm_dir_map_t::Iterator it = m_deleteMap.find(frame);
379 if (it != m_deleteMap.end())
380 {
381 int type = it.value();
382 if (MARK_PLACEHOLDER == type)
383 next = prev = frame;
384 else if (MARK_CUT_END == type)
385 next = frame;
386 else if (MARK_CUT_START == type)
387 prev = frame;
388 }
389
390 Delete(prev);
391 if (prev != next)
392 Delete(next);
393 CleanMap();
394}
395
397void DeleteMap::NewCut(uint64_t frame)
398{
400
401 // Defer pushing the undo entry until the end, when we're sure a
402 // change has been made.
403 frm_dir_map_t initialDeleteMap = m_deleteMap;
404
405 // find any existing temporary marker to determine cut range
406 int64_t existing = -1;
407 for (auto it = m_deleteMap.begin() ; it != m_deleteMap.end(); ++it)
408 {
409 if (MARK_PLACEHOLDER == it.value())
410 {
411 existing = it.key();
412 break;
413 }
414 }
415
416 if (existing > -1)
417 {
418 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
419 auto otherframe = static_cast<uint64_t>(existing);
420 if (otherframe == frame)
421 Delete(otherframe);
422 else
423 {
424 uint64_t startframe = 0;
425 uint64_t endframe = 0;
426 int64_t cut_start = -1;
427 int64_t cut_end = -1;
428 if (IsInDelete(frame))
429 {
431 cut_start = GetNearestMark(frame, false);
432 cut_end = GetNearestMark(frame, true);
433 frm_dir_map_t::Iterator it2 = m_deleteMap.find(frame);
434 if (it2 != m_deleteMap.end())
435 type = it2.value();
436 if (MARK_CUT_START == type)
437 {
438 cut_start = frame;
439 }
440 else if (MARK_CUT_END == type)
441 {
442 cut_end = frame;
443 }
444 }
445
446 if (otherframe < frame)
447 {
448 startframe = otherframe;
449 endframe = cut_end != -1 ? static_cast<uint64_t>(cut_end)
450 : frame;
451 }
452 else
453 {
454 startframe = cut_start != -1 ? static_cast<uint64_t>(cut_start)
455 : frame;
456 endframe = otherframe;
457 }
458
459 // Don't place a cut marker on first or last frame; instead cut
460 // to beginning or end
461 if (startframe == 1)
462 startframe = 0;
463 if (endframe >= total - 1)
464 endframe = total;
465
466 // Don't cut the entire recording
467 if ((startframe == 0) && (endframe == total))
468 {
469 LOG(VB_GENERAL, LOG_CRIT, LOC +
470 "Refusing to cut entire recording.");
471 return;
472 }
473
474 Delete(otherframe);
475 Add(startframe, MARK_CUT_START);
476 Add(endframe, MARK_CUT_END);
477 // Clear out any markers between the start and end frames
478 otherframe = 0;
479 frm_dir_map_t::Iterator it = m_deleteMap.find(startframe);
480 for ( ; it != m_deleteMap.end() && otherframe < endframe; ++it)
481 {
482 otherframe = it.key();
483 if ((startframe < otherframe) && (endframe > otherframe))
484 {
485 LOG(VB_PLAYBACK, LOG_INFO, LOC +
486 QString("Deleting bounded marker: %1").arg(otherframe));
487 it = m_deleteMap.erase(it);
488 m_changed = true;
489 }
490 }
491 }
492 }
493 else
494 {
495 Add(frame, MARK_PLACEHOLDER);
496 }
497
498 CleanMap();
499 PushDeferred(initialDeleteMap, tr("New Cut"));
500}
501
503void DeleteMap::MoveRelative(uint64_t frame, bool right)
504{
505 frm_dir_map_t::Iterator it = m_deleteMap.find(frame);
506 if (it != m_deleteMap.end())
507 {
508 int type = it.value();
509 if (((MARK_CUT_START == type) && !right) ||
510 ((MARK_CUT_END == type) && right))
511 {
512 // If on a mark, don't move a mark from a different cut region;
513 // instead, "move" this mark onto itself
514 return;
515 }
516 if (((MARK_CUT_START == type) && right) ||
517 ((MARK_CUT_END == type) && !right))
518 {
519 // If on a mark, don't collapse a cut region to 0;
520 // instead, delete the region
521 //: Delete the current cut or preserved region
522 Delete(frame, tr("Delete"));
523 return;
524 }
525 if (MARK_PLACEHOLDER == type)
526 {
527 // Delete the temporary mark before putting a real mark at its
528 // location
529 Delete(frame, "");
530 }
531 }
532
533 uint64_t from = GetNearestMark(frame, right);
534 Move(from, frame);
535}
536
538void DeleteMap::Move(uint64_t frame, uint64_t to)
539{
541 Push(tr("Move Mark"));
542 MarkTypes type = Delete(frame);
543 if (MARK_UNSET == type)
544 {
545 if (frame == 0)
547 else if (frame == m_ctx->m_player->GetTotalFrameCount())
549 }
550 AddMark(to, type);
551}
552
554void DeleteMap::Add(uint64_t frame, MarkTypes type)
555{
556 m_deleteMap[frame] = type;
557 m_changed = true;
558}
559
562{
563 if (m_deleteMap.contains(frame))
564 {
565 m_changed = true;
566 return m_deleteMap.take(frame);
567 }
568 return MARK_UNSET;
569}
570
575bool DeleteMap::IsInDelete(uint64_t frame) const
576{
577 if (m_deleteMap.isEmpty())
578 return false;
579
580 frm_dir_map_t::const_iterator it = m_deleteMap.find(frame);
581 if (it != m_deleteMap.end())
582 return true;
583
584 int lasttype = MARK_UNSET;
585 uint64_t lastframe = UINT64_MAX;
586 for (it = m_deleteMap.begin() ; it != m_deleteMap.end(); ++it)
587 {
588 if (it.key() > frame)
589 return MARK_CUT_END == it.value();
590 lasttype = it.value();
591 lastframe = it.key();
592 }
593
594 return lasttype == MARK_CUT_START && lastframe <= frame;
595}
596
600bool DeleteMap::IsTemporaryMark(uint64_t frame) const
601{
602 if (m_deleteMap.isEmpty())
603 return false;
604
605 frm_dir_map_t::const_iterator it = m_deleteMap.find(frame);
606 return (it != m_deleteMap.end()) && (MARK_PLACEHOLDER == it.value());
607}
608
615uint64_t DeleteMap::GetNearestMark(uint64_t frame, bool right, bool *hasMark)
616 const
617{
618 uint64_t result = 0;
619 if (hasMark)
620 *hasMark = true;
621 frm_dir_map_t::const_iterator it = m_deleteMap.begin();
622 if (right)
623 {
624 result = m_ctx->m_player->GetTotalFrameCount();
625 for (; it != m_deleteMap.end(); ++it)
626 if (it.key() > frame)
627 return it.key();
628 if (hasMark)
629 *hasMark = false;
630 }
631 else
632 {
633 result = 0;
634 for (; it != m_deleteMap.end(); ++it)
635 {
636 if (it.key() >= frame)
637 return result;
638 result = it.key();
639 }
640 }
641 return result;
642}
643
648{
649 if (!m_deleteMap.isEmpty())
650 {
651 for (auto it = m_deleteMap.cbegin(); it != m_deleteMap.cend(); ++it)
652 if (MARK_PLACEHOLDER == it.value())
653 return true;
654 }
655
656 return false;
657}
658
665{
666 if (IsEmpty())
667 return;
668
669 uint64_t total = m_ctx->m_player->GetTotalFrameCount();
670 Delete(0);
671 Delete(total);
672
673 bool clear = false;
674 while (!IsEmpty() && !clear)
675 {
676 clear = true;
677 int lasttype = MARK_UNSET;
678 int64_t lastframe = -1;
679 int64_t tempframe = -1;
680 QList<int64_t> deleteList;
681 for (auto it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
682 {
683 int thistype = it.value();
684 uint64_t thisframe = it.key();
685 if (thisframe >= total)
686 {
687 deleteList.append(thisframe);
688 }
689 else if (lasttype == thistype)
690 {
691 deleteList.append(thistype == MARK_CUT_END ? thisframe :
692 (uint64_t)lastframe);
693 clear = false;
694 break;
695 }
696 if (MARK_PLACEHOLDER == thistype)
697 {
698 if (tempframe > 0)
699 deleteList.append(tempframe);
700 tempframe = thisframe;
701 }
702 else
703 {
704 lasttype = thistype;
705 lastframe = thisframe;
706 }
707 }
708
709 // Delete the unwanted frame marks safely, and not while iterating over
710 // the map which would lead to a crash
711 for (const int64_t & dit : std::as_const(deleteList))
712 {
713 Delete(dit);
714 }
715 deleteList.clear();
716 }
717}
718
721{
722 // Can't save an undo point for SetMap() or transcodes fail.
723 // Leaving as a marker for refactor.
724 //Push(tr("Set New Cut List"));
725
726 Clear();
727 m_deleteMap = map;
728}
729
732{
733 Push(tr("Load Detected Commercials"));
734 Clear();
735 for (auto it = map.begin(); it != map.end(); ++it)
736 Add(it.key(), it.value() == MARK_COMM_START ?
738 CleanMap();
739}
740
742void DeleteMap::LoadMap(const QString& undoMessage)
743{
745 return;
746
747 if (!undoMessage.isEmpty())
748 Push(undoMessage);
749 Clear();
750 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
752 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
753 CleanMap();
754}
755
759{
761 return false;
762
763 frm_dir_map_t tmpDeleteMap = m_deleteMap;
764 Clear();
765 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
766 bool result = m_ctx->m_playingInfo->QueryCutList(m_deleteMap, true);
767 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
768 CleanMap();
769 if (result)
770 PushDeferred(tmpDeleteMap, tr("Load Auto-saved Cuts"));
771 else
772 m_deleteMap = tmpDeleteMap;
773
774 return result;
775}
776
778void DeleteMap::SaveMap(bool isAutoSave)
779{
781 return;
782
783 if (!isAutoSave)
784 {
785 // Remove temporary placeholder marks
786 QMutableMapIterator<uint64_t, MarkTypes> it(m_deleteMap);
787 while (it.hasNext())
788 {
789 it.next();
790 if (MARK_PLACEHOLDER == it.value())
791 {
792 it.remove();
793 m_changed = true;
794 }
795 }
796
797 CleanMap();
798 }
799 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
802 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
803}
804
811void DeleteMap::TrackerReset(uint64_t frame)
812{
813 m_nextCutStart = 0;
814 m_nextCutStartIsValid = false;
815 if (IsEmpty())
816 return;
817
818 frm_dir_map_t::iterator cutpoint = m_deleteMap.find(frame);
819 if (cutpoint != m_deleteMap.end())
820 {
821 if (cutpoint.value() == MARK_CUT_START)
822 {
824 m_nextCutStart = cutpoint.key();
825 }
826 else
827 {
828 ++cutpoint;
829 m_nextCutStartIsValid = (cutpoint != m_deleteMap.end());
830 m_nextCutStart = m_nextCutStartIsValid ? cutpoint.key() :
832 }
833 }
834 else
835 {
838 }
839 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Tracker next CUT_START: %1")
840 .arg(m_nextCutStart));
841}
842
847bool DeleteMap::TrackerWantsToJump(uint64_t frame, uint64_t &to) const
848{
849 if (IsEmpty() || !m_nextCutStartIsValid || frame < m_nextCutStart)
850 return false;
851
852 to = GetNearestMark(m_nextCutStart, true);
853 LOG(VB_PLAYBACK, LOG_INFO, LOC +
854 QString("Tracker wants to jump to: %1").arg(to));
855 return true;
856}
857
862uint64_t DeleteMap::GetLastFrame(void) const
863{
864 uint64_t result = m_ctx->m_player->GetCurrentFrameCount();
865 if (IsEmpty())
866 return result;
867
868 frm_dir_map_t::const_iterator it = m_deleteMap.end();
869 --it;
870
871 if (it.value() == MARK_CUT_START)
872 result = it.key();
873 return result;
874}
875
879bool DeleteMap::IsSaved(void) const
880{
882 return true;
883
884 frm_dir_map_t currentMap(m_deleteMap);
885 frm_dir_map_t savedMap;
886 m_ctx->LockPlayingInfo(__FILE__, __LINE__);
887 m_ctx->m_playingInfo->QueryCutList(savedMap);
888 m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
889
890 // Remove temporary placeholder marks from currentMap
891 QMutableMapIterator<uint64_t, MarkTypes> it(currentMap);
892 while (it.hasNext())
893 {
894 it.next();
895 if (MARK_PLACEHOLDER == it.value())
896 it.remove();
897 }
898
899 return currentMap == savedMap;
900}
901
902std::chrono::milliseconds DeleteMap::TranslatePositionFrameToMs(uint64_t position,
903 float fallback_framerate,
904 bool use_cutlist) const
905{
906 return m_ctx->m_player->GetDecoder()
907 ->TranslatePositionFrameToMs(position, fallback_framerate,
908 use_cutlist ? m_deleteMap :
909 frm_dir_map_t());
910}
911uint64_t DeleteMap::TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms,
912 float fallback_framerate,
913 bool use_cutlist) const
914{
915 return m_ctx->m_player->GetDecoder()
916 ->TranslatePositionMsToFrame(dur_ms, fallback_framerate,
917 use_cutlist ? m_deleteMap :
918 frm_dir_map_t());
919}
920
921uint64_t DeleteMap::TranslatePositionAbsToRel(uint64_t position) const
922{
924}
925
926uint64_t DeleteMap::TranslatePositionRelToAbs(uint64_t position) const
927{
929}
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:647
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:600
void NewCut(uint64_t frame)
Add a new cut marker (to start or end a cut region)
Definition: deletemap.cpp:397
void SetMap(const frm_dir_map_t &map)
Use the given map.
Definition: deletemap.cpp:720
void CleanMap(void)
Removes redundant marks and ensures the markup sequence is valid.
Definition: deletemap.cpp:664
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:811
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:778
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:554
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:862
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:847
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:615
bool LoadAutoSaveMap(void)
Returns true if an auto-save map was loaded.
Definition: deletemap.cpp:758
void MoveRelative(uint64_t frame, bool right)
Move the previous (!right) or next (right) cut to frame.
Definition: deletemap.cpp:503
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:538
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 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:575
std::chrono::milliseconds TranslatePositionFrameToMs(uint64_t position, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:902
uint64_t TranslatePositionRelToAbs(uint64_t position) const
Definition: deletemap.cpp:926
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:879
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:364
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:742
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:911
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:921
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:184
uint64_t GetTotalFrameCount(void) const
Definition: mythplayer.h:142
uint64_t GetCurrentFrameCount(void) const
bool IsWatchingInprogress(void) const
Definition: mythplayer.cpp:127
Definition: osd.h:94
void SetValues(const QString &Window, const QHash< QString, int > &Map, OSDTimeout Timeout)
Definition: osd.cpp:152
void SetRegions(const QString &Window, frm_dir_map_t &Map, long long Total)
Definition: osd.cpp:377
void HideWindow(const QString &Window) override
Definition: osd.cpp:675
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:210
void SetGraph(const QString &Window, const QString &Graph, std::chrono::milliseconds Timecode)
Definition: osd.cpp:443
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:551
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
static guint32 * tmp
Definition: goom_core.cpp:26
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:949
#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