diff options
Diffstat (limited to 'recording.c')
-rw-r--r-- | recording.c | 150 |
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; |