#! /bin/sh /usr/share/dpatch/dpatch-run ## opt-48_pin.dpatch by Jörg Wendel (Horchi) ## ## Thomas Günther <tom@toms-cafe.de>: ## - adapted to VDR-1.5.8 with liemikuutio, menuorg and MainMenuHooks patches ## - adapted to VDR-1.5.10 with liemikuutio, menuorg and MainMenuHooks patches ## - adapted to vdr-1.5.13-liemikuutio-1.17.diff.gz ## Tobias Grimm <tg@e-tobi.net>## ## - adapted to VDR 1.5.15 ## All lines beginning with `## DP:' are a description of the patch. ## DP: Patch for the PIN plugin from version 0.1.7 of the Plugin ## (vdr-1.4.5.diff) @DPATCH@ diff -urNad vdr-1.5.15~/Makefile vdr-1.5.15/Makefile --- vdr-1.5.15~/Makefile 2008-02-17 22:13:55.000000000 +0100 +++ vdr-1.5.15/Makefile 2008-02-17 22:13:56.000000000 +0100 @@ -45,6 +45,8 @@ OBJS += vdrttxtsubshooks.o +OBJS += childlock.o + ifndef NO_KBD DEFINES += -DREMOTE_KBD endif diff -urNad vdr-1.5.15~/childlock.c vdr-1.5.15/childlock.c --- vdr-1.5.15~/childlock.c 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.5.15/childlock.c 2008-02-17 22:13:56.000000000 +0100 @@ -0,0 +1,166 @@ +#include "childlock.h" +#include "childlockservice.h" +#include "plugin.h" + +using namespace PinPatch; + +IChildLockService* ChildLock::_cachedChildLockService = NULL; +INotificationService* ChildLock::_cachedNotificationService = NULL; + +IChildLockService* ChildLock::ChildLockService() +{ + if (!_cachedChildLockService) + { + IChildLockService* childLockService; + + if (cPluginManager::CallFirstService(CHILDLOCK_SERVICE_ID, &childLockService)) + { + _cachedChildLockService = childLockService; + } + else + { + _cachedChildLockService = NULL; + } + } + + return _cachedChildLockService; +} + +bool ChildLock::IsUnlocked() +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsUnlocked(); + } + else + { + return false; + } +} + +bool ChildLock::IsMenuProtected(const char* MenuName) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsMenuProtected(MenuName); + } + else + { + return false; + } +} + +bool ChildLock::IsChannelProtected(const cChannel* Channel) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsChannelProtected(Channel); + } + else + { + return false; + } +} + +bool ChildLock::IsRecordingProtected(const cRecording* Recording, const char* Name, const char* Base, bool isDirectory) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsRecordingProtected(Recording, Name, Base, isDirectory); + } + else + { + return false; + } +} + +bool ChildLock::IsPluginProtected(cPlugin* Plugin) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsPluginProtected(Plugin); + } + else + { + return false; + } +} + +bool ChildLock::IsMenuHidden(const char* MenuName) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsMenuHidden(MenuName); + } + else + { + return false; + } +} + +bool ChildLock::IsPluginHidden(cPlugin* Plugin) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsPluginHidden(Plugin); + } + else + { + return false; + } +} + +bool ChildLock::IsRecordingHidden(const cRecording* Recording, const char* Name, const char* Base, bool isDirectory) +{ + if (IChildLockService* childLockService = ChildLockService()) + { + return childLockService->IsRecordingHidden(Recording, Name, Base, isDirectory); + } + else + { + return false; + } +} + +INotificationService* ChildLock::NotificationService() +{ + if (!_cachedNotificationService) + { + INotificationService* notificationService; + + if (cPluginManager::CallFirstService(NOTIFICATION_SERVICE_ID, ¬ificationService)) + { + _cachedNotificationService = notificationService; + } + else + { + _cachedNotificationService = NULL; + } + } + + return _cachedNotificationService; +} + +void ChildLock::NotifyTimerCreation(cTimer* Timer, const cEvent *Event) +{ + if (INotificationService* notificationService = NotificationService()) + { + notificationService->NotifyTimerCreation(Timer, Event); + } +} + +void ChildLock::NotifyRecordingStart(const char* FileName) +{ + if (INotificationService* notificationService = NotificationService()) + { + notificationService->NotifyRecordingStart(FileName); + } +} + +void ChildLock::NotifyUserAction(const eKeys key, const cOsdObject* Interact) +{ + if (INotificationService* notificationService = NotificationService()) + { + notificationService->NotifyUserAction(key, Interact); + } +} diff -urNad vdr-1.5.15~/childlock.h vdr-1.5.15/childlock.h --- vdr-1.5.15~/childlock.h 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.5.15/childlock.h 2008-02-17 22:13:56.000000000 +0100 @@ -0,0 +1,47 @@ +#ifndef __CHILDLOCK_H +#define __CHILDLOCK_H + +#include "keys.h" + +class cChannel; +class cRecording; +class cPlugin; +class cTimer; +class cEvent; +class cOsdObject; + +namespace PinPatch +{ + +class IChildLockService; +class INotificationService; + +class ChildLock +{ + private: + static IChildLockService* _cachedChildLockService; + static INotificationService* _cachedNotificationService; + + private: + static IChildLockService* ChildLockService(); + static INotificationService* NotificationService(); + + public: + static bool IsUnlocked(); + + static bool IsMenuProtected(const char* MenuName); + static bool IsChannelProtected(const cChannel* Channel); + static bool IsRecordingProtected(const cRecording* Recording, const char* Name, const char* Base, bool isDirectory); + static bool IsPluginProtected(cPlugin* Plugin); + + static bool IsMenuHidden(const char* MenuName); + static bool IsPluginHidden(cPlugin* Plugin); + static bool IsRecordingHidden(const cRecording* Recording, const char* Name, const char* Base, bool isDirectory); + + static void NotifyTimerCreation(cTimer* Timer, const cEvent *Event); + static void NotifyRecordingStart(const char* FileName); + static void NotifyUserAction(const eKeys key, const cOsdObject* Interact); +}; + +}; +#endif diff -urNad vdr-1.5.15~/childlockservice.h vdr-1.5.15/childlockservice.h --- vdr-1.5.15~/childlockservice.h 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.5.15/childlockservice.h 2008-02-17 22:13:56.000000000 +0100 @@ -0,0 +1,46 @@ +#ifndef __CHILDLOCKSERVICE_H +#define __CHILDLOCKSERVICE_H + +#include "keys.h" + +class cChannel; +class cRecording; +class cPlugin; +class cTimer; +class cEvent; +class cOsdObject; + +namespace PinPatch +{ + +#define CHILDLOCK_SERVICE_ID "ChildLockService-v0.1::ChildLockService" + +class IChildLockService +{ + public: + virtual ~IChildLockService() {}; + virtual bool IsUnlocked() = 0; + + virtual bool IsMenuProtected(const char* MenuName) = 0; + virtual bool IsChannelProtected(const cChannel* Channel) = 0; + virtual bool IsRecordingProtected(const cRecording* Recording, const char* Name, const char* Base, bool isDirectory) = 0; + virtual bool IsPluginProtected(cPlugin* Plugin) = 0; + + virtual bool IsMenuHidden(const char* MenuName) = 0; + virtual bool IsPluginHidden(cPlugin* Plugin) = 0; + virtual bool IsRecordingHidden(const cRecording* Recording, const char* Name, const char* Base, bool isDirectory) = 0; +}; + +#define NOTIFICATION_SERVICE_ID "PinPlugin-v0.1::NotificationService" + +class INotificationService +{ + public: + virtual ~INotificationService() {}; + virtual void NotifyTimerCreation(cTimer* Timer, const cEvent *Event) = 0; + virtual void NotifyRecordingStart(const char* FileName) = 0; + virtual void NotifyUserAction(const eKeys key, const cOsdObject* Interact) = 0; +}; + +}; +#endif diff -urNad vdr-1.5.15~/device.c vdr-1.5.15/device.c --- vdr-1.5.15~/device.c 2008-02-17 22:13:55.000000000 +0100 +++ vdr-1.5.15/device.c 2008-02-17 22:13:56.000000000 +0100 @@ -18,6 +18,7 @@ #include "receiver.h" #include "status.h" #include "transfer.h" +#include "childlock.h" // --- cLiveSubtitle --------------------------------------------------------- @@ -761,6 +762,7 @@ cChannel *channel; while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { // try only channels which are currently available + if (PinPatch::ChildLock::IsChannelProtected(channel) == false) if (GetDevice(channel, 0, true)) break; n = channel->Number() + Direction; @@ -782,6 +784,9 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) { + if (LiveView && PinPatch::ChildLock::IsChannelProtected(Channel) == true) + return scrNotAvailable; + if (LiveView) { StopReplay(); DELETENULL(liveSubtitle); diff -urNad vdr-1.5.15~/menu.c vdr-1.5.15/menu.c --- vdr-1.5.15~/menu.c 2008-02-17 22:13:55.000000000 +0100 +++ vdr-1.5.15/menu.c 2008-02-17 22:13:56.000000000 +0100 @@ -32,6 +32,7 @@ #include "transfer.h" #include "vdrttxtsubshooks.h" #include "videodir.h" +#include "childlock.h" #define MAXWAIT4EPGINFO 3 // seconds #define MODETIMEOUT 3 // seconds @@ -756,6 +757,10 @@ Add(new cMenuEditBitItem( tr("VPS"), &data.flags, tfVps)); Add(new cMenuEditIntItem( tr("Priority"), &data.priority, 0, MAXPRIORITY)); Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, MAXLIFETIME)); + + if (PinPatch::ChildLock::IsUnlocked()) + Add(new cMenuEditBitItem(tr("Timer$Childlock"), &data.flags, tfProtected)); + Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file))); SetFirstDayItem(); } @@ -2300,7 +2305,8 @@ for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == '~')) { cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level); - if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) { + if ((*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) + && (!PinPatch::ChildLock::IsRecordingHidden(GetRecording(Item), Item->Name(), base, Item->IsDirectory()))) { Add(Item); LastItem = Item; free(LastItemText); @@ -2363,6 +2369,9 @@ { cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); if (ri) { + if (PinPatch::ChildLock::IsRecordingProtected(GetRecording(ri), ri->Name(), base, ri->IsDirectory()) == true) + return osContinue; + if (ri->IsDirectory()) Open(); else { @@ -3396,6 +3405,8 @@ } else if ((*i)->IsPluginItem()) { const char *item = (*i)->PluginMenuEntry(); + cPlugin *plugin = cPluginManager::GetPlugin((*i)->PluginIndex()); + if (!PinPatch::ChildLock::IsPluginHidden(plugin)) if (item) Add(new cMenuPluginItem(hk(item), (*i)->PluginIndex())); } @@ -3405,9 +3416,13 @@ // Basic menu items: + if (!PinPatch::ChildLock::IsMenuHidden("Schedule")) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); + if (!PinPatch::ChildLock::IsMenuHidden("Channels")) Add(new cOsdItem(hk(tr("Channels")), osChannels)); + if (!PinPatch::ChildLock::IsMenuHidden("Timers")) Add(new cOsdItem(hk(tr("Timers")), osTimers)); + if (!PinPatch::ChildLock::IsMenuHidden("Recordings")) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); // Plugins: @@ -3415,18 +3430,22 @@ for (int i = 0; ; i++) { cPlugin *p = cPluginManager::GetPlugin(i); if (p) { + if (!PinPatch::ChildLock::IsPluginHidden(p)) { const char *item = p->MainMenuEntry(); if (item) Add(new cMenuPluginItem(hk(item), i)); } + } else break; } // More basic menu items: + if (!PinPatch::ChildLock::IsMenuHidden("Setup")) Add(new cOsdItem(hk(tr("Setup")), osSetup)); if (Commands.Count()) + if (!PinPatch::ChildLock::IsMenuHidden("Commands")) Add(new cOsdItem(hk(tr("Commands")), osCommands)); } @@ -3507,6 +3526,11 @@ eOSState state = cOsdMenu::ProcessKey(Key); HadSubMenu |= HasSubMenu(); + cOsdItem* item = Get(Current()); + if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) + if (PinPatch::ChildLock::IsMenuProtected(item->Text())) + return osContinue; + cOsdMenu *menu = NULL; switch (state) { case osSchedule: @@ -3553,6 +3577,7 @@ if (item) { cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); if (p) { + if (!PinPatch::ChildLock::IsPluginProtected(p)) { cOsdObject *menu = p->MainMenuAction(); if (menu) { if (menu->IsMenu()) @@ -3564,6 +3589,7 @@ } } } + } state = osEnd; } break; @@ -3766,6 +3792,7 @@ if (Direction) { while (Channel) { Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel); + if (PinPatch::ChildLock::IsChannelProtected(Channel) == false) if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, 0, true)) return Channel; } @@ -4397,6 +4424,7 @@ for (int i = 0; i < MAXRECORDCONTROLS; i++) { if (!RecordControls[i]) { RecordControls[i] = new cRecordControl(device, Timer, Pause); + PinPatch::ChildLock::NotifyRecordingStart(RecordControls[i]->FileName()); return RecordControls[i]->Process(time(NULL)); } } diff -urNad vdr-1.5.15~/po/de_DE.po vdr-1.5.15/po/de_DE.po --- vdr-1.5.15~/po/de_DE.po 2008-02-17 22:13:55.000000000 +0100 +++ vdr-1.5.15/po/de_DE.po 2008-02-17 22:13:56.000000000 +0100 @@ -360,6 +360,9 @@ msgid "Lifetime" msgstr "Lebensdauer" +msgid "Timer$Childlock" +msgstr "Gesichert" + msgid "File" msgstr "Datei" diff -urNad vdr-1.5.15~/po/fr_FR.po vdr-1.5.15/po/fr_FR.po --- vdr-1.5.15~/po/fr_FR.po 2008-02-17 22:13:55.000000000 +0100 +++ vdr-1.5.15/po/fr_FR.po 2008-02-17 22:13:56.000000000 +0100 @@ -366,6 +366,9 @@ msgid "Lifetime" msgstr "Durée de vie" +msgid "Timer$Childlock" +msgstr "Adulte" + msgid "File" msgstr "Fichier" diff -urNad vdr-1.5.15~/timers.c vdr-1.5.15/timers.c --- vdr-1.5.15~/timers.c 2008-02-16 15:47:40.000000000 +0100 +++ vdr-1.5.15/timers.c 2008-02-17 22:14:19.000000000 +0100 @@ -16,6 +16,7 @@ #include "recording.h" #include "remote.h" #include "status.h" +#include "childlock.h" #define VFAT_MAX_FILENAME 40 // same as MAX_SUBTITLE_LENGTH in recording.c @@ -27,6 +28,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) { + aux = NULL; startTime = stopTime = 0; lastSetEvent = 0; recording = pending = inVpsMargin = false; @@ -47,7 +49,6 @@ priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; *file = 0; - aux = NULL; event = NULL; if (Instant && channel) snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); @@ -55,6 +56,7 @@ cTimer::cTimer(const cEvent *Event) { + aux = NULL; startTime = stopTime = 0; lastSetEvent = 0; recording = pending = inVpsMargin = false; @@ -83,8 +85,8 @@ const char *Title = Event->Title(); if (!isempty(Title)) Utf8Strn0Cpy(file, Event->Title(), sizeof(file)); - aux = NULL; event = NULL; // let SetEvent() be called to get a log message + PinPatch::ChildLock::NotifyTimerCreation(this, Event); } cTimer::cTimer(const cTimer &Timer) @@ -258,6 +260,8 @@ return ""; // not NULL, so the caller can always use the result } +#define AUX_STR_PROTECTED "<pin-plugin><protected>yes</protected></pin-plugin>" + bool cTimer::Parse(const char *s) { char *channelbuffer = NULL; @@ -312,6 +316,8 @@ result = false; } } + if (aux && strstr(aux, AUX_STR_PROTECTED)) + SetFlags(tfProtected); free(channelbuffer); free(daybuffer); free(filebuffer); @@ -581,6 +587,26 @@ void cTimer::SetFlags(uint Flags) { flags |= Flags; + + char* tmp = NULL; + char* position; + + if (HasFlags(tfProtected)) { + if (!aux || !strstr(aux, AUX_STR_PROTECTED)) { + if (aux) { + tmp = strdup(aux); + free(aux); + } + asprintf(&aux,"%s%s", tmp ? tmp : "", AUX_STR_PROTECTED); + } + } + else if (aux && (position = strstr(aux, AUX_STR_PROTECTED))) { + asprintf(&tmp, "%.*s%s", position-aux, aux, position+strlen(AUX_STR_PROTECTED)); + free(aux); + aux = strdup(tmp); + } + + free(tmp); } void cTimer::ClrFlags(uint Flags) diff -urNad vdr-1.5.15~/timers.h vdr-1.5.15/timers.h --- vdr-1.5.15~/timers.h 2008-02-16 15:33:23.000000000 +0100 +++ vdr-1.5.15/timers.h 2008-02-17 22:13:56.000000000 +0100 @@ -20,6 +20,7 @@ tfInstant = 0x0002, tfVps = 0x0004, tfRecording = 0x0008, + tfProtected = 0x8000, tfAll = 0xFFFF, }; enum eTimerMatch { tmNone, tmPartial, tmFull }; diff -urNad vdr-1.5.15~/vdr.c vdr-1.5.15/vdr.c --- vdr-1.5.15~/vdr.c 2008-02-17 22:13:55.000000000 +0100 +++ vdr-1.5.15/vdr.c 2008-02-17 22:13:56.000000000 +0100 @@ -64,6 +64,7 @@ #include "tools.h" #include "transfer.h" #include "videodir.h" +#include "childlock.h" #define MINCHANNELWAIT 10 // seconds to wait between failed channel switchings #define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping @@ -919,6 +920,7 @@ cOsdObject *Interact = Menu ? Menu : cControl::Control(); eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse()); if (ISREALKEY(key)) { + PinPatch::ChildLock::NotifyUserAction(key, Interact); EITScanner.Activity(); // Cancel shutdown countdown: if (ShutdownHandler.countdown) @@ -991,10 +993,12 @@ cControl::Control()->Hide(); cPlugin *plugin = cPluginManager::GetPlugin(PluginName); if (plugin) { + if (!PinPatch::ChildLock::IsPluginProtected(plugin)) { Menu = plugin->MainMenuAction(); if (Menu) Menu->Show(); } + } else esyslog("ERROR: unknown plugin '%s'", PluginName); } @@ -1203,9 +1207,11 @@ // Instant resume of the last viewed recording: case kPlay: if (cReplayControl::LastReplayed()) { + if (PinPatch::ChildLock::IsRecordingProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { cControl::Shutdown(); cControl::Launch(new cReplayControl); } + } break; default: break; }