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
8 #include "libmythbase/mythdate.h"
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 
26 void 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 
49 bool DeleteMap::Undo(void)
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 
62 bool DeleteMap::Redo(void)
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 
75 QString DeleteMap::GetUndoMessage(void) const
76 {
77  return (HasUndo() ? m_undoStack[m_undoStackPointer - 1].m_message :
78  tr("(Nothing to undo)"));
79 }
80 
81 QString DeleteMap::GetRedoMessage(void) const
82 {
83  return (HasRedo() ? m_undoStack[m_undoStackPointer].m_message :
84  tr("(Nothing to redo)"));
85 }
86 
87 bool DeleteMap::HandleAction(const QString &action, uint64_t frame)
88 {
89  bool handled = true;
90  if (action == ACTION_UP)
92  else if (action == ACTION_DOWN)
93  UpdateSeekAmount(-1);
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 
162 QString 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 
177 void 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));
213  osd->SetText(OSD_WIN_PROGEDIT, infoMap, kOSDTimeout_None);
214  if (m_changed || total != m_cachedTotalForOSD)
216  m_changed = false;
217  m_cachedTotalForOSD = total;
218 }
219 
220 void DeleteMap::UpdateOSD(std::chrono::milliseconds timecode, OSD *osd)
221 {
222  osd->SetGraph(OSD_WIN_PROGEDIT, "audiograph", timecode);
223 }
224 
226 void 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)
253  result = m_ctx->m_playingInfo->QueryIsEditing();
254  m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
255  }
256  return result;
257 }
258 
259 bool DeleteMap::IsEmpty(void) const
260 {
261  return m_deleteMap.empty();
262 }
263 
265 void DeleteMap::Clear(const QString& undoMessage)
266 {
267  if (!undoMessage.isEmpty())
268  Push(undoMessage);
269  m_deleteMap.clear();
270  m_changed = true;
271 }
272 
275 {
276  EDIT_CHECK;
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 :
280  MARK_CUT_END);
281  CleanMap();
282 }
283 
289 void DeleteMap::AddMark(uint64_t frame, MarkTypes type)
290 {
291  EDIT_CHECK;
292  if ((MARK_CUT_START != type) && (MARK_CUT_END != type) &&
293  (MARK_PLACEHOLDER != 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 
364 void DeleteMap::Delete(uint64_t frame, const QString& undoMessage)
365 {
366  EDIT_CHECK;
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 
397 void DeleteMap::NewCut(uint64_t frame)
398 {
399  EDIT_CHECK;
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 
503 void 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 
538 void DeleteMap::Move(uint64_t frame, uint64_t to)
539 {
540  EDIT_CHECK;
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())
548  type = MARK_CUT_END;
549  }
550  AddMark(to, type);
551 }
552 
554 void 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 
575 bool 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 
600 bool 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 
615 uint64_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 
742 void 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 
778 void 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 
811 void 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  {
823  m_nextCutStartIsValid = true;
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  {
836  m_nextCutStart = GetNearestMark(frame, !IsInDelete(frame),
838  }
839  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Tracker next CUT_START: %1")
840  .arg(m_nextCutStart));
841 }
842 
847 bool 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 
862 uint64_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 
879 bool 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 
902 std::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 }
911 uint64_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 
921 uint64_t DeleteMap::TranslatePositionAbsToRel(uint64_t position) const
922 {
924 }
925 
926 uint64_t DeleteMap::TranslatePositionRelToAbs(uint64_t position) const
927 {
929 }
DeleteMap::SaveMap
void SaveMap(bool isAutoSave=false)
Saves the delete map to the database.
Definition: deletemap.cpp:778
ACTION_DOWN
static constexpr const char * ACTION_DOWN
Definition: mythuiactions.h:17
PlayerContext::UnlockPlayingInfo
void UnlockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:249
DeleteMap::Add
void Add(uint64_t frame, MarkTypes type)
Private addition to the deleteMap.
Definition: deletemap.cpp:554
MythPlayer::GetTotalFrameCount
uint64_t GetTotalFrameCount(void) const
Definition: mythplayer.h:143
deletemap.h
MARK_PLACEHOLDER
@ MARK_PLACEHOLDER
Definition: programtypes.h:54
DeleteMap::ReverseAll
void ReverseAll(void)
Reverses the direction of each mark in the map.
Definition: deletemap.cpp:274
DeleteMap::TranslatePositionRelToAbs
uint64_t TranslatePositionRelToAbs(uint64_t position) const
Definition: deletemap.cpp:926
DeleteMap::TrackerReset
void TrackerReset(uint64_t frame)
Resets the internal state tracker.
Definition: deletemap.cpp:811
DeleteMap::m_undoStack
QVector< DeleteMapUndoEntry > m_undoStack
Definition: deletemap.h:116
DeleteMap::LoadAutoSaveMap
bool LoadAutoSaveMap(void)
Returns true if an auto-save map was loaded.
Definition: deletemap.cpp:758
DeleteMap::GetNearestMark
uint64_t GetNearestMark(uint64_t frame, bool right, bool *hasMark=nullptr) const
Returns the next or previous mark.
Definition: deletemap.cpp:615
DeleteMap::TranslatePositionFrameToMs
std::chrono::milliseconds TranslatePositionFrameToMs(uint64_t position, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:902
DeleteMap::SetMap
void SetMap(const frm_dir_map_t &map)
Use the given map.
Definition: deletemap.cpp:720
LOC
#define LOC
Definition: deletemap.cpp:18
MarkTypes
MarkTypes
Definition: programtypes.h:47
OSD::SetGraph
void SetGraph(const QString &Window, const QString &Graph, std::chrono::milliseconds Timecode)
Definition: osd.cpp:442
MythCoreContext::IsDatabaseIgnored
bool IsDatabaseIgnored(void) const
/brief Returns true if database is being ignored.
Definition: mythcorecontext.cpp:880
DeleteMap::SetFileEditing
void SetFileEditing(bool edit)
Update the editing status in the file's ProgramInfo.
Definition: deletemap.cpp:234
frm_dir_map_t
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:118
MythDate::formatTime
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:233
ProgramInfo::SetEditing
void SetEditing(bool editing)
Definition: programinfo.h:550
osd.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythPlayer::GetCurrentFrameCount
uint64_t GetCurrentFrameCount(void) const
Definition: mythplayer.cpp:1741
DeleteMap::IsEmpty
bool IsEmpty(void) const
Definition: deletemap.cpp:259
OSD::SetText
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:209
mythplayer.h
DeleteMap::m_nextCutStart
uint64_t m_nextCutStart
Definition: deletemap.h:107
MARK_UPDATED_CUT
@ MARK_UPDATED_CUT
Definition: programtypes.h:53
DeleteMapUndoEntry
Definition: deletemap.h:17
OSD::SetRegions
void SetRegions(const QString &Window, frm_dir_map_t &Map, long long Total)
Definition: osd.cpp:376
OSD_WIN_PROGEDIT
static constexpr const char * OSD_WIN_PROGEDIT
Definition: osd.h:35
DeleteMap::SetEditing
void SetEditing(bool edit, OSD *osd=nullptr)
Set the edit mode and optionally hide the edit mode OSD.
Definition: deletemap.cpp:226
DeleteMap::Push
void Push(const QString &undoMessage)
Definition: deletemap.cpp:26
DeleteMap::GetUndoMessage
QString GetUndoMessage(void) const
Definition: deletemap.cpp:75
DeleteMap::TrackerWantsToJump
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
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
DecoderBase::TranslatePositionMsToFrame
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms, float fallback_framerate, const frm_dir_map_t &cutlist)
Definition: decoderbase.cpp:1392
ACTION_INVERTMAP
#define ACTION_INVERTMAP
Definition: tv_actions.h:87
DeleteMap::CleanMap
void CleanMap(void)
Removes redundant marks and ensures the markup sequence is valid.
Definition: deletemap.cpp:664
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
DeleteMap::m_changed
bool m_changed
Definition: deletemap.h:110
mythdate.h
DecoderBase::TranslatePositionAbsToRel
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)
Definition: decoderbase.cpp:1416
kOSDTimeout_None
@ kOSDTimeout_None
Definition: osd.h:58
programinfo.h
mythlogging.h
ACTION_CLEARMAP
#define ACTION_CLEARMAP
Definition: tv_actions.h:86
PlayerContext::m_playingInfo
ProgramInfo * m_playingInfo
Currently playing info.
Definition: playercontext.h:117
tv_actions.h
DeleteMap::NewCut
void NewCut(uint64_t frame)
Add a new cut marker (to start or end a cut region)
Definition: deletemap.cpp:397
PlayerContext::LockPlayingInfo
void LockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:239
DecoderBase::TranslatePositionRelToAbs
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)
Definition: decoderbase.cpp:1465
DeleteMap::m_ctx
PlayerContext * m_ctx
Definition: deletemap.h:113
DeleteMap::IsInDelete
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
ProgramInfo::QueryCutList
bool QueryCutList(frm_dir_map_t &delMap, bool loadAutosave=false) const
Definition: programinfo.cpp:3469
mythtypes.h
DeleteMap::m_deleteMap
frm_dir_map_t m_deleteMap
Definition: deletemap.h:108
DecoderBase::TranslatePositionFrameToMs
std::chrono::milliseconds TranslatePositionFrameToMs(long long position, float fallback_framerate, const frm_dir_map_t &cutlist)
Definition: decoderbase.cpp:1364
MARK_CUT_START
@ MARK_CUT_START
Definition: programtypes.h:56
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:896
DeleteMap::LoadMap
void LoadMap(const QString &undoMessage="")
Loads the delete map from the database.
Definition: deletemap.cpp:742
ProgramInfo::ToMap
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...
Definition: programinfo.cpp:1547
EDIT_CHECK
#define EDIT_CHECK
Definition: deletemap.cpp:19
MARK_COMM_START
@ MARK_COMM_START
Definition: programtypes.h:59
DeleteMap::TranslatePositionAbsToRel
uint64_t TranslatePositionAbsToRel(uint64_t position) const
Definition: deletemap.cpp:921
DeleteMap::Clear
void Clear(const QString &undoMessage="")
Clears the deleteMap.
Definition: deletemap.cpp:265
DeleteMap::IsFileEditing
bool IsFileEditing(void)
Determines whether the file is currently in edit mode.
Definition: deletemap.cpp:246
DeleteMap::LoadCommBreakMap
void LoadCommBreakMap(frm_dir_map_t &map)
Loads the given commercial break map into the deleteMap.
Definition: deletemap.cpp:731
DeleteMap::HasRedo
bool HasRedo(void) const
Definition: deletemap.h:88
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
clamp
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:204
DeleteMap::TranslatePositionMsToFrame
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds dur_ms, float fallback_framerate, bool use_cutlist) const
Definition: deletemap.cpp:911
DeleteMap::AddMark
void AddMark(uint64_t frame, MarkTypes type)
Add a new mark of the given type.
Definition: deletemap.cpp:289
DeleteMap::m_nextCutStartIsValid
bool m_nextCutStartIsValid
Definition: deletemap.h:106
MythPlayer::GetDecoder
DecoderBase * GetDecoder(void)
Returns the stream decoder currently in use.
Definition: mythplayer.h:186
MARK_UNSET
@ MARK_UNSET
Definition: programtypes.h:50
DeleteMap::m_undoStackPointer
int m_undoStackPointer
Definition: deletemap.h:117
DeleteMap::CreateTimeString
QString CreateTimeString(uint64_t frame, bool use_cutlist, double frame_rate, bool full_resolution) const
Definition: deletemap.cpp:162
ACTION_UP
static constexpr const char * ACTION_UP
Definition: mythuiactions.h:16
DeleteMap::IsSaved
bool IsSaved(void) const
Compares the current cut list with the saved cut list.
Definition: deletemap.cpp:879
DeleteMap::m_cachedTotalForOSD
uint64_t m_cachedTotalForOSD
Definition: deletemap.h:114
MythPlayer::IsWatchingInprogress
bool IsWatchingInprogress(void) const
Definition: mythplayer.cpp:130
DeleteMap::Delete
void Delete(uint64_t frame, const QString &undoMessage)
Remove the mark at the given frame.
Definition: deletemap.cpp:364
MARK_CUT_END
@ MARK_CUT_END
Definition: programtypes.h:55
mythcorecontext.h
DeleteMap::Move
void Move(uint64_t frame, uint64_t to)
Move an existing mark to a new frame.
Definition: deletemap.cpp:538
playercontext.h
ProgramInfo::QueryIsEditing
bool QueryIsEditing(void) const
Queries "recorded" table for its "editing" field and returns true if it is set to true.
Definition: programinfo.cpp:3108
DeleteMap::Redo
bool Redo(void)
Definition: deletemap.cpp:62
DeleteMap::MoveRelative
void MoveRelative(uint64_t frame, bool right)
Move the previous (!right) or next (right) cut to frame.
Definition: deletemap.cpp:503
DeleteMap::PushDeferred
void PushDeferred(const frm_dir_map_t &savedMap, const QString &undoMessage)
Definition: deletemap.cpp:37
ProgramInfo::SaveCutList
void SaveCutList(frm_dir_map_t &delMap, bool isAutoSave=false) const
Definition: programinfo.cpp:3501
OSD::HideWindow
void HideWindow(const QString &Window) override
Definition: osd.cpp:674
DeleteMap::HasTemporaryMark
bool HasTemporaryMark(void) const
Returns true if a temporary placeholder mark is defined.
Definition: deletemap.cpp:647
build_compdb.action
action
Definition: build_compdb.py:9
DeleteMap::m_editing
bool m_editing
Definition: deletemap.h:105
OSD::SetValues
void SetValues(const QString &Window, const QHash< QString, int > &Map, OSDTimeout Timeout)
Definition: osd.cpp:151
ProgramInfo::SaveMarkupFlag
void SaveMarkupFlag(MarkTypes type) const
Clears the specified flag, then if sets it.
Definition: programinfo.cpp:3770
mythuiactions.h
DeleteMap::Undo
bool Undo(void)
Definition: deletemap.cpp:49
DeleteMap::m_seekamountpos
int m_seekamountpos
Definition: deletemap.h:111
DeleteMap::HasUndo
bool HasUndo(void) const
Definition: deletemap.h:87
DeleteMap::IsTemporaryMark
bool IsTemporaryMark(uint64_t frame) const
Returns true if the given frame is a temporary/placeholder mark.
Definition: deletemap.cpp:600
DeleteMap::GetLastFrame
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
DeleteMap::HandleAction
bool HandleAction(const QString &action, uint64_t frame)
Definition: deletemap.cpp:87
PlayerContext::m_player
MythPlayer * m_player
Definition: playercontext.h:112
DeleteMap::UpdateOSD
void UpdateOSD(uint64_t frame, double frame_rate, OSD *osd)
Show and update the edit mode On Screen Display.
Definition: deletemap.cpp:177
DeleteMap::m_seekText
QString m_seekText
Definition: deletemap.h:109
OSD
Definition: osd.h:93
DeleteMap::m_seekamount
float m_seekamount
Definition: deletemap.h:112
DeleteMap::UpdateSeekAmount
void UpdateSeekAmount(int change)
Definition: deletemap.cpp:140
DeleteMap::GetRedoMessage
QString GetRedoMessage(void) const
Definition: deletemap.cpp:81