summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY4
-rw-r--r--duplicates.c6
-rw-r--r--menu.c139
-rw-r--r--menu.h6
-rw-r--r--recording.c115
-rw-r--r--recording.h22
-rw-r--r--visibility.c22
-rw-r--r--visibility.h8
8 files changed, 127 insertions, 195 deletions
diff --git a/HISTORY b/HISTORY
index e3ab5a1..963550a 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,10 @@
VDR Plugin 'duplicates' Revision History
----------------------------------------
+20??-??-??: Version 1.0.0
+- Dropped support for VDR 2.2.0.
+- Added scanner thread for duplicates.
+
2018-09-02: Version 0.2.2
- Updated kNone handling in main menu.
diff --git a/duplicates.c b/duplicates.c
index 3b4a656..c1c5f12 100644
--- a/duplicates.c
+++ b/duplicates.c
@@ -10,9 +10,9 @@
#include <vdr/plugin.h>
#include "config.h"
#include "menu.h"
-#include "visibility.h"
+#include "recording.h"
-static const char *VERSION = "0.2.1";
+static const char *VERSION = "1.0.0-SNAPSHOT";
static const char *DESCRIPTION = trNOOP("Shows duplicate recordings");
static const char *MAINMENUENTRY = trNOOP("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 76cf338..44e197c 100644
--- a/menu.c
+++ b/menu.c
@@ -13,9 +13,7 @@
#include <vdr/menu.h>
#include <vdr/status.h>
#include <vdr/interface.h>
-#if VDRVERSNUM >= 20301
#include <vdr/svdrp.h>
-#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();
@@ -160,33 +147,34 @@ 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();
- Clear();
- 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)) {
+ dsyslog("duplicates: %s menu.", Refresh ? "Refreshing" : "Creating");
+ const char *CurrentRecording = NULL;
+ int currentIndex = -1;
+ if (Refresh)
+ currentIndex = Current();
+ else
+ CurrentRecording = cReplayControl::LastReplayed();
+ Clear();
+ 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();
}
}
-#if VDRVERSNUM >= 20301
static bool HandleRemoteModifications(cTimer *NewTimer, cTimer *OldTimer = NULL) {
cString ErrorMessage;
if (!HandleRemoteTimerModifications(NewTimer, OldTimer, &ErrorMessage)) {
@@ -195,41 +183,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) {
@@ -258,7 +229,6 @@ static bool TimerStillRecording(const char *FileName) {
}
}
}
-#endif
return false;
}
@@ -298,16 +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;
-#if VDRVERSNUM >= 20301
- 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?")))
@@ -315,47 +283,26 @@ 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!
-#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
+ cStateKey recordingsStateKey;
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();
} else {
Skins.Message(mtError, trVDR("Error while deleting recording!"));
-#if VDRVERSNUM >= 20301
recordingsStateKey.Remove();
-#endif
}
}
}
@@ -367,18 +314,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;
@@ -400,12 +339,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));
}
@@ -447,15 +382,7 @@ eOSState cMenuDuplicates::ProcessKey(eKeys Key) {
case kOk:
case kInfo: return Info();
case kBlue: return ToggleHidden();
- case kNone:
-#if VDRVERSNUM >= 20301
- if (cRecordings::GetRecordingsRead(recordingsStateKey)) {
- recordingsStateKey.Remove();
-#else
- if (Recordings.StateChanged(recordingsState)) {
-#endif
- Set(true);
- }
+ case kNone: Set(true);
break;
default: break;
}
@@ -470,9 +397,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..ac43d9b 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
+ cStateKey duplicateRecordingsStateKey;
int helpKeys;
void SetHelpKeys(void);
void Set(bool Refresh = false);
diff --git a/recording.c b/recording.c
index da1b624..5b98e82 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
@@ -92,77 +88,98 @@ 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) {
+ dsyslog("duplicates: Scanning of duplicates started.");
struct timeval startTime, stopTime;
gettimeofday(&startTime, NULL);
- cMutexLock MutexLock(&mutex);
-#ifdef DEBUG_VISIBILITY
- cVisibility::ClearCounters();
- int isDuplicateCount = 0;
-#endif
cDuplicateRecording *descriptionless = new cDuplicateRecording();
cList<cDuplicateRecording> 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
+ 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<cDuplicateRecording> duplicates;
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();
- 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()) {
-#ifdef DEBUG_VISIBILITY
- isDuplicateCount++;
-#endif
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()));
- 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()));
- 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;
-#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
}
-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<cDuplicateRecording> *Duplicates(void) { return duplicates; }
};
+// --- cDuplicateRecordings ------------------------------------------------------
+
class cDuplicateRecordings : public cList<cDuplicateRecording> {
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
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 <vdr/recording.h>
// --- 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