diff options
author | Timo Eskola <timo@tolleri.net> | 2015-09-08 12:59:54 +0300 |
---|---|---|
committer | Timo Eskola <timo@tolleri.net> | 2015-09-08 12:59:54 +0300 |
commit | b94ebafe8c2f32b404d69f1ea8e6bc2de68e606a (patch) | |
tree | cfcdfef1696b16df880e5be0d880e8f72e96446f | |
parent | 47a129b230b2b2e9a880948b5bc188ab715ba3b2 (diff) | |
download | vdr-plugin-duplicates-b94ebafe8c2f32b404d69f1ea8e6bc2de68e606a.tar.gz vdr-plugin-duplicates-b94ebafe8c2f32b404d69f1ea8e6bc2de68e606a.tar.bz2 |
Version 0.1.0:
- Added hiding of duplicate recordings.
- Updated German translations, thanks to Joerg Bornkessel.
-rw-r--r-- | HISTORY | 5 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makefile-vdr-1.7.33 | 2 | ||||
-rw-r--r-- | config.c | 5 | ||||
-rw-r--r-- | config.h | 1 | ||||
-rw-r--r-- | duplicates.c | 54 | ||||
-rw-r--r-- | menu.c | 506 | ||||
-rw-r--r-- | menu.h | 5 | ||||
-rw-r--r-- | po/de_DE.po | 26 | ||||
-rw-r--r-- | po/fi_FI.po | 20 | ||||
-rw-r--r-- | po/it_IT.po | 20 | ||||
-rw-r--r-- | visibility.c | 75 | ||||
-rw-r--r-- | visibility.h | 41 |
13 files changed, 475 insertions, 287 deletions
@@ -1,6 +1,11 @@ VDR Plugin 'duplicates' Revision History ---------------------------------------- +2015-08-31: Version 0.1.0 + +- Added hiding of duplicate recordings. +- Updated German translations, thanks to Joerg Bornkessel. + 2015-06-05: Version 0.0.6 - Added patch from Joerg Bornkessel: @@ -53,7 +53,7 @@ DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = $(PLUGIN).o menu.o config.o +OBJS = $(PLUGIN).o menu.o config.o visibility.o ### The main target: diff --git a/Makefile-vdr-1.7.33 b/Makefile-vdr-1.7.33 index 2eef0b0..7a75f82 100644 --- a/Makefile-vdr-1.7.33 +++ b/Makefile-vdr-1.7.33 @@ -51,7 +51,7 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = $(PLUGIN).o menu.o config.o +OBJS = $(PLUGIN).o menu.o config.o visibility.o ### The main target: @@ -13,13 +13,14 @@ cDuplicatesConfig::cDuplicatesConfig() { title = 1; + hidden = 0; } -cDuplicatesConfig::~cDuplicatesConfig() { } - +cDuplicatesConfig::~cDuplicatesConfig() {} bool cDuplicatesConfig::SetupParse(const char *Name, const char *Value) { if (!strcasecmp(Name, "title")) title = atoi(Value); + else if (!strcasecmp(Name, "hidden")) hidden = atoi(Value); else return false; return true; @@ -13,6 +13,7 @@ class cDuplicatesConfig { public: // variables int title; + int hidden; // member functions cDuplicatesConfig(); ~cDuplicatesConfig(); diff --git a/duplicates.c b/duplicates.c index acd714f..54c9834 100644 --- a/duplicates.c +++ b/duplicates.c @@ -10,8 +10,9 @@ #include <vdr/plugin.h> #include "config.h" #include "menu.h" +#include "visibility.h" -static const char *VERSION = "0.0.6"; +static const char *VERSION = "0.1.0"; static const char *DESCRIPTION = trNOOP("Shows duplicate recordings"); static const char *MAINMENUENTRY = trNOOP("Duplicate recordings"); @@ -41,102 +42,85 @@ public: virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode); }; -cPluginDuplicates::cPluginDuplicates(void) -{ +cPluginDuplicates::cPluginDuplicates(void) { // Initialize any member variables here. // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! } -cPluginDuplicates::~cPluginDuplicates() -{ +cPluginDuplicates::~cPluginDuplicates() { // Clean up after yourself! } -const char *cPluginDuplicates::CommandLineHelp(void) -{ +const char *cPluginDuplicates::CommandLineHelp(void) { // Return a string that describes all known command line options. return NULL; } -bool cPluginDuplicates::ProcessArgs(int argc, char *argv[]) -{ +bool cPluginDuplicates::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. return true; } -bool cPluginDuplicates::Initialize(void) -{ +bool cPluginDuplicates::Initialize(void) { // Initialize any background activities the plugin shall perform. return true; } -bool cPluginDuplicates::Start(void) -{ +bool cPluginDuplicates::Start(void) { // Start any background activities the plugin shall perform. return true; } -void cPluginDuplicates::Stop(void) -{ +void cPluginDuplicates::Stop(void) { // Stop any background activities the plugin is performing. } -void cPluginDuplicates::Housekeeping(void) -{ +void cPluginDuplicates::Housekeeping(void) { // Perform any cleanup or other regular tasks. } -void cPluginDuplicates::MainThreadHook(void) -{ +void cPluginDuplicates::MainThreadHook(void) { // Perform actions in the context of the main program thread. // WARNING: Use with great care - see PLUGINS.html! } -cString cPluginDuplicates::Active(void) -{ +cString cPluginDuplicates::Active(void) { // Return a message string if shutdown should be postponed return NULL; } -time_t cPluginDuplicates::WakeupTime(void) -{ +time_t cPluginDuplicates::WakeupTime(void) { // Return custom wakeup time for shutdown script return 0; } -cOsdObject *cPluginDuplicates::MainMenuAction(void) -{ +cOsdObject *cPluginDuplicates::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. return new cMenuDuplicates(); } -cMenuSetupPage *cPluginDuplicates::SetupMenu(void) -{ +cMenuSetupPage *cPluginDuplicates::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return new cMenuSetupDuplicates; } -bool cPluginDuplicates::SetupParse(const char *Name, const char *Value) -{ +bool cPluginDuplicates::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. return dc.SetupParse(Name, Value);; } -bool cPluginDuplicates::Service(const char *Id, void *Data) -{ +bool cPluginDuplicates::Service(const char *Id, void *Data) { // Handle custom service requests from other plugins return false; } -const char **cPluginDuplicates::SVDRPHelpPages(void) -{ +const char **cPluginDuplicates::SVDRPHelpPages(void) { // Return help text for SVDRP commands this plugin implements return NULL; } -cString cPluginDuplicates::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) -{ +cString cPluginDuplicates::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { // Process SVDRP commands this plugin implements return NULL; } @@ -9,14 +9,15 @@ */ #include "menu.h" +#include "visibility.h" #include <vdr/menu.h> #include <vdr/status.h> #include <vdr/interface.h> +#include <sys/time.h> #include <string> #include <sstream> -static inline cOsdItem *SeparatorItem(const char *Label) -{ +static inline cOsdItem *SeparatorItem(const char *Label) { cOsdItem *Item = new cOsdItem(cString::sprintf("----- %s -----", Label)); Item->SetSelectable(false); return Item; @@ -27,13 +28,11 @@ static inline cOsdItem *SeparatorItem(const char *Label) class cDuplicatesReplayControl : public cReplayControl { public: virtual eOSState ProcessKey(eKeys Key); - }; +}; -eOSState cDuplicatesReplayControl::ProcessKey(eKeys Key) -{ +eOSState cDuplicatesReplayControl::ProcessKey(eKeys Key) { eOSState state = cReplayControl::ProcessKey(Key); - if (state == osRecordings) - { + if (state == osRecordings) { cControl::Shutdown(); cRemote::CallPlugin("duplicates"); return osContinue; @@ -53,8 +52,7 @@ public: }; cMenuDuplicate::cMenuDuplicate(const cRecording *Recording) -:cOsdMenu(trVDR("Recording info")) -{ +:cOsdMenu(trVDR("Recording info")) { #if VDRVERSNUM >= 10728 SetMenuCategory(mcRecording); #endif @@ -62,8 +60,7 @@ cMenuDuplicate::cMenuDuplicate(const cRecording *Recording) SetHelp(trVDR("Button$Play")); } -void cMenuDuplicate::Display(void) -{ +void cMenuDuplicate::Display(void) { cOsdMenu::Display(); DisplayMenu()->SetRecording(recording); if (recording->Info()->Description()) @@ -86,7 +83,7 @@ eOSState cMenuDuplicate::ProcessKey(eKeys Key) return osContinue; case kInfo: return osBack; default: break; - } +} eOSState state = cOsdMenu::ProcessKey(Key); @@ -96,58 +93,32 @@ eOSState cMenuDuplicate::ProcessKey(eKeys Key) case kRed: cRemote::Put(Key, true); case kOk: return osBack; default: break; - } } + } return state; } -// --- cMenuDuplicateItem ---------------------------------------------------- - -class cMenuDuplicateItem : public cOsdItem { -private: - char *fileName; -public: - cMenuDuplicateItem(const cRecording *Recording); - ~cMenuDuplicateItem(); - const char *FileName(void) { return fileName; } - }; - -cMenuDuplicateItem::cMenuDuplicateItem(const cRecording *Recording) -{ - fileName = strdup(Recording->FileName()); -#if defined LIEMIKUUTIO && LIEMIKUUTIO < 131 - SetText(Recording->Title('\t', true, -1, false)); -#else - SetText(Recording->Title('\t', true)); -#endif -} - -cMenuDuplicateItem::~cMenuDuplicateItem() -{ - free(fileName); -} - // --- cDuplicateRecording ------------------------------------------------------- class cDuplicateRecording : public cListObject { private: const cRecording *recording; bool checked; -protected: + cVisibility visibility; std::string title; std::string description; public: cDuplicateRecording(const cRecording *Recording); - ~cDuplicateRecording(); - const cRecording *Recording(void); + cDuplicateRecording(const cDuplicateRecording &DuplicateRecording); + const cRecording *Recording(void) const { return recording; } bool HasDescription(void) const { return ! description.empty(); } - bool IsDuplicate(const cDuplicateRecording *DuplicateRecording); + bool IsDuplicate(cDuplicateRecording *DuplicateRecording); void SetChecked(bool chkd = true) { checked = chkd; } bool Checked() { return checked; } - }; + cVisibility Visibility() { return visibility; } +}; -cDuplicateRecording::cDuplicateRecording(const cRecording *Recording) -{ +cDuplicateRecording::cDuplicateRecording(const cRecording *Recording) : visibility(Recording->FileName()) { recording = Recording; checked = false; if (dc.title && recording->Info()->Title()) @@ -174,39 +145,59 @@ cDuplicateRecording::cDuplicateRecording(const cRecording *Recording) } } -cDuplicateRecording::~cDuplicateRecording() -{ - title.clear(); - description.clear(); -} - -const cRecording *cDuplicateRecording::Recording(void) -{ - return recording; -} +cDuplicateRecording::cDuplicateRecording(const cDuplicateRecording &DuplicateRecording) : + recording(DuplicateRecording.recording), + checked(DuplicateRecording.checked), + visibility(DuplicateRecording.visibility), + title(DuplicateRecording.title), + description(DuplicateRecording.description) {} -bool cDuplicateRecording::IsDuplicate(const cDuplicateRecording *DuplicateRecording) -{ +bool cDuplicateRecording::IsDuplicate(cDuplicateRecording *DuplicateRecording) { if (!HasDescription() || !DuplicateRecording->HasDescription()) - return false; + return false; size_t found; - if (dc.title) - { - found = title.size() > DuplicateRecording->title.size() ? - title.find(DuplicateRecording->title) : DuplicateRecording->title.find(title); - if (found == std::string::npos) - return false; + if (dc.title) { + found = title.size() > DuplicateRecording->title.size() ? + title.find(DuplicateRecording->title) : DuplicateRecording->title.find(title); + if (found == std::string::npos) + return false; } found = description.size() > DuplicateRecording->description.size() ? description.find(DuplicateRecording->description) : DuplicateRecording->description.find(description); if (found != std::string::npos) - return true; + return true; return false; } +// --- cMenuDuplicateItem ---------------------------------------------------- + +class cMenuDuplicateItem : public cOsdItem { +private: + char *fileName; + cVisibility visibility; +public: + cMenuDuplicateItem(cDuplicateRecording *DuplicateRecording); + ~cMenuDuplicateItem(); + const char *FileName(void) { return fileName; } + cVisibility Visibility() { return visibility; } +}; + +cMenuDuplicateItem::cMenuDuplicateItem(cDuplicateRecording *DuplicateRecording) : visibility(DuplicateRecording->Visibility()) { + fileName = strdup(DuplicateRecording->Recording()->FileName()); +#if defined LIEMIKUUTIO && LIEMIKUUTIO < 131 + SetText(DuplicateRecording->Recording()->Title('\t', true, -1, false)); +#else + SetText(DuplicateRecording->Recording()->Title('\t', true)); +#endif +} + +cMenuDuplicateItem::~cMenuDuplicateItem() { + free(fileName); +} + // --- cMenuDuplicates ------------------------------------------------------- cMenuDuplicates::cMenuDuplicates() @@ -226,255 +217,290 @@ cMenuDuplicates::cMenuDuplicates() SetHelpKeys(); } -cMenuDuplicates::~cMenuDuplicates() -{ +cMenuDuplicates::~cMenuDuplicates() { helpKeys = -1; } -void cMenuDuplicates::SetHelpKeys(void) -{ +void cMenuDuplicates::SetHelpKeys(void) { cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); int NewHelpKeys = 0; if (ri) { - NewHelpKeys = 1; - cRecording *recording = GetRecording(ri); - if (recording && recording->Info()->Title()) - NewHelpKeys = 2; - } + NewHelpKeys = 1; + if (ri->Visibility().Read() == HIDDEN) + NewHelpKeys = 2; + } if (NewHelpKeys != helpKeys) { - switch (NewHelpKeys) { - case 0: SetHelp(NULL); break; - case 1: - case 2: SetHelp(trVDR("Button$Play"), trVDR("Setup"), trVDR("Button$Delete"), NewHelpKeys == 2 ? trVDR("Button$Info") : NULL); - default: ; - } - helpKeys = NewHelpKeys; - } + switch (NewHelpKeys) { + case 0: SetHelp(NULL); break; + case 1: + case 2: SetHelp(trVDR("Button$Play"), trVDR("Setup"), trVDR("Button$Delete"), NewHelpKeys == 1 ? tr("Hide") : tr("Unhide")); + default: ; + } + helpKeys = NewHelpKeys; + } } -void cMenuDuplicates::Set(bool Refresh) -{ +void cMenuDuplicates::Set(bool Refresh) { + struct timeval startTime, stopTime; + gettimeofday(&startTime, NULL); +#ifdef DEBUG_VISIBILITY + cVisibility::ClearCounters(); + int isDuplicateCount = 0, menuDuplicateItemCount = 0; +#endif const char *CurrentRecording = NULL; int currentIndex = -1; if (Refresh) - currentIndex = Current(); + currentIndex = Current(); else - CurrentRecording = cReplayControl::LastReplayed(); - cList<cDuplicateRecording> *descriptionless = new cList<cDuplicateRecording>; - cList<cDuplicateRecording> *recordings = new cList<cDuplicateRecording>; - cThreadLock RecordingsLock(&Recordings); + CurrentRecording = cReplayControl::LastReplayed(); + cList<cDuplicateRecording> descriptionless; + cList<cDuplicateRecording> recordings; Clear(); - Recordings.Sort(); - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { + { + cThreadLock RecordingsLock(&Recordings); + Recordings.Sort(); + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { cDuplicateRecording *Item = new cDuplicateRecording(recording); if (Item->HasDescription()) - recordings->Add(Item); - else - descriptionless->Add(Item); + recordings.Add(Item); + else if (dc.hidden || Item->Visibility().Read() != HIDDEN) + descriptionless.Add(Item); } - for (cDuplicateRecording *recording = recordings->First(); recording; recording = recordings->Next(recording)) { - if (!recording->Checked()) { - recording->SetChecked(); - cList<cDuplicateRecording> *duplicates = new cList<cDuplicateRecording>; - duplicates->Add(new cDuplicateRecording(recording->Recording())); - for (cDuplicateRecording *compare = recordings->First(); compare; compare = recordings->Next(compare)) { - if (!compare->Checked() && recording->IsDuplicate(compare)) { - duplicates->Add(new cDuplicateRecording(compare->Recording())); - compare->SetChecked(); - } - } - if (duplicates->Count() > 1) { - Add(SeparatorItem(cString::sprintf(tr("%d duplicate recordings"), duplicates->Count()))); - for (cDuplicateRecording *DuplicateRecording = duplicates->First(); DuplicateRecording; DuplicateRecording = duplicates->Next(DuplicateRecording)) { - cMenuDuplicateItem *Item = new cMenuDuplicateItem(DuplicateRecording->Recording()); - if (*Item->Text()) - { - Add(Item); - if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) - SetCurrent(Item); - } - else - delete Item; - } - } - delete duplicates; - } + } + for (cDuplicateRecording *recording = recordings.First(); recording; recording = recordings.Next(recording)) { + if (!recording->Checked()) { + recording->SetChecked(); + cList<cDuplicateRecording> 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.Add(new cDuplicateRecording(*compare)); + compare->SetChecked(); + } + } } - if (descriptionless->Count() > 0) - Add(SeparatorItem(cString::sprintf(tr("%d recordings without description"), descriptionless->Count()))); - for (cDuplicateRecording *DescriptionlessRecording = descriptionless->First(); DescriptionlessRecording; DescriptionlessRecording = descriptionless->Next(DescriptionlessRecording)) { - cMenuDuplicateItem *Item = new cMenuDuplicateItem(DescriptionlessRecording->Recording()); - if (*Item->Text()) - { - Add(Item); - if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) - SetCurrent(Item); - } - else - delete Item; + int count = duplicates.Count(); + if (!dc.hidden && count > 1) { + for (cDuplicateRecording *DuplicateRecording = duplicates.First(); DuplicateRecording; DuplicateRecording = duplicates.Next(DuplicateRecording)) { + if (DuplicateRecording->Visibility().Read() == HIDDEN) + count--; + } } - delete descriptionless; - delete recordings; + if (count > 1) { + Add(SeparatorItem(cString::sprintf(tr("%d duplicate recordings"), duplicates.Count()))); + for (cDuplicateRecording *DuplicateRecording = duplicates.First(); DuplicateRecording; DuplicateRecording = duplicates.Next(DuplicateRecording)) { + if (dc.hidden || DuplicateRecording->Visibility().Read() != HIDDEN) { + cMenuDuplicateItem *Item = new cMenuDuplicateItem(DuplicateRecording); +#ifdef DEBUG_VISIBILITY + menuDuplicateItemCount++; +#endif + if (*Item->Text()) { + Add(Item); + if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) + SetCurrent(Item); + } else + delete Item; + } + } + } + } + } + if (descriptionless.Count() > 0) + Add(SeparatorItem(cString::sprintf(tr("%d recordings without description"), descriptionless.Count()))); + for (cDuplicateRecording *DescriptionlessRecording = descriptionless.First(); DescriptionlessRecording; DescriptionlessRecording = descriptionless.Next(DescriptionlessRecording)) { + cMenuDuplicateItem *Item = new cMenuDuplicateItem(DescriptionlessRecording); +#ifdef DEBUG_VISIBILITY + menuDuplicateItemCount++; +#endif + if (*Item->Text()) { + Add(Item); + if (CurrentRecording && strcmp(CurrentRecording, Item->FileName()) == 0) + SetCurrent(Item); + } else + delete Item; + } if (Count() == 0) - Add(SeparatorItem(cString::sprintf(tr("%d duplicate recordings"), 0))); + Add(SeparatorItem(cString::sprintf(tr("%d duplicate recordings"), 0))); if (Refresh) { - if (currentIndex >= 0) { - if(currentIndex >= Count()) - currentIndex = Count() - 1; - cOsdItem *current = Get(currentIndex); - while (current) { - if (current->Selectable()) { - SetCurrent(current); - break; - } - current = Prev(current); - } + if (currentIndex >= 0) { + if(currentIndex >= Count()) + currentIndex = Count() - 1; + cOsdItem *current = Get(currentIndex); + while (current) { + if (current->Selectable()) { + SetCurrent(current); + break; } - Display(); - } + current = Prev(current); + } + } + Display(); + } + 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: Displaying of duplicates took %.2f seconds, is duplicate count %d, get count %d, read count %d, access count %d, duplicate item count %d.", + seconds, isDuplicateCount, cVisibility::getCount, cVisibility::readCount, cVisibility::accessCount, menuDuplicateItemCount); +#else + dsyslog("duplicates: Displaying of duplicates took %.2f seconds.", seconds); +#endif } -cRecording *cMenuDuplicates::GetRecording(cMenuDuplicateItem *Item) -{ +cRecording *cMenuDuplicates::GetRecording(cMenuDuplicateItem *Item) { cRecording *recording = Recordings.GetByName(Item->FileName()); if (!recording) - Skins.Message(mtError, trVDR("Error while accessing recording!")); + Skins.Message(mtError, trVDR("Error while accessing recording!")); return recording; } -eOSState cMenuDuplicates::Delete(void) -{ +eOSState cMenuDuplicates::Delete(void) { if (HasSubMenu() || Count() == 0) - return osContinue; + return osContinue; cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); if (ri) { - if (Interface->Confirm(trVDR("Delete recording?"))) { - cRecordControl *rc = cRecordControls::GetRecordControl(ri->FileName()); - if (rc) { - if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) { - cTimer *timer = rc->Timer(); - if (timer) { - timer->Skip(); - cRecordControls::Process(time(NULL)); - if (timer->IsSingleEvent()) { - isyslog("deleting timer %s", *timer->ToDescr()); - Timers.Del(timer); - } - Timers.SetModified(); - } - } - else - return osContinue; - } - cRecording *recording = GetRecording(ri); - if (recording) { - if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), ri->FileName()) == 0) - cControl::Shutdown(); - if (recording->Delete()) { - cReplayControl::ClearLastReplayed(ri->FileName()); - Recordings.DelByName(ri->FileName()); - Set(true); - SetHelpKeys(); - } - else - Skins.Message(mtError, trVDR("Error while deleting recording!")); - } - } - } + if (Interface->Confirm(trVDR("Delete recording?"))) { + cRecordControl *rc = cRecordControls::GetRecordControl(ri->FileName()); + if (rc) { + if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) { + cTimer *timer = rc->Timer(); + if (timer) { + timer->Skip(); + cRecordControls::Process(time(NULL)); + if (timer->IsSingleEvent()) { + isyslog("deleting timer %s", *timer->ToDescr()); + Timers.Del(timer); + } + Timers.SetModified(); + } + } else + return osContinue; + } + cRecording *recording = GetRecording(ri); + if (recording) { + if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), ri->FileName()) == 0) + cControl::Shutdown(); + if (recording->Delete()) { + cReplayControl::ClearLastReplayed(ri->FileName()); + Recordings.DelByName(ri->FileName()); + Recordings.StateChanged(recordingsState); // update state after deletion + Set(true); + SetHelpKeys(); + } else + Skins.Message(mtError, trVDR("Error while deleting recording!")); + } + } + } return osContinue; } -eOSState cMenuDuplicates::Play(void) -{ +eOSState cMenuDuplicates::Play(void) { if (HasSubMenu() || Count() == 0) - return osContinue; + return osContinue; cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); if (ri) { - cRecording *recording = GetRecording(ri); - if (recording) { + cRecording *recording = GetRecording(ri); + if (recording) { #if VDRVERSNUM >= 10728 - cDuplicatesReplayControl::SetRecording(recording->FileName()); + cDuplicatesReplayControl::SetRecording(recording->FileName()); #else - cDuplicatesReplayControl::SetRecording(recording->FileName(), recording->Title()); + cDuplicatesReplayControl::SetRecording(recording->FileName(), recording->Title()); #endif - cControl::Shutdown(); - cControl::Launch(new cDuplicatesReplayControl); - return osEnd; - } - } + cControl::Shutdown(); + cControl::Launch(new cDuplicatesReplayControl); + return osEnd; + } + } return osContinue; } -eOSState cMenuDuplicates::Setup(void) -{ +eOSState cMenuDuplicates::Setup(void) { if (HasSubMenu()) - return osContinue; + return osContinue; cMenuSetupDuplicates *setupMenu = new cMenuSetupDuplicates(this); setupMenu->SetTitle(cString::sprintf("%s - %s", tr("Duplicate recordings"), trVDR("Setup"))); return AddSubMenu(setupMenu); } -eOSState cMenuDuplicates::Info(void) -{ +eOSState cMenuDuplicates::Info(void) { if (HasSubMenu() || Count() == 0) - return osContinue; + return osContinue; cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); if (ri) { - cRecording *recording = GetRecording(ri); - if (recording && recording->Info()->Title()) - return AddSubMenu(new cMenuDuplicate(recording)); - } + cRecording *recording = GetRecording(ri); + if (recording && recording->Info()->Title()) + return AddSubMenu(new cMenuDuplicate(recording)); + } return osContinue; } -eOSState cMenuDuplicates::ProcessKey(eKeys Key) -{ +eOSState cMenuDuplicates::ToggleHidden(void) { + if (HasSubMenu() || Count() == 0) + return osContinue; + cMenuDuplicateItem *ri = (cMenuDuplicateItem *)Get(Current()); + if (ri) { + 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); + else + Set(true); + SetHelpKeys(); + } else + Skins.Message(mtError, tr("Error while setting visibility!")); + } + } + return osContinue; +} + +eOSState cMenuDuplicates::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { - switch (Key) { - case kPlay: - case kRed: return Play(); - case kGreen: return Setup(); - case kYellow: return Delete(); - case kOk: - case kInfo: - case kBlue: return Info(); - case kNone: if (Recordings.StateChanged(recordingsState)) - Set(true); - break; - default: break; - } - } + switch (Key) { + case kPlay: + case kRed: return Play(); + case kGreen: return Setup(); + case kYellow: return Delete(); + case kOk: + case kInfo: return Info(); + case kBlue: return ToggleHidden(); + case kNone: if (Recordings.StateChanged(recordingsState)) + Set(true); + break; + default: break; + } + } if (!HasSubMenu()) { - if (Key != kNone) - SetHelpKeys(); - } + if (Key != kNone) + SetHelpKeys(); + } return state; } // --- cMenuSetupDuplicates -------------------------------------------------- -cMenuSetupDuplicates::cMenuSetupDuplicates(cMenuDuplicates *MenuDuplicates) -{ +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)); } -void cMenuSetupDuplicates::Store(void) -{ +void cMenuSetupDuplicates::Store(void) { dc.Store(); - if (menuDuplicates != NULL) - { - menuDuplicates->SetCurrent(NULL); - menuDuplicates->Set(); + if (menuDuplicates != NULL) { + menuDuplicates->SetCurrent(NULL); + menuDuplicates->Set(); } } -void cMenuSetupDuplicates::SetTitle(const char *Title) -{ +void cMenuSetupDuplicates::SetTitle(const char *Title) { cMenuSetupPage::SetTitle(Title); } @@ -32,13 +32,14 @@ private: eOSState Setup(void); eOSState Delete(void); eOSState Info(void); + eOSState ToggleHidden(void); protected: cRecording *GetRecording(cMenuDuplicateItem *Item); public: cMenuDuplicates(); ~cMenuDuplicates(); virtual eOSState ProcessKey(eKeys Key); - }; +}; // --- cMenuSetupDuplicates -------------------------------------------------- @@ -50,6 +51,6 @@ protected: public: cMenuSetupDuplicates(cMenuDuplicates *menuDuplicates = NULL); void SetTitle(const char *Title); - }; +}; #endif diff --git a/po/de_DE.po b/po/de_DE.po index 5d65e1c..7dc70b7 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -5,12 +5,12 @@ # msgid "" msgstr "" -"Project-Id-Version: vdr-duplicates 0.0.6\n" +"Project-Id-Version: vdr-duplicates 0.1.0\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2011-12-20 18:14+0200\n" -"PO-Revision-Date: 2015-02-03 11:12+0100\n" +"POT-Creation-Date: 2015-08-31 11:33+0300\n" +"PO-Revision-Date: 2015-09-06 17:57+0100\n" "Last-Translator: Joerg Bornkessel <hd_brummy@gentoo.org>\n" -"Language-Team: \n" +"Language-Team: Deutsch\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -25,6 +25,12 @@ msgstr "Zeigt doppelte Aufnahmen an" msgid "Duplicate recordings" msgstr "Doppelte Aufnahmen anzeigen" +msgid "Hide" +msgstr "Verstecken" + +msgid "Unhide" +msgstr "Aufnahme sichtbar machen" + #, c-format msgid "%d duplicate recordings" msgstr "%d doppelte Aufnahmen" @@ -33,5 +39,17 @@ msgstr "%d doppelte Aufnahmen" msgid "%d recordings without description" msgstr "%d Aufnahmen ohne Beschreibung" +msgid "Unhide recording?" +msgstr "Versteckte Aufnahme sichtbar machen?" + +msgid "Hide recording?" +msgstr "Aufnahme verstecken?" + +msgid "Error while setting visibility!" +msgstr "Fehler bei dem sichtbar machen der Aufnahme!" + msgid "Compare title" msgstr "Vergleiche Titel" + +msgid "Show hidden" +msgstr "Zeige versteckte Aufnahmen" diff --git a/po/fi_FI.po b/po/fi_FI.po index ada4590..fd94d10 100644 --- a/po/fi_FI.po +++ b/po/fi_FI.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-duplicates 0.0.1\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2011-12-20 18:14+0200\n" +"POT-Creation-Date: 2015-08-31 11:33+0300\n" "PO-Revision-Date: 2011-12-12 19:57+0300\n" "Last-Translator: Timo Eskola <timo@tolleri.net>\n" "Language-Team: Finnish\n" @@ -24,6 +24,12 @@ msgstr "Näyttää päällekkäiset tallenteet" msgid "Duplicate recordings" msgstr "Päällekkäiset tallenteet" +msgid "Hide" +msgstr "Piilota" + +msgid "Unhide" +msgstr "Älä piilota" + #, c-format msgid "%d duplicate recordings" msgstr "%d päällekkäistä tallennetta" @@ -32,5 +38,17 @@ msgstr "%d päällekkäistä tallennetta" msgid "%d recordings without description" msgstr "%d tallennetta ilman kuvausta" +msgid "Unhide recording?" +msgstr "Älä piilota tallennetta?" + +msgid "Hide recording?" +msgstr "Piilota tallenne?" + +msgid "Error while setting visibility!" +msgstr "Näkyvyyden asettaminen epäonnistui!" + msgid "Compare title" msgstr "Vertaa otsikkoa" + +msgid "Show hidden" +msgstr "Näytä piilotetut" diff --git a/po/it_IT.po b/po/it_IT.po index eaa4c47..6282908 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-duplicates 0.0.1\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2011-12-20 18:14+0200\n" +"POT-Creation-Date: 2015-08-31 11:33+0300\n" "PO-Revision-Date: 2011-06-05 23:37+0100\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Language-Team: \n" @@ -27,6 +27,12 @@ msgstr "Mostra registrazioni duplicate" msgid "Duplicate recordings" msgstr "Registrazioni duplicate" +msgid "Hide" +msgstr "" + +msgid "Unhide" +msgstr "" + #, c-format msgid "%d duplicate recordings" msgstr "%d registrazioni duplicate" @@ -35,5 +41,17 @@ msgstr "%d registrazioni duplicate" msgid "%d recordings without description" msgstr "%d registrazioni senza descrizione" +msgid "Unhide recording?" +msgstr "" + +msgid "Hide recording?" +msgstr "" + +msgid "Error while setting visibility!" +msgstr "" + msgid "Compare title" msgstr "" + +msgid "Show hidden" +msgstr "" diff --git a/visibility.c b/visibility.c new file mode 100644 index 0000000..35bdd97 --- /dev/null +++ b/visibility.c @@ -0,0 +1,75 @@ +/* + * visibility.c: Visibility classes for duplicates plugin. + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + +#include "visibility.h" + +// --- 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; +} + +cVisibility::cVisibility(const cVisibility &Visibility) : + hiddenFileName(Visibility.hiddenFileName), + visibility(Visibility.visibility) {} + +eVisibility cVisibility::Get(void) { +#ifdef DEBUG_VISIBILITY + getCount++; +#endif + return visibility; +} + +void cVisibility::Set(bool visible) { + visibility = visible ? VISIBLE : HIDDEN; +} + +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; +} + +bool cVisibility::Write(bool visible) { + if (visible) { + if (remove(hiddenFileName) == 0) { + visibility = VISIBLE; + return true; + } + } else { + FILE *f = fopen(hiddenFileName, "w"); + if (f) { + fclose(f); + visibility = HIDDEN; + return true; + } + } + return false; +} + +#ifdef DEBUG_VISIBILITY +void cVisibility::ClearCounters(void) { + getCount = 0; + readCount = 0; + accessCount = 0; +} +#endif diff --git a/visibility.h b/visibility.h new file mode 100644 index 0000000..dd29bf6 --- /dev/null +++ b/visibility.h @@ -0,0 +1,41 @@ +/* + * visibility.h: Visibility classes for duplicates plugin. + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + +#ifndef _DUPLICATES_VISIBILITY_H +#define _DUPLICATES_VISIBILITY_H + +//#define DEBUG_VISIBILITY + +#include <vdr/recording.h> + +// --- eVisibility ----------------------------------------------------------- + +enum eVisibility {UNKNOWN, VISIBLE, HIDDEN}; + +// --- cVisibility ----------------------------------------------------------- + +class cVisibility { +private: + cString hiddenFileName; + eVisibility visibility; +public: + cVisibility(const char *fileName); + cVisibility(const cVisibility &Visibility); + eVisibility Get(void); + 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 |