296 changes: 2 additions & 294 deletions mythtv/libs/libmythtv/mythplayerui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

MythPlayerUI::MythPlayerUI(MythMainWindow* MainWindow, TV* Tv,
PlayerContext *Context, PlayerFlags Flags)
: MythPlayerVisualiserUI(MainWindow, Tv, Context, Flags),
: MythPlayerEditorUI(MainWindow, Tv, Context, Flags),
MythVideoScanTracker(this)
{
// Finish setting up the overlays
Expand Down Expand Up @@ -52,7 +52,7 @@ MythPlayerUI::MythPlayerUI(MythMainWindow* MainWindow, TV* Tv,
void MythPlayerUI::InitialiseState()
{
LOG(VB_GENERAL, LOG_INFO, LOC + "Initialising player state");
MythPlayerVisualiserUI::InitialiseState();
MythPlayerEditorUI::InitialiseState();
}

bool MythPlayerUI::StartPlaying()
Expand Down Expand Up @@ -701,20 +701,6 @@ void MythPlayerUI::SetVideoParams(int Width, int Height, double FrameRate, float
ResetTracker();
}

bool MythPlayerUI::DoFastForwardSecs(float Seconds, double Inaccuracy, bool UseCutlist)
{
float current = ComputeSecs(m_framesPlayed, UseCutlist);
uint64_t targetFrame = FindFrame(current + Seconds, UseCutlist);
return DoFastForward(targetFrame - m_framesPlayed, Inaccuracy);
}

bool MythPlayerUI::DoRewindSecs(float Seconds, double Inaccuracy, bool UseCutlist)
{
float target = qMax(0.0F, ComputeSecs(m_framesPlayed, UseCutlist) - Seconds);
uint64_t targetFrame = FindFrame(target, UseCutlist);
return DoRewind(m_framesPlayed - targetFrame, Inaccuracy);
}

/**
* \brief Determines if the recording should be considered watched
*
Expand Down Expand Up @@ -1219,281 +1205,3 @@ void MythPlayerUI::JumpToProgram()
m_playerCtx->SetPlayerChangingBuffers(false);
LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - end");
}

// Only edit stuff below here - to be moved
#include "tv_actions.h"

uint64_t MythPlayerUI::GetNearestMark(uint64_t Frame, bool Right)
{
return m_deleteMap.GetNearestMark(Frame, Right);
}

bool MythPlayerUI::IsTemporaryMark(uint64_t Frame)
{
return m_deleteMap.IsTemporaryMark(Frame);
}

bool MythPlayerUI::HasTemporaryMark()
{
return m_deleteMap.HasTemporaryMark();
}

bool MythPlayerUI::IsCutListSaved()
{
return m_deleteMap.IsSaved();
}

bool MythPlayerUI::DeleteMapHasUndo()
{
return m_deleteMap.HasUndo();
}

bool MythPlayerUI::DeleteMapHasRedo()
{
return m_deleteMap.HasRedo();
}

QString MythPlayerUI::DeleteMapGetUndoMessage()
{
return m_deleteMap.GetUndoMessage();
}

QString MythPlayerUI::DeleteMapGetRedoMessage()
{
return m_deleteMap.GetRedoMessage();
}

void MythPlayerUI::EnableEdit()
{
m_deleteMap.SetEditing(false);

if (!m_hasFullPositionMap)
{
LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot edit - no full position map");
SetOSDStatus(tr("No Seektable"), kOSDTimeout_Med);
return;
}

if (m_deleteMap.IsFileEditing())
return;

QMutexLocker locker(&m_osdLock);
SetupAudioGraph(m_videoFrameRate);

m_savedAudioTimecodeOffset = m_tcWrap[TC_AUDIO];
m_tcWrap[TC_AUDIO] = 0ms;

m_speedBeforeEdit = m_playSpeed;
m_pausedBeforeEdit = Pause();
m_deleteMap.SetEditing(true);
m_osd.DialogQuit();
ResetCaptions();
m_osd.HideAll();

bool loadedAutoSave = m_deleteMap.LoadAutoSaveMap();
if (loadedAutoSave)
UpdateOSDMessage(tr("Using previously auto-saved cuts"), kOSDTimeout_Short);

m_deleteMap.UpdateSeekAmount(0);
m_deleteMap.UpdateOSD(m_framesPlayed, m_videoFrameRate, &m_osd);
m_deleteMap.SetFileEditing(true);
m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
if (m_playerCtx->m_playingInfo)
m_playerCtx->m_playingInfo->SaveEditing(true);
m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
m_editUpdateTimer.start();
}

/*! \brief Leave cutlist edit mode, saving work in 1 of 3 ways.
*
* \param HowToSave If 1, save all changes. If 0, discard all
* changes. If -1, do not explicitly save changes but leave
* auto-save information intact in the database.
*/
void MythPlayerUI::DisableEdit(int HowToSave)
{
QMutexLocker locker(&m_osdLock);
m_deleteMap.SetEditing(false, &m_osd);
if (HowToSave == 0)
m_deleteMap.LoadMap();
// Unconditionally save to remove temporary marks from the DB.
if (HowToSave >= 0)
m_deleteMap.SaveMap();
m_deleteMap.TrackerReset(m_framesPlayed);
m_deleteMap.SetFileEditing(false);
m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
if (m_playerCtx->m_playingInfo)
m_playerCtx->m_playingInfo->SaveEditing(false);
m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
ClearAudioGraph();
m_tcWrap[TC_AUDIO] = m_savedAudioTimecodeOffset;
m_savedAudioTimecodeOffset = 0ms;

if (!m_pausedBeforeEdit)
Play(m_speedBeforeEdit);
else
SetOSDStatus(tr("Paused"), kOSDTimeout_None);
}

void MythPlayerUI::HandleArbSeek(bool Direction)
{
if (qFuzzyCompare(m_deleteMap.GetSeekAmount() + 1000.0F, 1000.0F -2.0F))
{
uint64_t framenum = m_deleteMap.GetNearestMark(m_framesPlayed, Direction);
if (Direction && (framenum > m_framesPlayed))
DoFastForward(framenum - m_framesPlayed, kInaccuracyNone);
else if (!Direction && (m_framesPlayed > framenum))
DoRewind(m_framesPlayed - framenum, kInaccuracyNone);
}
else
{
if (Direction)
DoFastForward(2, kInaccuracyFull);
else
DoRewind(2, kInaccuracyFull);
}
}

bool MythPlayerUI::HandleProgramEditorActions(QStringList& Actions)
{
bool handled = false;
bool refresh = true;
auto frame = GetFramesPlayed();

for (int i = 0; i < Actions.size() && !handled; i++)
{
QString action = Actions[i];
handled = true;
float seekamount = m_deleteMap.GetSeekAmount();
bool seekzero = qFuzzyCompare(seekamount + 1.0F, 1.0F);
if (action == ACTION_LEFT)
{
if (seekzero) // 1 frame
{
DoRewind(1, kInaccuracyNone);
}
else if (seekamount > 0)
{
// Use fully-accurate seeks for less than 1 second.
DoRewindSecs(seekamount, seekamount < 1.0F ? kInaccuracyNone :
kInaccuracyEditor, false);
}
else
{
HandleArbSeek(false);
}
}
else if (action == ACTION_RIGHT)
{
if (seekzero) // 1 frame
{
DoFastForward(1, kInaccuracyNone);
}
else if (seekamount > 0)
{
// Use fully-accurate seeks for less than 1 second.
DoFastForwardSecs(seekamount, seekamount < 1.0F ? kInaccuracyNone :
kInaccuracyEditor, false);
}
else
{
HandleArbSeek(true);
}
}
else if (action == ACTION_LOADCOMMSKIP)
{
if (m_commBreakMap.HasMap())
{
frm_dir_map_t map;
m_commBreakMap.GetMap(map);
m_deleteMap.LoadCommBreakMap(map);
}
}
else if (action == ACTION_PREVCUT)
{
float old_seekamount = m_deleteMap.GetSeekAmount();
m_deleteMap.SetSeekAmount(-2);
HandleArbSeek(false);
m_deleteMap.SetSeekAmount(old_seekamount);
}
else if (action == ACTION_NEXTCUT)
{
float old_seekamount = m_deleteMap.GetSeekAmount();
m_deleteMap.SetSeekAmount(-2);
HandleArbSeek(true);
m_deleteMap.SetSeekAmount(old_seekamount);
}
#define FFREW_MULTICOUNT 10.0F
else if (action == ACTION_BIGJUMPREW)
{
if (seekzero)
DoRewind(FFREW_MULTICOUNT, kInaccuracyNone);
else if (seekamount > 0)
DoRewindSecs(seekamount * FFREW_MULTICOUNT, kInaccuracyEditor, false);
else
DoRewindSecs(FFREW_MULTICOUNT / 2, kInaccuracyNone, false);
}
else if (action == ACTION_BIGJUMPFWD)
{
if (seekzero)
DoFastForward(FFREW_MULTICOUNT, kInaccuracyNone);
else if (seekamount > 0)
DoFastForwardSecs(seekamount * FFREW_MULTICOUNT, kInaccuracyEditor, false);
else
DoFastForwardSecs(FFREW_MULTICOUNT / 2, kInaccuracyNone, false);
}
else if (action == ACTION_SELECT)
{
m_deleteMap.NewCut(frame);
UpdateOSDMessage(tr("New cut added."), kOSDTimeout_Short);
refresh = true;
}
else if (action == "DELETE")
{
m_deleteMap.Delete(frame, tr("Delete"));
refresh = true;
}
else if (action == "REVERT")
{
m_deleteMap.LoadMap(tr("Undo Changes"));
refresh = true;
}
else if (action == "REVERTEXIT")
{
DisableEdit(0);
refresh = false;
}
else if (action == ACTION_SAVEMAP)
{
m_deleteMap.SaveMap();
refresh = true;
}
else if (action == "EDIT" || action == "SAVEEXIT")
{
DisableEdit(1);
refresh = false;
}
else
{
QString undoMessage = m_deleteMap.GetUndoMessage();
QString redoMessage = m_deleteMap.GetRedoMessage();
handled = m_deleteMap.HandleAction(action, frame);
if (handled && (action == "CUTTOBEGINNING" || action == "CUTTOEND" || action == "NEWCUT"))
UpdateOSDMessage(tr("New cut added."), kOSDTimeout_Short);
else if (handled && action == "UNDO")
UpdateOSDMessage(tr("Undo - %1").arg(undoMessage), kOSDTimeout_Short);
else if (handled && action == "REDO")
UpdateOSDMessage(tr("Redo - %1").arg(redoMessage), kOSDTimeout_Short);
}
}

if (handled && refresh)
{
m_osdLock.lock();
m_deleteMap.UpdateOSD(m_framesPlayed, m_videoFrameRate, &m_osd);
m_osdLock.unlock();
}

return handled;
}

26 changes: 2 additions & 24 deletions mythtv/libs/libmythtv/mythplayerui.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
#define MYTHPLAYERUI_H

// MythTV
#include "mythplayervisualiserui.h"
#include "mythplayereditorui.h"
#include "mythvideoscantracker.h"
#include "jitterometer.h"
#include "mythplayer.h"

class MTV_PUBLIC MythPlayerUI : public MythPlayerVisualiserUI, public MythVideoScanTracker
class MTV_PUBLIC MythPlayerUI : public MythPlayerEditorUI, public MythVideoScanTracker
{
Q_OBJECT

Expand Down Expand Up @@ -36,28 +36,11 @@ class MTV_PUBLIC MythPlayerUI : public MythPlayerVisualiserUI, public MythVideoS
bool ForceUpdate, int ReferenceFrames,
FrameScanType Scan = kScan_Ignore,
const QString& CodecName = QString()) override;
bool DoFastForwardSecs(float Seconds, double Inaccuracy, bool UseCutlist);
bool DoRewindSecs(float Seconds, double Inaccuracy, bool UseCutlist);
void GetPlaybackData(InfoMap& Map);
void GetCodecDescription(InfoMap& Map);
bool CanSupportDoubleRate();
void SetWatched(bool ForceWatched = false);

// N.B. Editor - keep ringfenced and move into subclass
void EnableEdit();
void DisableEdit(int HowToSave);
bool HandleProgramEditorActions(QStringList& Actions);
uint64_t GetNearestMark(uint64_t Frame, bool Right);
bool IsTemporaryMark(uint64_t Frame);
bool HasTemporaryMark();
bool IsCutListSaved();
bool DeleteMapHasUndo();
bool DeleteMapHasRedo();
QString DeleteMapGetUndoMessage();
QString DeleteMapGetRedoMessage();
void HandleArbSeek(bool Direction);
// End editor stuff

protected:
void InitFrameInterval() override;
virtual void DisplayPauseFrame();
Expand All @@ -72,11 +55,6 @@ class MTV_PUBLIC MythPlayerUI : public MythPlayerVisualiserUI, public MythVideoS

Jitterometer m_outputJmeter { "Player" };

// N.B. Editor - keep ringfenced and move into subclass
QElapsedTimer m_editUpdateTimer;
float m_speedBeforeEdit { 1.0 };
bool m_pausedBeforeEdit { false };

private:
Q_DISABLE_COPY(MythPlayerUI)

Expand Down