summaryrefslogtreecommitdiff
path: root/recording.c
diff options
context:
space:
mode:
Diffstat (limited to 'recording.c')
-rw-r--r--recording.c150
1 files changed, 101 insertions, 49 deletions
diff --git a/recording.c b/recording.c
index da1b624..05cad27 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,133 @@ bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) {
// --- cDuplicateRecordings ------------------------------------------------------
-cDuplicateRecordings::cDuplicateRecordings(void) {}
+cDuplicateRecordings::cDuplicateRecordings(void) : cList("duplicates") {}
-void cDuplicateRecordings::Update(void) {
+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 ------------------------------------------
+
+cDuplicateRecordingScannerThread::cDuplicateRecordingScannerThread() : cThread("duplicate recording scanner", true) {
+ title = dc.title;
+ hidden = dc.hidden;
+}
+
+cDuplicateRecordingScannerThread::~cDuplicateRecordingScannerThread(){
+ Stop();
+}
+
+void cDuplicateRecordingScannerThread::Stop(void) {
+ 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(500);
+ }
+}
+
+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
+ cStateKey duplicateRecordingsStateKey;
+ DuplicateRecordings.Lock(duplicateRecordingsStateKey, true);
+ duplicateRecordingsStateKey.Remove(DuplicateRecordings.RemoveDeleted());
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() || RecordingsStateChanged()) {
+ delete descriptionless;
+ 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;
+ if (RecordingsStateChanged())
+ return;
+ 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;
+bool cDuplicateRecordingScannerThread::RecordingsStateChanged(void) {
+ if (cRecordings::GetRecordingsRead(recordingsStateKey)) {
+ recordingsStateKey.Reset();
+ recordingsStateKey.Remove();
+ dsyslog("duplicates: Recordings state changed while scanning.");
+ cCondWait::SleepMs(500);
+ return true;
+ }
+ return false;
+}
+
+cDuplicateRecordingScannerThread DuplicateRecordingScanner;