From ccf8878722725b66c78afdfdfa22d7be355f082f Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Wed, 29 Aug 2018 13:18:18 +0300 Subject: Dropped support for VDR 2.2.0. --- HISTORY | 3 +++ duplicates.c | 2 +- menu.c | 74 +----------------------------------------------------------- menu.h | 4 ---- recording.c | 12 ---------- 5 files changed, 5 insertions(+), 90 deletions(-) diff --git a/HISTORY b/HISTORY index 18348c8..bd393cf 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,9 @@ VDR Plugin 'duplicates' Revision History ---------------------------------------- +20??-??-??: Version 1.0.0 +- Dropped support for VDR 2.2.0. + 2018-08-29: Version 0.2.0 - Fixed compilation with VDR 2.4.0. diff --git a/duplicates.c b/duplicates.c index 254e272..f22de62 100644 --- a/duplicates.c +++ b/duplicates.c @@ -12,7 +12,7 @@ #include "menu.h" #include "visibility.h" -static const char *VERSION = "0.2.0"; +static const char *VERSION = "1.0.0-SNAPSHOT"; static const char *DESCRIPTION = trNOOP("Shows duplicate recordings"); static const char *MAINMENUENTRY = trNOOP("Duplicate recordings"); diff --git a/menu.c b/menu.c index 17ebe3f..88f180c 100644 --- a/menu.c +++ b/menu.c @@ -13,9 +13,7 @@ #include #include #include -#if VDRVERSNUM >= 20301 #include -#endif static inline cOsdItem *SeparatorItem(const char *Label) { cOsdItem *Item = new cOsdItem(cString::sprintf("----- %s -----", Label)); @@ -53,9 +51,7 @@ public: cMenuDuplicate::cMenuDuplicate(const cRecording *Recording) :cOsdMenu(trVDR("Recording info")) { -#if VDRVERSNUM >= 10728 SetMenuCategory(mcRecording); -#endif recording = Recording; SetHelp(trVDR("Button$Play")); } @@ -118,18 +114,9 @@ cMenuDuplicateItem::cMenuDuplicateItem(cDuplicateRecording *DuplicateRecording) // --- cMenuDuplicates ------------------------------------------------------- cMenuDuplicates::cMenuDuplicates() -#if defined LIEMIKUUTIO || VDRVERSNUM >= 10721 :cOsdMenu(tr("Duplicate recordings"), 9, 7, 7) -#else -:cOsdMenu(tr("Duplicate recordings"), 9, 7) -#endif { -#if VDRVERSNUM >= 10728 SetMenuCategory(mcRecording); -#endif -#if VDRVERSNUM < 20301 - Recordings.StateChanged(recordingsState); // just to get the current state -#endif helpKeys = -1; Set(); Display(); @@ -185,7 +172,6 @@ void cMenuDuplicates::Set(bool Refresh) { } } -#if VDRVERSNUM >= 20301 static bool HandleRemoteModifications(cTimer *NewTimer, cTimer *OldTimer = NULL) { cString ErrorMessage; if (!HandleRemoteTimerModifications(NewTimer, OldTimer, &ErrorMessage)) { @@ -194,41 +180,24 @@ static bool HandleRemoteModifications(cTimer *NewTimer, cTimer *OldTimer = NULL) } return true; } -#endif static bool TimerStillRecording(const char *FileName) { if (cRecordControl *rc = cRecordControls::GetRecordControl(FileName)) { // local timer if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) { -#if VDRVERSNUM >= 20301 LOCK_TIMERS_WRITE; -#endif if (cTimer *Timer = rc->Timer()) { Timer->Skip(); -#if VDRVERSNUM >= 20301 cRecordControls::Process(Timers, time(NULL)); -#else - cRecordControls::Process(time(NULL)); -#endif if (Timer->IsSingleEvent()) { -#if VDRVERSNUM >= 20301 Timers->Del(Timer); -#else - Timers.Del(Timer); -#endif isyslog("deleted timer %s", *Timer->ToDescr()); } -#if VDRVERSNUM >= 20301 Timers->SetModified(); -#else - Timers.SetModified(); -#endif } } else return true; // user didn't confirm deletion - } -#if VDRVERSNUM >= 20301 - else { + } else { // remote timer cString TimerId = GetRecordingTimerId(FileName); if (*TimerId) { @@ -257,7 +226,6 @@ static bool TimerStillRecording(const char *FileName) { } } } -#endif return false; } @@ -302,7 +270,6 @@ eOSState cMenuDuplicates::Delete(void) { if (Interface->Confirm(trVDR("Delete recording?"))) { if (TimerStillRecording(ri->FileName())) return osContinue; -#if VDRVERSNUM >= 20301 cString FileName; { LOCK_RECORDINGS_READ @@ -315,38 +282,17 @@ eOSState cMenuDuplicates::Delete(void) { } } RecordingsHandler.Del(FileName); // must do this w/o holding a lock, because the cleanup section in cDirCopier::Action() might request one! -#else - cString FileName = ri->FileName(); - if (RecordingsHandler.GetUsage(FileName)) { - if (Interface->Confirm(trVDR("Recording is being edited - really delete?"))) { - RecordingsHandler.Del(FileName); - } else - return osContinue; - } -#endif if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName) == 0) cControl::Shutdown(); -#if VDRVERSNUM >= 20301 cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); Recordings->SetExplicitModify(); cRecording *recording = Recordings->GetByName(FileName); -#else - cRecording *recording = Recordings.GetByName(FileName); -#endif if (!recording || recording->Delete()) { -#if VDRVERSNUM >= 20301 cReplayControl::ClearLastReplayed(FileName); Recordings->DelByName(FileName); -#else - cReplayControl::ClearLastReplayed(FileName); - Recordings.DelByName(FileName); - Recordings.StateChanged(recordingsState); // update state after deletion -#endif cVideoDiskUsage::ForceCheck(); -#if VDRVERSNUM >= 20301 Recordings->SetModified(); recordingsStateKey.Remove(); -#endif Del(Current()); SetHelpKeys(); Display(); @@ -362,18 +308,10 @@ eOSState cMenuDuplicates::Play(void) { return osContinue; cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); if (ri) { -#if VDRVERSNUM >= 20301 LOCK_RECORDINGS_READ; const cRecording *recording = Recordings->GetByName(ri->FileName()); -#else - cRecording *recording = Recordings.GetByName(ri->FileName()); -#endif if (recording) { -#if VDRVERSNUM >= 10728 cDuplicatesReplayControl::SetRecording(recording->FileName()); -#else - cDuplicatesReplayControl::SetRecording(recording->FileName(), recording->Title()); -#endif cControl::Shutdown(); cControl::Launch(new cDuplicatesReplayControl); return osEnd; @@ -395,12 +333,8 @@ eOSState cMenuDuplicates::Info(void) { return osContinue; cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); if (ri) { -#if VDRVERSNUM >= 20301 LOCK_RECORDINGS_READ; const cRecording *recording = Recordings->GetByName(ri->FileName()); -#else - cRecording *recording = Recordings.GetByName(ri->FileName()); -#endif if (recording && recording->Info()->Title()) return AddSubMenu(new cMenuDuplicate(recording)); } @@ -446,12 +380,8 @@ eOSState cMenuDuplicates::ProcessKey(eKeys Key) { } } if (!HasSubMenu()) { -#if VDRVERSNUM >= 20301 if (cRecordings::GetRecordingsRead(recordingsStateKey)) { recordingsStateKey.Remove(); -#else - if (Recordings.StateChanged(recordingsState)) { -#endif Set(true); } if (Key != kNone) @@ -463,9 +393,7 @@ eOSState cMenuDuplicates::ProcessKey(eKeys Key) { // --- cMenuSetupDuplicates -------------------------------------------------- cMenuSetupDuplicates::cMenuSetupDuplicates(cMenuDuplicates *MenuDuplicates) { -#if VDRVERSNUM >= 10728 SetMenuCategory(mcSetup); -#endif menuDuplicates = MenuDuplicates; Add(new cMenuEditBoolItem(tr("Compare title"), &dc.title)); Add(new cMenuEditBoolItem(tr("Show hidden"), &dc.hidden)); diff --git a/menu.h b/menu.h index 3044f72..2cb5f41 100644 --- a/menu.h +++ b/menu.h @@ -25,11 +25,7 @@ class cMenuSetupDuplicates; class cMenuDuplicates : public cOsdMenu { friend class cMenuSetupDuplicates; private: -#if VDRVERSNUM >= 20301 cStateKey recordingsStateKey; -#else - int recordingsState; -#endif int helpKeys; void SetHelpKeys(void); void Set(bool Refresh = false); diff --git a/recording.c b/recording.c index 086d3dc..96db78a 100644 --- a/recording.c +++ b/recording.c @@ -20,11 +20,7 @@ cDuplicateRecording::cDuplicateRecording(void) : visibility(NULL) { cDuplicateRecording::cDuplicateRecording(const cRecording *Recording) : visibility(Recording->FileName()) { checked = false; fileName = std::string(Recording->FileName()); -#if defined LIEMIKUUTIO && LIEMIKUUTIO < 131 - text = std::string(Recording->Title('\t', true, -1, false)); -#else text = std::string(Recording->Title('\t', true)); -#endif if (dc.title && Recording->Info()->Title()) title = std::string(Recording->Info()->Title()); else @@ -99,25 +95,17 @@ void cDuplicateRecordings::Update(void) { cList recordings; Clear(); { -#if VDRVERSNUM >= 20301 cStateKey recordingsStateKey; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! Recordings->Sort(); for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { -#else - cThreadLock RecordingsLock(&Recordings); - Recordings.Sort(); - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { -#endif cDuplicateRecording *Item = new cDuplicateRecording(recording); if (Item->HasDescription()) recordings.Add(Item); else if (dc.hidden || Item->Visibility().Read() != HIDDEN) descriptionless->Duplicates()->Add(Item); } -#if VDRVERSNUM >= 20301 recordingsStateKey.Remove(false); // sorting doesn't count as a real modification -#endif } for (cDuplicateRecording *recording = recordings.First(); recording; recording = recordings.Next(recording)) { if (!recording->Checked()) { -- cgit v1.2.3 From 1f68da4ab12ed7473208285fe7f98c8d0231a79b Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Thu, 30 Aug 2018 08:56:41 +0300 Subject: Added scanner thread for duplicates. --- HISTORY | 1 + duplicates.c | 4 +++- menu.c | 49 ++++++++++++++++++++++++------------------------- menu.h | 2 +- recording.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-------- recording.h | 22 ++++++++++++++++++++-- 6 files changed, 95 insertions(+), 37 deletions(-) diff --git a/HISTORY b/HISTORY index bd393cf..3e154dd 100644 --- a/HISTORY +++ b/HISTORY @@ -3,6 +3,7 @@ VDR Plugin 'duplicates' Revision History 20??-??-??: Version 1.0.0 - Dropped support for VDR 2.2.0. +- Added scanner thread for duplicates. 2018-08-29: Version 0.2.0 diff --git a/duplicates.c b/duplicates.c index f22de62..c1c5f12 100644 --- a/duplicates.c +++ b/duplicates.c @@ -10,7 +10,7 @@ #include #include "config.h" #include "menu.h" -#include "visibility.h" +#include "recording.h" static const char *VERSION = "1.0.0-SNAPSHOT"; static const char *DESCRIPTION = trNOOP("Shows duplicate recordings"); @@ -69,11 +69,13 @@ bool cPluginDuplicates::Initialize(void) { bool cPluginDuplicates::Start(void) { // Start any background activities the plugin shall perform. + DuplicateRecordingScanner.Start(); return true; } void cPluginDuplicates::Stop(void) { // Stop any background activities the plugin is performing. + DuplicateRecordingScanner.Stop(); } void cPluginDuplicates::Housekeeping(void) { diff --git a/menu.c b/menu.c index 88f180c..d2c8562 100644 --- a/menu.c +++ b/menu.c @@ -147,28 +147,29 @@ void cMenuDuplicates::SetHelpKeys(void) { } void cMenuDuplicates::Set(bool Refresh) { - DuplicateRecordings.Update(); - const char *CurrentRecording = NULL; - int currentIndex = -1; - if (Refresh) - currentIndex = Current(); - else - CurrentRecording = cReplayControl::LastReplayed(); - cMutexLock MutexLock(&DuplicateRecordings.mutex); - for (cDuplicateRecording *Duplicates = DuplicateRecordings.First(); Duplicates; Duplicates = DuplicateRecordings.Next(Duplicates)) { - Add(SeparatorItem(Duplicates->Text())); - for (cDuplicateRecording *Duplicate = Duplicates->Duplicates()->First(); Duplicate; Duplicate = Duplicates->Duplicates()->Next(Duplicate)) { - cMenuDuplicateItem *Item = new cMenuDuplicateItem(Duplicate); - Add(Item); - if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) - SetCurrent(Item); + if (DuplicateRecordings.Lock(duplicateRecordingsStateKey)) { + const char *CurrentRecording = NULL; + int currentIndex = -1; + if (Refresh) + currentIndex = Current(); + else + CurrentRecording = cReplayControl::LastReplayed(); + for (cDuplicateRecording *Duplicates = DuplicateRecordings.First(); Duplicates; Duplicates = DuplicateRecordings.Next(Duplicates)) { + Add(SeparatorItem(Duplicates->Text())); + for (cDuplicateRecording *Duplicate = Duplicates->Duplicates()->First(); Duplicate; Duplicate = Duplicates->Duplicates()->Next(Duplicate)) { + cMenuDuplicateItem *Item = new cMenuDuplicateItem(Duplicate); + Add(Item); + if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) + SetCurrent(Item); + } + } + duplicateRecordingsStateKey.Remove(); + if (Count() == 0) + Add(SeparatorItem(cString::sprintf(tr("%d duplicate recordings"), 0))); + if (Refresh) { + SetCurrentIndex(currentIndex); + Display(); } - } - if (Count() == 0) - Add(SeparatorItem(cString::sprintf(tr("%d duplicate recordings"), 0))); - if (Refresh) { - SetCurrentIndex(currentIndex); - Display(); } } @@ -284,6 +285,7 @@ eOSState cMenuDuplicates::Delete(void) { RecordingsHandler.Del(FileName); // must do this w/o holding a lock, because the cleanup section in cDirCopier::Action() might request one! if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName) == 0) cControl::Shutdown(); + cStateKey recordingsStateKey; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); Recordings->SetExplicitModify(); cRecording *recording = Recordings->GetByName(FileName); @@ -380,10 +382,7 @@ eOSState cMenuDuplicates::ProcessKey(eKeys Key) { } } if (!HasSubMenu()) { - if (cRecordings::GetRecordingsRead(recordingsStateKey)) { - recordingsStateKey.Remove(); - Set(true); - } + Set(true); if (Key != kNone) SetHelpKeys(); } diff --git a/menu.h b/menu.h index 2cb5f41..ac43d9b 100644 --- a/menu.h +++ b/menu.h @@ -25,7 +25,7 @@ class cMenuSetupDuplicates; class cMenuDuplicates : public cOsdMenu { friend class cMenuSetupDuplicates; private: - cStateKey recordingsStateKey; + cStateKey duplicateRecordingsStateKey; int helpKeys; void SetHelpKeys(void); void Set(bool Refresh = false); diff --git a/recording.c b/recording.c index 96db78a..4cb5f7d 100644 --- a/recording.c +++ b/recording.c @@ -81,21 +81,54 @@ bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) { // --- cDuplicateRecordings ------------------------------------------------------ -cDuplicateRecordings::cDuplicateRecordings(void) {} +cDuplicateRecordings::cDuplicateRecordings(void) : cList("duplicates") {} -void cDuplicateRecordings::Update(void) { +cDuplicateRecordings DuplicateRecordings; + +// --- cDuplicateRecordingScannerThread ------------------------------------------ + +cDuplicateRecordingScannerThread::cDuplicateRecordingScannerThread() : cThread("duplicate recording scanner", true) { + title = dc.title; + hidden = dc.hidden; +} + +cDuplicateRecordingScannerThread::~cDuplicateRecordingScannerThread(){ + Stop(); +} + +void cDuplicateRecordingScannerThread::Stop() { + Cancel(3); +} + +void cDuplicateRecordingScannerThread::Action(void) { + while (Running()) { + if (title != dc.title || hidden != dc.hidden) { + recordingsStateKey.Reset(); + title = dc.title; + hidden = dc.hidden; + } + if (cRecordings::GetRecordingsRead(recordingsStateKey)) { + recordingsStateKey.Remove(); + Scan(); + } + if (Running()) + cCondWait::SleepMs(250); + } +} + +void cDuplicateRecordingScannerThread::Scan(void) { struct timeval startTime, stopTime; gettimeofday(&startTime, NULL); - cMutexLock MutexLock(&mutex); + cStateKey duplicateRecordingsStateKey; + DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); #ifdef DEBUG_VISIBILITY cVisibility::ClearCounters(); int isDuplicateCount = 0; #endif cDuplicateRecording *descriptionless = new cDuplicateRecording(); cList recordings; - Clear(); + DuplicateRecordings.Clear(); { - cStateKey recordingsStateKey; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! Recordings->Sort(); for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { @@ -108,6 +141,10 @@ void cDuplicateRecordings::Update(void) { recordingsStateKey.Remove(false); // sorting doesn't count as a real modification } for (cDuplicateRecording *recording = recordings.First(); recording; recording = recordings.Next(recording)) { + if (!Running()) + return; + if (cIoThrottle::Engaged()) + cCondWait::SleepMs(100); if (!recording->Checked()) { recording->SetChecked(); cDuplicateRecording *duplicates = new cDuplicateRecording(); @@ -125,16 +162,17 @@ void cDuplicateRecordings::Update(void) { } if (duplicates->Duplicates()->Count() > 1) { duplicates->SetText(cString::sprintf(tr("%d duplicate recordings"), duplicates->Duplicates()->Count())); - Add(duplicates); + DuplicateRecordings.Add(duplicates); } else delete duplicates; } } if (descriptionless->Duplicates()->Count() > 0) { descriptionless->SetText(cString::sprintf(tr("%d recordings without description"), descriptionless->Duplicates()->Count())); - Add(descriptionless); + DuplicateRecordings.Add(descriptionless); } else delete descriptionless; + duplicateRecordingsStateKey.Remove(); gettimeofday(&stopTime, NULL); double seconds = (((long long)stopTime.tv_sec * 1000000 + stopTime.tv_usec) - ((long long)startTime.tv_sec * 1000000 + startTime.tv_usec)) / 1000000.0; #ifdef DEBUG_VISIBILITY @@ -145,5 +183,5 @@ void cDuplicateRecordings::Update(void) { #endif } -cDuplicateRecordings DuplicateRecordings; +cDuplicateRecordingScannerThread DuplicateRecordingScanner; diff --git a/recording.h b/recording.h index 0987af4..ce766cc 100644 --- a/recording.h +++ b/recording.h @@ -40,13 +40,31 @@ public: cList *Duplicates(void) { return duplicates; } }; +// --- cDuplicateRecordings ------------------------------------------------------ + class cDuplicateRecordings : public cList { public: cDuplicateRecordings(void); - cMutex mutex; - void Update(void); }; extern cDuplicateRecordings DuplicateRecordings; +// --- cDuplicateRecordingScannerThread ------------------------------------------ + +class cDuplicateRecordingScannerThread : public cThread { +private: + cStateKey recordingsStateKey; + int title; + int hidden; + void Scan(void); +protected: + virtual void Action(void); +public: + cDuplicateRecordingScannerThread(); + ~cDuplicateRecordingScannerThread(); + void Stop(void); +}; + +extern cDuplicateRecordingScannerThread DuplicateRecordingScanner; + #endif -- cgit v1.2.3 From 1a8bbe881248d1e060a13a635cea8f52ab2b14ce Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Fri, 31 Aug 2018 08:59:27 +0300 Subject: Updated kNone handling in main menu. --- menu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/menu.c b/menu.c index f80feac..341355d 100644 --- a/menu.c +++ b/menu.c @@ -379,11 +379,12 @@ eOSState cMenuDuplicates::ProcessKey(eKeys Key) { case kOk: case kInfo: return Info(); case kBlue: return ToggleHidden(); + case kNone: Set(true); + break; default: break; } } if (!HasSubMenu()) { - Set(true); if (Key != kNone) SetHelpKeys(); } -- cgit v1.2.3 From d2f7e660b4648e592690e31dc298ae353298fdfe Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Fri, 31 Aug 2018 10:20:32 +0300 Subject: Removed visibility debugging. --- recording.c | 12 ------------ visibility.c | 22 ---------------------- visibility.h | 8 -------- 3 files changed, 42 deletions(-) diff --git a/recording.c b/recording.c index 4cb5f7d..d318549 100644 --- a/recording.c +++ b/recording.c @@ -121,10 +121,6 @@ void cDuplicateRecordingScannerThread::Scan(void) { gettimeofday(&startTime, NULL); cStateKey duplicateRecordingsStateKey; DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); -#ifdef DEBUG_VISIBILITY - cVisibility::ClearCounters(); - int isDuplicateCount = 0; -#endif cDuplicateRecording *descriptionless = new cDuplicateRecording(); cList recordings; DuplicateRecordings.Clear(); @@ -151,9 +147,6 @@ void cDuplicateRecordingScannerThread::Scan(void) { duplicates->Duplicates()->Add(new cDuplicateRecording(*recording)); for (cDuplicateRecording *compare = recordings.First(); compare; compare = recordings.Next(compare)) { if (!compare->Checked()) { -#ifdef DEBUG_VISIBILITY - isDuplicateCount++; -#endif if (recording->IsDuplicate(compare)) { duplicates->Duplicates()->Add(new cDuplicateRecording(*compare)); compare->SetChecked(); @@ -175,12 +168,7 @@ void cDuplicateRecordingScannerThread::Scan(void) { duplicateRecordingsStateKey.Remove(); gettimeofday(&stopTime, NULL); double seconds = (((long long)stopTime.tv_sec * 1000000 + stopTime.tv_usec) - ((long long)startTime.tv_sec * 1000000 + startTime.tv_usec)) / 1000000.0; -#ifdef DEBUG_VISIBILITY - dsyslog("duplicates: Scanning of duplicates took %.2f seconds, is duplicate count %d, get count %d, read count %d, access count %d.", - seconds, isDuplicateCount, cVisibility::getCount, cVisibility::readCount, cVisibility::accessCount); -#else dsyslog("duplicates: Scanning of duplicates took %.2f seconds.", seconds); -#endif } cDuplicateRecordingScannerThread DuplicateRecordingScanner; diff --git a/visibility.c b/visibility.c index 35bdd97..1213f89 100644 --- a/visibility.c +++ b/visibility.c @@ -10,12 +10,6 @@ // --- cVisibility ----------------------------------------------------------- -#ifdef DEBUG_VISIBILITY -int cVisibility::getCount = 0; -int cVisibility::readCount = 0; -int cVisibility::accessCount = 0; -#endif - cVisibility::cVisibility(const char *fileName) { hiddenFileName = AddDirectory(fileName, "duplicates.hidden"); visibility = UNKNOWN; @@ -26,9 +20,6 @@ cVisibility::cVisibility(const cVisibility &Visibility) : visibility(Visibility.visibility) {} eVisibility cVisibility::Get(void) { -#ifdef DEBUG_VISIBILITY - getCount++; -#endif return visibility; } @@ -37,13 +28,7 @@ void cVisibility::Set(bool visible) { } eVisibility cVisibility::Read(void) { -#ifdef DEBUG_VISIBILITY - readCount++; -#endif if (visibility == UNKNOWN) { -#ifdef DEBUG_VISIBILITY - accessCount++; -#endif visibility = access(hiddenFileName, F_OK) == 0 ? HIDDEN : VISIBLE; } return visibility; @@ -66,10 +51,3 @@ bool cVisibility::Write(bool visible) { return false; } -#ifdef DEBUG_VISIBILITY -void cVisibility::ClearCounters(void) { - getCount = 0; - readCount = 0; - accessCount = 0; -} -#endif diff --git a/visibility.h b/visibility.h index dd29bf6..60d8b1d 100644 --- a/visibility.h +++ b/visibility.h @@ -9,8 +9,6 @@ #ifndef _DUPLICATES_VISIBILITY_H #define _DUPLICATES_VISIBILITY_H -//#define DEBUG_VISIBILITY - #include // --- eVisibility ----------------------------------------------------------- @@ -30,12 +28,6 @@ public: void Set(bool visible); eVisibility Read(void); bool Write(bool visible); -#ifdef DEBUG_VISIBILITY - static int getCount; - static int readCount; - static int accessCount; - static void ClearCounters(void); -#endif }; #endif -- cgit v1.2.3 From e12245cacc509ca76a9e2192a3c9c42be0a52861 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Sun, 2 Sep 2018 09:05:22 +0300 Subject: Use temporary list when scanning duplicate recordings. --- menu.c | 2 +- recording.c | 49 ++++++++++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/menu.c b/menu.c index 341355d..6160e96 100644 --- a/menu.c +++ b/menu.c @@ -286,7 +286,7 @@ eOSState cMenuDuplicates::Delete(void) { RecordingsHandler.Del(FileName); // must do this w/o holding a lock, because the cleanup section in cDirCopier::Action() might request one! if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName) == 0) cControl::Shutdown(); - cStateKey recordingsStateKey; + cStateKey recordingsStateKey; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); Recordings->SetExplicitModify(); cRecording *recording = Recordings->GetByName(FileName); diff --git a/recording.c b/recording.c index 1555640..5b98e82 100644 --- a/recording.c +++ b/recording.c @@ -96,7 +96,7 @@ cDuplicateRecordings DuplicateRecordings; cDuplicateRecordingScannerThread::cDuplicateRecordingScannerThread() : cThread("duplicate recording scanner", true) { title = dc.title; - hidden = dc.hidden; + hidden = dc.hidden; } cDuplicateRecordingScannerThread::~cDuplicateRecordingScannerThread(){ @@ -124,25 +124,22 @@ void cDuplicateRecordingScannerThread::Action(void) { } void cDuplicateRecordingScannerThread::Scan(void) { + dsyslog("duplicates: Scanning of duplicates started."); struct timeval startTime, stopTime; gettimeofday(&startTime, NULL); - cStateKey duplicateRecordingsStateKey; - DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); cDuplicateRecording *descriptionless = new cDuplicateRecording(); cList recordings; - DuplicateRecordings.Clear(); - { - cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! - Recordings->Sort(); - for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { - cDuplicateRecording *Item = new cDuplicateRecording(recording); - if (Item->HasDescription()) - recordings.Add(Item); - else if (dc.hidden || Item->Visibility().Read() != HIDDEN) - descriptionless->Duplicates()->Add(Item); - } - recordingsStateKey.Remove(false); // sorting doesn't count as a real modification + cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! + Recordings->Sort(); + for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { + cDuplicateRecording *Item = new cDuplicateRecording(recording); + if (Item->HasDescription()) + recordings.Add(Item); + else if (dc.hidden || Item->Visibility().Read() != HIDDEN) + descriptionless->Duplicates()->Add(Item); } + recordingsStateKey.Remove(false); // sorting doesn't count as a real modification + cList duplicates; for (cDuplicateRecording *recording = recordings.First(); recording; recording = recordings.Next(recording)) { if (!Running()) return; @@ -150,28 +147,34 @@ void cDuplicateRecordingScannerThread::Scan(void) { cCondWait::SleepMs(100); if (!recording->Checked()) { recording->SetChecked(); - cDuplicateRecording *duplicates = new cDuplicateRecording(); - duplicates->Duplicates()->Add(new cDuplicateRecording(*recording)); + cDuplicateRecording *duplicate = new cDuplicateRecording(); + duplicate->Duplicates()->Add(new cDuplicateRecording(*recording)); for (cDuplicateRecording *compare = recordings.First(); compare; compare = recordings.Next(compare)) { if (!compare->Checked()) { if (recording->IsDuplicate(compare)) { - duplicates->Duplicates()->Add(new cDuplicateRecording(*compare)); + duplicate->Duplicates()->Add(new cDuplicateRecording(*compare)); compare->SetChecked(); } } } - if (duplicates->Duplicates()->Count() > 1) { - duplicates->SetText(cString::sprintf(tr("%d duplicate recordings"), duplicates->Duplicates()->Count())); - DuplicateRecordings.Add(duplicates); + if (duplicate->Duplicates()->Count() > 1) { + duplicate->SetText(cString::sprintf(tr("%d duplicate recordings"), duplicate->Duplicates()->Count())); + duplicates.Add(duplicate); } else - delete duplicates; + delete duplicate; } } if (descriptionless->Duplicates()->Count() > 0) { descriptionless->SetText(cString::sprintf(tr("%d recordings without description"), descriptionless->Duplicates()->Count())); - DuplicateRecordings.Add(descriptionless); + duplicates.Add(descriptionless); } else delete descriptionless; + cStateKey duplicateRecordingsStateKey; + DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); + DuplicateRecordings.Clear(); + for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { + DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); + } duplicateRecordingsStateKey.Remove(); gettimeofday(&stopTime, NULL); double seconds = (((long long)stopTime.tv_sec * 1000000 + stopTime.tv_usec) - ((long long)startTime.tv_sec * 1000000 + startTime.tv_usec)) / 1000000.0; -- cgit v1.2.3 From c15444b2020a155f4101fc6b8e225cb317892423 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Sun, 2 Sep 2018 14:22:53 +0300 Subject: Improved logging. --- menu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/menu.c b/menu.c index 6160e96..6b2a1f9 100644 --- a/menu.c +++ b/menu.c @@ -148,6 +148,7 @@ void cMenuDuplicates::SetHelpKeys(void) { void cMenuDuplicates::Set(bool Refresh) { if (DuplicateRecordings.Lock(duplicateRecordingsStateKey)) { + dsyslog("duplicates: %s menu.", Refresh ? "Refreshing" : "Creating"); const char *CurrentRecording = NULL; int currentIndex = -1; if (Refresh) @@ -267,15 +268,14 @@ void cMenuDuplicates::Del(int index) { eOSState cMenuDuplicates::Delete(void) { if (HasSubMenu() || Count() == 0) return osContinue; - cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); - if (ri) { + if (cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current())) { + const char *FileName = ri->FileName(); if (Interface->Confirm(trVDR("Delete recording?"))) { - if (TimerStillRecording(ri->FileName())) + if (TimerStillRecording(FileName)) return osContinue; - cString FileName; { LOCK_RECORDINGS_READ - if (const cRecording *Recording = Recordings->GetByName(ri->FileName())) { + if (const cRecording *Recording = Recordings->GetByName(FileName)) { FileName = Recording->FileName(); if (RecordingsHandler.GetUsage(FileName)) { if (!Interface->Confirm(trVDR("Recording is being edited - really delete?"))) @@ -283,6 +283,7 @@ eOSState cMenuDuplicates::Delete(void) { } } } + dsyslog("duplicates: Deleting recording %s.", FileName); RecordingsHandler.Del(FileName); // must do this w/o holding a lock, because the cleanup section in cDirCopier::Action() might request one! if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName) == 0) cControl::Shutdown(); -- cgit v1.2.3 From e793e61250bc01c5c8ab30c61ee88b38ffe56429 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Sun, 2 Sep 2018 17:10:01 +0300 Subject: Abort duplicate scanning if recordings state has changed. --- menu.c | 6 +++--- recording.c | 29 ++++++++++++++++++++++------- recording.h | 1 + 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/menu.c b/menu.c index 44e197c..392e1cb 100644 --- a/menu.c +++ b/menu.c @@ -148,7 +148,7 @@ void cMenuDuplicates::SetHelpKeys(void) { void cMenuDuplicates::Set(bool Refresh) { if (DuplicateRecordings.Lock(duplicateRecordingsStateKey)) { - dsyslog("duplicates: %s menu.", Refresh ? "Refreshing" : "Creating"); + dsyslog("duplicates: %s menu.", Refresh ? "Refreshing" : "Creating"); const char *CurrentRecording = NULL; int currentIndex = -1; if (Refresh) @@ -269,7 +269,7 @@ eOSState cMenuDuplicates::Delete(void) { if (HasSubMenu() || Count() == 0) return osContinue; if (cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current())) { - const char *FileName = ri->FileName(); + const char *FileName = ri->FileName(); if (Interface->Confirm(trVDR("Delete recording?"))) { if (TimerStillRecording(FileName)) return osContinue; @@ -301,8 +301,8 @@ eOSState cMenuDuplicates::Delete(void) { SetHelpKeys(); Display(); } else { - Skins.Message(mtError, trVDR("Error while deleting recording!")); recordingsStateKey.Remove(); + Skins.Message(mtError, trVDR("Error while deleting recording!")); } } } diff --git a/recording.c b/recording.c index 5b98e82..6dee18c 100644 --- a/recording.c +++ b/recording.c @@ -103,7 +103,7 @@ cDuplicateRecordingScannerThread::~cDuplicateRecordingScannerThread(){ Stop(); } -void cDuplicateRecordingScannerThread::Stop() { +void cDuplicateRecordingScannerThread::Stop(void) { Cancel(3); } @@ -141,8 +141,10 @@ void cDuplicateRecordingScannerThread::Scan(void) { recordingsStateKey.Remove(false); // sorting doesn't count as a real modification cList duplicates; for (cDuplicateRecording *recording = recordings.First(); recording; recording = recordings.Next(recording)) { - if (!Running()) + if (!Running() || RecordingsStateChanged()) { + delete descriptionless; return; + } if (cIoThrottle::Engaged()) cCondWait::SleepMs(100); if (!recording->Checked()) { @@ -171,15 +173,28 @@ void cDuplicateRecordingScannerThread::Scan(void) { delete descriptionless; cStateKey duplicateRecordingsStateKey; DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); - DuplicateRecordings.Clear(); - for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { - DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); - } - duplicateRecordingsStateKey.Remove(); + if (!RecordingsStateChanged()) { + DuplicateRecordings.Clear(); + for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { + DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); + } + duplicateRecordingsStateKey.Remove(); + } else + duplicateRecordingsStateKey.Remove(false); gettimeofday(&stopTime, NULL); double seconds = (((long long)stopTime.tv_sec * 1000000 + stopTime.tv_usec) - ((long long)startTime.tv_sec * 1000000 + startTime.tv_usec)) / 1000000.0; dsyslog("duplicates: Scanning of duplicates took %.2f seconds.", seconds); } +bool cDuplicateRecordingScannerThread::RecordingsStateChanged(void) { + if (cRecordings::GetRecordingsRead(recordingsStateKey)) { + recordingsStateKey.Reset(); + recordingsStateKey.Remove(); + dsyslog("duplicates: Recordings state changed while scanning."); + return true; + } + return false; +} + cDuplicateRecordingScannerThread DuplicateRecordingScanner; diff --git a/recording.h b/recording.h index ce766cc..0a93dfb 100644 --- a/recording.h +++ b/recording.h @@ -57,6 +57,7 @@ private: int title; int hidden; void Scan(void); + bool RecordingsStateChanged(void); protected: virtual void Action(void); public: -- cgit v1.2.3 From 143c520f9894e777b95a72a65b1261922001c7b0 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Mon, 3 Sep 2018 09:54:41 +0300 Subject: Wait if recordings state changed while scanning. --- recording.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/recording.c b/recording.c index 6dee18c..e670289 100644 --- a/recording.c +++ b/recording.c @@ -119,7 +119,7 @@ void cDuplicateRecordingScannerThread::Action(void) { Scan(); } if (Running()) - cCondWait::SleepMs(250); + cCondWait::SleepMs(500); } } @@ -171,16 +171,15 @@ void cDuplicateRecordingScannerThread::Scan(void) { duplicates.Add(descriptionless); } else delete descriptionless; + if (RecordingsStateChanged()) + return; cStateKey duplicateRecordingsStateKey; DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); - if (!RecordingsStateChanged()) { - DuplicateRecordings.Clear(); - for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { - DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); - } - duplicateRecordingsStateKey.Remove(); - } else - duplicateRecordingsStateKey.Remove(false); + DuplicateRecordings.Clear(); + for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { + DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); + } + duplicateRecordingsStateKey.Remove(); gettimeofday(&stopTime, NULL); double seconds = (((long long)stopTime.tv_sec * 1000000 + stopTime.tv_usec) - ((long long)startTime.tv_sec * 1000000 + startTime.tv_usec)) / 1000000.0; dsyslog("duplicates: Scanning of duplicates took %.2f seconds.", seconds); @@ -191,6 +190,7 @@ bool cDuplicateRecordingScannerThread::RecordingsStateChanged(void) { recordingsStateKey.Reset(); recordingsStateKey.Remove(); dsyslog("duplicates: Recordings state changed while scanning."); + cCondWait::SleepMs(500); return true; } return false; -- cgit v1.2.3 From 170e9ab1b4f04303ae7de32a858730dc595ba6fa Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Mon, 3 Sep 2018 11:35:43 +0300 Subject: Added removal of deleted recordings method. --- menu.c | 37 ++++++++++--------------------------- menu.h | 1 - recording.c | 22 +++++++++++++++++++++- recording.h | 1 + 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/menu.c b/menu.c index 392e1cb..d584994 100644 --- a/menu.c +++ b/menu.c @@ -247,24 +247,6 @@ void cMenuDuplicates::SetCurrentIndex(int index) { } } -void cMenuDuplicates::Del(int index) { - cOsdMenu::Del(index); - // remove items that have less than 2 duplicates - int d = 0; - for (int i = Count() - 1; i >= 0; i--) { - if (!SelectableItem(i)) { - if (d < 2) { - for (int j = 0; j <= d; j++) { - cOsdMenu::Del(i); - } - } - d = 0; - } else - d++; - } - SetCurrentIndex(index); -} - eOSState cMenuDuplicates::Delete(void) { if (HasSubMenu() || Count() == 0) return osContinue; @@ -297,9 +279,11 @@ eOSState cMenuDuplicates::Delete(void) { cVideoDiskUsage::ForceCheck(); Recordings->SetModified(); recordingsStateKey.Remove(); - Del(Current()); + cStateKey stateKey; + DuplicateRecordings.Lock(stateKey, true); + stateKey.Remove(DuplicateRecordings.RemoveDeleted()); + Set(true); SetHelpKeys(); - Display(); } else { recordingsStateKey.Remove(); Skins.Message(mtError, trVDR("Error while deleting recording!")); @@ -355,14 +339,13 @@ eOSState cMenuDuplicates::ToggleHidden(void) { bool hidden = ri->Visibility().Read() == HIDDEN; if (Interface->Confirm(hidden ? tr("Unhide recording?") : tr("Hide recording?"))) { if (ri->Visibility().Write(hidden)) { - if (dc.hidden) { - ri->Visibility().Set(!hidden); - SetHelpKeys(); - } else { - Del(Current()); - SetHelpKeys(); - Display(); + if (!dc.hidden) { + cStateKey stateKey; + DuplicateRecordings.Lock(stateKey, true); + stateKey.Remove(DuplicateRecordings.RemoveDeleted()); + Set(true); } + SetHelpKeys(); } else Skins.Message(mtError, tr("Error while setting visibility!")); } diff --git a/menu.h b/menu.h index ac43d9b..9d24481 100644 --- a/menu.h +++ b/menu.h @@ -30,7 +30,6 @@ private: void SetHelpKeys(void); void Set(bool Refresh = false); void SetCurrentIndex(int index); - void Del(int index); eOSState Play(void); eOSState Setup(void); eOSState Delete(void); diff --git a/recording.c b/recording.c index e670289..05cad27 100644 --- a/recording.c +++ b/recording.c @@ -90,6 +90,24 @@ bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) { cDuplicateRecordings::cDuplicateRecordings(void) : cList("duplicates") {} +bool cDuplicateRecordings::RemoveDeleted(void) { + LOCK_RECORDINGS_READ + int removed = 0; + for (cDuplicateRecording *duplicates = First(); duplicates; duplicates = Next(duplicates)) { + for (cDuplicateRecording *duplicate = duplicates->Duplicates()->First(); duplicate; duplicate = duplicates->Duplicates()->Next(duplicate)) { + const cRecording *recording = Recordings->GetByName(duplicate->FileName().c_str()); + if (!recording || !dc.hidden && duplicate->Visibility().Read() == HIDDEN) { + duplicates->Duplicates()->Del(duplicate); + removed++; + } + } + if (duplicates->Duplicates()->Count() < 2) + Del(duplicates); + } + dsyslog("duplicates: Removed %d deleted recordings.", removed); + return removed > 0; +} + cDuplicateRecordings DuplicateRecordings; // --- cDuplicateRecordingScannerThread ------------------------------------------ @@ -127,6 +145,9 @@ void cDuplicateRecordingScannerThread::Scan(void) { dsyslog("duplicates: Scanning of duplicates started."); struct timeval startTime, stopTime; gettimeofday(&startTime, NULL); + cStateKey duplicateRecordingsStateKey; + DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); + duplicateRecordingsStateKey.Remove(DuplicateRecordings.RemoveDeleted()); cDuplicateRecording *descriptionless = new cDuplicateRecording(); cList recordings; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! @@ -173,7 +194,6 @@ void cDuplicateRecordingScannerThread::Scan(void) { delete descriptionless; if (RecordingsStateChanged()) return; - cStateKey duplicateRecordingsStateKey; DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); DuplicateRecordings.Clear(); for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { diff --git a/recording.h b/recording.h index 0a93dfb..1d2ffb2 100644 --- a/recording.h +++ b/recording.h @@ -45,6 +45,7 @@ public: class cDuplicateRecordings : public cList { public: cDuplicateRecordings(void); + bool RemoveDeleted(void); }; extern cDuplicateRecordings DuplicateRecordings; -- cgit v1.2.3 From fd9080c0778c5145842bbcd5d0ab14faca3956d0 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Mon, 3 Sep 2018 12:26:02 +0300 Subject: Expose std::string in cDuplicateRecording. --- menu.c | 4 ++-- recording.c | 4 ++-- recording.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/menu.c b/menu.c index d584994..def6110 100644 --- a/menu.c +++ b/menu.c @@ -108,7 +108,7 @@ public: cMenuDuplicateItem::cMenuDuplicateItem(cDuplicateRecording *DuplicateRecording) : visibility(DuplicateRecording->Visibility()) { fileName = DuplicateRecording->FileName(); - SetText(DuplicateRecording->Text()); + SetText(DuplicateRecording->Text().c_str()); } // --- cMenuDuplicates ------------------------------------------------------- @@ -157,7 +157,7 @@ void cMenuDuplicates::Set(bool Refresh) { CurrentRecording = cReplayControl::LastReplayed(); Clear(); for (cDuplicateRecording *Duplicates = DuplicateRecordings.First(); Duplicates; Duplicates = DuplicateRecordings.Next(Duplicates)) { - Add(SeparatorItem(Duplicates->Text())); + Add(SeparatorItem(Duplicates->Text().c_str())); for (cDuplicateRecording *Duplicate = Duplicates->Duplicates()->First(); Duplicate; Duplicate = Duplicates->Duplicates()->Next(Duplicate)) { cMenuDuplicateItem *Item = new cMenuDuplicateItem(Duplicate); Add(Item); diff --git a/recording.c b/recording.c index 05cad27..b1762e1 100644 --- a/recording.c +++ b/recording.c @@ -181,14 +181,14 @@ void cDuplicateRecordingScannerThread::Scan(void) { } } if (duplicate->Duplicates()->Count() > 1) { - duplicate->SetText(cString::sprintf(tr("%d duplicate recordings"), duplicate->Duplicates()->Count())); + duplicate->SetText(std::string(cString::sprintf(tr("%d duplicate recordings"), duplicate->Duplicates()->Count()))); duplicates.Add(duplicate); } else delete duplicate; } } if (descriptionless->Duplicates()->Count() > 0) { - descriptionless->SetText(cString::sprintf(tr("%d recordings without description"), descriptionless->Duplicates()->Count())); + descriptionless->SetText(std::string(cString::sprintf(tr("%d recordings without description"), descriptionless->Duplicates()->Count()))); duplicates.Add(descriptionless); } else delete descriptionless; diff --git a/recording.h b/recording.h index 1d2ffb2..37ec660 100644 --- a/recording.h +++ b/recording.h @@ -35,8 +35,8 @@ public: bool Checked() { return checked; } cVisibility Visibility() { return visibility; } std::string FileName(void) { return fileName; } - void SetText(const char *t) { text = std::string(t); } - const char *Text(void) { return text.c_str(); } + void SetText(std::string t) { text = t; } + std::string Text(void) { return text; } cList *Duplicates(void) { return duplicates; } }; -- cgit v1.2.3 From 7a15b576e0c71258506e37e7e522a6763f3529a0 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Wed, 5 Sep 2018 08:25:54 +0300 Subject: Logging changes. --- recording.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/recording.c b/recording.c index b1762e1..666f499 100644 --- a/recording.c +++ b/recording.c @@ -91,10 +91,11 @@ bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) { cDuplicateRecordings::cDuplicateRecordings(void) : cList("duplicates") {} bool cDuplicateRecordings::RemoveDeleted(void) { - LOCK_RECORDINGS_READ + dsyslog("duplicates: Removing deleted recordings."); int removed = 0; for (cDuplicateRecording *duplicates = First(); duplicates; duplicates = Next(duplicates)) { for (cDuplicateRecording *duplicate = duplicates->Duplicates()->First(); duplicate; duplicate = duplicates->Duplicates()->Next(duplicate)) { + LOCK_RECORDINGS_READ const cRecording *recording = Recordings->GetByName(duplicate->FileName().c_str()); if (!recording || !dc.hidden && duplicate->Visibility().Read() == HIDDEN) { duplicates->Duplicates()->Del(duplicate); @@ -142,7 +143,7 @@ void cDuplicateRecordingScannerThread::Action(void) { } void cDuplicateRecordingScannerThread::Scan(void) { - dsyslog("duplicates: Scanning of duplicates started."); + dsyslog("duplicates: Scanning of duplicate recordings started."); struct timeval startTime, stopTime; gettimeofday(&startTime, NULL); cStateKey duplicateRecordingsStateKey; @@ -202,7 +203,7 @@ void cDuplicateRecordingScannerThread::Scan(void) { duplicateRecordingsStateKey.Remove(); gettimeofday(&stopTime, NULL); double seconds = (((long long)stopTime.tv_sec * 1000000 + stopTime.tv_usec) - ((long long)startTime.tv_sec * 1000000 + startTime.tv_usec)) / 1000000.0; - dsyslog("duplicates: Scanning of duplicates took %.2f seconds.", seconds); + dsyslog("duplicates: Scanning of duplicate recordings took %.2f seconds.", seconds); } bool cDuplicateRecordingScannerThread::RecordingsStateChanged(void) { -- cgit v1.2.3 From 3f0ea3e26158e52cb8e6306cca6301bd18e3f687 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Thu, 6 Sep 2018 22:03:03 +0300 Subject: Fixed deleted recording removal. --- menu.c | 8 ++------ recording.c | 41 ++++++++++++++++++++++++----------------- recording.h | 2 +- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/menu.c b/menu.c index a5ec3d3..ca3ad71 100644 --- a/menu.c +++ b/menu.c @@ -297,9 +297,7 @@ eOSState cMenuDuplicates::Delete(void) { cVideoDiskUsage::ForceCheck(); Recordings->SetModified(); recordingsStateKey.Remove(); - cStateKey stateKey; - DuplicateRecordings.Lock(stateKey, true); - stateKey.Remove(DuplicateRecordings.RemoveDeleted()); + DuplicateRecordings.RemoveDeleted(); Set(true); SetHelpKeys(); } else { @@ -366,9 +364,7 @@ eOSState cMenuDuplicates::ToggleHidden(void) { if (Interface->Confirm(hidden ? tr("Unhide recording?") : tr("Hide recording?"))) { if (ri->Visibility().Write(hidden)) { if (!dc.hidden) { - cStateKey stateKey; - DuplicateRecordings.Lock(stateKey, true); - stateKey.Remove(DuplicateRecordings.RemoveDeleted()); + DuplicateRecordings.RemoveDeleted(); Set(true); } SetHelpKeys(); diff --git a/recording.c b/recording.c index c3a6ae9..1490494 100644 --- a/recording.c +++ b/recording.c @@ -53,7 +53,7 @@ cDuplicateRecording::cDuplicateRecording(const cDuplicateRecording &DuplicateRec text(DuplicateRecording.text), title(DuplicateRecording.title), description(DuplicateRecording.description) { - if (DuplicateRecording.duplicates != NULL) { + if (DuplicateRecording.duplicates != NULL && DuplicateRecording.duplicates->Count() > 0) { duplicates = new cList; for (const cDuplicateRecording *duplicate = DuplicateRecording.duplicates->First(); duplicate; duplicate = DuplicateRecording.duplicates->Next(duplicate)) { if (duplicate) @@ -91,27 +91,35 @@ bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) { cDuplicateRecordings::cDuplicateRecordings(void) : cList("duplicates") {} -bool cDuplicateRecordings::RemoveDeleted(void) { - dsyslog("duplicates: Removing deleted recordings."); - int removed = 0; - for (cDuplicateRecording *duplicates = First(); duplicates; duplicates = Next(duplicates)) { - if (duplicates) { - for (cDuplicateRecording *duplicate = duplicates->Duplicates()->First(); duplicate; duplicate = duplicates->Duplicates()->Next(duplicate)) { - if (duplicate) { +void cDuplicateRecordings::RemoveDeleted(void) { + dsyslog("duplicates: Checking %d duplicate recordings while removing deleted recordings.", Count()); + cStateKey duplicateRecordingsStateKey; + Lock(duplicateRecordingsStateKey, true); + int rr = 0, rd = 0; + for (cDuplicateRecording *dr = First(); dr;) { + if (dr && dr->Duplicates()) { + cDuplicateRecording *duplicateRecording = dr; + dr = Next(dr); + for (cDuplicateRecording *d = duplicateRecording->Duplicates()->First(); d;) { + if (d) { + cDuplicateRecording *duplicate = d; + d = duplicateRecording->Duplicates()->Next(d); LOCK_RECORDINGS_READ const cRecording *recording = Recordings->GetByName(duplicate->FileName().c_str()); if (!recording || !dc.hidden && duplicate->Visibility().Read() == HIDDEN) { - duplicates->Duplicates()->Del(duplicate); - removed++; + duplicateRecording->Duplicates()->Del(duplicate); + rr++; } } } - if (duplicates->Duplicates()->Count() < 2) - Del(duplicates); + if (duplicateRecording->Duplicates()->Count() < 2) { + Del(duplicateRecording); + rd++; + } } } - dsyslog("duplicates: Removed %d deleted recordings.", removed); - return removed > 0; + duplicateRecordingsStateKey.Remove(rr > 0); + dsyslog("duplicates: Removed %d deleted recordings and %d duplicate recordings.", rr, rd); } cDuplicateRecordings DuplicateRecordings; @@ -151,9 +159,7 @@ void cDuplicateRecordingScannerThread::Scan(void) { dsyslog("duplicates: Scanning of duplicate recordings started."); struct timeval startTime, stopTime; gettimeofday(&startTime, NULL); - cStateKey duplicateRecordingsStateKey; - DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); - duplicateRecordingsStateKey.Remove(DuplicateRecordings.RemoveDeleted()); + DuplicateRecordings.RemoveDeleted(); cDuplicateRecording *descriptionless = new cDuplicateRecording(); cList recordings; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! @@ -202,6 +208,7 @@ void cDuplicateRecordingScannerThread::Scan(void) { delete descriptionless; if (RecordingsStateChanged()) return; + cStateKey duplicateRecordingsStateKey; DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); DuplicateRecordings.Clear(); for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { diff --git a/recording.h b/recording.h index 37ec660..cb08e2e 100644 --- a/recording.h +++ b/recording.h @@ -45,7 +45,7 @@ public: class cDuplicateRecordings : public cList { public: cDuplicateRecordings(void); - bool RemoveDeleted(void); + void RemoveDeleted(void); }; extern cDuplicateRecordings DuplicateRecordings; -- cgit v1.2.3 From b137e467c469853d6ddd6fa5200663e113cba9ac Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Thu, 6 Sep 2018 22:22:01 +0300 Subject: Removed some superfluous code. --- menu.c | 16 ++++++---------- recording.c | 40 +++++++++++++++++----------------------- 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/menu.c b/menu.c index ca3ad71..e26ee05 100644 --- a/menu.c +++ b/menu.c @@ -176,16 +176,12 @@ void cMenuDuplicates::Set(bool Refresh) { CurrentRecording = cReplayControl::LastReplayed(); Clear(); for (cDuplicateRecording *Duplicates = DuplicateRecordings.First(); Duplicates; Duplicates = DuplicateRecordings.Next(Duplicates)) { - if (Duplicates) { - Add(SeparatorItem(Duplicates->Text().c_str())); - for (cDuplicateRecording *Duplicate = Duplicates->Duplicates()->First(); Duplicate; Duplicate = Duplicates->Duplicates()->Next(Duplicate)) { - if (Duplicate) { - cMenuDuplicateItem *Item = new cMenuDuplicateItem(Duplicate); - Add(Item); - if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) - SetCurrent(Item); - } - } + Add(SeparatorItem(Duplicates->Text().c_str())); + for (cDuplicateRecording *Duplicate = Duplicates->Duplicates()->First(); Duplicate; Duplicate = Duplicates->Duplicates()->Next(Duplicate)) { + cMenuDuplicateItem *Item = new cMenuDuplicateItem(Duplicate); + Add(Item); + if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) + SetCurrent(Item); } } duplicateRecordingsStateKey.Remove(); diff --git a/recording.c b/recording.c index 1490494..59aee2f 100644 --- a/recording.c +++ b/recording.c @@ -56,8 +56,7 @@ cDuplicateRecording::cDuplicateRecording(const cDuplicateRecording &DuplicateRec if (DuplicateRecording.duplicates != NULL && DuplicateRecording.duplicates->Count() > 0) { duplicates = new cList; for (const cDuplicateRecording *duplicate = DuplicateRecording.duplicates->First(); duplicate; duplicate = DuplicateRecording.duplicates->Next(duplicate)) { - if (duplicate) - duplicates->Add(new cDuplicateRecording(*duplicate)); + duplicates->Add(new cDuplicateRecording(*duplicate)); } } else duplicates = NULL; @@ -97,19 +96,17 @@ void cDuplicateRecordings::RemoveDeleted(void) { Lock(duplicateRecordingsStateKey, true); int rr = 0, rd = 0; for (cDuplicateRecording *dr = First(); dr;) { - if (dr && dr->Duplicates()) { + if (dr->Duplicates()) { cDuplicateRecording *duplicateRecording = dr; dr = Next(dr); for (cDuplicateRecording *d = duplicateRecording->Duplicates()->First(); d;) { - if (d) { - cDuplicateRecording *duplicate = d; - d = duplicateRecording->Duplicates()->Next(d); - LOCK_RECORDINGS_READ - const cRecording *recording = Recordings->GetByName(duplicate->FileName().c_str()); - if (!recording || !dc.hidden && duplicate->Visibility().Read() == HIDDEN) { - duplicateRecording->Duplicates()->Del(duplicate); - rr++; - } + cDuplicateRecording *duplicate = d; + d = duplicateRecording->Duplicates()->Next(d); + LOCK_RECORDINGS_READ + const cRecording *recording = Recordings->GetByName(duplicate->FileName().c_str()); + if (!recording || !dc.hidden && duplicate->Visibility().Read() == HIDDEN) { + duplicateRecording->Duplicates()->Del(duplicate); + rr++; } } if (duplicateRecording->Duplicates()->Count() < 2) { @@ -165,13 +162,11 @@ void cDuplicateRecordingScannerThread::Scan(void) { cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! Recordings->Sort(); for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { - if (recording) { - cDuplicateRecording *Item = new cDuplicateRecording(recording); - if (Item->HasDescription()) - recordings.Add(Item); - else if (dc.hidden || Item->Visibility().Read() != HIDDEN) - descriptionless->Duplicates()->Add(Item); - } + cDuplicateRecording *Item = new cDuplicateRecording(recording); + if (Item->HasDescription()) + recordings.Add(Item); + else if (dc.hidden || Item->Visibility().Read() != HIDDEN) + descriptionless->Duplicates()->Add(Item); } recordingsStateKey.Remove(false); // sorting doesn't count as a real modification cList duplicates; @@ -182,12 +177,12 @@ void cDuplicateRecordingScannerThread::Scan(void) { } if (cIoThrottle::Engaged()) cCondWait::SleepMs(100); - if (recording &&!recording->Checked()) { + if (!recording->Checked()) { recording->SetChecked(); cDuplicateRecording *duplicate = new cDuplicateRecording(); duplicate->Duplicates()->Add(new cDuplicateRecording(*recording)); for (cDuplicateRecording *compare = recordings.First(); compare; compare = recordings.Next(compare)) { - if (compare && !compare->Checked()) { + if (!compare->Checked()) { if (recording->IsDuplicate(compare)) { duplicate->Duplicates()->Add(new cDuplicateRecording(*compare)); compare->SetChecked(); @@ -212,8 +207,7 @@ void cDuplicateRecordingScannerThread::Scan(void) { DuplicateRecordings.Lock(duplicateRecordingsStateKey, true); DuplicateRecordings.Clear(); for (cDuplicateRecording *duplicate = duplicates.First(); duplicate; duplicate = duplicates.Next(duplicate)) { - if (duplicate) - DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); + DuplicateRecordings.Add(new cDuplicateRecording(*duplicate)); } duplicateRecordingsStateKey.Remove(); gettimeofday(&stopTime, NULL); -- cgit v1.2.3 From 1319c9dfac793756aa84fa584fbe65908dd374fa Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Fri, 7 Sep 2018 21:47:55 +0300 Subject: Fixed duplicate recording count after deletion and hiding. --- menu.c | 4 ++-- recording.c | 24 +++++++++++++----------- recording.h | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/menu.c b/menu.c index e26ee05..ef451f5 100644 --- a/menu.c +++ b/menu.c @@ -293,7 +293,7 @@ eOSState cMenuDuplicates::Delete(void) { cVideoDiskUsage::ForceCheck(); Recordings->SetModified(); recordingsStateKey.Remove(); - DuplicateRecordings.RemoveDeleted(); + DuplicateRecordings.Remove(std::string(FileName)); Set(true); SetHelpKeys(); } else { @@ -360,7 +360,7 @@ eOSState cMenuDuplicates::ToggleHidden(void) { if (Interface->Confirm(hidden ? tr("Unhide recording?") : tr("Hide recording?"))) { if (ri->Visibility().Write(hidden)) { if (!dc.hidden) { - DuplicateRecordings.RemoveDeleted(); + DuplicateRecordings.Remove(std::string(ri->FileName())); Set(true); } SetHelpKeys(); diff --git a/recording.c b/recording.c index 59aee2f..0217b1e 100644 --- a/recording.c +++ b/recording.c @@ -90,21 +90,18 @@ bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) { cDuplicateRecordings::cDuplicateRecordings(void) : cList("duplicates") {} -void cDuplicateRecordings::RemoveDeleted(void) { - dsyslog("duplicates: Checking %d duplicate recordings while removing deleted recordings.", Count()); +void cDuplicateRecordings::Remove(std::string fileName) { cStateKey duplicateRecordingsStateKey; Lock(duplicateRecordingsStateKey, true); int rr = 0, rd = 0; for (cDuplicateRecording *dr = First(); dr;) { - if (dr->Duplicates()) { - cDuplicateRecording *duplicateRecording = dr; - dr = Next(dr); + cDuplicateRecording *duplicateRecording = dr; + dr = Next(dr); + if (duplicateRecording->Duplicates()) { for (cDuplicateRecording *d = duplicateRecording->Duplicates()->First(); d;) { cDuplicateRecording *duplicate = d; d = duplicateRecording->Duplicates()->Next(d); - LOCK_RECORDINGS_READ - const cRecording *recording = Recordings->GetByName(duplicate->FileName().c_str()); - if (!recording || !dc.hidden && duplicate->Visibility().Read() == HIDDEN) { + if (duplicate->FileName() == fileName) { duplicateRecording->Duplicates()->Del(duplicate); rr++; } @@ -112,11 +109,17 @@ void cDuplicateRecordings::RemoveDeleted(void) { if (duplicateRecording->Duplicates()->Count() < 2) { Del(duplicateRecording); rd++; - } + } else if (duplicateRecording->HasDescription()) { + duplicateRecording->SetText(std::string(cString::sprintf(tr("%d duplicate recordings"), duplicateRecording->Duplicates()->Count()))); + } else + duplicateRecording->SetText(std::string(cString::sprintf(tr("%d recordings without description"), duplicateRecording->Duplicates()->Count()))); + } else { + Del(duplicateRecording); + rd++; } } duplicateRecordingsStateKey.Remove(rr > 0); - dsyslog("duplicates: Removed %d deleted recordings and %d duplicate recordings.", rr, rd); + dsyslog("duplicates: Removed %d recordings and %d duplicate recordings.", rr, rd); } cDuplicateRecordings DuplicateRecordings; @@ -156,7 +159,6 @@ void cDuplicateRecordingScannerThread::Scan(void) { dsyslog("duplicates: Scanning of duplicate recordings started."); struct timeval startTime, stopTime; gettimeofday(&startTime, NULL); - DuplicateRecordings.RemoveDeleted(); cDuplicateRecording *descriptionless = new cDuplicateRecording(); cList recordings; cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting! diff --git a/recording.h b/recording.h index cb08e2e..18a666f 100644 --- a/recording.h +++ b/recording.h @@ -45,7 +45,7 @@ public: class cDuplicateRecordings : public cList { public: cDuplicateRecordings(void); - void RemoveDeleted(void); + void Remove(std::string fileName); }; extern cDuplicateRecordings DuplicateRecordings; -- cgit v1.2.3 From 1ec4bc9a669072ce536433fd9fc38b5223f3f3c7 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Fri, 7 Sep 2018 21:49:24 +0300 Subject: Updated version. --- duplicates.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/duplicates.c b/duplicates.c index c1c5f12..7ffbeff 100644 --- a/duplicates.c +++ b/duplicates.c @@ -12,7 +12,7 @@ #include "menu.h" #include "recording.h" -static const char *VERSION = "1.0.0-SNAPSHOT"; +static const char *VERSION = "1.0.0"; static const char *DESCRIPTION = trNOOP("Shows duplicate recordings"); static const char *MAINMENUENTRY = trNOOP("Duplicate recordings"); -- cgit v1.2.3 From 9904b08d6cf42f13cd6210a83d78246cf2644ec2 Mon Sep 17 00:00:00 2001 From: Timo Eskola Date: Fri, 7 Sep 2018 21:57:17 +0300 Subject: Updated history. --- HISTORY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY b/HISTORY index 12facb2..6487ba0 100644 --- a/HISTORY +++ b/HISTORY @@ -1,7 +1,7 @@ VDR Plugin 'duplicates' Revision History ---------------------------------------- -20??-??-??: Version 1.0.0 +2018-09-07: Version 1.0.0 - Dropped support for VDR 2.2.0. - Added scanner thread for duplicates. -- cgit v1.2.3