diff options
author | horchi <vdr@jwendel.de> | 2017-03-05 16:48:30 +0100 |
---|---|---|
committer | horchi <vdr@jwendel.de> | 2017-03-05 16:48:30 +0100 |
commit | bf558fd824c7ab8c794448f718b364ad403a706a (patch) | |
tree | e0ba2269c08ccc9c9bd9c336df06b1fa6fce5ec6 | |
download | vdr-plugin-pin-0.1.16.tar.gz vdr-plugin-pin-0.1.16.tar.bz2 |
git init0.1.16
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | HISTORY | 130 | ||||
l--------- | Makefile | 1 | ||||
-rw-r--r-- | Makefile.pre-1.7.35 | 125 | ||||
-rw-r--r-- | Makefile.since-1.7.35 | 131 | ||||
-rw-r--r-- | README | 62 | ||||
-rw-r--r-- | brdclocks.c | 125 | ||||
-rw-r--r-- | def.c | 41 | ||||
-rw-r--r-- | def.h | 178 | ||||
-rw-r--r-- | fskcheck.c | 172 | ||||
-rw-r--r-- | locks.c | 274 | ||||
-rw-r--r-- | locks.h | 182 | ||||
-rw-r--r-- | menu.c | 518 | ||||
-rw-r--r-- | menu.h | 151 | ||||
-rw-r--r-- | msgreceiver.c | 141 | ||||
-rw-r--r-- | patches/epgsearch-0.9.19.diff | 85 | ||||
-rw-r--r-- | patches/epgsearch-0.9.20.diff | 221 | ||||
-rw-r--r-- | patches/epgsearch-0.9.21.diff | 194 | ||||
-rw-r--r-- | patches/vdr-1.4.5.diff | 454 | ||||
-rw-r--r-- | patches/vdr-1.7.17.diff | 416 | ||||
-rw-r--r-- | patches/vdr-1.7.32.diff | 426 | ||||
-rw-r--r-- | patches/vdr-1.7.33.diff | 427 | ||||
-rw-r--r-- | patches/vdr-2.0.2.diff | 420 | ||||
-rw-r--r-- | patches/vdr-2.3.1.diff | 432 | ||||
-rw-r--r-- | pin.c | 882 | ||||
-rw-r--r-- | pin.h | 237 | ||||
-rw-r--r-- | po/de_DE.po | 170 | ||||
-rw-r--r-- | po/fr_FR.po | 173 | ||||
-rw-r--r-- | po/hu_HU.po | 171 | ||||
-rw-r--r-- | po/it_IT.po | 172 | ||||
-rw-r--r-- | po/ru_RU.po | 170 | ||||
-rw-r--r-- | rep.c | 77 | ||||
-rw-r--r-- | rep.h | 31 | ||||
-rwxr-xr-x | scripts/cut.sh | 14 | ||||
-rwxr-xr-x | scripts/fskcheck-demo.sh | 23 | ||||
-rwxr-xr-x | scripts/fskprotect.sh | 34 | ||||
-rwxr-xr-x | scripts/getSetupMenues | 8 | ||||
-rw-r--r-- | setupmenu.c | 139 | ||||
-rw-r--r-- | setupmenu.h | 42 | ||||
-rw-r--r-- | talk.c | 198 | ||||
-rw-r--r-- | talk.h | 97 | ||||
-rw-r--r-- | test.cc | 13 |
43 files changed, 8305 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f0cc9a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.dependencies +po/*~ +po/*.mo +po/*.pot +*.so +*.o +*~ +fskcheck
\ No newline at end of file @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. @@ -0,0 +1,130 @@ + * --------------------------------------------------------------------- + * Version - History + * --------------------------------------------------------------------- + * + * build version date comment + * + + * #41 0.1.16 01.11.15, added: fixed backward compatibility + * #40 0.1.15 09.10.15, added: ported to vdr 2.3.1 + * #39 0.1.14 22.05.13, added: patch for vdr 2.0.2 + added: Makefile for vdr >= 1.7.35 + * #38 0.1.13 10.12.12, added: patch for vdr 1.7.33 + * #37 0.1.12 07.12.12, added: patch for vdr 1.7.32 + * #36 0.1.11 31.03.11, added: patch for vdr 1.7.17 + * #35 0.1.10 20.07.08, added: italian translations (thanks to Gringo) + * #34 0.1.9 19.05.07, added: setup option for log-level + More frensh translations from pat, thanks! + 'no translation found' message now appear + only once for each text + (added internal cache for menu item translations) + * #33 0.1.8 12.02.07, added: Autofill of list with menu-entry + * #32 0.1.7 31.01.07, added: Hiding protected plugins. + bugfix: Fixed problem with hotkey handling in pin menu + added: Protection of menu entries. + Hiding protected menu entries. + New search mode 'start with'. + Extended search modes (exact, regular expression, includes, start with) + now available for all items (channels, plugins, menuitems). + Hiding protected items now configuable. + added patch for epgsearch 0.9.20 + * #31 0.1.6a 29.01.07, bugfix: Fixed syntax error in vdr patch (reported by zulu) + * #30 0.1.6 28.01.07, added: Hiding protected recorings in recordings menu + * #29 0.1.5b 12.01.07, bugfix: Fixed error message when closing setup. + Fixed translation in timer menue, thanks to Marc (zulu) + added: Patch for vdr 1.4.5 + change: Patch for epgsearch changed + * #28 0.1.5a 07.01.07, change: pin in setup dialog now hidden again. + * #27 0.1.5 06.01.07, bugfix: Fixed protection leak when replaying via + the 'Play' key, reported by Christian Reiser. + change: Edit of timers fsk setting only protected if the + timer 'not' already locked + * #26 0.1.4 23.11.06, added: Frensh translations from pat, thanks! + * #25 0.1.3 23.11.06, change: Pin input dialog now calls status class + (thereby it's shown on graphTFT, ...) + added: Edit of timers fsk setting only when unlocked ;) + bugfix: Some small fixes + * #24 0.1.2 09.11.06, change: limited pin to 5 digits + change: many namings and translations + bugfix: fixed handling of daylightsavingtime. + change: ask for inital pincode setup when entering menue + added: EXCLUDEPLUGINS to makefile, here can defined which + plugins can't protected + added: setup-plugin lock to pin menu (for fast and easy access) + added: button blue now toggle protection in list + added: patch for the timer menu of epgsearch + the changes of thes release mostly suggested by Andreas Ritter + * #23 0.1.1 11.09.06, added: Redesign of fskcheck communication (some code rework) + bugfix: Fixed translation bug in patch (Danke Frank!) + bugfix: Take care of daylightsavingtime. + added: Changed patch due to epgsearch plugin requirements. + * #22 0.1.0 09.09.06, change: No protection until a pin code was configured + (requested by Andreas Ritter) + change: Enter pin menu directly if pin was + accepted (configurable) (requested by Andreas Ritter) + added: Translation of script messages by + plugin (as far as found in translation list) + Frensh translations from pat, thanks! + bugix: Fixed calculation of 'inactivity' time + change: Some code cleanup + * #21 0.0.21 10.06.06, change: Removed green and yellow button in plugin-lock menu + * #20 0.0.20 30.05.06, bugfix: Fixed crash in empty lock menus (reported by Andreas Ritter) + Fixed permissions of config path (reported by wilderigel) + * #19 0.0.19 20.05.06, change: Using skin for pin request dialog + * #18 0.0.18 04.05.06, change: Code redesign, pooled similar classes, .. + * added: Paragraph-Sign to mark activated locks in pin menu lists + * #17 0.0.17 04.05.06, added: plugin protection + * bugfix: fixed problem with recording subdirectories + * (bug was reported by Viking, thanks!) + * #16 0.0.16 01.05.06, bugfix: fixed permissions ot system message queues. + * added: num keys navigation for pin menu + * added: Missing translation for 'Recording + * protected, enter pin code first'. + * All this detected and reported by Michael Nausch, many thanks! + * #15 0.0.15 29.04.06, added: french translations (thanks to Pat!) + * change: Makefile due to VDR's new APIVERSION feature + * #14 0.0.14 08.04.06, added: protection feature for scripting + * #13 0.0.13 26.03.06, bugfix: autoProtectionMode now respect start time + * of event (needed since channels not + * protected every time) + * #12 0.0.12 20.03.06, change: now using aux field in timer config patch + * bugfix: autoProtectionMode will now restored from config + * (Bug reported by rookie1, thanks!) + * bugfix: autoProtectionMode now working even with vdr 1.3.44 + * (Bug reported by rookie1, thanks!) + * #11 0.0.11 26.02.06, bugfix: create missing config directory at startup. + * bugfix: keys 1-5 in pin menu now working. + * added: hungary translations (thanks to Albert Papp!) + * change: silend skip of channels works now again + * (fixed problems due to changes of VDR 1.3.40) + * #10 0.0.10 28.01.06, added: regular expressions for brodcasts locks. + * added: russian translations (appropriated by Monchenko Vladimir, thanks!) + * bugfix: only 3 chars of pin in setup menu (reported by Monchenko Vladimir, thanks!) + * #9 0.0.9 26.01.06, added: lock for brodcasts. + * #8 0.0.8 17.01.06, added: channel lock time range. + * #7 0.0.7 15.01.06, added: channel lock list and improved configuration + * #6 0.0.6f 13.01.06, change: removed pin request on demand + * 0.0.6e 23.12.05, bugfix: syslog message at channel check + * 0.0.6d 18.12.05, added: dynamic handling of menu entries + * 0.0.6c 18.12.05, added: internationalisation + * 0.0.6b 18.12.05, change: reset time now in minutes + * 0.0.6a 17.12.05, added: reset time for pin code + * 0.0.6 17.12.05, added: protection flag to timer config + * #5 0.0.5b 11.12.05, bugfix: some bugfixes, added handling for recording + * 0.0.5a 10.12.05, added: pin request on demand, even for replay of recorings + * 0.0.5 10.12.05, added: pin request on demand + * #4 0.0.4 08.12.05, added: channel protection + * #3 0.0.3 06.12.05, added: protection of recording sub-directorys + * #2 0.0.2 01.12.05, bugfixes + * #1 0.0.1 11.04.05, initial release + * + * + + * --------------------------------------------------------------------- + * Todos + * --------------------------------------------------------------------- + * + * - broadcast locks via event description and/or epg text + * + * --------------------------------------------------------------------- + diff --git a/Makefile b/Makefile new file mode 120000 index 0000000..b3f546d --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +Makefile.since-1.7.35
\ No newline at end of file diff --git a/Makefile.pre-1.7.35 b/Makefile.pre-1.7.35 new file mode 100644 index 0000000..84d629d --- /dev/null +++ b/Makefile.pre-1.7.35 @@ -0,0 +1,125 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id: Makefile,v 1.8 2011-03-31 08:59:31 root Exp $ + +# The official name of this plugin. +# This name will be used in the '-P...' option of VDR to load the plugin. +# By default the main source file also carries this name. +# +PLUGIN = pin + +### User settings, list of plugins which can not protected + +EXCLUDEPLUGINS = "femon,text2skin,span,remote,premiereepg" + +### The version number of this plugin (taken from the main source file): + +VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).h | awk '{ print $$6 }' | sed -e 's/[";]//g') + +### The C++ compiler and options: + +CXX ?= g++ +#CXXFLAGS ?= -ggdb -fPIC -O2 -Wall -Wno-unused-result -Woverloaded-virtual +CXXFLAGS ?= -fPIC -O2 -Wall -Wno-unused-result -Woverloaded-virtual + +### The directory environment: + +DVBDIR = ../../../../DVB +VDRDIR = ../../.. +LIBDIR = ../../lib +TMPDIR = /tmp +FSKCHKDIR = /usr/bin + +### Allow user defined options to overwrite defaults: + +-include $(VDRDIR)/Make.config + +### The version number of VDR (taken from VDR's "config.h"): + +APIVERSION = $(shell grep 'define APIVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g') + +### The name of the distribution archive: + +ARCHIVE = $(PLUGIN)-$(VERSION) +PACKAGE = vdr-$(ARCHIVE) + +### Includes and Defines (add further entries here): + +INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include + +DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -D__EXCL_PLUGINS='""$(EXCLUDEPLUGINS)""' + +### The object files (add further files here): + +OBJS = $(PLUGIN).o setupmenu.o def.o menu.o locks.o brdclocks.o rep.o msgreceiver.o talk.o +CMDOBJS = fskcheck.o talk.o def.o + +### Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< + +# Dependencies: + +MAKEDEP = g++ -MM -MG +DEPFILE = .dependencies +$(DEPFILE): Makefile + @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +### Internationalization (I18N): + +PODIR = po +LOCALEDIR = $(VDRDIR)/locale +I18Npo = $(wildcard $(PODIR)/*.po) +I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) +I18Ndirs = $(notdir $(foreach file, $(I18Npo), $(basename $(file)))) +I18Npot = $(PODIR)/$(PLUGIN).pot + +%.mo: %.po + msgfmt -c -o $@ $< + +$(I18Npot): $(wildcard *.c) + xgettext -C -cTRANSLATORS --no-wrap -F -k -ktr -ktrNOOP --msgid-bugs-address='<vdr@jwendel.de>' -o $@ $(wildcard *.c) + +$(I18Npo): $(I18Npot) + msgmerge -U --no-wrap -F --backup=none -q $@ $< + +i18n: $(I18Nmo) + @mkdir -p $(LOCALEDIR) + for i in $(I18Ndirs); do\ + mkdir -p $(LOCALEDIR)/$$i/LC_MESSAGES;\ + cp $(PODIR)/$$i.mo $(LOCALEDIR)/$$i/LC_MESSAGES/vdr-$(PLUGIN).mo;\ + done + +### Targets: + +all: i18n + @make fskcheck + @make plugin + +plugin: libvdr-$(PLUGIN).so + +fskcheck: $(CMDOBJS) + $(CXX) $(CXXFLAGS) $(CMDOBJS) -o $@ + @strip $@ +# @cp $@ $(FSKCHKDIR) + +libvdr-$(PLUGIN).so: $(OBJS) + $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ + @cp $@ $(LIBDIR)/$@.$(APIVERSION) + +dist: clean + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @mkdir $(TMPDIR)/$(ARCHIVE) + @cp -a * $(TMPDIR)/$(ARCHIVE) + @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE) + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @echo Distribution package created as $(PACKAGE).tgz + +clean: + @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot $(PODIR)/*~ + @-rm -f $(OBJS) $(CMDOBJS) $(DEPFILE) *.so *.tgz core* *~ fskcheck + diff --git a/Makefile.since-1.7.35 b/Makefile.since-1.7.35 new file mode 100644 index 0000000..fa84228 --- /dev/null +++ b/Makefile.since-1.7.35 @@ -0,0 +1,131 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id$ + +# The official name of this plugin. +# This name will be used in the '-P...' option of VDR to load the plugin. +# By default the main source file also carries this name. + +PLUGIN = pin + +### The version number of this plugin (taken from the main source file): + +VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).h | awk '{ print $$6 }' | sed -e 's/[";]//g') + +### User settings, list of plugins which can not protected + +EXCLUDEPLUGINS = "femon,text2skin,span,remote,premiereepg" + +### The directory environment: + +# Use package data if installed...otherwise assume we're under the VDR source directory: +PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc)) +LIBDIR = $(call PKGCFG,libdir) +LOCDIR = $(call PKGCFG,locdir) +PLGCFG = $(call PKGCFG,plgcfg) +# +TMPDIR ?= /tmp + +### The compiler options: + +export CFLAGS = $(call PKGCFG,cflags) +export CXXFLAGS = $(call PKGCFG,cxxflags) + +### The version number of VDR's plugin API: + +APIVERSION = $(call PKGCFG,apiversion) + +### Allow user defined options to overwrite defaults: + +-include $(PLGCFG) + +### The name of the distribution archive: + +ARCHIVE = $(PLUGIN)-$(VERSION) +PACKAGE = vdr-$(ARCHIVE) + +### The name of the shared object file: + +SOFILE = libvdr-$(PLUGIN).so + +### Includes and Defines (add further entries here): + +INCLUDES += -I$(VDRDIR)/include + +DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -D__EXCL_PLUGINS='""$(EXCLUDEPLUGINS)""' + +### The object files (add further files here): + +OBJS = $(PLUGIN).o setupmenu.o def.o menu.o locks.o brdclocks.o rep.o msgreceiver.o talk.o +CMDOBJS = fskcheck.o talk.o def.o + +### The main target: + +all: $(SOFILE) i18n fskcheck + +### Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $< + +### Dependencies: + +MAKEDEP = $(CXX) -MM -MG +DEPFILE = .dependencies +$(DEPFILE): Makefile + @$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +### Internationalization (I18N): + +PODIR = po +I18Npo = $(wildcard $(PODIR)/*.po) +I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) +I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file)))))) +I18Npot = $(PODIR)/$(PLUGIN).pot + +%.mo: %.po + msgfmt -c -o $@ $< + +$(I18Npot): $(wildcard *.c) + xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^` + +%.po: $(I18Npot) + msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $< + @touch $@ + +$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo + install -D -m644 $< $@ + +.PHONY: i18n +i18n: $(I18Nmo) $(I18Npot) + +install-i18n: $(I18Nmsgs) + +### Targets: + +$(SOFILE): $(OBJS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@ + +fskcheck: $(CMDOBJS) + $(CXX) $(CXXFLAGS) $(CMDOBJS) -o $@ + @strip $@ + +install-lib: $(SOFILE) + install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) + +install: install-lib install-i18n + +dist: $(I18Npo) clean + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @mkdir $(TMPDIR)/$(ARCHIVE) + @cp -a * $(TMPDIR)/$(ARCHIVE) + @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE) + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @echo Distribution package created as $(PACKAGE).tgz + +clean: + @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot $(PODIR)/*~ + @-rm -f $(OBJS) $(CMDOBJS) $(DEPFILE) *.so *.tgz core* *~ fskcheck @@ -0,0 +1,62 @@ + +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Jörg Wendel (horchi@vdr-portal) +Project's homepage: http://www.jwendel.de +Latest version available at: vdr-developer.org + +This software is released under the GPL, version 2 (see COPYING). +Additionally, compiling, linking, and/or using the OpenSSL toolkit in +conjunction with this software is allowed. + +PIN Plugin: +----------- +Das Plugin ist eine Kindersicherung für Aufnahmen, Kanäle, Sendungen, Plugins und Shell-Skripten. +Der bis zu 5-stellige numerische PIN kann im Plugin-Setup Menü eingestellt werden. +Das freischalten mittels des PIN Codes erfolgt über den Menüpunkt 'Kindersicherung' im Hauptmenü. +Der Code wird nach jedem Neustart zurückgesetzt. Die Sperre kann jederzeit mit dem entsprechenden +Menüpunktes oder auch automatisch nach einer einstellbaren Zeit aktiviert werden. + +Es werden Aufnahmen in deren Ordner sich die Datei 'protection.fsk' befindet geschützt. +Hierzu 'Aufnahmen->Befehle' - 'FSK Schutz hinzufügen' oder 'FSK Schutz entfernen' wählen. +Plugin, Kanal- und Sendungs-Sperren werden über das Plugin-Menü verwaltet. + +Zum Schutz von Shell-Skripten dient das Tool fskcheck, dieses stellt ein Shell-Interface zum +PIN Plugin dar. Hierüber kann aus einem Skript bzw. von der Kommandozeile abgefragt werden ob die +Kindersicherung gerade aktiviert ist. Auch OSD Meldungen können mittels fskcheck angezeigt werden. +Ein Beispiel Skript hierzu ist im Ordner scripts enthalten. + +Es werden VDR Versionen ab 1.3.47 bis 2.0.2 unterstützt. + +Installation: +------------- + + Plugin in .../VDR/PLUGINS/src/ + auspacken und Link anlegen. + + Ggf. dir Zeile EXCLUDEPLUGINS im Makefile anpassen, die hier aufgelisteten Plugins werden nicht + in der Sperrliste aufgeführt und lassen sich somit auch nicht sperren. + + PIN-Patch auf den VDR anwenden. + + cd /usr/src/VDR + cat PLUGINS/src/pin/patches/vdr-<version>.diff | patch (etwaige rejects auflösen) + make plugins + + ALLE Plugins neu gegen den gepatchten VDR übersezten und installieren! + + Das Skript fskprotect.sh und das tool fskcheck in den Suchpfad (PATH) z.B.: '/usr/local/bin' oder '/usr/bin' + kopieren und in die Konfigurationsdatei reccmd.conf eintragen. + + Beispiel: + + cp -p /usr/src/VDR/PLUGINS/src/pin/scripts/*.sh /usr/bin + cp -p /usr/src/VDR/PLUGINS/src/pin/fskcheck /usr/bin + echo 'FSK Schutz hinzufügen: /usr/bin/fskprotect.sh protect' >> /etc/vdr/reccmds.conf + echo 'FSK Schutz entfernen: /usr/bin/fskprotect.sh unprotect' >> /etc/vdr/reccmds.conf + + Bitte die beiden unteren Zeilen nicht so in die reccmds.conf eintragen sondern auf der Kommandozeile ausführen ;) ! + + Beim scheiden einer Aufnahme wird diese vom VDR umkopiert, diese Kopie ist nun nicht gesperrt! + Um die Sperre automatisch zu übernehmen das beim Start des VDR mit der Option -r angegebene + Skript (noadcall.sh, vdr-recordingaction, ...) um den Code aus scripts/cut.sh erweitern. diff --git a/brdclocks.c b/brdclocks.c new file mode 100644 index 0000000..e22a748 --- /dev/null +++ b/brdclocks.c @@ -0,0 +1,125 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 25.01.06 - 02.02.07, horchi + */ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include "locks.h" +#include "def.h" + +//*************************************************************************** +// Object +//*************************************************************************** + +cLockedBroadcast::cLockedBroadcast() + : cLockItem(yes) +{ + hasRange = no; +} + +cLockedBroadcast::cLockedBroadcast(const char* aName) + : cLockItem(aName, yes) +{ + hasRange = no; +} + +cLockedBroadcast::~cLockedBroadcast() +{ + // nothicng yet ... +} + +//*************************************************************************** +// Parse +//*************************************************************************** + +bool cLockedBroadcast::Parse(char* line) +{ + int fields; + + char* aName = 0; + char* aPattern = 0; + char* aSearchMode = 0; + char* aActive = 0; + + fields = sscanf(line, "%a[^:]:%a[^:]:%a[^:]:%a[^\n]", + &aName, &aPattern, &aSearchMode, &aActive); + + if (fields == 4) + { + if (name) free(name); + name = aName; + + if (pattern) free(pattern); + pattern = aPattern; + + for (int i = 0; i < smCount; i++) + { + if (strcmp(searchModes[i], aSearchMode) == 0) + { + searchMode = i; + break; + } + } + + active = strcmp(aActive, "yes") == 0; + } + + if (aSearchMode) free(aSearchMode); + if (aActive) free(aActive); + + return fields == 4; +} + +//*************************************************************************** +// Save +//*************************************************************************** + +bool cLockedBroadcast::Save(FILE* file) +{ + // Format: "<name>:<pattern>:<searchMode>:<active>" + + return fprintf(file, "%s:%s:%s:%s\n", + name, + pattern, + searchModes[searchMode], + active ? "yes" : "no") > 0; +} + +//*************************************************************************** +// Locked +//*************************************************************************** + +int cLockedBroadcast::Locked(long /*startTime*/) +{ + return active; +} + +//*************************************************************************** +// Class cLockedBroadcasts +//*************************************************************************** +//*************************************************************************** +// Locked +//*************************************************************************** + +int cLockedBroadcasts::Locked(const char* aName, long /*startTime*/) +{ + cLockedBroadcast* broadcast; + + if (!aName) + return no; + + for (broadcast = First(); broadcast; broadcast = Next(broadcast)) + { + if (broadcast->MatchPattern(aName)) + if (broadcast->Locked()) + return yes; + } + + return no; +} @@ -0,0 +1,41 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 11.04.05 - 12.02.07, horchi + */ + +//*************************************************************************** +// Include +//*************************************************************************** + +#include <stdarg.h> +#include <syslog.h> + +#include "def.h" + +int logLevel = eloOff; + +//*************************************************************************** +// Tell +//*************************************************************************** + +int tell(int eloquence, const char* format, ...) +{ + char tmp[1024]; + va_list ap; + + va_start(ap, format); + + if (logLevel >= eloquence) + { + vsnprintf(tmp + 5, sizeof tmp - 5, format, ap); + memcpy(tmp, "[pin] ", 5); + syslog(LOG_INFO, "%s", tmp); + } + + va_end(ap); + + return success; +} @@ -0,0 +1,178 @@ +/* + * def.h + * + * See the README file for copyright information and how to reach the author. + * + */ + + +#ifndef __DEF_H__ +#define __DEF_H__ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> // memset +#include <time.h> +#include <ctype.h> // isdigit + +//*************************************************************************** +// Public Declarations +//*************************************************************************** + +enum Misc +{ + success = 0, + done = success, + fail = -1, + ignore = -1, + na = -1, + yes = 1, + no = 0, + TB = 1 +}; + +enum Eloquence +{ + eloOff, // 0 + eloNormal, // 1 + eloAlways = eloNormal, // 1 historical ;) + eloDetail, // 2 + + eloDebug, // 3 + eloDebug1 = eloDebug, // 3 + eloDebug2, // 4 + eloDebug3 // 5 +}; + +enum Sizes +{ + sizeStamp = 14, + sizeTime = 6, + sizeDate = 8, + sizeHHMM = 4 +}; + +enum TimeFact +{ + // Defintion + + tfMonthsPerYear = 12, + tfWeeksPerYear = 52, + tfDaysPerYear = 365, + tfDaysPerWeek = 7, + tfHoursPerDay = 24, + tfMinutesPerHour = 60, + tfSecondsPerMinute = 60, + + // Calculation + + tfSecondsPerHour = tfMinutesPerHour * tfSecondsPerMinute, + tfSecondsPerDay = tfHoursPerDay * tfSecondsPerHour, + tfSecondsPerYear = tfDaysPerYear * tfSecondsPerDay, + tfSecondsPerWeek = tfDaysPerWeek * tfSecondsPerDay, +}; + +//*************************************************************************** +// Tell +//*************************************************************************** + +extern int logLevel; + +int tell(int eloquence, const char* format, ...); + +//*************************************************************************** +// Date Time +//*************************************************************************** + +class DT +{ + public: + + typedef tm STime; + + static long lNow() + { + long lt = time(0); + STime st; + + localtime_r(<, &st); + lt = mktime(&st); + + lt -= timezone; // care timezone + lt += st.tm_isdst ? tfSecondsPerHour : 0; // care daylightsavingtime + + return lt; + } + + static char* int2Hhmm(long lt, char* ct) + { + STime st; + memset(&st, 0, sizeof(STime)); + gmtime_r(<, &st); + + sprintf(ct, "%2.2d%2.2d", st.tm_hour, st.tm_min); + + return ct; + } + + static long hhmm2Int(const char* c) + { + long lt = 0; + char ct[sizeHHMM+TB]; + + if (strlen(c) != 4) + return na; + + strcpy(ct, c); + lt = atoi(ct+2) * 60; + ct[2] = 0; + lt += atoi(ct) * 60 * 60; + + return lt; + } +}; + +//*************************************************************************** +// String +//*************************************************************************** + +class Str +{ + public: + + static const char* stripHotKey(const char* text) + { + static char buffer[64]; + const char* p = text; + + while (*p) + { + if (*p == ' ') + p++; + else if (isdigit(*p) && isdigit(*(p+1))) + p++; + else if (isdigit(*p) && *(p+1) == ' ') + { + p++; + while (*p == ' ') p++; + break; + } + else + { + p = text; + break; + } + } + + strcpy(buffer, p); + + return buffer; + } +}; + +//*************************************************************************** +#endif // __DEF_H__ diff --git a/fskcheck.c b/fskcheck.c new file mode 100644 index 0000000..c860c30 --- /dev/null +++ b/fskcheck.c @@ -0,0 +1,172 @@ +//*************************************************************************** +/* + * fskcheck.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: fskcheck.c,v 1.3 2007/01/13 07:52:27 root Exp $ + */ +//*************************************************************************** + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/time.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/msg.h> + +#include "def.h" +#include "talk.h" + +//************************************************************************* +// Global +//************************************************************************* + +int choice(char** argv, int& cmd, const char*& msg, long& timeout); + +const char* commands[] = +{ + "Check", + "Info", + + 0 +}; + +enum Command +{ + cmdUnknown = na, + + cmdCheck, + cmdInfo, + + cmdCount +}; + +//*************************************************************************** +// Main +//*************************************************************************** + +int main(int argc, char** argv) +{ + Talk sender; + int status; + int event = Talk::evtUnknown; + const char* msg; + int cmd; + long t; + + if ((status = sender.open(11)) != success) + { + printf("Falal: Can't init message queue, '%s'!\n", strerror(errno)); + return fail; + } + + t = sender.getTimeout(); + msg = 0; + + if (choice(argv, cmd, msg, t) != success) + { + printf("Usage: fskcheck <command> [-t timeout][-v]\n"); + printf(" command: check - check if vdr currently protected\n"); + printf(" command: info <message> - show message on osd\n"); + + return fail; + } + + // init + + sender.init(); + sender.setTimeout(t); + + // select command + + switch (cmd) + { + case cmdCheck: event = Talk::evtCheck; break; + case cmdInfo: event = Talk::evtShow; break; + } + + // send + + if (sender.send(10, event, msg) != success) + { + printf("Fatal: Can't send event (%d) with message '%s' to vdr (port %d), '%s'\n", + event, msg ? msg : "", 10, strerror(errno)); + return fail; + } + + // wait + + if (cmd == cmdCheck) + { + if (sender.wait() == success) + { + // printf("Got (%d) \n", sender.getEvent()); + + if (sender.getEvent() == Talk::evtConfirm) return 1; + if (sender.getEvent() == Talk::evtAbort) return 2; + + return 0; + } + + else + return 0; + } + + return 0; +} + +//*************************************************************************** +// Choise +//*************************************************************************** + +int choice(char** argv, int& cmd, const char*& msg, long& timeout) +{ + // skip program path + + argv++; + + // get command + + if (!(*argv)) + return fail; + + for (cmd = 0; cmd < cmdCount; cmd++) + if (strcasecmp(commands[cmd], *argv) == 0) + break; + + if (cmd >= cmdCount) + return fail; + + argv++; + + while (*argv) + { + if (**argv == '-') + { + if (strcmp(*argv, "-t") == 0) + { + // timeout + + if (!(*(++argv))) break; + + timeout = atoi(*argv); + } + } + else + { + // the message + + msg = *argv; + } + + argv++; + } + + return success; +} @@ -0,0 +1,274 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 11.04.05 - 02.02.07, horchi + */ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include "locks.h" +#include "def.h" + +//*************************************************************************** +// Statics +//*************************************************************************** + +const char* cLockItem::searchModes[] = +{ + "regular expression", + "includes", + "exact", + "start with", + 0 +}; + +//*************************************************************************** +// Object +//*************************************************************************** + +cLockItem::cLockItem(int aActive) +{ + name = 0; + title = 0; + active = aActive; + hasRange = yes; + start = 0; + end = 0; + pattern = 0; + searchMode = smExact; +} + +cLockItem::cLockItem(const char* aName, int aActive, const char* aTitle) +{ + int res; + res = asprintf(&name, "%s", aName); + res = asprintf(&pattern, "%s", aName); + if (res < 0) ; // memory problems :o + active = aActive; + hasRange = yes; + title = 0; + start = DT::hhmm2Int("0000"); + end = DT::hhmm2Int("2359"); + searchMode = smExact; + + if (aTitle) + res = asprintf(&title, "%s", aTitle); +} + +cLockItem::~cLockItem() +{ + if (name) free(name); + if (title) free(title); + if (pattern) free(pattern); +} + +//*************************************************************************** +// Name +//*************************************************************************** + +void cLockItem::SetName(const char* aName) +{ + int res; + + if (!aName) + return; + + if (name) + free(name); + + res = asprintf(&name, "%s", aName); + if (res < 0) ; // memory problems :o +} + +//*************************************************************************** +// Pattern +//*************************************************************************** + +void cLockItem::SetPattern(const char* aPattern) +{ + int res; + + if (pattern) + free(pattern); + + res = asprintf(&pattern, "%s", aPattern); + if (res < 0) ; // memory problems :o +} + +//*************************************************************************** +// Title +//*************************************************************************** + +void cLockItem::SetTitle(const char* aTitle) +{ + int res; + + if (!aTitle) + return; + + if (title) + free(title); + + res = asprintf(&title, "%s", aTitle); + + if (res < 0) ; // memory problems :o +} + +//*************************************************************************** +// Parse +//*************************************************************************** + +bool cLockItem::Parse(char* line) +{ + int fields; + + char* aName = 0; + char* aActive = 0; + char* aStart = 0; + char* aEnd = 0; + char* aPattern = 0; + char* aSearchMode = 0; + + fields = sscanf(line, "%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^\n]", + &aName, &aActive, &aStart, &aEnd, + &aPattern, &aSearchMode); + + if (fields >= 4) + { + if (name) free(name); + name = aName; + active = strcmp(aActive, "yes") == 0; + start = DT::hhmm2Int(aStart); + end = DT::hhmm2Int(aEnd); + } + + if (fields == 6) + { + if (pattern) free(pattern); + pattern = aPattern; + + for (int i = 0; i < smCount; i++) + { + if (strcmp(searchModes[i], aSearchMode) == 0) + { + searchMode = i; + break; + } + } + } + else if (fields == 4) + { + SetPattern(name); + searchMode = smExact; + } + + if (aActive) free(aActive); + if (aStart) free(aStart); + if (aEnd) free(aEnd); + if (aSearchMode) free(aSearchMode); + + return fields == 4 || fields == 6; +} + +//*************************************************************************** +// Save +//*************************************************************************** + +bool cLockItem::Save(FILE* file) +{ + char aStart[sizeHHMM+TB]; + char aEnd[sizeHHMM+TB]; + + DT::int2Hhmm(start, aStart); + DT::int2Hhmm(end, aEnd); + + // Format: "<name>:<active>:<start>:<end>:<pattern>:<searchMode>" + + return fprintf(file, "%s:%s:%s:%s:%s:%s\n", + name, + active ? "yes" : "no", + aStart, aEnd, pattern, + searchModes[searchMode]) > 0; +} + +//*************************************************************************** +// Locked +//*************************************************************************** + +int cLockItem::Locked(long startTime) +{ + long sec; + char ct[sizeHHMM+TB]; + long theTime; + + if (startTime) + theTime = startTime; + else + theTime = DT::lNow(); // get now in seconds + + // get seconds from today 00:00 in actual timezone + + tell(eloDebug, "Checking protection at '%s'", DT::int2Hhmm(theTime, ct)); + + sec = DT::hhmm2Int(DT::int2Hhmm(theTime, ct)); + + if (sec >= start && sec <= end && active) + return yes; + + return no; +} + +//*************************************************************************** +// Match Pattern +//*************************************************************************** + +bool cLockItem::MatchPattern(const char* aName) +{ + if (searchMode == smRegexp) + return rep(aName, pattern) == success; + else if (searchMode == smExact) + return strcmp(pattern, aName) == 0; + else if (searchMode == smInclude) + return strstr(aName, pattern) > 0; + else if (searchMode == smStartWith) + return strstr(aName, pattern) == aName; + + return no; +} + +//*************************************************************************** +// Has Name +//*************************************************************************** + +bool cLockItem::HasName(const char* aName) +{ + return strcmp(name, aName) == 0; +} + +//*************************************************************************** +// Class cLockItems +//*************************************************************************** +//*************************************************************************** +// Locked +//*************************************************************************** + +int cLockItems::Locked(const char* aName, long startTime) +{ + cLockItem* item; + + if (!aName) + return no; + + for (item = First(); item; item = Next(item)) + { + if (item->MatchPattern(aName)) + if (item->Locked(startTime)) + return yes; + } + + return no; +} @@ -0,0 +1,182 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 11.04.05 - 02.02.07, horchi + */ + +#ifndef VDR_PIN_LOCKS_H +#define VDR_PIN_LOCKS_H + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/tools.h> +#include <vdr/config.h> + +#include "rep.h" +#include "def.h" + +//*************************************************************************** +// Lock Item +//*************************************************************************** + +class cLockItem : public cListObject +{ + public: + + enum SearchMode + { + smUnknown = na, + + smRegexp, + smInclude, + smExact, + smStartWith, + + smCount + }; + + cLockItem(int aActive = no); + cLockItem(const char* aName, int aActive = yes, const char* aTitle = 0); + virtual ~cLockItem(); + + // interface + + virtual bool Parse(char* line); + virtual bool Save(FILE* file); + + // tests + + virtual int Locked(long startTime = 0); + bool MatchPattern(const char* aName); + bool HasName(const char* aName); + + // gettings + + int GetActive() { return active; } + const char* GetName() { return name; } + const char* GetTitle() { return title; } + long GetStart() { return start; } + long GetEnd() { return end; } + char* GetStart(char* ct) { return DT::int2Hhmm(start, ct); } + char* GetEnd(char* ct) { return DT::int2Hhmm(end, ct); } + int HasRange() { return hasRange; } + const char* GetPattern() { return pattern; } + int SearchMode() { return searchMode; } + + // settings + + void SetActive(int aActive) { active = aActive; } + void SetName(const char* aName); + void SetTitle(const char* aTitle); + void SetStart(const char* ct) { start = DT::hhmm2Int(ct); } + void SetEnd(const char* ct) { end = DT::hhmm2Int(ct); } + void SetStart(long lt) { start = lt; } + void SetEnd(long lt) { end = lt; } + void SetRangeFlag(int flag) { hasRange = flag; } + void SetSearchMode(int aMode) { searchMode = aMode; } + void SetPattern(const char* aPattern); + + static const char* searchModes[smCount+1]; + + protected: + + char* name; + char* title; + long start; // in seconds + long end; // in seconds + int active; + int hasRange; + char* pattern; + int searchMode; +}; + +//*************************************************************************** +// Locked Broadcast +//*************************************************************************** + +class cLockedBroadcast : public cLockItem +{ + public: + + cLockedBroadcast(); + cLockedBroadcast(const char* aName); + virtual ~cLockedBroadcast(); + + // interface + + virtual bool Parse(char* line); + virtual bool Save(FILE* file); + + // tests + + virtual int Locked(long startTime = 0); +}; + +//*************************************************************************** +// Lock List Base +//*************************************************************************** + +template<class T> class cLockList : public cConfig<T> +{ + public: + + cLockList(int aType) : cConfig<T>::cConfig() { listType = aType; } + + virtual int Locked(const char* aName, long startTime = 0) = 0; + virtual int GetListType() { return listType; } + virtual void SetListType(int aType) { listType = aType; } + + virtual cLockItem* FindByName(const char* aName) + { + T* item; + + if (!aName) + return 0; + + for (item = (T*)this->First(); item; item = (T*)this->Next(item)) + { + if (item->HasName(aName)) + return item; + } + + return 0; + } + + protected: + + int listType; +}; + +//*************************************************************************** +// Lock Item List +//*************************************************************************** + +class cLockItems : public cLockList<cLockItem> +{ + public: + + cLockItems(int aType = na) : cLockList<cLockItem>::cLockList(aType) {} + + virtual int Locked(const char* aName, long startTime = 0); +}; + +//*************************************************************************** +// Lock Broadcasts List +//*************************************************************************** + +class cLockedBroadcasts : public cLockList<cLockedBroadcast> +{ + public: + + cLockedBroadcasts(int aType = na) : cLockList<cLockedBroadcast>::cLockList(aType) {} + + virtual int Locked(const char* aName, long startTime = 0); +}; + +//*************************************************************************** +#endif // VDR_PIN_LOCKS_H + @@ -0,0 +1,518 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + */ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/interface.h> + +#include "menu.h" +#include "pin.h" + +//*************************************************************************** +// Pin Menu +//*************************************************************************** +//*************************************************************************** +// Object +//*************************************************************************** + +cPinMenu::cPinMenu(const char* title, cLockItems* theChannels, + cLockedBroadcasts* theBroadcasts, cLockItems* thePlugins, + cLockItems* theMenuItems) + : cOsdMenu(title) +{ + cLockItem* setupItem; + int setupLocked = no; + + lockedChannels = theChannels; + lockedBroadcasts = theBroadcasts; + lockedPlugins = thePlugins; + lockedMenuItems = theMenuItems; + + if ((setupItem = lockedMenuItems->FindByName(tr("Setup")))) + setupLocked = setupItem->GetActive(); + + if (!setupLocked) + if ((setupItem = lockedPlugins->FindByName("setup"))) + setupLocked = setupItem->GetActive(); + + SetHasHotkeys(); + + cOsdMenu::Add(new cPinMenuItem(hk(tr("Add current channel to protection list")), miAddCurrentChannel)); + cOsdMenu::Add(new cPinMenuItem(hk(tr("Add current broadcast to protection list")), miAddCurrentBroadcast)); + cOsdMenu::Add(new cPinMenuItem(hk(tr("Edit channel locks")), miEditChannelList)); + cOsdMenu::Add(new cPinMenuItem(hk(tr("Edit broadcast locks")), miEditBroadcastList)); + cOsdMenu::Add(new cPinMenuItem(hk(tr("Edit plugin locks")), miEditPluginList)); + cOsdMenu::Add(new cPinMenuItem(hk(tr("Edit menu locks")), miEditMenuItemList)); + cOsdMenu::Add(new cPinMenuItem(setupLocked ? hk(tr("Unlock setup")) : hk(tr("Lock setup")), miProtectSetup)); + cOsdMenu::Add(new cPinMenuItem(hk(tr("Activate childlock")), miLock)); + + Display(); +} + +cPinMenu::~cPinMenu() +{ + // Aenderungen speichern + + lockedChannels->Save(); + lockedBroadcasts->Save(); + lockedPlugins->Save(); + lockedMenuItems->Save(); +} + +//*************************************************************************** +// Process Key +//*************************************************************************** + +eOSState cPinMenu::ProcessKey(eKeys key) +{ + eOSState state = cOsdMenu::ProcessKey(key); + + switch (state) + { + case miLock: + { + if (*cPinPlugin::pinCode) + { + cOsd::pinValid = false; + Skins.Message(mtInfo, tr("Activated pin protection")); + } + else + { + Skins.Message(mtInfo, tr("Please setup a pin code first!")); + } + + return osEnd; + } + + case miAddCurrentChannel: addCurrentChannel(); break; + case miAddCurrentBroadcast: addCurrentBroadcast(); break; + + case miEditChannelList: + state = AddSubMenu(new cLockMenu(tr("Protected channels"), + lockedChannels, ltChannels)); + break; + case miEditBroadcastList: + state = AddSubMenu(new cLockMenu(tr("Protected broadcasts"), + (cLockItems*)lockedBroadcasts, ltBroadcasts)); + break; + case miEditPluginList: + state = AddSubMenu(new cLockMenu(tr("Plugin protections"), + lockedPlugins, ltPlugins)); + break; + case miEditMenuItemList: + state = AddSubMenu(new cLockMenu(tr("Menu protections"), + lockedMenuItems, ltMenuItems)); + break; + case miProtectSetup: + { + char* buf; + int res; + int locked = protectSetup(); + cPinMenuItem* item = (cPinMenuItem*)Get(7-1); + int hotKey = atoi(item->Text()); + + res = asprintf(&buf, " %2d %s", hotKey, locked ? tr("Unlock setup") : tr("Lock setup")); + if (res < 0) ; // memory problems :o + item->SetText(buf, /*copy*/ true); + free(buf); + + Display(); + break; + } + + default: ; + } + + return state; +} + +//*************************************************************************** +// Protect Setup +//*************************************************************************** + +int cPinMenu::protectSetup() +{ + cLockItem* setupItemPlugin; + cLockItem* setupItemMenu; + char* buf; + int locked; + int res; + + if (!(setupItemMenu = lockedMenuItems->FindByName(tr("Setup")))) + lockedMenuItems->Add(setupItemMenu = new cLockItem(tr("Setup"))); + + if (!(setupItemPlugin = lockedPlugins->FindByName("setup"))) + lockedPlugins->Add(setupItemPlugin = new cLockItem("setup")); + + locked = !(setupItemPlugin->GetActive() && setupItemMenu->GetActive()); + + setupItemPlugin->SetActive(locked); + setupItemMenu->SetActive(locked); + + res = asprintf(&buf, "setup %s", locked ? tr("locked") : tr("unlocked")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + free(buf); + + return locked; +} + +//*************************************************************************** +// Add Current Channel +//*************************************************************************** + +int cPinMenu::addCurrentChannel() +{ + const cChannel* channel = 0; + char* buf; + int res; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + + channel = Channels->GetByNumber(cDevice::CurrentChannel()); +#else + channel = Channels.GetByNumber(cDevice::CurrentChannel()); +#endif + + if (!channel || channel->GroupSep()) + return ignore; + + if (lockedChannels->FindByName(channel->Name())) + { + res = asprintf(&buf, "%s - %s", channel->Name(), tr("already in list")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + free(buf); + + return ignore; + } + + res = asprintf(&buf, "%s - %s", channel->Name(), tr("added to protection list")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + free(buf); + + // append channel to lock list + + lockedChannels->Add(new cLockItem(channel->Name())); + + return success; +} + +//*************************************************************************** +// Add Current Broadcast +//*************************************************************************** + +int cPinMenu::addCurrentBroadcast() +{ + const cChannel* channel = 0; + const cSchedule* sched; + const cEvent* event; + char* buf; + int res; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + + channel = Channels->GetByNumber(cDevice::CurrentChannel()); +#else + channel = Channels.GetByNumber(cDevice::CurrentChannel()); +#endif + + if (channel && !channel->GroupSep()) + { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + cStateKey schedulesKey; + cSchedules* schedules = cSchedules::GetSchedulesWrite(schedulesKey, 100/*ms*/); +#else + cSchedulesLock schedulesLock(true); + cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + + if (!schedules) + return done; + + if (!(sched = schedules->GetSchedule(channel->GetChannelID())) || + !(event = sched->GetPresentEvent())) + { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + schedulesKey.Remove(); +#endif + return done; + } + + // Info + + res = asprintf(&buf, "%s - %s", event->Title(), tr("added to protection list")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + free(buf); + + // append event to lock list + + lockedBroadcasts->Add(new cLockedBroadcast(event->Title())); + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + schedulesKey.Remove(); +#endif + } + + return success; +} + +//*************************************************************************** +// Pin Menu Item +//*************************************************************************** +//*************************************************************************** +// Process Key +//*************************************************************************** + +cPinMenuItem::cPinMenuItem(const char* title, int osState) + : cOsdItem(title, (eOSState)osState) +{ + +} + +//*************************************************************************** +// Lock Menu +//*************************************************************************** +//*************************************************************************** +// Object +//*************************************************************************** + +cLockMenu::cLockMenu(const char* title, cLockItems* theItems, ListType theType) + : cOsdMenu(title) +{ + cLockItem* item; + + items = theItems; + type = theType; + + for (item = items->First(); item; item = items->Next(item)) + cOsdMenu::Add(new cLockMenuItem(item)); + + if (type == ltPlugins) + SetHelp(tr("Edit"), 0, 0, tr("On/Off")); + else + SetHelp(tr("Edit"), tr("Add"), tr("Delete"), tr("On/Off")); + + Display(); +} + +cLockMenu::~cLockMenu() +{ +} + +//*************************************************************************** +// Process Key +//*************************************************************************** + +eOSState cLockMenu::ProcessKey(eKeys key) +{ + eOSState state = cOsdMenu::ProcessKey(key); + + if (state == osUnknown) + { + switch (key) + { + case kOk: + case kRed: // Edit + { + if (!items->Count() || !Get(Current())) + break; + + if (items->GetListType() == cPinPlugin::ltBroadcasts) + state = AddSubMenu(new cBroadcastEditMenu((cLockedBroadcast*) + (((cLockMenuItem*)Get(Current()))->GetLockItem()))); + else + state = AddSubMenu(new cLockEditMenu(((cLockMenuItem*)Get(Current()))->GetLockItem())); + + break; + } + + case kGreen: // New + { + cLockItem* item; + + if (type != ltPlugins) + { + if (items->GetListType() == cPinPlugin::ltBroadcasts) + items->Add(item = new cLockedBroadcast("- new -")); + else + items->Add(item = new cLockItem("- new -")); + + cOsdMenu::Add(new cLockMenuItem(item)); + + Display(); + } + + break; + } + + case kYellow: // Delete + { + if (type != ltPlugins) + { + if (!items->Count() || !Get(Current())) + break; + + if (Interface->Confirm(tr("Remove entry?"))) + { + // remove from list + + items->Del(((cLockMenuItem*)Get(Current()))->GetLockItem()); + cOsdMenu::Del(Current()); + } + + Display(); + } + + break; + } + + case kBlue: // Toggle + { + cLockItem* p = ((cLockMenuItem*)Get(Current()))->GetLockItem(); + + p->SetActive(!p->GetActive()); + ((cLockMenuItem*)Get(Current()))->Set(); + + Display(); + + break; + } + + default: break; + } + } + + return state; +} + +//*************************************************************************** +// Lock Menu Item +//*************************************************************************** +//*************************************************************************** +// Object +//*************************************************************************** + +cLockMenuItem::cLockMenuItem(cLockItem* aItem) + : cOsdItem() +{ + item = aItem; + Set(); +} + +cLockMenuItem::~cLockMenuItem() +{ +} + +//*************************************************************************** +// Set +//*************************************************************************** + +void cLockMenuItem::Set() +{ + char* tmp; + int res; + res = asprintf(&tmp, "%c %s", item->GetActive() ? '§' : ' ', GetTitle()); + if (res < 0) ; // memory problems :o + SetText(tmp, /*copy*/ true); + free(tmp); +} + +//*************************************************************************** +// Get Title +//*************************************************************************** + +const char* cLockMenuItem::GetTitle() +{ + if (item->GetTitle()) + return item->GetTitle(); + + return item->GetName(); +} + +//*************************************************************************** +// Lock Edit Menu +//*************************************************************************** +//*************************************************************************** +// Object +//*************************************************************************** + +cLockEditMenu::cLockEditMenu(cLockItem* aItem) +{ + static const char* trSearchModes[cLockedBroadcast::smCount] = { 0 }; + + item = aItem; + strncpy(name, item->GetName(), sizeNameMax); + name[sizeNameMax] = 0; + strncpy(pattern, aItem->GetPattern(), sizePatternMax); + pattern[sizePatternMax] = 0; + active = item->GetActive(); + searchMode = aItem->SearchMode(); + + // translate search modes + + if (!trSearchModes[0]) + for (int i = 0; i < cLockedBroadcast::smCount; i++) + trSearchModes[i] = tr(cLockedBroadcast::searchModes[i]); + + Add(new cMenuEditStrItem(tr("Name"), name, sizeNameMax, editCharacters)); + Add(new cMenuEditBoolItem(tr("Lock active"), &active)); + Add(new cMenuEditStrItem(tr("Keyword"), pattern, sizePatternMax, editCharacters)); + Add(new cMenuEditStraItem(tr("Search mode"), &searchMode, cLockedBroadcast::smCount, trSearchModes)); + + if (item->HasRange()) + { + long l; + + l = item->GetStart(); + start = (l/60/60) * 100 + l/60%60; + l = item->GetEnd(); + end = (l/60/60) * 100 + l/60%60; + + Add(new cMenuEditTimeItem(tr("Start"), &start)); + Add(new cMenuEditTimeItem(tr("Stop"), &end)); + } + + SetTitle(item->GetTitle() ? item->GetTitle() : item->GetName()); +} + +//*************************************************************************** +// Store +//*************************************************************************** + +void cLockEditMenu::Store(void) +{ + item->SetName(name); + item->SetActive(active); + item->SetPattern(pattern); + item->SetSearchMode(searchMode); + + if (item->HasRange()) + { + item->SetStart((start/100)*60*60 + (start%100)*60); + item->SetEnd((end/100)*60*60 + (end%100)*60); + } +} + +//*************************************************************************** +// Broadcast Edit Menu +//*************************************************************************** +//*************************************************************************** +// Object +//*************************************************************************** + +cBroadcastEditMenu::cBroadcastEditMenu(cLockedBroadcast* aItem) + : cLockEditMenu((cLockItem*)aItem) +{ + // notching yet ... +} @@ -0,0 +1,151 @@ +/* + * menu.h: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + */ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/interface.h> +#include <vdr/osdbase.h> +#include <vdr/plugin.h> + +#include "locks.h" +#include "pin.h" + +#define editCharacters " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-/()[]{}ßöäüÖÄÜ.,;#<>@0123456789" + +//*************************************************************************** +// Pin Menu Item +//*************************************************************************** + +class cPinMenuItem : public cOsdItem +{ + public: + + cPinMenuItem(const char* title, int osState); +}; + +//*************************************************************************** +// Pin Menu +//*************************************************************************** + +class cPinMenu : public cOsdMenu, public PinService +{ + public: + + enum Item + { + miLock = os_User, + miAddCurrentChannel, + miDelChannel, + miEditChannelList, + miEditBroadcastList, + miAddCurrentBroadcast, + miEditPluginList, + miEditMenuItemList, + miProtectSetup + }; + + cPinMenu(const char* title, cLockItems* theChannels, + cLockedBroadcasts* theBroadcasts, cLockItems* thePlugins, + cLockItems* theMenuItems); + virtual ~cPinMenu(); + + virtual eOSState ProcessKey(eKeys key); + + int addCurrentChannel(); + int addCurrentBroadcast(); + int protectSetup(); + + protected: + + cLockItems* lockedChannels; + cLockedBroadcasts* lockedBroadcasts; + cLockItems* lockedPlugins; + cLockItems* lockedMenuItems; +}; + +//*************************************************************************** +// Channel Menu Item +//*************************************************************************** + +class cLockMenuItem : public cOsdItem +{ + + public: + + cLockMenuItem(cLockItem* aItem); + virtual ~cLockMenuItem(); + + const char* GetTitle(); + cLockItem* GetLockItem() { return item; } + virtual void Set(); + + protected: + + cLockItem* item; +}; + +//*************************************************************************** +// Channel Menu +//*************************************************************************** + +class cLockMenu : public cOsdMenu, public PinService +{ + public: + + cLockMenu(const char* title, cLockItems* theItems, ListType theType); + virtual ~cLockMenu(); + + eOSState ProcessKey(eKeys key); + + protected: + + cLockItems* items; + ListType type; +}; + +//*************************************************************************** +// Channel Edit Menu +//*************************************************************************** + +class cLockEditMenu : public cMenuSetupPage +{ + public: + + enum Misc + { + sizeNameMax = 50, + sizePatternMax = 50, + sizeTitleMax = 50 + }; + + cLockEditMenu(cLockItem* aItem); + virtual ~cLockEditMenu() {}; + + virtual void Store(void); + + protected: + + cLockItem* item; + char name[sizeNameMax+TB]; + int active; + int start; + int end; + char pattern[sizePatternMax+TB]; + int searchMode; +}; + +//*************************************************************************** +// Broadcast Edit Menu +//*************************************************************************** + +class cBroadcastEditMenu : public cLockEditMenu +{ + public: + + cBroadcastEditMenu(cLockedBroadcast* aBroadcast); +}; diff --git a/msgreceiver.c b/msgreceiver.c new file mode 100644 index 0000000..478b65b --- /dev/null +++ b/msgreceiver.c @@ -0,0 +1,141 @@ +/* + * msgreceiver.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 11.04.05 - 10.09.06 + */ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <sys/stat.h> +#include <sys/msg.h> +#include <signal.h> + +#include <vdr/interface.h> +#include "pin.h" + +//*************************************************************************** +// Object +//*************************************************************************** + +MessageReceiver::MessageReceiver() +{ + active = false; + talk = new Talk; + talk->setTimeout(0); // wichtig !! +} + +MessageReceiver::~MessageReceiver() +{ + delete talk; +} + +//*************************************************************************** +// Start Receiver +//*************************************************************************** + +int MessageReceiver::StartReceiver() +{ + if (!talk->isOpen()) + talk->open(10); + + if (!active) + { + Start(); + } + else + { + tell(eloDebug, "Info: Receiver still running, stopping first!"); + + StopReceiver(); + usleep(250); + Start(); + } + + return success; +} + +//*************************************************************************** +// Stop Receiver +//*************************************************************************** + +int MessageReceiver::StopReceiver() +{ + tell(eloAlways, "Try to stop receiver thread (%d)", pid); + active = false; + talk->send(10, Talk::evtExit); + Cancel(3); + + return success; +} + +//*************************************************************************** +// Action +//*************************************************************************** + +void MessageReceiver::Action() +{ + active = true; + pid = getpid(); + + tell(eloAlways, "PIN plugin receiver thread started (pid=%d)", pid); + + while (active) + { + wait(); + tell(eloDebug, "wait ..."); + } + + tell(eloAlways, "PIN plugin receiver thread ended (pid=%d)", pid); +} + +//*************************************************************************** +// Wait +//*************************************************************************** + +int MessageReceiver::wait() +{ + int status; + + if ((status = talk->wait()) != success) + { + sleep(1); + + return status; + } + + // info + + tell(eloDebug, "Got event (%d) from (%ld) with message [%s]", + talk->getEvent(), talk->getFrom(), + talk->getMessage() ? talk->getMessage() : ""); + + // perform request + + switch (talk->getEvent()) + { + case Talk::evtShow: + { + if (talk->getMessage() && *talk->getMessage()) + { + Skins.QueueMessage(mtInfo, tr(talk->getMessage())); + tell(eloDebug, "Got '%s'", talk->getMessage()); + } + + break; + } + + case Talk::evtCheck: + { + int evt = cOsd::pinValid ? Talk::evtConfirm : Talk::evtAbort; + + if (talk->send(11, evt) != success) + tell(eloDebug, "Sending event (%d) to (%d) failed", evt, 11); + } + } + + return success; +} diff --git a/patches/epgsearch-0.9.19.diff b/patches/epgsearch-0.9.19.diff new file mode 100644 index 0000000..75d6d29 --- /dev/null +++ b/patches/epgsearch-0.9.19.diff @@ -0,0 +1,85 @@ +--- ../epgsearch-0.9.19/menu_myedittimer.c 2006-09-24 20:05:41.000000000 +0200 ++++ menu_myedittimer.c 2006-11-28 13:50:41.000000000 +0100 +@@ -29,6 +29,7 @@ + stop = Timer->Stop(); + priority = Timer->Priority(); + lifetime = Timer->Lifetime(); ++ fskProtection = Timer->FskProtection(); // PIN PATCH + strcpy(file, Timer->File()); + channel = Timer->Channel()->Number(); + if (forcechannel) +@@ -94,6 +95,14 @@ + Add(new cMenuEditBitItem( tr("VPS"), &flags, tfVps)); + Add(new cMenuEditIntItem( tr("Priority"), &priority, 0, MAXPRIORITY)); + Add(new cMenuEditIntItem( tr("Lifetime"), &lifetime, 0, MAXLIFETIME)); ++ // PIN PATCH ++ if (cOsd::pinValid || !fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&fskProtection)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Childlock"), fskProtection ? tr("yes") : tr("no")); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } + Add(new cMenuEditStrItem( tr("File"), file, MaxFileName, tr(FileNameChars))); + Add(new cMenuEditStrItem( tr("Directory"), directory, MaxFileName, tr(AllowedChars))); + +@@ -204,6 +213,33 @@ + return osContinue; + } + ++char* cMenuMyEditTimer::SetFskProtection(int fskProtection, char* aux) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ asprintf(&aux,"%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info to aux ++ ++ asprintf(&tmp, "%.*s%s", p-aux, aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (tmp) ++ free(tmp); ++ ++ return aux; ++} ++ + eOSState cMenuMyEditTimer::ProcessKey(eKeys Key) + { + eOSState state = cOsdMenu::ProcessKey(Key); +@@ -284,6 +320,7 @@ + char* tmpSummary = NULL; + if (timer && timer->Aux()) + tmpSummary = strdup(timer->Aux()); ++ tmpSummary = SetFskProtection(fskProtection, tmpSummary); // PIN PATCH + if (timer) + { + char* cmdbuf = NULL; +--- ../epgsearch-0.9.19/menu_myedittimer.h 2006-09-24 20:05:41.000000000 +0200 ++++ menu_myedittimer.h 2006-11-28 13:48:45.000000000 +0100 +@@ -15,6 +15,7 @@ + cMenuEditDateItem *firstday; + void SetFirstDayItem(void); + cMenuEditStrItem* m_DirItem; ++ char* SetFskProtection(int fskProtection, char* aux); // PIN PATCH + + uint flags; + time_t day; +@@ -25,6 +26,7 @@ + int lifetime; + char file[MaxFileName]; + char directory[MaxFileName]; ++ int fskProtection; // PIN PATCH + public: + cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* event, const cChannel* forcechannel=NULL); + virtual ~cMenuMyEditTimer(); diff --git a/patches/epgsearch-0.9.20.diff b/patches/epgsearch-0.9.20.diff new file mode 100644 index 0000000..c1c2602 --- /dev/null +++ b/patches/epgsearch-0.9.20.diff @@ -0,0 +1,221 @@ +--- ../plain/epgsearch-0.9.20//i18n.c 2007-01-28 16:29:57.000000000 +0100 ++++ i18n.c 2007-02-03 16:54:11.000000000 +0100 +@@ -7327,6 +7327,28 @@ + "",// TODO + "",// TODO + }, ++ { "Childlock", ++ "Kindersicherung", ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "Adulte", ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ }, + { NULL } + }; + +--- ../plain/epgsearch-0.9.20//menu_commands.c 2007-01-13 15:20:59.000000000 +0100 ++++ menu_commands.c 2007-02-10 09:38:32.000000000 +0100 +@@ -135,11 +135,11 @@ + else + { + string fullaux = ""; ++ string aux = ""; + if (event) + { + int bstart = event->StartTime() - timer->StartTime(); + int bstop = timer->StopTime() - event->EndTime(); +- string aux = ""; + int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); + aux = UpdateAuxValue(aux, "update", checkmode); + aux = UpdateAuxValue(aux, "eventid", event->EventID()); +@@ -147,6 +147,12 @@ + aux = UpdateAuxValue(aux, "bstop", bstop); + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } ++ ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); ++ + SetAux(timer, fullaux); + Timers.Add(timer); + timer->Matches(); +--- ../plain/epgsearch-0.9.20//menu_main.c 2007-01-16 23:38:11.000000000 +0100 ++++ menu_main.c 2007-02-10 09:38:47.000000000 +0100 +@@ -159,12 +159,12 @@ + else + { + string fullaux = ""; ++ string aux = ""; + if (item->event) + { + const cEvent* event = item->event; + int bstart = event->StartTime() - timer->StartTime(); + int bstop = timer->StopTime() - event->EndTime(); +- string aux = ""; + int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); + aux = UpdateAuxValue(aux, "update", checkmode); + aux = UpdateAuxValue(aux, "eventid", event->EventID()); +@@ -172,6 +172,12 @@ + aux = UpdateAuxValue(aux, "bstop", bstop); + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } ++ ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); ++ + SetAux(timer, fullaux); + Timers.Add(timer); + timer->Matches(); +--- ../plain/epgsearch-0.9.20//menu_myedittimer.c 2007-01-23 20:26:12.000000000 +0100 ++++ menu_myedittimer.c 2007-02-10 09:40:33.000000000 +0100 +@@ -36,6 +36,7 @@ + stop = Timer->Stop(); + priority = Timer->Priority(); + lifetime = Timer->Lifetime(); ++ fskProtection = Timer->FskProtection(); // PIN PATCH + strcpy(file, Timer->File()); + channel = Timer->Channel()->Number(); + if (forcechannel) +@@ -107,6 +108,14 @@ + Add(new cMenuEditBitItem( tr("VPS"), &flags, tfVps)); + Add(new cMenuEditIntItem( tr("Priority"), &priority, 0, MAXPRIORITY)); + Add(new cMenuEditIntItem( tr("Lifetime"), &lifetime, 0, MAXLIFETIME)); ++ // PIN PATCH ++ if (cOsd::pinValid || !fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&fskProtection)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Childlock"), fskProtection ? tr("yes") : tr("no")); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } + Add(new cMenuEditStrItem( tr("File"), file, MaxFileName, tr(FileNameChars))); + Add(new cMenuEditStrItem( tr("Directory"), directory, MaxFileName, tr(AllowedChars))); + +@@ -211,6 +220,33 @@ + return osContinue; + } + ++char* cMenuMyEditTimer::SetFskProtection(int fskProtection, char* aux) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ asprintf(&aux,"%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info to aux ++ ++ asprintf(&tmp, "%.*s%s", p-aux, aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (tmp) ++ free(tmp); ++ ++ return aux; ++} ++ + eOSState cMenuMyEditTimer::ProcessKey(eKeys Key) + { + bool bWasSingleEvent = IsSingleEvent(); +@@ -290,6 +326,7 @@ + } + + string fullaux = ""; ++ string aux = ""; + if (timer && timer->Aux()) + fullaux = timer->Aux(); + +@@ -307,7 +344,6 @@ + bstop = stopTime - event->EndTime(); + + char* epgsearchaux = GetAuxValue(timer, "epgsearch"); +- string aux = ""; + if (epgsearchaux) + { + aux = epgsearchaux; +@@ -320,6 +356,10 @@ + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } + ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); + + char* tmpFile = strdup(file); + tmpFile = strreplace(tmpFile, ':', '|'); +--- ../plain/epgsearch-0.9.20//menu_myedittimer.h 2006-12-08 21:50:22.000000000 +0100 ++++ menu_myedittimer.h 2007-02-03 16:40:11.000000000 +0100 +@@ -13,6 +13,7 @@ + bool addIfConfirmed; + int UserDefDaysOfWeek; + cMenuEditStrItem* m_DirItem; ++ char* SetFskProtection(int fskProtection, char* aux); // PIN PATCH + + uint flags; + time_t day; +@@ -23,6 +24,7 @@ + int lifetime; + char file[MaxFileName]; + char directory[MaxFileName]; ++ int fskProtection; // PIN PATCH + int checkmode; + public: + cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* event, const cChannel* forcechannel=NULL); +--- ../plain/epgsearch-0.9.20//menu_whatson.c 2007-01-27 14:30:52.000000000 +0100 ++++ menu_whatson.c 2007-02-10 09:39:52.000000000 +0100 +@@ -450,12 +450,12 @@ + else + { + string fullaux = ""; ++ string aux = ""; + if (item->event) + { + const cEvent* event = item->event; + int bstart = event->StartTime() - timer->StartTime(); + int bstop = timer->StopTime() - event->EndTime(); +- string aux = ""; + int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); + aux = UpdateAuxValue(aux, "update", checkmode); + aux = UpdateAuxValue(aux, "eventid", event->EventID()); +@@ -463,6 +463,12 @@ + aux = UpdateAuxValue(aux, "bstop", bstop); + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } ++ ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); ++ + SetAux(timer, fullaux); + Timers.Add(timer); + timer->Matches(); diff --git a/patches/epgsearch-0.9.21.diff b/patches/epgsearch-0.9.21.diff new file mode 100644 index 0000000..f5d49e7 --- /dev/null +++ b/patches/epgsearch-0.9.21.diff @@ -0,0 +1,194 @@ +--- ../epgsearch-0.9.21-plain//i18n.c 2007-04-28 11:42:43.000000000 +0200 ++++ i18n.c 2007-05-28 09:33:29.000000000 +0200 +@@ -9,6 +9,28 @@ + #include "i18n.h" + + const tI18nPhrase Phrases[] = { ++ { "Childlock", ++ "Kindersicherung", ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "Adulte", ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ }, + { "search the EPG for repeats and more", + "Suche im EPG nach Wiederholungen und anderem",// Deutsch + "",// TODO Slovenski +--- ../epgsearch-0.9.21-plain//menu_commands.c 2007-03-28 21:17:40.000000000 +0200 ++++ menu_commands.c 2007-05-28 09:33:29.000000000 +0200 +@@ -135,11 +135,11 @@ + else + { + string fullaux = ""; ++ string aux = ""; + if (event) + { + int bstart = event->StartTime() - timer->StartTime(); + int bstop = timer->StopTime() - event->EndTime(); +- string aux = ""; + int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); + aux = UpdateAuxValue(aux, "update", checkmode); + aux = UpdateAuxValue(aux, "eventid", event->EventID()); +@@ -147,6 +147,11 @@ + aux = UpdateAuxValue(aux, "bstop", bstop); + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); ++ + SetAux(timer, fullaux); + Timers.Add(timer); + timer->Matches(); +--- ../epgsearch-0.9.21-plain//menu_main.c 2007-03-20 19:35:50.000000000 +0100 ++++ menu_main.c 2007-05-28 09:33:29.000000000 +0200 +@@ -159,12 +159,12 @@ + else + { + string fullaux = ""; ++ string aux = ""; + if (item->event) + { + const cEvent* event = item->event; + int bstart = event->StartTime() - timer->StartTime(); + int bstop = timer->StopTime() - event->EndTime(); +- string aux = ""; + int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); + aux = UpdateAuxValue(aux, "update", checkmode); + aux = UpdateAuxValue(aux, "eventid", event->EventID()); +@@ -172,6 +172,12 @@ + aux = UpdateAuxValue(aux, "bstop", bstop); + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } ++ ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); ++ + SetAux(timer, fullaux); + Timers.Add(timer); + timer->Matches(); +--- ../epgsearch-0.9.21-plain//menu_myedittimer.c 2007-03-28 20:43:21.000000000 +0200 ++++ menu_myedittimer.c 2007-06-02 22:48:46.000000000 +0200 +@@ -36,6 +36,7 @@ + stop = Timer->Stop(); + priority = Timer->Priority(); + lifetime = Timer->Lifetime(); ++ fskProtection = Timer->FskProtection(); // PIN PATCH + strcpy(file, Timer->File()); + channel = Timer->Channel()->Number(); + if (forcechannel) +@@ -96,7 +97,14 @@ + cSearchExt* search = TriggeredFromSearchTimer(timer); + + Add(new cMenuEditBitItem( tr("Active"), &flags, tfActive)); +- Add(new cMenuEditChanItem(tr("Channel"), &channel)); ++ // PIN PATCH ++ if (cOsd::pinValid) Add(new cMenuEditChanItem(tr("Channel"), &channel)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Channel"), Channels.GetByNumber(channel)->Name()); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } + Add(new cMenuEditDateItem(tr("Day"), &day, &weekdays)); + + if (!IsSingleEvent()) +@@ -107,6 +115,14 @@ + Add(new cMenuEditBitItem( tr("VPS"), &flags, tfVps)); + Add(new cMenuEditIntItem( tr("Priority"), &priority, 0, MAXPRIORITY)); + Add(new cMenuEditIntItem( tr("Lifetime"), &lifetime, 0, MAXLIFETIME)); ++ // PIN PATCH ++ if (cOsd::pinValid || !fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&fskProtection)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Childlock"), fskProtection ? tr("yes") : tr("no")); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } + Add(new cMenuEditStrItem( tr("File"), file, MaxFileName, tr(FileNameChars))); + Add(new cMenuEditStrItem( tr("Directory"), directory, MaxFileName, tr(AllowedChars))); + +@@ -290,6 +306,7 @@ + } + + string fullaux = ""; ++ string aux = ""; + if (timer && timer->Aux()) + fullaux = timer->Aux(); + +@@ -307,7 +324,6 @@ + bstop = stopTime - event->EndTime(); + + char* epgsearchaux = GetAuxValue(timer, "epgsearch"); +- string aux = ""; + if (epgsearchaux) + { + aux = epgsearchaux; +@@ -321,6 +337,10 @@ + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } + ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); + + char* tmpFile = strdup(file); + tmpFile = strreplace(tmpFile, ':', '|'); +--- ../epgsearch-0.9.21-plain//menu_myedittimer.h 2007-02-07 19:55:36.000000000 +0100 ++++ menu_myedittimer.h 2007-05-28 09:33:29.000000000 +0200 +@@ -23,6 +23,7 @@ + int lifetime; + char file[MaxFileName]; + char directory[MaxFileName]; ++ int fskProtection; // PIN PATCH + int checkmode; + public: + cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* event, const cChannel* forcechannel=NULL); +--- ../epgsearch-0.9.21-plain//menu_whatson.c 2007-03-24 13:20:54.000000000 +0100 ++++ menu_whatson.c 2007-05-28 09:34:19.000000000 +0200 +@@ -450,12 +450,12 @@ + else + { + string fullaux = ""; ++ string aux = ""; + if (item->event) + { + const cEvent* event = item->event; + int bstart = event->StartTime() - timer->StartTime(); + int bstop = timer->StopTime() - event->EndTime(); +- string aux = ""; + int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); + aux = UpdateAuxValue(aux, "update", checkmode); + aux = UpdateAuxValue(aux, "eventid", event->EventID()); +@@ -463,6 +463,12 @@ + aux = UpdateAuxValue(aux, "bstop", bstop); + fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); + } ++ ++ // #PIN PATCH ++ aux = ""; ++ aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); ++ fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); ++ + SetAux(timer, fullaux); + Timers.Add(timer); + timer->Matches(); diff --git a/patches/vdr-1.4.5.diff b/patches/vdr-1.4.5.diff new file mode 100644 index 0000000..59972e1 --- /dev/null +++ b/patches/vdr-1.4.5.diff @@ -0,0 +1,454 @@ +--- ../vdr-1.4.5//device.c 2006-09-03 12:13:25.000000000 +0200 ++++ device.c 2007-01-28 19:24:06.000000000 +0100 +@@ -581,8 +581,10 @@ + int n = CurrentChannel() + Direction; + int first = n; + cChannel *channel; +- while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { ++ while ((channel = Channels.GetByNumber(n, Direction)) != NULL) ++ { + // try only channels which are currently available ++ if (cStatus::MsgChannelProtected(0, channel) == false) // PIN PATCH + if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0)) + break; + n = channel->Number() + Direction; +@@ -604,6 +606,11 @@ + + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) + { ++ // I hope 'LiveView = false' indicates a channel switch for recording, // PIN PATCH ++ // I really don't know, but it works ... // PIN PATCH ++ if (LiveView && cStatus::MsgChannelProtected(this, Channel) == true) // PIN PATCH ++ return scrNotAvailable; // PIN PATCH ++ + if (LiveView) + StopReplay(); + +--- ../vdr-1.4.5//i18n.c 2006-10-14 11:26:41.000000000 +0200 ++++ i18n.c 2007-01-28 19:24:06.000000000 +0100 +@@ -6126,6 +6126,27 @@ + "Ingen titel", + "Bez názvu", + }, ++ { "Childlock", // PIN PATCH ++ "Kindersicherung", ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "Adulte", ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ "",//TODO ++ }, + { NULL } + }; + +--- ../vdr-1.4.5//menu.c 2006-12-02 12:12:02.000000000 +0100 ++++ menu.c 2007-02-03 12:16:23.000000000 +0100 +@@ -664,6 +664,16 @@ + 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)); ++ ++ // PIN PATCH ++ if (cOsd::pinValid || !data.fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&data.fskProtection)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Childlock"), data.fskProtection ? tr("yes") : tr("no")); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } ++ + Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file), tr(FileNameChars))); + SetFirstDayItem(); + } +@@ -1913,7 +1923,9 @@ + 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)) ++ && (!cStatus::MsgReplayProtected(GetRecording(Item), Item->Name(), base, ++ Item->IsDirectory(), true))) { // PIN PATCH + Add(Item); + LastItem = Item; + free(LastItemText); +@@ -1963,6 +1975,9 @@ + { + cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); + if (ri) { ++ if (cStatus::MsgReplayProtected(GetRecording(ri), ri->Name(), base, ++ ri->IsDirectory()) == true) // PIN PATCH ++ return osContinue; // PIN PATCH + if (ri->IsDirectory()) + Open(); + else { +@@ -2818,28 +2833,32 @@ + + // Basic menu items: + +- Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); +- Add(new cOsdItem(hk(tr("Channels")), osChannels)); +- Add(new cOsdItem(hk(tr("Timers")), osTimers)); +- Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); ++ // PIN PATCH ++ if (!cStatus::MsgMenuItemProtected("Schedule", true)) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); ++ if (!cStatus::MsgMenuItemProtected("Channels", true)) Add(new cOsdItem(hk(tr("Channels")), osChannels)); ++ if (!cStatus::MsgMenuItemProtected("Timers", true)) Add(new cOsdItem(hk(tr("Timers")), osTimers)); ++ if (!cStatus::MsgMenuItemProtected("Recordings", true)) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); + + // Plugins: + + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { ++ if (!cStatus::MsgPluginProtected(p, true)) { // PIN PATCH + const char *item = p->MainMenuEntry(); + if (item) + Add(new cMenuPluginItem(hk(item), i)); + } ++ } + else + break; + } + + // More basic menu items: + +- Add(new cOsdItem(hk(tr("Setup")), osSetup)); ++ if (!cStatus::MsgMenuItemProtected("Setup", true)) Add(new cOsdItem(hk(tr("Setup")), osSetup)); // PIN PATCH + if (Commands.Count()) ++ if (!cStatus::MsgMenuItemProtected("Commands", true)) // PIN PATCH + Add(new cOsdItem(hk(tr("Commands")), osCommands)); + + Update(true); +@@ -2927,6 +2946,14 @@ + eOSState state = cOsdMenu::ProcessKey(Key); + HadSubMenu |= HasSubMenu(); + ++ // > PIN PATCH ++ cOsdItem* item = Get(Current()); ++ ++ if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) ++ if (cStatus::MsgMenuItemProtected(item->Text())) ++ return osContinue; ++ // PIN PATCH < ++ + switch (state) { + case osSchedule: return AddSubMenu(new cMenuSchedule); + case osChannels: return AddSubMenu(new cMenuChannels); +@@ -2952,6 +2979,7 @@ + if (item) { + cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); + if (p) { ++ if (!cStatus::MsgPluginProtected(p)) { // PIN PATCH + cOsdObject *menu = p->MainMenuAction(); + if (menu) { + if (menu->IsMenu()) +@@ -2963,6 +2991,7 @@ + } + } + } ++ } + state = osEnd; + } + break; +@@ -3126,6 +3155,7 @@ + if (Direction) { + while (Channel) { + Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel); ++ if (cStatus::MsgChannelProtected(0, Channel) == false) // PIN PATCH + if (Channel && !Channel->GroupSep() && (cDevice::PrimaryDevice()->ProvidesChannel(Channel, Setup.PrimaryLimit) || cDevice::GetDevice(Channel, 0))) + return Channel; + } +@@ -3663,6 +3693,7 @@ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (!RecordControls[i]) { + RecordControls[i] = new cRecordControl(device, Timer, Pause); ++ cStatus::MsgRecordingFile(RecordControls[i]->FileName()); // PIN PATCH + return RecordControls[i]->Process(time(NULL)); + } + } +--- ../vdr-1.4.5//osd.c 2006-02-26 15:31:31.000000000 +0100 ++++ osd.c 2007-01-28 19:24:06.000000000 +0100 +@@ -594,6 +594,7 @@ + // --- cOsd ------------------------------------------------------------------ + + int cOsd::isOpen = 0; ++bool cOsd::pinValid = false; // PIN PATCH + + cOsd::cOsd(int Left, int Top) + { +--- ../vdr-1.4.5//osd.h 2006-02-26 15:45:05.000000000 +0100 ++++ osd.h 2007-01-28 19:24:06.000000000 +0100 +@@ -324,6 +324,7 @@ + ///< 7: vertical, falling, upper + virtual void Flush(void); + ///< Actually commits all data to the OSD hardware. ++ static bool pinValid; // PIN PATCH + }; + + class cOsdProvider { +--- ../vdr-1.4.5//status.c 2005-12-31 16:10:10.000000000 +0100 ++++ status.c 2007-02-03 12:04:26.000000000 +0100 +@@ -112,3 +112,55 @@ + for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) + sm->OsdProgramme(PresentTime, PresentTitle, PresentSubtitle, FollowingTime, FollowingTitle, FollowingSubtitle); + } ++ ++bool cStatus::MsgChannelProtected(const cDevice* Device, const cChannel* Channel) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ChannelProtected(Device, Channel) == true) ++ return true; ++ ++ return false; ++} ++ ++bool cStatus::MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ReplayProtected(Recording, Name, Base, isDirectory, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgRecordingFile(const char* FileName) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->RecordingFile(FileName); ++} ++ ++void cStatus::MsgTimerCreation(cTimer* Timer, const cEvent *Event) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->TimerCreation(Timer, Event); ++} ++ ++bool cStatus::MsgPluginProtected(cPlugin* Plugin, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->PluginProtected(Plugin, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgUserAction(const eKeys key, const cOsdObject* Interact) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ sm->UserAction(key, Interact); ++} ++ ++bool cStatus::MsgMenuItemProtected(const char* Name, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->MenuItemProtected(Name, menuView) == true) ++ return true; ++ return false; ++} +--- ../vdr-1.4.5//status.h 2005-12-31 16:15:25.000000000 +0100 ++++ status.h 2007-02-03 12:03:19.000000000 +0100 +@@ -14,6 +14,7 @@ + #include "device.h" + #include "player.h" + #include "tools.h" ++#include "plugin.h" + + class cStatus : public cListObject { + private: +@@ -67,6 +68,24 @@ + // The OSD displays the single line Text with the current channel information. + virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle) {} + // The OSD displays the given programme information. ++ virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel) { return false; } // PIN PATCH ++ // Checks if a channel is protected. ++ virtual bool ReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a recording is protected. ++ virtual void RecordingFile(const char* FileName) {} // PIN PATCH ++ // The given DVB device has started recording to FileName. FileName is the name of the ++ // recording directory ++ virtual void TimerCreation(cTimer* Timer, const cEvent *Event) {} // PIN PATCH ++ // The given timer is created ++ virtual bool PluginProtected(cPlugin* Plugin, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a plugin is protected. ++ virtual void UserAction(const eKeys key, const cOsdObject* Interact) {} // PIN PATCH ++ // report user action ++ virtual bool MenuItemProtected(const char* Name, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a menu entry is protected. ++ ++ + public: + cStatus(void); + virtual ~cStatus(); +@@ -86,6 +105,15 @@ + static void MsgOsdTextItem(const char *Text, bool Scroll = false); + static void MsgOsdChannel(const char *Text); + static void MsgOsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); ++ static bool MsgChannelProtected(const cDevice* Device, const cChannel* Channel); // PIN PATCH ++ static bool MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false); // PIN PATCH ++ static void MsgRecordingFile(const char* FileName); // PIN PATCH ++ static void MsgTimerCreation(cTimer* Timer, const cEvent *Event); // PIN PATCH ++ static bool MsgPluginProtected(cPlugin* Plugin, int menuView = false); // PIN PATCH ++ static void MsgUserAction(const eKeys key, const cOsdObject* Interact); ++ static bool MsgMenuItemProtected(const char* Name, int menuView = false); // PIN PATCH ++ + }; + + #endif //__STATUS_H +--- ../vdr-1.4.5//timers.c 2006-09-15 16:15:53.000000000 +0200 ++++ timers.c 2007-01-28 19:24:06.000000000 +0100 +@@ -14,6 +14,7 @@ + #include "i18n.h" + #include "libsi/si.h" + #include "remote.h" ++#include "status.h" // PIN PATCH + + // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d' + // format characters in order to allow any number of blanks after a numeric +@@ -42,6 +43,7 @@ + stop -= 2400; + priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; + lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + *file = 0; + aux = NULL; + event = NULL; +@@ -75,12 +77,14 @@ + stop -= 2400; + priority = Setup.DefaultPriority; + lifetime = Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + *file = 0; + const char *Title = Event->Title(); + if (!isempty(Title)) + strn0cpy(file, Event->Title(), sizeof(file)); + aux = NULL; + event = NULL; // let SetEvent() be called to get a log message ++ cStatus::MsgTimerCreation(this, Event); // PIN PATCH + } + + cTimer::cTimer(const cTimer &Timer) +@@ -113,6 +117,7 @@ + stop = Timer.stop; + priority = Timer.priority; + lifetime = Timer.lifetime; ++ fskProtection = Timer.fskProtection; // PIN PATCH + strncpy(file, Timer.file, sizeof(file)); + free(aux); + aux = Timer.aux ? strdup(Timer.aux) : NULL; +@@ -288,6 +293,7 @@ + result = false; + } + } ++ fskProtection = aux && strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"); // PIN PATCH + free(channelbuffer); + free(daybuffer); + free(filebuffer); +@@ -597,6 +603,33 @@ + Matches(); // refresh start and end time + } + ++void cTimer::SetFskProtection(int aFlag) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ ++ fskProtection = aFlag; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ asprintf(&aux,"%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info to aux ++ ++ asprintf(&tmp, "%.*s%s", p-aux, aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (tmp) ++ free(tmp); ++} ++ + // -- cTimers ---------------------------------------------------------------- + + cTimers Timers; +--- ../vdr-1.4.5//timers.h 2006-09-04 19:07:39.000000000 +0200 ++++ timers.h 2007-01-28 19:24:06.000000000 +0100 +@@ -37,6 +37,7 @@ + int start; + int stop; + int priority; ++ int fskProtection; // PIN PATCH + int lifetime; + char file[MaxFileName]; + char *aux; +@@ -58,6 +59,7 @@ + int Start(void) const { return start; } + int Stop(void) const { return stop; } + int Priority(void) const { return priority; } ++ int FskProtection(void) const { return fskProtection; } // PIN PATCH + int Lifetime(void) const { return lifetime; } + const char *File(void) const { return file; } + time_t FirstDay(void) const { return weekdays ? day : 0; } +@@ -86,6 +88,7 @@ + void SetInVpsMargin(bool InVpsMargin); + void SetPriority(int Priority); + void SetFlags(uint Flags); ++ void SetFskProtection(int aFlag); // PIN PATCH + void ClrFlags(uint Flags); + void InvFlags(uint Flags); + bool HasFlags(uint Flags) const; +--- ../vdr-1.4.5//vdr.c 2006-12-02 17:22:12.000000000 +0100 ++++ vdr.c 2007-01-28 19:32:00.000000000 +0100 +@@ -865,6 +865,7 @@ + cOsdObject *Interact = Menu ? Menu : cControl::Control(); + eKeys key = Interface->GetKey((!Interact || !Interact->NeedsFastResponse()) && time(NULL) - LastCamMenu > LASTCAMMENUTIMEOUT); + if (NORMALKEY(key) != kNone) { ++ cStatus::MsgUserAction(key, Interact); // PIN PATCH + EITScanner.Activity(); + LastActivity = time(NULL); + } +@@ -930,10 +931,12 @@ + cControl::Control()->Hide(); + cPlugin *plugin = cPluginManager::GetPlugin(PluginName); + if (plugin) { ++ if (!cStatus::MsgPluginProtected(plugin)) { + Menu = plugin->MainMenuAction(); + if (Menu) + Menu->Show(); + } ++ } + else + esyslog("ERROR: unknown plugin '%s'", PluginName); + } +@@ -1137,9 +1140,11 @@ + // Instant resume of the last viewed recording: + case kPlay: + if (cReplayControl::LastReplayed()) { ++ if (cStatus::MsgReplayProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { // PIN PATCH + cControl::Shutdown(); + cControl::Launch(new cReplayControl); + } ++ } + break; + default: break; + } diff --git a/patches/vdr-1.7.17.diff b/patches/vdr-1.7.17.diff new file mode 100644 index 0000000..5909652 --- /dev/null +++ b/patches/vdr-1.7.17.diff @@ -0,0 +1,416 @@ +--- ../vdr-1.7.17.plain//device.c 2011-02-25 16:12:03.000000000 +0100 ++++ device.c 2011-03-31 11:47:58.122037275 +0200 +@@ -665,6 +665,7 @@ + cChannel *channel; + while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { + // try only channels which are currently available ++ if (!cStatus::MsgChannelProtected(0, channel)) // PIN PATCH + if (GetDevice(channel, 0, true)) + break; + n = channel->Number() + Direction; +@@ -686,6 +687,12 @@ + + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) + { ++ // I hope 'LiveView = false' indicates a channel switch for recording, // PIN PATCH ++ // I really don't know, but it works ... // PIN PATCH ++ ++ if (LiveView && cStatus::MsgChannelProtected(this, Channel)) // PIN PATCH ++ return scrNotAvailable; // PIN PATCH ++ + if (LiveView) { + StopReplay(); + DELETENULL(liveSubtitle); +--- ../vdr-1.7.17.plain//menu.c 2011-02-27 13:37:48.000000000 +0100 ++++ menu.c 2011-03-31 12:17:34.903691287 +0200 +@@ -918,6 +918,16 @@ + 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)); ++ ++ // PIN PATCH ++ if (cOsd::pinValid || !data.fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&data.fskProtection)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Childlock"), data.fskProtection ? tr("yes") : tr("no")); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } ++ + Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file))); + SetFirstDayItem(); + } +@@ -2276,7 +2286,10 @@ + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { + if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == FOLDERDELIMCHAR)) { + cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level); +- if (*Item->Text() && (!Item->IsDirectory() || (!LastItem || !LastItem->IsDirectory() || strcmp(Item->Text(), LastItemText) != 0))) { ++ ++ if (*Item->Text() && (!Item->IsDirectory() || (!LastItem || !LastItem->IsDirectory() || strcmp(Item->Text(), LastItemText) != 0)) ++ && (!cStatus::MsgReplayProtected(GetRecording(Item), Item->Name(), base, ++ Item->IsDirectory(), true))) { // PIN PATCH + Add(Item); + LastItem = Item; + free(LastItemText); +@@ -2326,6 +2339,9 @@ + { + cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); + if (ri) { ++ if (cStatus::MsgReplayProtected(GetRecording(ri), ri->Name(), base, ++ ri->IsDirectory()) == true) // PIN PATCH ++ return osContinue; // PIN PATCH + if (ri->IsDirectory()) + Open(); + else { +@@ -3305,28 +3321,32 @@ + + // Basic menu items: + +- Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); +- Add(new cOsdItem(hk(tr("Channels")), osChannels)); +- Add(new cOsdItem(hk(tr("Timers")), osTimers)); +- Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); ++ // PIN PATCH ++ if (!cStatus::MsgMenuItemProtected("Schedule", true)) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); ++ if (!cStatus::MsgMenuItemProtected("Channels", true)) Add(new cOsdItem(hk(tr("Channels")), osChannels)); ++ if (!cStatus::MsgMenuItemProtected("Timers", true)) Add(new cOsdItem(hk(tr("Timers")), osTimers)); ++ if (!cStatus::MsgMenuItemProtected("Recordings", true)) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); + + // Plugins: + + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { ++ if (!cStatus::MsgPluginProtected(p, true)) { // PIN PATCH + const char *item = p->MainMenuEntry(); + if (item) + Add(new cMenuPluginItem(hk(item), i)); + } ++ } + else + break; + } + + // More basic menu items: + +- Add(new cOsdItem(hk(tr("Setup")), osSetup)); ++ if (!cStatus::MsgMenuItemProtected("Setup", true)) Add(new cOsdItem(hk(tr("Setup")), osSetup)); // PIN PATCH + if (Commands.Count()) ++ if (!cStatus::MsgMenuItemProtected("Commands", true)) // PIN PATCH + Add(new cOsdItem(hk(tr("Commands")), osCommands)); + + Update(true); +@@ -3402,6 +3422,14 @@ + eOSState state = cOsdMenu::ProcessKey(Key); + HadSubMenu |= HasSubMenu(); + ++ // > PIN PATCH ++ cOsdItem* item = Get(Current()); ++ ++ if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) ++ if (cStatus::MsgMenuItemProtected(item->Text())) ++ return osContinue; ++ // PIN PATCH < ++ + switch (state) { + case osSchedule: return AddSubMenu(new cMenuSchedule); + case osChannels: return AddSubMenu(new cMenuChannels); +@@ -3427,6 +3455,7 @@ + if (item) { + cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); + if (p) { ++ if (!cStatus::MsgPluginProtected(p)) { // PIN PATCH + cOsdObject *menu = p->MainMenuAction(); + if (menu) { + if (menu->IsMenu()) +@@ -3438,6 +3467,7 @@ + } + } + } ++ } + state = osEnd; + } + break; +@@ -3608,6 +3638,8 @@ + Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel); + if (!Channel && Setup.ChannelsWrap) + Channel = Direction > 0 ? Channels.First() : Channels.Last(); ++ ++ if (!cStatus::MsgChannelProtected(0, Channel)) // PIN PATCH + if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, 0, true)) + return Channel; + } +@@ -4241,6 +4273,7 @@ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (!RecordControls[i]) { + RecordControls[i] = new cRecordControl(device, Timer, Pause); ++ cStatus::MsgRecordingFile(RecordControls[i]->FileName()); // PIN PATCH + return RecordControls[i]->Process(time(NULL)); + } + } +--- ../vdr-1.7.17.plain//osd.c 2011-03-12 16:32:33.000000000 +0100 ++++ osd.c 2011-03-31 11:57:37.102037290 +0200 +@@ -1576,6 +1576,7 @@ + int cOsd::osdWidth = 0; + int cOsd::osdHeight = 0; + cVector<cOsd *> cOsd::Osds; ++bool cOsd::pinValid = false; // PIN PATCH + + cOsd::cOsd(int Left, int Top, uint Level) + { +--- ../vdr-1.7.17.plain//osd.h 2011-03-12 17:06:48.000000000 +0100 ++++ osd.h 2011-03-31 11:58:26.802037290 +0200 +@@ -917,6 +917,7 @@ + ///< MyOsdDrawPixmap(Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y(), pm->Data(), w, h, h * d); + ///< delete pm; + ///< } ++ static bool pinValid; // PIN PATCH + }; + + #define MAXOSDIMAGES 64 +--- ../vdr-1.7.17.plain//status.c 2008-02-16 15:46:31.000000000 +0100 ++++ status.c 2011-03-31 11:40:45.532037296 +0200 +@@ -124,3 +124,55 @@ + for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) + sm->OsdProgramme(PresentTime, PresentTitle, PresentSubtitle, FollowingTime, FollowingTitle, FollowingSubtitle); + } ++ ++bool cStatus::MsgChannelProtected(const cDevice* Device, const cChannel* Channel) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ChannelProtected(Device, Channel) == true) ++ return true; ++ ++ return false; ++} ++ ++bool cStatus::MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ReplayProtected(Recording, Name, Base, isDirectory, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgRecordingFile(const char* FileName) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->RecordingFile(FileName); ++} ++ ++void cStatus::MsgTimerCreation(cTimer* Timer, const cEvent *Event) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->TimerCreation(Timer, Event); ++} ++ ++bool cStatus::MsgPluginProtected(cPlugin* Plugin, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->PluginProtected(Plugin, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgUserAction(const eKeys key, const cOsdObject* Interact) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ sm->UserAction(key, Interact); ++} ++ ++bool cStatus::MsgMenuItemProtected(const char* Name, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->MenuItemProtected(Name, menuView) == true) ++ return true; ++ return false; ++} +--- ../vdr-1.7.17.plain//status.h 2008-02-16 16:00:33.000000000 +0100 ++++ status.h 2011-03-31 11:40:45.532037296 +0200 +@@ -14,6 +14,7 @@ + #include "device.h" + #include "player.h" + #include "tools.h" ++#include "plugin.h" + + enum eTimerChange { tcMod, tcAdd, tcDel }; + +@@ -80,6 +81,24 @@ + // The OSD displays the single line Text with the current channel information. + virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle) {} + // The OSD displays the given programme information. ++ virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel) { return false; } // PIN PATCH ++ // Checks if a channel is protected. ++ virtual bool ReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a recording is protected. ++ virtual void RecordingFile(const char* FileName) {} // PIN PATCH ++ // The given DVB device has started recording to FileName. FileName is the name of the ++ // recording directory ++ virtual void TimerCreation(cTimer* Timer, const cEvent *Event) {} // PIN PATCH ++ // The given timer is created ++ virtual bool PluginProtected(cPlugin* Plugin, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a plugin is protected. ++ virtual void UserAction(const eKeys key, const cOsdObject* Interact) {} // PIN PATCH ++ // report user action ++ virtual bool MenuItemProtected(const char* Name, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a menu entry is protected. ++ ++ + public: + cStatus(void); + virtual ~cStatus(); +@@ -101,6 +120,15 @@ + static void MsgOsdTextItem(const char *Text, bool Scroll = false); + static void MsgOsdChannel(const char *Text); + static void MsgOsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); ++ static bool MsgChannelProtected(const cDevice* Device, const cChannel* Channel); // PIN PATCH ++ static bool MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false); // PIN PATCH ++ static void MsgRecordingFile(const char* FileName); // PIN PATCH ++ static void MsgTimerCreation(cTimer* Timer, const cEvent *Event); // PIN PATCH ++ static bool MsgPluginProtected(cPlugin* Plugin, int menuView = false); // PIN PATCH ++ static void MsgUserAction(const eKeys key, const cOsdObject* Interact); ++ static bool MsgMenuItemProtected(const char* Name, int menuView = false); // PIN PATCH ++ + }; + + #endif //__STATUS_H +--- ../vdr-1.7.17.plain//timers.c 2010-01-16 12:18:53.000000000 +0100 ++++ timers.c 2011-03-31 12:07:34.363691286 +0200 +@@ -46,6 +46,7 @@ + stop -= 2400; + priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; + lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + *file = 0; + aux = NULL; + event = NULL; +@@ -84,6 +85,7 @@ + stop -= 2400; + priority = Setup.DefaultPriority; + lifetime = Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + *file = 0; + const char *Title = Event->Title(); + if (!isempty(Title)) +@@ -95,6 +97,7 @@ + } + aux = NULL; + event = NULL; // let SetEvent() be called to get a log message ++ cStatus::MsgTimerCreation(this, Event); + } + + cTimer::cTimer(const cTimer &Timer) +@@ -129,6 +132,7 @@ + stop = Timer.stop; + priority = Timer.priority; + lifetime = Timer.lifetime; ++ fskProtection = Timer.fskProtection; // PIN PATCH + strncpy(file, Timer.file, sizeof(file)); + free(aux); + aux = Timer.aux ? strdup(Timer.aux) : NULL; +@@ -323,6 +327,7 @@ + result = false; + } + } ++ fskProtection = aux && strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"); // PIN PATCH + free(channelbuffer); + free(daybuffer); + free(filebuffer); +@@ -632,6 +637,33 @@ + Matches(); // refresh start and end time + } + ++void cTimer::SetFskProtection(int aFlag) ++{ ++ char* p; ++ char* tmp = 0; ++ ++ fskProtection = aFlag; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ asprintf(&aux,"%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info to aux ++ ++ asprintf(&tmp, "%.*s%s", p-aux, aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (tmp) ++ free(tmp); ++} ++ + // --- cTimers --------------------------------------------------------------- + + cTimers Timers; +--- ../vdr-1.7.17.plain//timers.h 2008-02-16 15:33:23.000000000 +0100 ++++ timers.h 2011-03-31 11:40:45.532037296 +0200 +@@ -37,6 +37,7 @@ + int start; + int stop; + int priority; ++ int fskProtection; // PIN PATCH + int lifetime; + mutable char file[MaxFileName]; + char *aux; +@@ -58,6 +59,7 @@ + int Start(void) const { return start; } + int Stop(void) const { return stop; } + int Priority(void) const { return priority; } ++ int FskProtection(void) const { return fskProtection; } // PIN PATCH + int Lifetime(void) const { return lifetime; } + const char *File(void) const { return file; } + time_t FirstDay(void) const { return weekdays ? day : 0; } +@@ -86,6 +88,7 @@ + void SetInVpsMargin(bool InVpsMargin); + void SetPriority(int Priority); + void SetFlags(uint Flags); ++ void SetFskProtection(int aFlag); // PIN PATCH + void ClrFlags(uint Flags); + void InvFlags(uint Flags); + bool HasFlags(uint Flags) const; +--- ../vdr-1.7.17.plain//vdr.c 2010-12-12 14:42:00.000000000 +0100 ++++ vdr.c 2011-03-31 12:09:31.913691288 +0200 +@@ -929,6 +929,7 @@ + cOsdObject *Interact = Menu ? Menu : cControl::Control(); + eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse()); + if (ISREALKEY(key)) { ++ cStatus::MsgUserAction(key, Interact); // PIN PATCH + EITScanner.Activity(); + // Cancel shutdown countdown: + if (ShutdownHandler.countdown) +@@ -1001,10 +1002,12 @@ + cControl::Control()->Hide(); + cPlugin *plugin = cPluginManager::GetPlugin(PluginName); + if (plugin) { ++ if (!cStatus::MsgPluginProtected(plugin)) { + Menu = plugin->MainMenuAction(); + if (Menu) + Menu->Show(); + } ++ } + else + esyslog("ERROR: unknown plugin '%s'", PluginName); + } +@@ -1218,9 +1221,11 @@ + // Instant resume of the last viewed recording: + case kPlay: + if (cReplayControl::LastReplayed()) { ++ if (cStatus::MsgReplayProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { // PIN PATCH + cControl::Shutdown(); + cControl::Launch(new cReplayControl); + } ++ } + break; + default: break; + } diff --git a/patches/vdr-1.7.32.diff b/patches/vdr-1.7.32.diff new file mode 100644 index 0000000..35d4219 --- /dev/null +++ b/patches/vdr-1.7.32.diff @@ -0,0 +1,426 @@ +--- ../vdr-1.7.32.plain//device.c 2012-11-13 10:11:43.000000000 +0100 ++++ device.c 2012-12-07 11:15:14.952979954 +0100 +@@ -721,6 +721,7 @@ + cChannel *channel; + while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { + // try only channels which are currently available ++ if (!cStatus::MsgChannelProtected(0, channel)) // PIN PATCH + if (GetDevice(channel, LIVEPRIORITY, true, true)) + break; + n = channel->Number() + Direction; +@@ -742,6 +743,12 @@ + + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) + { ++ // I hope 'LiveView = false' indicates a channel switch for recording, // PIN PATCH ++ // I really don't know, but it works ... // PIN PATCH ++ ++ if (LiveView && cStatus::MsgChannelProtected(this, Channel)) // PIN PATCH ++ return scrNotAvailable; // PIN PATCH ++ + cStatus::MsgChannelSwitch(this, 0, LiveView); + + if (LiveView) { +--- ../vdr-1.7.32.plain//menu.c 2012-11-18 14:07:53.000000000 +0100 ++++ menu.c 2012-12-07 10:42:08.664909711 +0100 +@@ -889,6 +889,16 @@ + 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)); ++ ++ // PIN PATCH ++ if (cOsd::pinValid || !data.fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&data.fskProtection)); ++ else { ++ char* buf = 0; ++ asprintf(&buf, "%s\t%s", tr("Childlock"), data.fskProtection ? tr("yes") : tr("no")); ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } ++ + Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file))); + SetFirstDayItem(); + } +@@ -2261,7 +2271,10 @@ + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { + if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == FOLDERDELIMCHAR)) { + cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level); +- if (*Item->Text() && (!Item->IsDirectory() || (!LastItem || !LastItem->IsDirectory() || strcmp(Item->Text(), LastItemText) != 0))) { ++ ++ if (*Item->Text() && (!Item->IsDirectory() || (!LastItem || !LastItem->IsDirectory() || strcmp(Item->Text(), LastItemText) != 0)) ++ && (!cStatus::MsgReplayProtected(GetRecording(Item), Item->Name(), base, ++ Item->IsDirectory(), true))) { // PIN PATCH + Add(Item); + LastItem = Item; + free(LastItemText); +@@ -2321,6 +2334,9 @@ + { + cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); + if (ri) { ++ if (cStatus::MsgReplayProtected(GetRecording(ri), ri->Name(), base, ++ ri->IsDirectory()) == true) // PIN PATCH ++ return osContinue; // PIN PATCH + if (ri->IsDirectory()) + Open(); + else { +@@ -3373,28 +3389,32 @@ + + // Basic menu items: + +- Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); +- Add(new cOsdItem(hk(tr("Channels")), osChannels)); +- Add(new cOsdItem(hk(tr("Timers")), osTimers)); +- Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); ++ // PIN PATCH ++ if (!cStatus::MsgMenuItemProtected("Schedule", true)) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); ++ if (!cStatus::MsgMenuItemProtected("Channels", true)) Add(new cOsdItem(hk(tr("Channels")), osChannels)); ++ if (!cStatus::MsgMenuItemProtected("Timers", true)) Add(new cOsdItem(hk(tr("Timers")), osTimers)); ++ if (!cStatus::MsgMenuItemProtected("Recordings", true)) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); + + // Plugins: + + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { ++ if (!cStatus::MsgPluginProtected(p, true)) { // PIN PATCH + const char *item = p->MainMenuEntry(); + if (item) + Add(new cMenuPluginItem(hk(item), i)); + } ++ } + else + break; + } + + // More basic menu items: + +- Add(new cOsdItem(hk(tr("Setup")), osSetup)); ++ if (!cStatus::MsgMenuItemProtected("Setup", true)) Add(new cOsdItem(hk(tr("Setup")), osSetup)); // PIN PATCH + if (Commands.Count()) ++ if (!cStatus::MsgMenuItemProtected("Commands", true)) // PIN PATCH + Add(new cOsdItem(hk(tr("Commands")), osCommands)); + + Update(true); +@@ -3463,6 +3483,14 @@ + eOSState state = cOsdMenu::ProcessKey(Key); + HadSubMenu |= HasSubMenu(); + ++ // > PIN PATCH ++ cOsdItem* item = Get(Current()); ++ ++ if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) ++ if (cStatus::MsgMenuItemProtected(item->Text())) ++ return osContinue; ++ // PIN PATCH < ++ + switch (state) { + case osSchedule: return AddSubMenu(new cMenuSchedule); + case osChannels: return AddSubMenu(new cMenuChannels); +@@ -3488,6 +3516,7 @@ + if (item) { + cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); + if (p) { ++ if (!cStatus::MsgPluginProtected(p)) { // PIN PATCH + cOsdObject *menu = p->MainMenuAction(); + if (menu) { + if (menu->IsMenu()) +@@ -3499,6 +3528,7 @@ + } + } + } ++ } + state = osEnd; + } + break; +@@ -3669,6 +3699,7 @@ + Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel); + if (!Channel && Setup.ChannelsWrap) + Channel = Direction > 0 ? Channels.First() : Channels.Last(); ++ if (!cStatus::MsgChannelProtected(0, Channel)) // PIN PATCH + if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, LIVEPRIORITY, true, true)) + return Channel; + } +@@ -4318,6 +4349,7 @@ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (!RecordControls[i]) { + RecordControls[i] = new cRecordControl(device, Timer, Pause); ++ cStatus::MsgRecordingFile(RecordControls[i]->FileName()); // PIN PATCH + return RecordControls[i]->Process(time(NULL)); + } + } +--- ../vdr-1.7.32.plain//osd.c 2012-06-09 16:37:24.000000000 +0200 ++++ osd.c 2012-12-07 10:44:54.184915564 +0100 +@@ -1623,6 +1623,7 @@ + int cOsd::osdHeight = 0; + cVector<cOsd *> cOsd::Osds; + cMutex cOsd::mutex; ++bool cOsd::pinValid = false; // PIN PATCH + + cOsd::cOsd(int Left, int Top, uint Level) + { +--- ../vdr-1.7.32.plain//osd.h 2012-06-02 12:32:38.000000000 +0200 ++++ osd.h 2012-12-07 10:38:33.248902093 +0100 +@@ -931,6 +931,7 @@ + ///< MyOsdDrawPixmap(Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y(), pm->Data(), w, h, h * d); + ///< delete pm; + ///< } ++ static bool pinValid; // PIN PATCH + }; + + #define MAXOSDIMAGES 64 +--- ../vdr-1.7.32.plain//status.c 2012-03-07 15:17:24.000000000 +0100 ++++ status.c 2012-12-07 10:38:33.248902093 +0100 +@@ -124,3 +124,55 @@ + for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) + sm->OsdProgramme(PresentTime, PresentTitle, PresentSubtitle, FollowingTime, FollowingTitle, FollowingSubtitle); + } ++ ++bool cStatus::MsgChannelProtected(const cDevice* Device, const cChannel* Channel) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ChannelProtected(Device, Channel) == true) ++ return true; ++ ++ return false; ++} ++ ++bool cStatus::MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ReplayProtected(Recording, Name, Base, isDirectory, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgRecordingFile(const char* FileName) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->RecordingFile(FileName); ++} ++ ++void cStatus::MsgTimerCreation(cTimer* Timer, const cEvent *Event) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->TimerCreation(Timer, Event); ++} ++ ++bool cStatus::MsgPluginProtected(cPlugin* Plugin, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->PluginProtected(Plugin, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgUserAction(const eKeys key, const cOsdObject* Interact) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ sm->UserAction(key, Interact); ++} ++ ++bool cStatus::MsgMenuItemProtected(const char* Name, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->MenuItemProtected(Name, menuView) == true) ++ return true; ++ return false; ++} +--- ../vdr-1.7.32.plain//status.h 2012-03-07 15:16:57.000000000 +0100 ++++ status.h 2012-12-07 10:38:33.248902093 +0100 +@@ -14,6 +14,7 @@ + #include "device.h" + #include "player.h" + #include "tools.h" ++#include "plugin.h" + + enum eTimerChange { tcMod, tcAdd, tcDel }; + +@@ -81,6 +82,24 @@ + // The OSD displays the single line Text with the current channel information. + virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle) {} + // The OSD displays the given programme information. ++ virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel) { return false; } // PIN PATCH ++ // Checks if a channel is protected. ++ virtual bool ReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a recording is protected. ++ virtual void RecordingFile(const char* FileName) {} // PIN PATCH ++ // The given DVB device has started recording to FileName. FileName is the name of the ++ // recording directory ++ virtual void TimerCreation(cTimer* Timer, const cEvent *Event) {} // PIN PATCH ++ // The given timer is created ++ virtual bool PluginProtected(cPlugin* Plugin, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a plugin is protected. ++ virtual void UserAction(const eKeys key, const cOsdObject* Interact) {} // PIN PATCH ++ // report user action ++ virtual bool MenuItemProtected(const char* Name, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a menu entry is protected. ++ ++ + public: + cStatus(void); + virtual ~cStatus(); +@@ -102,6 +121,15 @@ + static void MsgOsdTextItem(const char *Text, bool Scroll = false); + static void MsgOsdChannel(const char *Text); + static void MsgOsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); ++ static bool MsgChannelProtected(const cDevice* Device, const cChannel* Channel); // PIN PATCH ++ static bool MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false); // PIN PATCH ++ static void MsgRecordingFile(const char* FileName); // PIN PATCH ++ static void MsgTimerCreation(cTimer* Timer, const cEvent *Event); // PIN PATCH ++ static bool MsgPluginProtected(cPlugin* Plugin, int menuView = false); // PIN PATCH ++ static void MsgUserAction(const eKeys key, const cOsdObject* Interact); ++ static bool MsgMenuItemProtected(const char* Name, int menuView = false); // PIN PATCH ++ + }; + + #endif //__STATUS_H +--- ../vdr-1.7.32.plain//timers.c 2012-10-16 10:22:39.000000000 +0200 ++++ timers.c 2012-12-07 11:07:02.344962535 +0100 +@@ -78,6 +78,7 @@ + stop -= 2400; + priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; + lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + if (Instant && channel) + snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); + if (VfatFileSystem && (Utf8StrLen(file) > VFAT_MAX_FILENAME)) { +@@ -117,6 +118,7 @@ + stop -= 2400; + priority = Setup.DefaultPriority; + lifetime = Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + const char *Title = Event->Title(); + if (!isempty(Title)) + Utf8Strn0Cpy(file, Event->Title(), sizeof(file)); +@@ -126,6 +128,7 @@ + dsyslog("timer file name truncated to '%s'", file); + } + SetEvent(Event); ++ cStatus::MsgTimerCreation(this, Event); // PIN PATCH + } + + cTimer::cTimer(const cTimer &Timer) +@@ -161,6 +164,7 @@ + stop = Timer.stop; + priority = Timer.priority; + lifetime = Timer.lifetime; ++ fskProtection = Timer.fskProtection; // PIN PATCH + strncpy(file, Timer.file, sizeof(file)); + free(aux); + aux = Timer.aux ? strdup(Timer.aux) : NULL; +@@ -355,6 +359,7 @@ + result = false; + } + } ++ fskProtection = aux && strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"); // PIN PATCH + free(channelbuffer); + free(daybuffer); + free(filebuffer); +@@ -713,6 +718,36 @@ + Matches(); // refresh start and end time + } + ++void cTimer::SetFskProtection(int aFlag) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ int res = 0; ++ ++ fskProtection = aFlag; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ res = asprintf(&aux, "%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info from aux ++ ++ res = asprintf(&tmp, "%.*s%s", (int)(p-aux), aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (res < 0) ; // memory problems :o ++ ++ if (tmp) ++ free(tmp); ++} ++ + // --- cTimers --------------------------------------------------------------- + + cTimers Timers; +--- ../vdr-1.7.32.plain//timers.h 2012-04-15 15:21:31.000000000 +0200 ++++ timers.h 2012-12-07 10:38:33.248902093 +0100 +@@ -38,6 +38,7 @@ + int start; + int stop; + int priority; ++ int fskProtection; // PIN PATCH + int lifetime; + mutable char file[MaxFileName]; + char *aux; +@@ -59,6 +60,7 @@ + int Start(void) const { return start; } + int Stop(void) const { return stop; } + int Priority(void) const { return priority; } ++ int FskProtection(void) const { return fskProtection; } // PIN PATCH + int Lifetime(void) const { return lifetime; } + const char *File(void) const { return file; } + time_t FirstDay(void) const { return weekdays ? day : 0; } +@@ -95,6 +97,7 @@ + void SetAux(const char *Aux); + void SetDeferred(int Seconds); + void SetFlags(uint Flags); ++ void SetFskProtection(int aFlag); // PIN PATCH + void ClrFlags(uint Flags); + void InvFlags(uint Flags); + bool HasFlags(uint Flags) const; +--- ../vdr-1.7.32.plain//vdr.c 2012-10-13 14:48:56.000000000 +0200 ++++ vdr.c 2012-12-07 11:07:50.728964248 +0100 +@@ -65,6 +65,7 @@ + #include "tools.h" + #include "transfer.h" + #include "videodir.h" ++#include "status.h" // PIN PATCH + + #define MINCHANNELWAIT 10 // seconds to wait between failed channel switchings + #define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping +@@ -948,6 +949,7 @@ + cOsdObject *Interact = Menu ? Menu : cControl::Control(); + eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse()); + if (ISREALKEY(key)) { ++ cStatus::MsgUserAction(key, Interact); // PIN PATCH + EITScanner.Activity(); + // Cancel shutdown countdown: + if (ShutdownHandler.countdown) +@@ -1020,10 +1022,12 @@ + cControl::Control()->Hide(); + cPlugin *plugin = cPluginManager::GetPlugin(PluginName); + if (plugin) { ++ if (!cStatus::MsgPluginProtected(plugin)) { + Menu = plugin->MainMenuAction(); + if (Menu) + Menu->Show(); + } ++ } + else + esyslog("ERROR: unknown plugin '%s'", PluginName); + } +@@ -1235,9 +1239,11 @@ + // Instant resume of the last viewed recording: + case kPlay: + if (cReplayControl::LastReplayed()) { ++ if (cStatus::MsgReplayProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { // PIN PATCH + cControl::Shutdown(); + cControl::Launch(new cReplayControl); + } ++ } + else + DirectMainFunction(osRecordings); // no last viewed recording, so enter the Recordings menu + break; diff --git a/patches/vdr-1.7.33.diff b/patches/vdr-1.7.33.diff new file mode 100644 index 0000000..38ba45f --- /dev/null +++ b/patches/vdr-1.7.33.diff @@ -0,0 +1,427 @@ +--- ../vdr-1.7.33/device.c 2012-11-19 10:59:09.000000000 +0100 ++++ device.c 2012-12-10 10:14:03.106016736 +0100 +@@ -721,6 +721,7 @@ + cChannel *channel; + while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { + // try only channels which are currently available ++ if (!cStatus::MsgChannelProtected(0, channel)) // PIN PATCH + if (GetDevice(channel, LIVEPRIORITY, true, true)) + break; + n = channel->Number() + Direction; +@@ -742,6 +743,12 @@ + + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) + { ++ // I hope 'LiveView = false' indicates a channel switch for recording, // PIN PATCH ++ // I really don't know, but it works ... // PIN PATCH ++ ++ if (LiveView && cStatus::MsgChannelProtected(this, Channel)) // PIN PATCH ++ return scrNotAvailable; // PIN PATCH ++ + cStatus::MsgChannelSwitch(this, 0, LiveView); + + if (LiveView) { +--- ../vdr-1.7.33/menu.c 2012-12-07 14:48:15.000000000 +0100 ++++ menu.c 2012-12-10 10:21:12.498031920 +0100 +@@ -896,6 +896,17 @@ + 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)); ++ ++ // PIN PATCH ++ if (cOsd::pinValid || !data.fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&data.fskProtection)); ++ else { ++ char* buf = 0; ++ if (asprintf(&buf, "%s\t%s", tr("Childlock"), data.fskProtection ? tr("yes") : tr("no")) >= 0){ ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } ++ } ++ + Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file))); + SetFirstDayItem(); + } +@@ -2285,7 +2296,10 @@ + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { + if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == FOLDERDELIMCHAR)) { + cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level); +- if (*Item->Text() && (!Item->IsDirectory() || (!LastItem || !LastItem->IsDirectory() || strcmp(Item->Text(), LastItemText) != 0))) { ++ ++ if (*Item->Text() && (!Item->IsDirectory() || (!LastItem || !LastItem->IsDirectory() || strcmp(Item->Text(), LastItemText) != 0)) ++ && (!cStatus::MsgReplayProtected(Item->Recording(), Item->Name(), base, ++ Item->IsDirectory(), true))) { // PIN PATCH + Add(Item); + LastItem = Item; + free(LastItemText); +@@ -2337,6 +2351,9 @@ + { + cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); + if (ri) { ++ if (cStatus::MsgReplayProtected(ri->Recording(), ri->Name(), base, ++ ri->IsDirectory()) == true) // PIN PATCH ++ return osContinue; // PIN PATCH + if (ri->IsDirectory()) + Open(); + else { +@@ -3379,28 +3396,32 @@ + + // Basic menu items: + +- Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); +- Add(new cOsdItem(hk(tr("Channels")), osChannels)); +- Add(new cOsdItem(hk(tr("Timers")), osTimers)); +- Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); ++ // PIN PATCH ++ if (!cStatus::MsgMenuItemProtected("Schedule", true)) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); ++ if (!cStatus::MsgMenuItemProtected("Channels", true)) Add(new cOsdItem(hk(tr("Channels")), osChannels)); ++ if (!cStatus::MsgMenuItemProtected("Timers", true)) Add(new cOsdItem(hk(tr("Timers")), osTimers)); ++ if (!cStatus::MsgMenuItemProtected("Recordings", true)) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); + + // Plugins: + + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { ++ if (!cStatus::MsgPluginProtected(p, true)) { // PIN PATCH + const char *item = p->MainMenuEntry(); + if (item) + Add(new cMenuPluginItem(hk(item), i)); + } ++ } + else + break; + } + + // More basic menu items: + +- Add(new cOsdItem(hk(tr("Setup")), osSetup)); ++ if (!cStatus::MsgMenuItemProtected("Setup", true)) Add(new cOsdItem(hk(tr("Setup")), osSetup)); // PIN PATCH + if (Commands.Count()) ++ if (!cStatus::MsgMenuItemProtected("Commands", true)) // PIN PATCH + Add(new cOsdItem(hk(tr("Commands")), osCommands)); + + Update(true); +@@ -3469,6 +3490,14 @@ + eOSState state = cOsdMenu::ProcessKey(Key); + HadSubMenu |= HasSubMenu(); + ++ // > PIN PATCH ++ cOsdItem* item = Get(Current()); ++ ++ if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) ++ if (cStatus::MsgMenuItemProtected(item->Text())) ++ return osContinue; ++ // PIN PATCH < ++ + switch (state) { + case osSchedule: return AddSubMenu(new cMenuSchedule); + case osChannels: return AddSubMenu(new cMenuChannels); +@@ -3494,6 +3523,7 @@ + if (item) { + cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); + if (p) { ++ if (!cStatus::MsgPluginProtected(p)) { // PIN PATCH + cOsdObject *menu = p->MainMenuAction(); + if (menu) { + if (menu->IsMenu()) +@@ -3505,6 +3535,7 @@ + } + } + } ++ } + state = osEnd; + } + break; +@@ -3675,6 +3706,7 @@ + Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel); + if (!Channel && Setup.ChannelsWrap) + Channel = Direction > 0 ? Channels.First() : Channels.Last(); ++ if (!cStatus::MsgChannelProtected(0, Channel)) // PIN PATCH + if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, LIVEPRIORITY, true, true)) + return Channel; + } +@@ -4324,6 +4356,7 @@ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (!RecordControls[i]) { + RecordControls[i] = new cRecordControl(device, Timer, Pause); ++ cStatus::MsgRecordingFile(RecordControls[i]->FileName()); // PIN PATCH + return RecordControls[i]->Process(time(NULL)); + } + } +--- ../vdr-1.7.33/osd.c 2012-06-09 16:37:24.000000000 +0200 ++++ osd.c 2012-12-10 10:14:03.110016736 +0100 +@@ -1623,6 +1623,7 @@ + int cOsd::osdHeight = 0; + cVector<cOsd *> cOsd::Osds; + cMutex cOsd::mutex; ++bool cOsd::pinValid = false; // PIN PATCH + + cOsd::cOsd(int Left, int Top, uint Level) + { +--- ../vdr-1.7.33/osd.h 2012-12-03 14:49:02.000000000 +0100 ++++ osd.h 2012-12-10 10:14:03.114016736 +0100 +@@ -931,6 +931,7 @@ + ///< MyOsdDrawPixmap(Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y(), pm->Data(), w, h, h * d); + ///< delete pm; + ///< } ++ static bool pinValid; // PIN PATCH + }; + + #define MAXOSDIMAGES 64 +--- ../vdr-1.7.33/status.c 2012-03-07 15:17:24.000000000 +0100 ++++ status.c 2012-12-10 10:14:03.114016736 +0100 +@@ -124,3 +124,55 @@ + for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) + sm->OsdProgramme(PresentTime, PresentTitle, PresentSubtitle, FollowingTime, FollowingTitle, FollowingSubtitle); + } ++ ++bool cStatus::MsgChannelProtected(const cDevice* Device, const cChannel* Channel) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ChannelProtected(Device, Channel) == true) ++ return true; ++ ++ return false; ++} ++ ++bool cStatus::MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ReplayProtected(Recording, Name, Base, isDirectory, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgRecordingFile(const char* FileName) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->RecordingFile(FileName); ++} ++ ++void cStatus::MsgTimerCreation(cTimer* Timer, const cEvent *Event) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->TimerCreation(Timer, Event); ++} ++ ++bool cStatus::MsgPluginProtected(cPlugin* Plugin, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->PluginProtected(Plugin, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgUserAction(const eKeys key, const cOsdObject* Interact) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ sm->UserAction(key, Interact); ++} ++ ++bool cStatus::MsgMenuItemProtected(const char* Name, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->MenuItemProtected(Name, menuView) == true) ++ return true; ++ return false; ++} +--- ../vdr-1.7.33/status.h 2012-03-07 15:16:57.000000000 +0100 ++++ status.h 2012-12-10 10:14:03.114016736 +0100 +@@ -14,6 +14,7 @@ + #include "device.h" + #include "player.h" + #include "tools.h" ++#include "plugin.h" + + enum eTimerChange { tcMod, tcAdd, tcDel }; + +@@ -81,6 +82,24 @@ + // The OSD displays the single line Text with the current channel information. + virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle) {} + // The OSD displays the given programme information. ++ virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel) { return false; } // PIN PATCH ++ // Checks if a channel is protected. ++ virtual bool ReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a recording is protected. ++ virtual void RecordingFile(const char* FileName) {} // PIN PATCH ++ // The given DVB device has started recording to FileName. FileName is the name of the ++ // recording directory ++ virtual void TimerCreation(cTimer* Timer, const cEvent *Event) {} // PIN PATCH ++ // The given timer is created ++ virtual bool PluginProtected(cPlugin* Plugin, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a plugin is protected. ++ virtual void UserAction(const eKeys key, const cOsdObject* Interact) {} // PIN PATCH ++ // report user action ++ virtual bool MenuItemProtected(const char* Name, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a menu entry is protected. ++ ++ + public: + cStatus(void); + virtual ~cStatus(); +@@ -102,6 +121,15 @@ + static void MsgOsdTextItem(const char *Text, bool Scroll = false); + static void MsgOsdChannel(const char *Text); + static void MsgOsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); ++ static bool MsgChannelProtected(const cDevice* Device, const cChannel* Channel); // PIN PATCH ++ static bool MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false); // PIN PATCH ++ static void MsgRecordingFile(const char* FileName); // PIN PATCH ++ static void MsgTimerCreation(cTimer* Timer, const cEvent *Event); // PIN PATCH ++ static bool MsgPluginProtected(cPlugin* Plugin, int menuView = false); // PIN PATCH ++ static void MsgUserAction(const eKeys key, const cOsdObject* Interact); ++ static bool MsgMenuItemProtected(const char* Name, int menuView = false); // PIN PATCH ++ + }; + + #endif //__STATUS_H +--- ../vdr-1.7.33/timers.c 2012-12-07 14:14:00.000000000 +0100 ++++ timers.c 2012-12-10 10:14:03.114016736 +0100 +@@ -78,6 +78,7 @@ + stop -= 2400; + priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; + lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + if (Instant && channel) + snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); + if (VfatFileSystem && (Utf8StrLen(file) > VFAT_MAX_FILENAME)) { +@@ -117,6 +118,7 @@ + stop -= 2400; + priority = Setup.DefaultPriority; + lifetime = Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + const char *Title = Event->Title(); + if (!isempty(Title)) + Utf8Strn0Cpy(file, Event->Title(), sizeof(file)); +@@ -126,6 +128,7 @@ + dsyslog("timer file name truncated to '%s'", file); + } + SetEvent(Event); ++ cStatus::MsgTimerCreation(this, Event); // PIN PATCH + } + + cTimer::cTimer(const cTimer &Timer) +@@ -161,6 +164,7 @@ + stop = Timer.stop; + priority = Timer.priority; + lifetime = Timer.lifetime; ++ fskProtection = Timer.fskProtection; // PIN PATCH + strncpy(file, Timer.file, sizeof(file)); + free(aux); + aux = Timer.aux ? strdup(Timer.aux) : NULL; +@@ -355,6 +359,7 @@ + result = false; + } + } ++ fskProtection = aux && strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"); // PIN PATCH + free(channelbuffer); + free(daybuffer); + free(filebuffer); +@@ -713,6 +718,36 @@ + Matches(); // refresh start and end time + } + ++void cTimer::SetFskProtection(int aFlag) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ int res = 0; ++ ++ fskProtection = aFlag; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ res = asprintf(&aux, "%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info from aux ++ ++ res = asprintf(&tmp, "%.*s%s", (int)(p-aux), aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (res < 0) ; // memory problems :o ++ ++ if (tmp) ++ free(tmp); ++} ++ + // --- cTimers --------------------------------------------------------------- + + cTimers Timers; +--- ../vdr-1.7.33/timers.h 2012-12-07 14:13:40.000000000 +0100 ++++ timers.h 2012-12-10 10:14:03.114016736 +0100 +@@ -38,6 +38,7 @@ + int start; + int stop; + int priority; ++ int fskProtection; // PIN PATCH + int lifetime; + mutable char file[MaxFileName]; + char *aux; +@@ -59,6 +60,7 @@ + int Start(void) const { return start; } + int Stop(void) const { return stop; } + int Priority(void) const { return priority; } ++ int FskProtection(void) const { return fskProtection; } // PIN PATCH + int Lifetime(void) const { return lifetime; } + const char *File(void) const { return file; } + time_t FirstDay(void) const { return weekdays ? day : 0; } +@@ -95,6 +97,7 @@ + void SetAux(const char *Aux); + void SetDeferred(int Seconds); + void SetFlags(uint Flags); ++ void SetFskProtection(int aFlag); // PIN PATCH + void ClrFlags(uint Flags); + void InvFlags(uint Flags); + bool HasFlags(uint Flags) const; +--- ../vdr-1.7.33/vdr.c 2012-12-06 11:29:23.000000000 +0100 ++++ vdr.c 2012-12-10 10:14:03.114016736 +0100 +@@ -65,6 +65,7 @@ + #include "tools.h" + #include "transfer.h" + #include "videodir.h" ++#include "status.h" // PIN PATCH + + #define MINCHANNELWAIT 10 // seconds to wait between failed channel switchings + #define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping +@@ -947,6 +948,7 @@ + cOsdObject *Interact = Menu ? Menu : cControl::Control(); + eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse()); + if (ISREALKEY(key)) { ++ cStatus::MsgUserAction(key, Interact); // PIN PATCH + EITScanner.Activity(); + // Cancel shutdown countdown: + if (ShutdownHandler.countdown) +@@ -1019,10 +1021,12 @@ + cControl::Control()->Hide(); + cPlugin *plugin = cPluginManager::GetPlugin(PluginName); + if (plugin) { ++ if (!cStatus::MsgPluginProtected(plugin)) { + Menu = plugin->MainMenuAction(); + if (Menu) + Menu->Show(); + } ++ } + else + esyslog("ERROR: unknown plugin '%s'", PluginName); + } +@@ -1235,9 +1239,11 @@ + // Instant resume of the last viewed recording: + case kPlay: + if (cReplayControl::LastReplayed()) { ++ if (cStatus::MsgReplayProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { // PIN PATCH + cControl::Shutdown(); + cControl::Launch(new cReplayControl); + } ++ } + else + DirectMainFunction(osRecordings); // no last viewed recording, so enter the Recordings menu + break; diff --git a/patches/vdr-2.0.2.diff b/patches/vdr-2.0.2.diff new file mode 100644 index 0000000..81dcd22 --- /dev/null +++ b/patches/vdr-2.0.2.diff @@ -0,0 +1,420 @@ +--- ../vdr-2.0.2/device.c 2013-04-05 12:47:38.000000000 +0200 ++++ device.c 2013-05-22 10:17:56.758196352 +0200 +@@ -722,6 +722,7 @@ + cChannel *channel; + while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { + // try only channels which are currently available ++ if (!cStatus::MsgChannelProtected(0, channel)) // PIN PATCH + if (GetDevice(channel, LIVEPRIORITY, true, true)) + break; + n = channel->Number() + Direction; +@@ -743,6 +744,12 @@ + + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) + { ++ // I hope 'LiveView = false' indicates a channel switch for recording, // PIN PATCH ++ // I really don't know, but it works ... // PIN PATCH ++ ++ if (LiveView && cStatus::MsgChannelProtected(this, Channel)) // PIN PATCH ++ return scrNotAvailable; // PIN PATCH ++ + cStatus::MsgChannelSwitch(this, 0, LiveView); + + if (LiveView) { +--- ../vdr-2.0.2/menu.c 2013-04-27 12:32:28.000000000 +0200 ++++ menu.c 2013-05-22 10:26:55.198215394 +0200 +@@ -896,6 +896,18 @@ + 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)); ++ ++ // PIN PATCH ++ if (cOsd::pinValid || !data.fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&data.fskProtection)); ++ else { ++ char* buf = 0; ++ int res = 0; ++ res = asprintf(&buf, "%s\t%s", tr("Childlock"), data.fskProtection ? tr("yes") : tr("no")); ++ if (res < 0) ; // memory problems :o ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } ++ + Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file))); + SetFirstDayItem(); + } +@@ -2294,7 +2306,8 @@ + } + } + } +- if (*Item->Text() && !LastDir) { ++ if (*Item->Text() && !LastDir ++ && (!cStatus::MsgReplayProtected(Item->Recording(), Item->Name(), base, Item->IsDirectory(), true))) { // PIN PATCH + Add(Item); + LastItem = Item; + if (Item->IsDirectory()) +@@ -2345,6 +2358,9 @@ + { + cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); + if (ri) { ++ if (cStatus::MsgReplayProtected(ri->Recording(), ri->Name(), base, ++ ri->IsDirectory()) == true) // PIN PATCH ++ return osContinue; // PIN PATCH + if (ri->IsDirectory()) + Open(); + else { +@@ -3403,28 +3419,32 @@ + + // Basic menu items: + +- Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); +- Add(new cOsdItem(hk(tr("Channels")), osChannels)); +- Add(new cOsdItem(hk(tr("Timers")), osTimers)); +- Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); ++ // PIN PATCH ++ if (!cStatus::MsgMenuItemProtected("Schedule", true)) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); ++ if (!cStatus::MsgMenuItemProtected("Channels", true)) Add(new cOsdItem(hk(tr("Channels")), osChannels)); ++ if (!cStatus::MsgMenuItemProtected("Timers", true)) Add(new cOsdItem(hk(tr("Timers")), osTimers)); ++ if (!cStatus::MsgMenuItemProtected("Recordings", true)) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); + + // Plugins: + + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { ++ if (!cStatus::MsgPluginProtected(p, true)) { // PIN PATCH + const char *item = p->MainMenuEntry(); + if (item) + Add(new cMenuPluginItem(hk(item), i)); + } ++ } + else + break; + } + + // More basic menu items: + +- Add(new cOsdItem(hk(tr("Setup")), osSetup)); ++ if (!cStatus::MsgMenuItemProtected("Setup", true)) Add(new cOsdItem(hk(tr("Setup")), osSetup)); // PIN PATCH + if (Commands.Count()) ++ if (!cStatus::MsgMenuItemProtected("Commands", true)) // PIN PATCH + Add(new cOsdItem(hk(tr("Commands")), osCommands)); + + Update(true); +@@ -3493,6 +3513,14 @@ + eOSState state = cOsdMenu::ProcessKey(Key); + HadSubMenu |= HasSubMenu(); + ++ // > PIN PATCH ++ cOsdItem* item = Get(Current()); ++ ++ if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) ++ if (cStatus::MsgMenuItemProtected(item->Text())) ++ return osContinue; ++ // PIN PATCH < ++ + switch (state) { + case osSchedule: return AddSubMenu(new cMenuSchedule); + case osChannels: return AddSubMenu(new cMenuChannels); +@@ -3518,6 +3546,7 @@ + if (item) { + cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); + if (p) { ++ if (!cStatus::MsgPluginProtected(p)) { // PIN PATCH + cOsdObject *menu = p->MainMenuAction(); + if (menu) { + if (menu->IsMenu()) +@@ -3529,6 +3558,7 @@ + } + } + } ++ } + state = osEnd; + } + break; +@@ -3699,6 +3729,7 @@ + Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel); + if (!Channel && Setup.ChannelsWrap) + Channel = Direction > 0 ? Channels.First() : Channels.Last(); ++ if (!cStatus::MsgChannelProtected(0, Channel)) // PIN PATCH + if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, LIVEPRIORITY, true, true)) + return Channel; + } +@@ -4348,6 +4379,7 @@ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (!RecordControls[i]) { + RecordControls[i] = new cRecordControl(device, Timer, Pause); ++ cStatus::MsgRecordingFile(RecordControls[i]->FileName()); // PIN PATCH + return RecordControls[i]->Process(time(NULL)); + } + } +--- ../vdr-2.0.2/osd.c 2013-05-18 14:41:48.000000000 +0200 ++++ osd.c 2013-05-22 10:17:56.758196352 +0200 +@@ -1623,6 +1623,7 @@ + int cOsd::osdHeight = 0; + cVector<cOsd *> cOsd::Osds; + cMutex cOsd::mutex; ++bool cOsd::pinValid = false; // PIN PATCH + + cOsd::cOsd(int Left, int Top, uint Level) + { +--- ../vdr-2.0.2/osd.h 2013-02-12 14:39:08.000000000 +0100 ++++ osd.h 2013-05-22 10:24:49.822210960 +0200 +@@ -926,6 +926,7 @@ + ///< MyOsdDrawPixmap(Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y(), pm->Data(), w, h, h * d); + ///< delete pm; + ///< } ++ static bool pinValid; // PIN PATCH + }; + + #define MAXOSDIMAGES 64 +--- ../vdr-2.0.2/status.c 2012-03-07 15:17:24.000000000 +0100 ++++ status.c 2013-05-22 10:17:56.758196352 +0200 +@@ -124,3 +124,55 @@ + for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) + sm->OsdProgramme(PresentTime, PresentTitle, PresentSubtitle, FollowingTime, FollowingTitle, FollowingSubtitle); + } ++ ++bool cStatus::MsgChannelProtected(const cDevice* Device, const cChannel* Channel) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ChannelProtected(Device, Channel) == true) ++ return true; ++ ++ return false; ++} ++ ++bool cStatus::MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ReplayProtected(Recording, Name, Base, isDirectory, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgRecordingFile(const char* FileName) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->RecordingFile(FileName); ++} ++ ++void cStatus::MsgTimerCreation(cTimer* Timer, const cEvent *Event) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->TimerCreation(Timer, Event); ++} ++ ++bool cStatus::MsgPluginProtected(cPlugin* Plugin, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->PluginProtected(Plugin, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgUserAction(const eKeys key, const cOsdObject* Interact) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ sm->UserAction(key, Interact); ++} ++ ++bool cStatus::MsgMenuItemProtected(const char* Name, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->MenuItemProtected(Name, menuView) == true) ++ return true; ++ return false; ++} +--- ../vdr-2.0.2/status.h 2012-03-07 15:16:57.000000000 +0100 ++++ status.h 2013-05-22 10:20:19.902201414 +0200 +@@ -14,6 +14,7 @@ + #include "device.h" + #include "player.h" + #include "tools.h" ++#include "plugin.h" + + enum eTimerChange { tcMod, tcAdd, tcDel }; + +@@ -81,6 +82,22 @@ + // The OSD displays the single line Text with the current channel information. + virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle) {} + // The OSD displays the given programme information. ++ virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel) { return false; } // PIN PATCH ++ // Checks if a channel is protected. ++ virtual bool ReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a recording is protected. ++ virtual void RecordingFile(const char* FileName) {} // PIN PATCH ++ // The given DVB device has started recording to FileName. FileName is the name of the ++ // recording directory ++ virtual void TimerCreation(cTimer* Timer, const cEvent *Event) {} // PIN PATCH ++ // The given timer is created ++ virtual bool PluginProtected(cPlugin* Plugin, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a plugin is protected. ++ virtual void UserAction(const eKeys key, const cOsdObject* Interact) {} // PIN PATCH ++ // report user action ++ virtual bool MenuItemProtected(const char* Name, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a menu entry is protected. + public: + cStatus(void); + virtual ~cStatus(); +@@ -102,6 +119,14 @@ + static void MsgOsdTextItem(const char *Text, bool Scroll = false); + static void MsgOsdChannel(const char *Text); + static void MsgOsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); ++ static bool MsgChannelProtected(const cDevice* Device, const cChannel* Channel); // PIN PATCH ++ static bool MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false); // PIN PATCH ++ static void MsgRecordingFile(const char* FileName); // PIN PATCH ++ static void MsgTimerCreation(cTimer* Timer, const cEvent *Event); // PIN PATCH ++ static bool MsgPluginProtected(cPlugin* Plugin, int menuView = false); // PIN PATCH ++ static void MsgUserAction(const eKeys key, const cOsdObject* Interact); ++ static bool MsgMenuItemProtected(const char* Name, int menuView = false); // PIN PATCH + }; + + #endif //__STATUS_H +--- ../vdr-2.0.2/timers.c 2013-03-29 16:37:16.000000000 +0100 ++++ timers.c 2013-05-22 10:17:56.762196352 +0200 +@@ -76,6 +76,7 @@ + stop -= 2400; + priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; + lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + if (Instant && channel) + snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); + } +@@ -110,10 +111,12 @@ + stop -= 2400; + priority = Setup.DefaultPriority; + lifetime = Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + const char *Title = Event->Title(); + if (!isempty(Title)) + Utf8Strn0Cpy(file, Event->Title(), sizeof(file)); + SetEvent(Event); ++ cStatus::MsgTimerCreation(this, Event); // PIN PATCH + } + + cTimer::cTimer(const cTimer &Timer) +@@ -149,6 +152,7 @@ + stop = Timer.stop; + priority = Timer.priority; + lifetime = Timer.lifetime; ++ fskProtection = Timer.fskProtection; // PIN PATCH + strncpy(file, Timer.file, sizeof(file)); + free(aux); + aux = Timer.aux ? strdup(Timer.aux) : NULL; +@@ -331,6 +335,7 @@ + result = false; + } + } ++ fskProtection = aux && strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"); // PIN PATCH + free(channelbuffer); + free(daybuffer); + free(filebuffer); +@@ -689,6 +694,36 @@ + Matches(); // refresh start and end time + } + ++void cTimer::SetFskProtection(int aFlag) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ int res = 0; ++ ++ fskProtection = aFlag; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ res = asprintf(&aux, "%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info from aux ++ ++ res = asprintf(&tmp, "%.*s%s", (int)(p-aux), aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (res < 0) ; // memory problems :o ++ ++ if (tmp) ++ free(tmp); ++} ++ + // --- cTimers --------------------------------------------------------------- + + cTimers Timers; +--- ../vdr-2.0.2/timers.h 2013-03-11 11:35:53.000000000 +0100 ++++ timers.h 2013-05-22 10:17:56.762196352 +0200 +@@ -38,6 +38,7 @@ + int start; + int stop; + int priority; ++ int fskProtection; // PIN PATCH + int lifetime; + mutable char file[NAME_MAX * 2 + 1]; // *2 to be able to hold 'title' and 'episode', which can each be up to 255 characters long + char *aux; +@@ -59,6 +60,7 @@ + int Start(void) const { return start; } + int Stop(void) const { return stop; } + int Priority(void) const { return priority; } ++ int FskProtection(void) const { return fskProtection; } // PIN PATCH + int Lifetime(void) const { return lifetime; } + const char *File(void) const { return file; } + time_t FirstDay(void) const { return weekdays ? day : 0; } +@@ -95,6 +97,7 @@ + void SetAux(const char *Aux); + void SetDeferred(int Seconds); + void SetFlags(uint Flags); ++ void SetFskProtection(int aFlag); // PIN PATCH + void ClrFlags(uint Flags); + void InvFlags(uint Flags); + bool HasFlags(uint Flags) const; +--- ../vdr-2.0.2/vdr.c 2013-03-15 11:44:54.000000000 +0100 ++++ vdr.c 2013-05-22 10:17:56.762196352 +0200 +@@ -65,6 +65,7 @@ + #include "tools.h" + #include "transfer.h" + #include "videodir.h" ++#include "status.h" // PIN PATCH + + #define MINCHANNELWAIT 10 // seconds to wait between failed channel switchings + #define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping +@@ -1015,6 +1016,7 @@ + cOsdObject *Interact = Menu ? Menu : cControl::Control(); + eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse()); + if (ISREALKEY(key)) { ++ cStatus::MsgUserAction(key, Interact); // PIN PATCH + EITScanner.Activity(); + // Cancel shutdown countdown: + if (ShutdownHandler.countdown) +@@ -1087,10 +1089,12 @@ + cControl::Control()->Hide(); + cPlugin *plugin = cPluginManager::GetPlugin(PluginName); + if (plugin) { ++ if (!cStatus::MsgPluginProtected(plugin)) { // PIN PATCH + Menu = plugin->MainMenuAction(); + if (Menu) + Menu->Show(); + } ++ } + else + esyslog("ERROR: unknown plugin '%s'", PluginName); + } +@@ -1303,9 +1307,11 @@ + // Instant resume of the last viewed recording: + case kPlay: + if (cReplayControl::LastReplayed()) { ++ if (cStatus::MsgReplayProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { // PIN PATCH + cControl::Shutdown(); + cControl::Launch(new cReplayControl); + } ++ } + else + DirectMainFunction(osRecordings); // no last viewed recording, so enter the Recordings menu + break; diff --git a/patches/vdr-2.3.1.diff b/patches/vdr-2.3.1.diff new file mode 100644 index 0000000..4ec4be9 --- /dev/null +++ b/patches/vdr-2.3.1.diff @@ -0,0 +1,432 @@ +--- ../vdr-2.3.1.plain//device.c 2015-09-05 13:42:17.000000000 +0200 ++++ device.c 2015-10-09 16:43:27.982132231 +0200 +@@ -726,6 +726,7 @@ + const cChannel *Channel; + while ((Channel = Channels->GetByNumber(n, Direction)) != NULL) { + // try only channels which are currently available ++ if (!cStatus::MsgChannelProtected(0, Channel)) // PIN PATCH + if (GetDevice(Channel, LIVEPRIORITY, true, true)) + break; + n = Channel->Number() + Direction; +@@ -747,6 +748,12 @@ + + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) + { ++ // I hope 'LiveView = false' indicates a channel switch for recording, // PIN PATCH ++ // I really don't know, but it works ... // PIN PATCH ++ ++ if (LiveView && cStatus::MsgChannelProtected(this, Channel)) // PIN PATCH ++ return scrNotAvailable; // PIN PATCH ++ + cStatus::MsgChannelSwitch(this, 0, LiveView); + + if (LiveView) { +--- ../vdr-2.3.1.plain//Makefile 2015-02-09 13:28:24.000000000 +0100 ++++ Makefile 2015-10-12 08:49:55.734546896 +0200 +@@ -324,7 +324,7 @@ + clean: + @$(MAKE) --no-print-directory -C $(LSIDIR) clean + @-rm -f $(OBJS) $(DEPFILE) vdr vdr.pc core* *~ +- @-rm -rf $(LOCALEDIR) $(PODIR)/*.mo $(PODIR)/*.pot ++ @-rm -rf $(LOCALEDIR) $(PODIR)/*~ $(PODIR)/*.mo $(PODIR)/*.pot + @-rm -rf include + @-rm -rf srcdoc + CLEAN: clean +--- ../vdr-2.3.1.plain//menu.c 2015-09-14 15:22:49.000000000 +0200 ++++ menu.c 2015-10-09 16:26:16.481017293 +0200 +@@ -997,6 +997,18 @@ + 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)); ++ ++ // PIN PATCH ++ if (cOsd::pinValid || !data.fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&data.fskProtection)); ++ else { ++ char* buf = 0; ++ int res = 0; ++ res = asprintf(&buf, "%s\t%s", tr("Childlock"), data.fskProtection ? tr("yes") : tr("no")); ++ if (res < 0) ; // memory problems :o ++ Add(new cOsdItem(buf)); ++ free(buf); ++ } ++ + Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file))); + SetFirstDayItem(); + if (data.remote) +@@ -2973,7 +2985,8 @@ + } + } + } +- if (*Item->Text() && !LastDir) { ++ if (*Item->Text() && !LastDir ++ && (!cStatus::MsgReplayProtected(Item->Recording(), Item->Name(), base, Item->IsDirectory(), true))) { // PIN PATCH + Add(Item); + LastItem = Item; + if (Item->IsDirectory()) +@@ -3041,6 +3054,9 @@ + { + cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); + if (ri) { ++ if (cStatus::MsgReplayProtected(ri->Recording(), ri->Name(), base, ++ ri->IsDirectory()) == true) // PIN PATCH ++ return osContinue; // PIN PATCH + if (ri->IsDirectory()) + Open(); + else { +@@ -4282,28 +4298,32 @@ + + // Basic menu items: + +- Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); +- Add(new cOsdItem(hk(tr("Channels")), osChannels)); +- Add(new cOsdItem(hk(tr("Timers")), osTimers)); +- Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); ++ // PIN PATCH ++ if (!cStatus::MsgMenuItemProtected("Schedule", true)) Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); ++ if (!cStatus::MsgMenuItemProtected("Channels", true)) Add(new cOsdItem(hk(tr("Channels")), osChannels)); ++ if (!cStatus::MsgMenuItemProtected("Timers", true)) Add(new cOsdItem(hk(tr("Timers")), osTimers)); ++ if (!cStatus::MsgMenuItemProtected("Recordings", true)) Add(new cOsdItem(hk(tr("Recordings")), osRecordings)); + + // Plugins: + + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { ++ if (!cStatus::MsgPluginProtected(p, true)) { // PIN PATCH + const char *item = p->MainMenuEntry(); + if (item) + Add(new cMenuPluginItem(hk(item), i)); + } ++ } + else + break; + } + + // More basic menu items: + +- Add(new cOsdItem(hk(tr("Setup")), osSetup)); ++ if (!cStatus::MsgMenuItemProtected("Setup", true)) Add(new cOsdItem(hk(tr("Setup")), osSetup)); // PIN PATCH + if (Commands.Count()) ++ if (!cStatus::MsgMenuItemProtected("Commands", true)) // PIN PATCH + Add(new cOsdItem(hk(tr("Commands")), osCommands)); + + Update(true); +@@ -4372,6 +4392,14 @@ + eOSState state = cOsdMenu::ProcessKey(Key); + HadSubMenu |= HasSubMenu(); + ++ // > PIN PATCH ++ cOsdItem* item = Get(Current()); ++ ++ if (item && item->Text() && state != osContinue && state != osUnknown && state != osBack) ++ if (cStatus::MsgMenuItemProtected(item->Text())) ++ return osContinue; ++ // PIN PATCH < ++ + switch (state) { + case osSchedule: return AddSubMenu(new cMenuSchedule); + case osChannels: return AddSubMenu(new cMenuChannels); +@@ -4396,6 +4424,7 @@ + if (item) { + cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex()); + if (p) { ++ if (!cStatus::MsgPluginProtected(p)) { // PIN PATCH + cOsdObject *menu = p->MainMenuAction(); + if (menu) { + if (menu->IsMenu()) +@@ -4407,6 +4436,7 @@ + } + } + } ++ } + state = osEnd; + } + break; +@@ -4576,6 +4606,7 @@ + Channel = Direction > 0 ? Channels->Next(Channel) : Channels->Prev(Channel); + if (!Channel && Setup.ChannelsWrap) + Channel = Direction > 0 ? Channels->First() : Channels->Last(); ++ if (!cStatus::MsgChannelProtected(0, Channel)) // PIN PATCH + if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, LIVEPRIORITY, true, true)) + return Channel; + } +@@ -5226,6 +5257,7 @@ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (!RecordControls[i]) { + RecordControls[i] = new cRecordControl(device, Timers, Timer, Pause); ++ cStatus::MsgRecordingFile(RecordControls[i]->FileName()); // PIN PATCH + return RecordControls[i]->Process(time(NULL)); + } + } +--- ../vdr-2.3.1.plain//osd.c 2015-09-10 16:12:06.000000000 +0200 ++++ osd.c 2015-10-09 16:10:13.400241634 +0200 +@@ -1644,6 +1644,7 @@ + cSize cOsd::maxPixmapSize(2048, 2048); + cVector<cOsd *> cOsd::Osds; + cMutex cOsd::mutex; ++bool cOsd::pinValid = false; // PIN PATCH + + cOsd::cOsd(int Left, int Top, uint Level) + { +--- ../vdr-2.3.1.plain//osd.h 2015-04-19 14:18:25.000000000 +0200 ++++ osd.h 2015-10-09 16:10:13.400241634 +0200 +@@ -952,6 +952,7 @@ + ///< + ///< If a plugin uses a derived cPixmap implementation, it needs to use that + ///< type instead of cPixmapMemory. ++ static bool pinValid; // PIN PATCH + }; + + #define MAXOSDIMAGES 64 +--- ../vdr-2.3.1.plain//status.c 2014-01-25 11:47:39.000000000 +0100 ++++ status.c 2015-10-12 10:41:28.695735498 +0200 +@@ -130,3 +130,55 @@ + for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) + sm->OsdProgramme(PresentTime, PresentTitle, PresentSubtitle, FollowingTime, FollowingTitle, FollowingSubtitle); + } ++ ++bool cStatus::MsgChannelProtected(const cDevice* Device, const cChannel* Channel) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ChannelProtected(Device, Channel) == true) ++ return true; ++ ++ return false; ++} ++ ++bool cStatus::MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->ReplayProtected(Recording, Name, Base, isDirectory, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgRecordingFile(const char* FileName) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->RecordingFile(FileName); ++} ++ ++void cStatus::MsgTimerCreation(cTimer* Timer, const cEvent *Event) ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) // PIN PATCH ++ sm->TimerCreation(Timer, Event); ++} ++ ++bool cStatus::MsgPluginProtected(cPlugin* Plugin, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->PluginProtected(Plugin, menuView) == true) ++ return true; ++ return false; ++} ++ ++void cStatus::MsgUserAction(const eKeys key) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ sm->UserAction(key); ++} ++ ++bool cStatus::MsgMenuItemProtected(const char* Name, int menuView) // PIN PATCH ++{ ++ for (cStatus *sm = statusMonitors.First(); sm; sm = statusMonitors.Next(sm)) ++ if (sm->MenuItemProtected(Name, menuView) == true) ++ return true; ++ return false; ++} +--- ../vdr-2.3.1.plain//status.h 2015-08-02 12:34:44.000000000 +0200 ++++ status.h 2015-10-12 10:41:15.287669011 +0200 +@@ -14,6 +14,7 @@ + #include "device.h" + #include "player.h" + #include "tools.h" ++#include "plugin.h" + + enum eTimerChange { tcMod, tcAdd, tcDel }; // tcMod is obsolete and no longer used! + +@@ -81,6 +82,23 @@ + // The OSD displays the single line Text with the current channel information. + virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle) {} + // The OSD displays the given programme information. ++ virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel) { return false; } // PIN PATCH ++ // Checks if a channel is protected. ++ virtual bool ReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a recording is protected. ++ virtual void RecordingFile(const char* FileName) {} // PIN PATCH ++ // The given DVB device has started recording to FileName. FileName is the name of the ++ // recording directory ++ virtual void TimerCreation(cTimer* Timer, const cEvent *Event) {} // PIN PATCH ++ // The given timer is created ++ virtual bool PluginProtected(cPlugin* Plugin, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a plugin is protected. ++ virtual void UserAction(const eKeys key) {} // PIN PATCH ++ // report user action ++ virtual bool MenuItemProtected(const char* Name, int menuView = false) { return false; } // PIN PATCH ++ // Checks if a menu entry is protected. ++ + public: + cStatus(void); + virtual ~cStatus(); +@@ -103,6 +121,14 @@ + static void MsgOsdTextItem(const char *Text, bool Scroll = false); + static void MsgOsdChannel(const char *Text); + static void MsgOsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); ++ static bool MsgChannelProtected(const cDevice* Device, const cChannel* Channel); // PIN PATCH ++ static bool MsgReplayProtected(const cRecording* Recording, const char* Name, ++ const char* Base, bool isDirectory, int menuView = false); // PIN PATCH ++ static void MsgRecordingFile(const char* FileName); // PIN PATCH ++ static void MsgTimerCreation(cTimer* Timer, const cEvent *Event); // PIN PATCH ++ static bool MsgPluginProtected(cPlugin* Plugin, int menuView = false); // PIN PATCH ++ static void MsgUserAction(const eKeys key); // PIN PATCH ++ static bool MsgMenuItemProtected(const char* Name, int menuView = false); // PIN PATCH + }; + + #endif //__STATUS_H +--- ../vdr-2.3.1.plain//timers.c 2015-09-13 15:10:24.000000000 +0200 ++++ timers.c 2015-10-09 16:10:13.404241653 +0200 +@@ -77,6 +77,7 @@ + stop -= 2400; + priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; + lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + if (Instant && channel) + snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); + } +@@ -114,10 +115,12 @@ + stop -= 2400; + priority = Setup.DefaultPriority; + lifetime = Setup.DefaultLifetime; ++ fskProtection = 0; // PIN PATCH + const char *Title = Event->Title(); + if (!isempty(Title)) + Utf8Strn0Cpy(file, Event->Title(), sizeof(file)); + SetEvent(Event); ++ cStatus::MsgTimerCreation(this, Event); // PIN PATCH + } + + cTimer::cTimer(const cTimer &Timer) +@@ -156,6 +159,7 @@ + stop = Timer.stop; + priority = Timer.priority; + lifetime = Timer.lifetime; ++ fskProtection = Timer.fskProtection; // PIN PATCH + strncpy(file, Timer.file, sizeof(file)); + free(aux); + aux = Timer.aux ? strdup(Timer.aux) : NULL; +@@ -344,6 +348,7 @@ + result = false; + } + } ++ fskProtection = aux && strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"); // PIN PATCH + free(channelbuffer); + free(daybuffer); + free(filebuffer); +@@ -708,6 +713,36 @@ + Matches(); // refresh start and end time + } + ++void cTimer::SetFskProtection(int aFlag) // PIN PATCH ++{ ++ char* p; ++ char* tmp = 0; ++ int res = 0; ++ ++ fskProtection = aFlag; ++ ++ if (fskProtection && (!aux || !strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // add protection info to aux ++ ++ if (aux) { tmp = strdup(aux); free(aux); } ++ res = asprintf(&aux, "%s<pin-plugin><protected>yes</protected></pin-plugin>", tmp ? tmp : ""); ++ } ++ else if (!fskProtection && aux && (p = strstr(aux, "<pin-plugin><protected>yes</protected></pin-plugin>"))) ++ { ++ // remove protection info from aux ++ ++ res = asprintf(&tmp, "%.*s%s", (int)(p-aux), aux, p+strlen("<pin-plugin><protected>yes</protected></pin-plugin>")); ++ free(aux); ++ aux = strdup(tmp); ++ } ++ ++ if (res < 0) ; // memory problems :o ++ ++ if (tmp) ++ free(tmp); ++} ++ + // --- cTimers --------------------------------------------------------------- + + cTimers cTimers::timers; +--- ../vdr-2.3.1.plain//timers.h 2015-09-09 12:40:24.000000000 +0200 ++++ timers.h 2015-10-09 16:10:13.404241653 +0200 +@@ -39,6 +39,7 @@ + int start; + int stop; + int priority; ++ int fskProtection; // PIN PATCH + int lifetime; + mutable char file[NAME_MAX * 2 + 1]; // *2 to be able to hold 'title' and 'episode', which can each be up to 255 characters long + char *aux; +@@ -62,6 +63,7 @@ + int Start(void) const { return start; } + int Stop(void) const { return stop; } + int Priority(void) const { return priority; } ++ int FskProtection(void) const { return fskProtection; } // PIN PATCH + int Lifetime(void) const { return lifetime; } + const char *File(void) const { return file; } + time_t FirstDay(void) const { return weekdays ? day : 0; } +@@ -102,6 +104,7 @@ + void SetRemote(const char *Remote); + void SetDeferred(int Seconds); + void SetFlags(uint Flags); ++ void SetFskProtection(int aFlag); // PIN PATCH + void ClrFlags(uint Flags); + void InvFlags(uint Flags); + bool HasFlags(uint Flags) const; +--- ../vdr-2.3.1.plain//vdr.c 2015-09-11 10:02:50.000000000 +0200 ++++ vdr.c 2015-10-12 10:40:33.159460108 +0200 +@@ -71,6 +71,7 @@ + #include "tools.h" + #include "transfer.h" + #include "videodir.h" ++#include "status.h" // PIN PATCH + + #define MINCHANNELWAIT 10 // seconds to wait between failed channel switchings + #define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping +@@ -1153,6 +1154,7 @@ + cOsdObject *Interact = Menu ? Menu : cControl::Control(); + eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse()); + if (ISREALKEY(key)) { ++ cStatus::MsgUserAction(key); // PIN PATCH + EITScanner.Activity(); + // Cancel shutdown countdown: + if (ShutdownHandler.countdown) +@@ -1225,10 +1227,12 @@ + cControl::Control()->Hide(); + cPlugin *plugin = cPluginManager::GetPlugin(PluginName); + if (plugin) { ++ if (!cStatus::MsgPluginProtected(plugin)) { // PIN PATCH + Menu = plugin->MainMenuAction(); + if (Menu) + Menu->Show(); + } ++ } + else + esyslog("ERROR: unknown plugin '%s'", PluginName); + } +@@ -1446,9 +1450,11 @@ + // Instant resume of the last viewed recording: + case kPlay: + if (cReplayControl::LastReplayed()) { ++ if (cStatus::MsgReplayProtected(0, cReplayControl::LastReplayed(), 0, false) == false) { // PIN PATCH + cControl::Shutdown(); + cControl::Launch(new cReplayControl); + } ++ } + else + DirectMainFunction(osRecordings); // no last viewed recording, so enter the Recordings menu + break; @@ -0,0 +1,882 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 11.04.05 - 23.11.06 + */ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/interface.h> +#include <vdr/videodir.h> +#include <vdr/menu.h> + +#include "pin.h" +#include "menu.h" +#include "setupmenu.h" + +//*************************************************************************** +// Pin Service +//*************************************************************************** + +void Translations::append(const char* in, const char* out) +{ + if (!in) + return ; + + Translation* t = new Translation; + + Add(t); + + strncpy(t->in, in, 200); + t->in[200] = 0; + strncpy(t->out, out ? out : "", 200); + t->out[200] = 0; +} + +const char* Translations::lookup(const char* in) +{ + for (Translation* p = First(); p; p = Next(p)) + if (strcmp(p->in, in) == 0) + return p->out; + + return 0; +} + +//*************************************************************************** +// Pin +//*************************************************************************** +//*************************************************************************** +// Object +//*************************************************************************** + +cPin::cPin(void) +{ + pinSetup = *cPinPlugin::pinCode ? no : yes; // code already configured + + if (pinSetup) + pinTxt = tr("Setup your pin code: "); + else + pinTxt = tr("Pin Code: "); + + tell(eloDebug, "Debug: pin is '%s', text = '%s'", cPinPlugin::pinCode, pinTxt); + + display = 0; + clear(); +} + +cPin::~cPin() +{ + if (display) delete display; +} + +//*************************************************************************** +// Clear +//*************************************************************************** + +void cPin::clear() +{ + *code = 0; + cOsd::pinValid = no; +} + +//*************************************************************************** +// Show +//*************************************************************************** + +void cPin::Show(void) +{ + display = Skins.Current()->DisplayMessage(); + display->SetMessage(mtInfo, pinTxt); + cStatus::MsgOsdStatusMessage(pinTxt); + display->Flush(); +} + +//*************************************************************************** +// Process Key +//*************************************************************************** + +eOSState cPin::ProcessKey(eKeys Key) +{ + char txt[50+TB]; + int len = strlen(code); + eOSState state = cOsdObject::ProcessKey(Key); + + if (state == osUnknown) + { + switch (Key) + { + case kBack: + { + return osEnd; + } + + case kLeft: + { + if (len <= 0) + break; + + len--; + code[len] = 0; + break; + } + + case k0 ... k9: + { + if (len >= 5) // max 5 digits + break; + + code[len++] = Key-k0+48; + code[len] = 0; + break; + } + + case kOk: + { + cOsd::pinValid = no; + + if (!pinSetup || (pinSetup && *code)) + { + if (pinSetup) + strcpy(cPinPlugin::pinCode, code); // setup pin code + + if (strcmp(code, cPinPlugin::pinCode) == 0) + cOsd::pinValid = yes; + } + + state = osEnd; + break; + } + + default: return state; + } + + if (state == osEnd) + { + if (pinSetup && cOsd::pinValid) + { + (cPinPlugin::getObject())->StorePin(); + display->SetMessage(mtInfo, tr("Pin code successfully setup")); + cStatus::MsgOsdStatusMessage(tr("Pin code successfully setup")); + display->Flush(); + sleep(2); + } + + if (cOsd::pinValid && cPinPlugin::autoMenuOpen) + { + cRemote::CallPlugin("pin"); + } + else + { + display->SetMessage(cOsd::pinValid ? mtInfo : mtWarning, + cOsd::pinValid ? tr("Code accepted") : tr("Invalid Code !")); + cStatus::MsgOsdStatusMessage(cOsd::pinValid ? tr("Code accepted") : tr("Invalid Code !")); + display->Flush(); + sleep(1); + } + } + else + { + int i; + + strcpy(txt, pinTxt); + + for (i = 0; i < len; i++) + txt[strlen(pinTxt)+i] = '*'; + + txt[strlen(pinTxt)+i] = 0; + + display->SetMessage(mtInfo, txt); + cStatus::MsgOsdStatusMessage(txt); + display->Flush(); + state = osContinue; + } + } + + return state; +} + +//*************************************************************************** +// PIN Plugin +//*************************************************************************** +//*************************************************************************** +// Static Stuff +//*************************************************************************** + +char cPinPlugin::pinCode[] = ""; +cPinPlugin* cPinPlugin::object = 0; +bool cPinPlugin::skipChannelSilent = no; +bool cPinPlugin::hideProtectedMenus = no; +bool cPinPlugin::hideProtectedPlugins = no; +bool cPinPlugin::hideProtectedRecordings = no; +int cPinPlugin::pinResetTime = 90 /* minutes */; // default 1,5 hour +bool cPinPlugin::autoMenuOpen = yes; +int cPinPlugin::autoProtectionMode = apmIntelligent; + +const char* cPinPlugin::autoProtectionModes[] = +{ + "always", + "intelligent", + "never", + + 0 +}; + +//*************************************************************************** +// Object +//*************************************************************************** + +cPinPlugin::cPinPlugin(void) + : lockedChannels(ltChannels), + lockedBroadcasts(ltBroadcasts), + lockedPlugins(ltPlugins), + lockedMenuItems(ltMenuItems) +{ + statusMonitor = 0; + lastAction = time(0); + receiver = 0; + cOsd::pinValid = no; // initial sperren +} + +cPinPlugin::~cPinPlugin() +{ + if (receiver) delete receiver; + if (statusMonitor) delete statusMonitor; +} + +//*************************************************************************** +// Store Pin Code +//*************************************************************************** + +void cPinPlugin::StorePin() +{ + SetupStore("pinCode", cPinPlugin::pinCode); +} + +//*************************************************************************** +// Initialize +//*************************************************************************** + +bool cPinPlugin::Initialize(void) +{ + char* path; + int res; + + res = asprintf(&path, "%s/%s", cPlugin::ConfigDirectory(), "pin"); + + if (res < 0) ; // memory problems :o + + if (!DirectoryOk(path, no)) + { + if (mkdir(path, 0770)) + { + // cannot create the directory + + tell(eloAlways, "Creating of directory '%s' failed, errno was (%d) - '%s'", + path, errno, strerror(errno)); + free(path); + + return true; // anyhow let vdr start + } + } + + free(path); + + lockedChannels.Load(AddDirectory(cPlugin::ConfigDirectory(), + "pin/channellocks.conf"), true, false); + lockedBroadcasts.Load(AddDirectory(cPlugin::ConfigDirectory(), + "pin/broadcastlocks.conf"), true, false); + lockedPlugins.Load(AddDirectory(cPlugin::ConfigDirectory(), + "pin/pluginlocks.conf"), true, false); + lockedMenuItems.Load(AddDirectory(cPlugin::ConfigDirectory(), + "pin/menulocks.conf"), true, false); + + return true; +} + +//*************************************************************************** +// Main Menu Action +//*************************************************************************** + +cOsdObject* cPinPlugin::MainMenuAction(void) +{ + initPluginList(); + + if (cOsd::pinValid) + return new cPinMenu(MAINMENUENTRY, &lockedChannels, + &lockedBroadcasts, &lockedPlugins, + &lockedMenuItems); + + return new cPin(); +} + +//*************************************************************************** +// Start +//*************************************************************************** + +bool cPinPlugin::Start(void) +{ + statusMonitor = new cPinStatusMonitor; + object = this; + + receiver = new MessageReceiver; + receiver->StartReceiver(); + + return true; +} + +//*************************************************************************** +// Stop +//*************************************************************************** + +void cPinPlugin::Stop(void) +{ + receiver->StopReceiver(); +} + +//*************************************************************************** +// Setup Menu +//*************************************************************************** + +cMenuSetupPage* cPinPlugin::SetupMenu(void) +{ + if (cOsd::pinValid) + return new PinSetupMenu; + + Skins.Message(mtInfo, tr("Please enter pin code first")); + + return 0; +} + +//*************************************************************************** +// Setup Parse +//*************************************************************************** + +bool cPinPlugin::SetupParse(const char *Name, const char *Value) +{ + // Pase Setup Parameters + + if (!strcasecmp(Name, "pinCode")) + strcpy(pinCode, Value); + else if (!strcasecmp(Name, "skipChannelSilent")) + skipChannelSilent = atoi(Value); + else if (!strcasecmp(Name, "hideProtectedMenus")) + hideProtectedMenus = atoi(Value); + else if (!strcasecmp(Name, "hideProtectedPlugins")) + hideProtectedPlugins = atoi(Value); + else if (!strcasecmp(Name, "hideProtectedRecordings")) + hideProtectedRecordings = atoi(Value); + else if (!strcasecmp(Name, "pinResetTime")) + pinResetTime = atoi(Value); + else if (!strcasecmp(Name, "autoMenuOpen")) + autoMenuOpen = atoi(Value); + else if (!strcasecmp(Name, "autoProtectionMode")) + autoProtectionMode = atoi(Value); + else + return false; + + return true; +} + +//*************************************************************************** +// Test if Channel Protected +//*************************************************************************** + +int cPinPlugin::channelProtected(const char* name, long startTime) +{ + return lockedChannels.Locked(name, startTime); +} + +//*************************************************************************** +// Test if Plugin Protected +//*************************************************************************** + +int cPinPlugin::pluginProtected(const char* name) +{ + return lockedPlugins.Locked(name); +} + +//*************************************************************************** +// Test if Menu Item Protected +//*************************************************************************** + +int cPinPlugin::menuItemProtected(const char* text) +{ + return lockedMenuItems.Locked(text); +} + +//*************************************************************************** +// Append Menu Item +//*************************************************************************** + +int cPinPlugin::menuItemAppend(const char* text) +{ + cLockItem* item; + + if (!lockedMenuItems.FindByName(text)) + { + lockedMenuItems.Add(item = new cLockItem(text)); + item->SetActive(no); + } + + return success; +} + +//*************************************************************************** +// Test if Broadcast Protected +//*************************************************************************** + +int cPinPlugin::broadcastProtected(const char* title) +{ + return lockedBroadcasts.Locked(title); +} + +//*************************************************************************** +// Check Action Time +//*************************************************************************** + +void cPinPlugin::checkActivity() +{ + time_t lNow = time(0); + + if (pinResetTime > 0 && lNow > lastAction+(pinResetTime*60) && cOsd::pinValid) + { + // keine User Aktion, Kindersicherung aktivieren .. + + tell(eloAlways, "Pin: Locking pin due to no user inactivity of (%ld) seconds", + lNow-lastAction); + + cOsd::pinValid = no; + } + + lastAction = lNow; +} + +//*************************************************************************** +// Init Plugin List +//*************************************************************************** + +int cPinPlugin::initPluginList() +{ + static int initialized = no; + + cPlugin* plugin; + int i = 0; + int cnt = 0; + cLockItem* item; + + if (initialized) + return done; + + initialized = yes; + +#ifdef __EXCL_PLUGINS + tell(eloAlways, "exclude plugins '%s' from pin protection", __EXCL_PLUGINS); +#endif + + while ((plugin = cPluginManager::GetPlugin(i))) + { + if (strcasecmp(plugin->Name(), "pin") != 0 +#ifdef __EXCL_PLUGINS + && !strstr(__EXCL_PLUGINS, plugin->Name()) +#endif + ) + { + // nicht das pin plugin und keine Plugs aus der Exclude Liste + + if (!(item = lockedPlugins.FindByName(plugin->Name()))) + { + lockedPlugins.Add(new cLockItem(plugin->Name(), no, + plugin->MainMenuEntry())); + + tell(eloAlways, "PIN added plugin (%d) '%s' - '%s'", + i, plugin->Name(), plugin->MainMenuEntry()); + + cnt++; + } + else + { + item->SetTitle(plugin->MainMenuEntry()); + } + } + + i++; + }; + + if (cnt) + lockedPlugins.Save(); + + return done; +} + +//*************************************************************************** +// Channel Switch +//*************************************************************************** + +void cPinStatusMonitor::ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView) +{ + // cChannel* channel = Channels.GetByNumber(ChannelNumber); +} + +//*************************************************************************** +// User Action +//*************************************************************************** + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) +void cPinStatusMonitor::UserAction(const eKeys key) +#else +void cPinStatusMonitor::UserAction(const eKeys key, const cOsdObject* Interact) +#endif +{ + tell(eloDebug, "Pin: UserAction, key (%d)", key); + + (cPinPlugin::getObject())->checkActivity(); +} + +//*************************************************************************** +// Replay Protected +//*************************************************************************** + +bool cPinStatusMonitor::ReplayProtected(const cRecording* Recording, const char* Name, + const char* Base, bool isDirectory, int menuView) +{ + bool fProtected; + struct stat ifo; + char* path = 0; + char* base = 0; + char* name = 0; + int res; + + if (Base) + { + base = strdup(Base); + base = ExchangeChars(base, true); + } + + if (Name) + { + name = strdup(Name); + + if (isDirectory) + name = ExchangeChars(name, true); + } + + tell(eloDebug, "checking protection of %s '%s%s%s'", + isDirectory ? "directory" : "recording", + isDirectory && base ? base : "", + isDirectory && base ? "/" : "", + isDirectory || !Recording ? name : Recording->Name()); + + if (cOsd::pinValid) + return false; + + if (menuView && !cPinPlugin::hideProtectedRecordings) + return false; + + if (isDirectory) + res = asprintf(&path, "%s%s%s/%s/%s", +#if APIVERSNUM > 20103 + cVideoDirectory::Name(), +#else + VideoDirectory, +#endif + base ? "/" : "", + base ? base : "", + name ? name : "", + PROTECTION_FILE); + else + res = asprintf(&path, "%s/%s", + Recording ? Recording->FileName() : name, + PROTECTION_FILE); + + + if (res < 0) ; // memory problems :o + + tell(eloDebug, "checking rights, protection file is '%s'", path); + + fProtected = stat(path, &ifo) == 0; + + if (path) free(path); + if (base) free(base); + if (name) free(name); + + if (fProtected) + { + if (!menuView) + Skins.Message(mtError, tr("Recording protected, enter pin code first")); + + return true; + } + + return false; +} + +//*************************************************************************** +// Channel Protected +//*************************************************************************** + +bool cPinStatusMonitor::ChannelProtected(const cDevice *Device, const cChannel* Channel) +{ + char* buf; + const cEvent* event; + + if (cOsd::pinValid) + return false; + + if (!Channel || !Channel->Name() || Channel->GroupSep()) + return false; + + // first check channel protection + + tell(eloDebug, "checking protection of channel '%s', '%s'", + Channel->Name(), + Channel->ShortName()); + + if ((cPinPlugin::getObject())->channelProtected(Channel->Name())) + { + int res; + + tell(eloDebug, "channel %d '%s' is protected", Channel->Number(), Channel->Name()); + + if (cPinPlugin::skipChannelSilent) + return true; + + res = asprintf(&buf, "%d %s - %s", Channel->Number(), Channel->Name(), tr("channel is protected")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + + free(buf); + + return true; + } + + // get schedules lock + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + + if (!(event = GetEventOf(Schedules, Channel))) + return false; +#else + cSchedulesLock schedLock; + const cSchedules* schedules; + + if (!(schedules = cSchedules::Schedules(schedLock))) + return false; + + if (!(event = GetEventOf(schedules, Channel))) + return false; +#endif + + // second check broadcast protection + + if ((cPinPlugin::getObject())->broadcastProtected(event->Title())) + { + int res; + + if (cPinPlugin::skipChannelSilent) + return true; + + tell(eloDebug, "broadcast '%s' is protected", event->Title()); + res = asprintf(&buf, "%s - %s", event->Title(), tr("broadcast is protected")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + + free(buf); + + return true; + } + + return false; +} + +//*************************************************************************** +// Recording +//*************************************************************************** + +void cPinStatusMonitor::RecordingFile(const char* FileName) +{ + char* path = 0; + cRecordControl* rc; + FILE* f; + + if (!FileName || !strlen(FileName)) + return; + + rc = cRecordControls::GetRecordControl(FileName); + + tell(eloDebug, "checking if autoprotection for '%s' is needed", FileName); + + if (rc && rc->Timer() && rc->Timer()->Channel()) + { + if (rc->Timer()->FskProtection()) + { + int res; + res = asprintf(&path, "%s/%s", FileName, PROTECTION_FILE); + if (res < 0) ; // memory problems :o + + tell(eloDebug, "autoprotecting recording due to '%s'; channel '%s'; file '%s'", + rc->Timer()->FskProtection() ? "timer configuration" : "of protected channel", + rc->Timer()->Channel()->Name(), path); + + f = fopen(path, "w"); + if (f) fclose(f); + + free(path); + } + } +} + +//*************************************************************************** +// Get Event Of +//*************************************************************************** + +const cEvent* cPinStatusMonitor::GetEventOf(const cSchedules* schedules, const cChannel* Channel) +{ + const cSchedule* schedule; + const cEvent* event; + + if (!(schedule = schedules->GetSchedule(Channel->GetChannelID()))) + return 0; + + if (!(event = schedule->GetPresentEvent())) + return 0; + + return event; +} + +//*************************************************************************** +// Timer Creation +//*************************************************************************** + +void cPinStatusMonitor::TimerCreation(cTimer* Timer, const cEvent* Event) +{ + int fsk = 0; + + if (!Timer || !Event || !Timer->Channel()) + return; + + tell(eloDebug, "Timer creation, event '%s', protection mode (%d)", + Event->Title(), cPinPlugin::autoProtectionMode); + + switch (cPinPlugin::autoProtectionMode) + { + case cPinPlugin::apmAlways: fsk = 1; break; + case cPinPlugin::apmNever: fsk = 0; break; + + case cPinPlugin::apmIntelligent: + { + tell(eloDebug, "Checking protection for channel '%s' at (%ld))", + Timer->Channel()->Name(), Event->StartTime()); + + fsk = (cPinPlugin::getObject())->channelProtected( + Timer->Channel()->Name(), Event->StartTime()) + || (cPinPlugin::getObject())->broadcastProtected(Event->Title()); + + break; + } + } + + Timer->SetFskProtection(fsk); +} + +//*************************************************************************** +// Plugin Protected +//*************************************************************************** + +bool cPinStatusMonitor::PluginProtected(cPlugin* Plugin, int menuView) +{ + char* buf; + + if (cOsd::pinValid) + return false; + + if (menuView && !cPinPlugin::hideProtectedPlugins) + return false; + + if (!Plugin) + return false; + + // check if plugin is protected + + tell(eloDebug, "checking protection of plugin '%s'",Plugin->MainMenuEntry()); + + if ((cPinPlugin::getObject())->pluginProtected(Plugin->Name())) + { + tell(eloDebug, "plugin '%s' is protected", Plugin->MainMenuEntry()); + + if (!menuView) + { + int res; + res = asprintf(&buf, "%s %s", Plugin->MainMenuEntry(), tr("is protected")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + free(buf); + } + + return true; + } + + return false; +} + +//*************************************************************************** +// Menu Item Protectes +//*************************************************************************** + +bool cPinStatusMonitor::MenuItemProtected(const char* Name, int menuView) +{ + char* buf; + const char* name; + + if (!Name) + return false; + + if (!(name = translations.lookup(Name))) + { + name = tr(Str::stripHotKey(Name)); + translations.append(Name, name); + } + + tell(eloDebug, "translation: '%s' -> '%'s ", + Str::stripHotKey(Name), name); + + if (menuView) + (cPinPlugin::getObject())->menuItemAppend(name); + + if (cOsd::pinValid) + return false; + + if (menuView && !cPinPlugin::hideProtectedMenus) + return false; + + // check if menu item is protected + + tell(eloDebug, "checking protection of menu entry '%s' for '%s'", + name, menuView ? "view": "execution"); + + if ((cPinPlugin::getObject())->menuItemProtected(name)) + { + tell(eloDebug, "menu entry '%s' is protected", name); + + if (!menuView) + { + int res; + res = asprintf(&buf, "%s %s", name, tr("is protected")); + if (res < 0) ; // memory problems :o + Skins.Message(mtInfo, buf); + free(buf); + } + + return true; + } + + return false; +} + +//*************************************************************************** + +VDRPLUGINCREATOR(cPinPlugin); @@ -0,0 +1,237 @@ +/* + * A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * File: pin.h + * + */ + +#ifndef __PIN_H__ +#define __PIN_H__ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/status.h> +#include <vdr/plugin.h> + +#include "locks.h" +#include "def.h" +#include "talk.h" + +//*************************************************************************** +// Constants +//*************************************************************************** + +static const char *VERSION = "0.1.16"; +static const char *DESCRIPTION = "Childlock plugin"; +static const char *MAINMENUENTRY = tr("Childlock"); + +#define PROTECTION_FILE "protection.fsk" +// #define __DEBUG__ + +//*************************************************************************** +// Pin Service +//*************************************************************************** + +class PinService +{ + public: + + enum Size + { + sizePinCode = 5 + }; + + enum ListType + { + ltUnknown = na, + ltChannels, + ltBroadcasts, + ltPlugins, + ltMenuItems + }; + + class Translation : public cListObject + { + public: + + char in[200+TB]; + char out[200+TB]; + }; +}; + +class Translations : public cList<PinService::Translation>, PinService +{ + public: + + void append(const char* in, const char* out); + const char* lookup(const char* in); + +}; + +//*************************************************************************** +// Message Reciver +//*************************************************************************** + +class MessageReceiver : public cThread +{ + public: + + MessageReceiver(); + ~MessageReceiver(); + + int StartReceiver(); + int StopReceiver(); + + protected: + + void Action(); + int wait(); + + // data + + Talk* talk; + int pid; + bool active; +}; + +//*************************************************************************** +// Pin Status Monitor +//*************************************************************************** + +class cPinStatusMonitor : public cStatus +{ + protected: + + // interface + + virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView); + virtual bool ChannelProtected(const cDevice *Device, const cChannel* Channel); + virtual bool ReplayProtected(const cRecording* Recording, const char* Name, + const char* Base, bool isDirectory, int menuView = false); + virtual void RecordingFile(const char* FileName); + virtual void TimerCreation(cTimer* Timer, const cEvent *Event); + virtual bool PluginProtected(cPlugin* Plugin, int menuView = false); + virtual bool MenuItemProtected(const char* Name, int menuView = false); + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + virtual void UserAction(const eKeys key); +#else + virtual void UserAction(const eKeys key, const cOsdObject* Interact); +#endif + + // internal stuff + + const cEvent* GetEventOf(const cSchedules* schedules, const cChannel* Channel); + + Translations translations; +}; + +//*************************************************************************** +// Pin +//*************************************************************************** + +class cPin : public cOsdObject, public PinService +{ + public: + + cPin(void); + virtual ~cPin(); + virtual void Show(void); + virtual eOSState ProcessKey(eKeys Key); + void clear(); + + private: + + cOsd* osd; + int textWidth; + const char* pinTxt; + char code[sizePinCode+TB]; + cSkinDisplayMessage* display; + int pinSetup; +}; + +//*************************************************************************** +// Pin Plugin +//*************************************************************************** + +class cPinPlugin : public cPlugin, public PinService +{ + public: + + enum AutoProtectionMode + { + apmUnknown = na, + + apmAlways, + apmIntelligent, + apmNever, + + apmCount + }; + + cPinPlugin(void); + virtual ~cPinPlugin(); + + const char* CommandLineHelp(void) { return 0; } + bool ProcessArgs(int argc, char *argv[]) { return true; } + bool Start(void); + void Stop(void); + void Housekeeping(void) {} + + virtual cMenuSetupPage *SetupMenu(void); + virtual bool SetupParse(const char *Name, const char *Value); + const char* Version(void) { return VERSION; } + const char* Description(void) { return trNOOP(DESCRIPTION); } + virtual bool Initialize(void); + virtual const char* MainMenuEntry(void) { return tr(MAINMENUENTRY); } + virtual cOsdObject* MainMenuAction(void); + + void addChannel(); + void delChannel(); + int channelProtected(const char* name, long startTime = 0); + int pluginProtected(const char* name); + int menuItemProtected(const char* text); + int menuItemAppend(const char* text); + int broadcastProtected(const char* title); + void checkActivity(); + int initPluginList(); + void StorePin(); + + static cPinPlugin* getObject() { return object; } + + // static config items + + static char pinCode[sizePinCode+TB]; + static bool skipChannelSilent; + static bool hideProtectedMenus; + static bool hideProtectedPlugins; + static bool hideProtectedRecordings; + static int pinResetTime; + static bool autoMenuOpen; + static int autoProtectionMode; + + // other static stuff + + static const char* autoProtectionModes[apmCount+1]; + + protected: + + // data + + cLockItems lockedChannels; + cLockedBroadcasts lockedBroadcasts; + cLockItems lockedPlugins; + cLockItems lockedMenuItems; + time_t lastAction; + cPinStatusMonitor* statusMonitor; + MessageReceiver* receiver; + + static cPinPlugin* object; // the object +}; + +//*************************************************************************** +#endif // __PIN_H__ diff --git a/po/de_DE.po b/po/de_DE.po new file mode 100644 index 0000000..2872afc --- /dev/null +++ b/po/de_DE.po @@ -0,0 +1,170 @@ +# VDR plugin language source file. +# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> +# This file is distributed under the same license as the VDR package. +# Klaus Schmidinger <kls@cadsoft.de>, 2000 +# +msgid "" +msgstr "" +"Project-Id-Version: VDR 1.5.7\n" +"Report-Msgid-Bugs-To: <see README>\n" +"POT-Creation-Date: 2013-05-22 11:28+0200\n" +"PO-Revision-Date: 2013-05-22 10:37+0200\n" +"Last-Translator: Klaus Schmidinger <kls@cadsoft.de>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Setup" +msgstr "" + +msgid "Add current channel to protection list" +msgstr "Aktuellen Kanal sperren" + +msgid "Add current broadcast to protection list" +msgstr "Aktuelle Sendung sperren" + +msgid "Edit channel locks" +msgstr "Gesperrte Kanäle bearbeiten" + +msgid "Edit broadcast locks" +msgstr "Gesperrte Sendungen bearbeiten" + +msgid "Edit plugin locks" +msgstr "Systemeinstellungen bearbeiten" + +msgid "Edit menu locks" +msgstr "Menüsperren bearbeiten" + +msgid "Unlock setup" +msgstr "Setup entsperren" + +msgid "Lock setup" +msgstr "Setup sperren" + +msgid "Activate childlock" +msgstr "Kindersicherung aktivieren" + +msgid "Activated pin protection" +msgstr "Kindersicherung aktiviert" + +msgid "Please setup a pin code first!" +msgstr "Bitte konfigurieren zuerst einen Pin Code!" + +msgid "Protected channels" +msgstr "Gesperrte Kanäle" + +msgid "Protected broadcasts" +msgstr "Gesperrte Sendungen" + +msgid "Plugin protections" +msgstr "Sperren / Entsperren" + +msgid "Menu protections" +msgstr "Menü sperren" + +msgid "locked" +msgstr "gesperrt" + +msgid "unlocked" +msgstr "entsperrt" + +msgid "already in list" +msgstr "bereits in der Liste" + +msgid "added to protection list" +msgstr "hinzugefügt" + +msgid "Edit" +msgstr "Bearbeiten" + +msgid "On/Off" +msgstr "An/Aus" + +msgid "Add" +msgstr "Hinzufügen" + +msgid "Delete" +msgstr "Löschen" + +msgid "Remove entry?" +msgstr "Eintrag entfernen?" + +msgid "Name" +msgstr "" + +msgid "Lock active" +msgstr "Sperre aktiv" + +msgid "Keyword" +msgstr "Suchbegriff" + +msgid "Search mode" +msgstr "" + +msgid "Start" +msgstr "" + +msgid "Stop" +msgstr "" + +msgid "Setup your pin code: " +msgstr "Bitte Pin Code festlegen: " + +msgid "Pin Code: " +msgstr "Pin Eingabe: " + +msgid "Pin code successfully setup" +msgstr "Pin Code erfolgreich festgelegt." + +msgid "Code accepted" +msgstr "Eingabe angenommen" + +msgid "Invalid Code !" +msgstr "Falsche Eingabe !" + +msgid "Please enter pin code first" +msgstr "Bitte zuerst Pin Code eingeben" + +msgid "Recording protected, enter pin code first" +msgstr "Aufnahme gesperrt, bitte Kindersicherung freischalten" + +msgid "channel is protected" +msgstr "Kanal gesperrt" + +msgid "broadcast is protected" +msgstr "Sendung gesperrt" + +msgid "is protected" +msgstr "ist gesperrt" + +msgid "Pin code" +msgstr "" + +msgid "Skip protected channel silent" +msgstr "Gesperrte Kanäle ohne Meldung überspringen" + +msgid "Hide protected menus" +msgstr "Gesperrte Menüs verstecken" + +msgid "Hide protected plugins" +msgstr "Gesperrte Plugins verstecken" + +msgid "Hide protected recordings" +msgstr "Gesperrte Aufnahmen verstecken" + +msgid "Open menu after pin request" +msgstr "Menü nach Eingabe des Pin öffnen" + +msgid "Pin inactivity time [min]" +msgstr "Sperre aktivieren nach Inaktivität [min]" + +msgid "Autoprotection of recordings" +msgstr "Automatischer Schutz der Aufnahmen" + +msgid "Log Level [0-5]" +msgstr "" + +msgid "Ignoring invalid pin" +msgstr "Ungültiger code" diff --git a/po/fr_FR.po b/po/fr_FR.po new file mode 100644 index 0000000..2c11b4f --- /dev/null +++ b/po/fr_FR.po @@ -0,0 +1,173 @@ +# VDR plugin language source file. +# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> +# This file is distributed under the same license as the VDR package. +# Jean-Claude Repetto <jc@repetto.org>, 2001 +# Olivier Jacques <jacquesolivier@hotmail.com>, 2003 +# Gregoire Favre <greg@magma.unil.ch>, 2003 +# Nicolas Huillard <nhuillard@e-dition.fr>, 2005 +# +msgid "" +msgstr "" +"Project-Id-Version: VDR 1.5.7\n" +"Report-Msgid-Bugs-To: <see README>\n" +"POT-Creation-Date: 2013-05-22 11:28+0200\n" +"PO-Revision-Date: 2013-05-22 10:37+0200\n" +"Last-Translator: Nicolas Huillard <nhuillard@e-dition.fr>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Setup" +msgstr "" + +msgid "Add current channel to protection list" +msgstr "Ajouter la chaîne actuelle à la protection parentale" + +msgid "Add current broadcast to protection list" +msgstr "Ajouter l'émission actuelle dans la liste de protection parentale" + +msgid "Edit channel locks" +msgstr "Editer la liste de chaînes" + +msgid "Edit broadcast locks" +msgstr "Editer les émissions protégés" + +msgid "Edit plugin locks" +msgstr "editer la protection de plugin" + +msgid "Edit menu locks" +msgstr "" + +msgid "Unlock setup" +msgstr "" + +msgid "Lock setup" +msgstr "" + +msgid "Activate childlock" +msgstr "Protection parentales activée" + +msgid "Activated pin protection" +msgstr "Activé la protection parentale" + +msgid "Please setup a pin code first!" +msgstr "Entrer le code de protection d'abord!" + +msgid "Protected channels" +msgstr "Protéger chaîne" + +msgid "Protected broadcasts" +msgstr "Proteger l'émission" + +msgid "Plugin protections" +msgstr "Plugin sous protection" + +msgid "Menu protections" +msgstr "Protégier des menus" + +msgid "locked" +msgstr "protégé" + +msgid "unlocked" +msgstr "libéré" + +msgid "already in list" +msgstr "Toujours dans la liste" + +msgid "added to protection list" +msgstr "ajouter" + +msgid "Edit" +msgstr "Editer" + +msgid "On/Off" +msgstr "Enclencher/déclencher" + +msgid "Add" +msgstr "Ajouter" + +msgid "Delete" +msgstr "Effacer" + +msgid "Remove entry?" +msgstr "Enlever?" + +msgid "Name" +msgstr "" + +msgid "Lock active" +msgstr "Protection active" + +msgid "Keyword" +msgstr "Expression de recherche" + +msgid "Search mode" +msgstr "" + +msgid "Start" +msgstr "" + +msgid "Stop" +msgstr "" + +msgid "Setup your pin code: " +msgstr "Introduisez le code d'accès:" + +msgid "Pin Code: " +msgstr "Le code pin" + +msgid "Pin code successfully setup" +msgstr "Le code d'accès est accepté" + +msgid "Code accepted" +msgstr "Le code est accepté" + +msgid "Invalid Code !" +msgstr "Le code est faux!" + +msgid "Please enter pin code first" +msgstr "Entré d'abord le code" + +msgid "Recording protected, enter pin code first" +msgstr "Entrée le code de protection" + +msgid "channel is protected" +msgstr "Chaînes protégée" + +msgid "broadcast is protected" +msgstr "Emission protégée" + +msgid "is protected" +msgstr "est protégé" + +msgid "Pin code" +msgstr "" + +msgid "Skip protected channel silent" +msgstr "Les chaînes protégés seront ignorées sans infos" + +msgid "Hide protected menus" +msgstr "Menu protégés sont invisibles" + +msgid "Hide protected plugins" +msgstr "Plugins protégés sont invisibles" + +msgid "Hide protected recordings" +msgstr "Enregistrements protégés sont invisibles" + +msgid "Open menu after pin request" +msgstr "Ouvrir le menu après la rentré de la cléed" + +msgid "Pin inactivity time [min]" +msgstr "Protection après une inactivitées de [min]" + +msgid "Autoprotection of recordings" +msgstr "Protection automatique des enregistrement" + +msgid "Log Level [0-5]" +msgstr "" + +msgid "Ignoring invalid pin" +msgstr "Le code est fau" diff --git a/po/hu_HU.po b/po/hu_HU.po new file mode 100644 index 0000000..a834225 --- /dev/null +++ b/po/hu_HU.po @@ -0,0 +1,171 @@ +# VDR plugin language source file. +# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> +# This file is distributed under the same license as the VDR package. +# Istvan Koenigsberger <istvnko@hotmail.com>, 2002 +# Guido Josten <guido.josten@t-online.de>, 2002 +# +msgid "" +msgstr "" +"Project-Id-Version: VDR 1.5.7\n" +"Report-Msgid-Bugs-To: <see README>\n" +"POT-Creation-Date: 2013-05-22 11:28+0200\n" +"PO-Revision-Date: 2013-05-22 10:37+0200\n" +"Last-Translator: Istvan Koenigsberger <istvnko@hotmail.com>, Guido Josten <guido.josten@t-online.de>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Setup" +msgstr "" + +msgid "Add current channel to protection list" +msgstr "Aktuális csatorna zároltakhoz adása" + +msgid "Add current broadcast to protection list" +msgstr "Aktuális adás zároltakhoz adása" + +msgid "Edit channel locks" +msgstr "Zárolt csatornák szerkesztése" + +msgid "Edit broadcast locks" +msgstr "Zárolt adások szerkesztése" + +msgid "Edit plugin locks" +msgstr "" + +msgid "Edit menu locks" +msgstr "" + +msgid "Unlock setup" +msgstr "" + +msgid "Lock setup" +msgstr "" + +msgid "Activate childlock" +msgstr "Gyerekzár aktiválása" + +msgid "Activated pin protection" +msgstr "Gyerekzár aktiválva" + +msgid "Please setup a pin code first!" +msgstr "" + +msgid "Protected channels" +msgstr "Védett csatornák" + +msgid "Protected broadcasts" +msgstr "Védett adások" + +msgid "Plugin protections" +msgstr "" + +msgid "Menu protections" +msgstr "" + +msgid "locked" +msgstr "" + +msgid "unlocked" +msgstr "" + +msgid "already in list" +msgstr "mar a zaroltak között" + +msgid "added to protection list" +msgstr "Zároltakhoz hozzáadva" + +msgid "Edit" +msgstr "" + +msgid "On/Off" +msgstr "" + +msgid "Add" +msgstr "Hozzáadás" + +msgid "Delete" +msgstr "Törlés" + +msgid "Remove entry?" +msgstr "Törlése?" + +msgid "Name" +msgstr "" + +msgid "Lock active" +msgstr "Zár aktiválva" + +msgid "Keyword" +msgstr "Kulcsszó" + +msgid "Search mode" +msgstr "" + +msgid "Start" +msgstr "" + +msgid "Stop" +msgstr "" + +msgid "Setup your pin code: " +msgstr "" + +msgid "Pin Code: " +msgstr "Pin kód" + +msgid "Pin code successfully setup" +msgstr "" + +msgid "Code accepted" +msgstr "" + +msgid "Invalid Code !" +msgstr "" + +msgid "Please enter pin code first" +msgstr "" + +msgid "Recording protected, enter pin code first" +msgstr "Kérem oldja fel a gyerekzárat" + +msgid "channel is protected" +msgstr "Csatorna zárolva" + +msgid "broadcast is protected" +msgstr "Adás zárolva" + +msgid "is protected" +msgstr "" + +msgid "Pin code" +msgstr "" + +msgid "Skip protected channel silent" +msgstr "Zárolt csatornákat nem megjeleníteni" + +msgid "Hide protected menus" +msgstr "" + +msgid "Hide protected plugins" +msgstr "" + +msgid "Hide protected recordings" +msgstr "" + +msgid "Open menu after pin request" +msgstr "" + +msgid "Pin inactivity time [min]" +msgstr "Zár aktiválása [perc] inaktivitás után" + +msgid "Autoprotection of recordings" +msgstr "Automatikus védelem felvétel ellen" + +msgid "Log Level [0-5]" +msgstr "" + +msgid "Ignoring invalid pin" +msgstr "Érvénytelen pin kód" diff --git a/po/it_IT.po b/po/it_IT.po new file mode 100644 index 0000000..0143791 --- /dev/null +++ b/po/it_IT.po @@ -0,0 +1,172 @@ +# VDR plugin language source file. +# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> +# This file is distributed under the same license as the VDR package. +# Alberto Carraro <bertocar@tin.it>, 2001 +# Antonio Ospite <ospite@studenti.unina.it>, 2003 +# Sean Carlos <seanc@libero.it>, 2005 +# +msgid "" +msgstr "" +"Project-Id-Version: VDR 1.5.7\n" +"Report-Msgid-Bugs-To: <see README>\n" +"POT-Creation-Date: 2013-05-22 11:28+0200\n" +"PO-Revision-Date: 2013-05-22 10:37+0200\n" +"Last-Translator: Sean Carlos <seanc@libero.it>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Setup" +msgstr "" + +msgid "Add current channel to protection list" +msgstr "Aggiungi canale attuale all'elenco protezione" + +msgid "Add current broadcast to protection list" +msgstr "Aggiungi trasmissione attuale all'elenco protezione" + +msgid "Edit channel locks" +msgstr "Modifica protezioni canale" + +msgid "Edit broadcast locks" +msgstr "Modifica protezioni trasmissione" + +msgid "Edit plugin locks" +msgstr "Modifica protezioni plugin" + +msgid "Edit menu locks" +msgstr "Modifica protezioni menu" + +msgid "Unlock setup" +msgstr "Sblocca impostazioni" + +msgid "Lock setup" +msgstr "Blocca impostazioni" + +msgid "Activate childlock" +msgstr "Attiva filtro famiglia" + +msgid "Activated pin protection" +msgstr "Attivato filtro famiglia" + +msgid "Please setup a pin code first!" +msgstr "Per favore imposta prima un codice Pin" + +msgid "Protected channels" +msgstr "Canali protetti" + +msgid "Protected broadcasts" +msgstr "Trasmissioni protette" + +msgid "Plugin protections" +msgstr "Plugin di protezione" + +msgid "Menu protections" +msgstr "Protezioni menu" + +msgid "locked" +msgstr "protetto" + +msgid "unlocked" +msgstr "sprotetto" + +msgid "already in list" +msgstr "già nell'elenco" + +msgid "added to protection list" +msgstr "aggiunto all'elenco protezione" + +msgid "Edit" +msgstr "Modifica" + +msgid "On/Off" +msgstr "Attivo/Disattivo" + +msgid "Add" +msgstr "Aggiungi" + +msgid "Delete" +msgstr "Elimina" + +msgid "Remove entry?" +msgstr "Rimuovere valore?" + +msgid "Name" +msgstr "" + +msgid "Lock active" +msgstr "Protezione attiva" + +msgid "Keyword" +msgstr "Parola chiave" + +msgid "Search mode" +msgstr "" + +msgid "Start" +msgstr "" + +msgid "Stop" +msgstr "" + +msgid "Setup your pin code: " +msgstr "Imposta il codice pin:" + +msgid "Pin Code: " +msgstr "Codice Pin" + +msgid "Pin code successfully setup" +msgstr "Codice pin impostato con successo" + +msgid "Code accepted" +msgstr "Codice accettato" + +msgid "Invalid Code !" +msgstr "Codice non valido !" + +msgid "Please enter pin code first" +msgstr "Per favore inserisci prima un codice Pin" + +msgid "Recording protected, enter pin code first" +msgstr "Registrazione protetta, inserisci prima il codice pin" + +msgid "channel is protected" +msgstr "Canale protetto" + +msgid "broadcast is protected" +msgstr "Trasmissione protetta" + +msgid "is protected" +msgstr "è protetta" + +msgid "Pin code" +msgstr "" + +msgid "Skip protected channel silent" +msgstr "Salta i canali protetti in modo silenzioso" + +msgid "Hide protected menus" +msgstr "Nascondi menu protetti" + +msgid "Hide protected plugins" +msgstr "Nascondi plugin protetti" + +msgid "Hide protected recordings" +msgstr "Nascondi registrazioni protette" + +msgid "Open menu after pin request" +msgstr "Apri menu dopo richiesta Pin" + +msgid "Pin inactivity time [min]" +msgstr "Tempo inattività Pin [min]" + +msgid "Autoprotection of recordings" +msgstr "Protezione automatica registrazioni" + +msgid "Log Level [0-5]" +msgstr "" + +msgid "Ignoring invalid pin" +msgstr "Ignora pin non valido" diff --git a/po/ru_RU.po b/po/ru_RU.po new file mode 100644 index 0000000..848a9e8 --- /dev/null +++ b/po/ru_RU.po @@ -0,0 +1,170 @@ +# VDR plugin language source file. +# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> +# This file is distributed under the same license as the VDR package. +# Vyacheslav Dikonov <sdiconov@mail.ru>, 2004 +# +msgid "" +msgstr "" +"Project-Id-Version: VDR 1.5.7\n" +"Report-Msgid-Bugs-To: <see README>\n" +"POT-Creation-Date: 2013-05-22 11:28+0200\n" +"PO-Revision-Date: 2013-05-22 10:37+0200\n" +"Last-Translator: Vyacheslav Dikonov <sdiconov@mail.ru>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Setup" +msgstr "" + +msgid "Add current channel to protection list" +msgstr "´ÞÑÐÒØâì âÕÚãéØÙ ÚÐÝÐÛ Ò ÑÛÞÚ. áßØáÞÚ" + +msgid "Add current broadcast to protection list" +msgstr "´ÞÑÐÒØâì âÕÚãéãî àÐÔØÞßÕàÕÔÐçã Ò ÑÛÞÚ. áßØáÞÚ" + +msgid "Edit channel locks" +msgstr "ÀÕÔÐÚâØàÞÒÐâì ÑÛÞÚØàÞÒÚã ÚÐÝÐÛÐ" + +msgid "Edit broadcast locks" +msgstr "ÀÕÔÐÚâØàÞÒÐâì ÑÛÞÚØàÞÒÚã àÐÔØÞßÕàÕÔÐçØ" + +msgid "Edit plugin locks" +msgstr "" + +msgid "Edit menu locks" +msgstr "" + +msgid "Unlock setup" +msgstr "" + +msgid "Lock setup" +msgstr "" + +msgid "Activate childlock" +msgstr "°ÚâØÒØàÞÒÐâì ÑÛÞÚØàÞÒÚã" + +msgid "Activated pin protection" +msgstr "°ÚâØÒØàÞÒÐâì ÑÛÞÚØàÞÒÚã" + +msgid "Please setup a pin code first!" +msgstr "" + +msgid "Protected channels" +msgstr "·ÐÑÛÞÚØàÞÒÐÝÝëÕ ÚÐÝÐÛë" + +msgid "Protected broadcasts" +msgstr "·ÐÑÛÞÚØàÞÒÐÝÝëÕ àÐÔØÞßÕàÕÔÐçØ" + +msgid "Plugin protections" +msgstr "" + +msgid "Menu protections" +msgstr "" + +msgid "locked" +msgstr "" + +msgid "unlocked" +msgstr "" + +msgid "already in list" +msgstr "ãÖÕ Ò áßØáÚÕ" + +msgid "added to protection list" +msgstr "ÔÞÑÐÒÛÕÝÞ Ò áßØáÞÚ ÑÛÞÚØàÞÒÚØ" + +msgid "Edit" +msgstr "ÀÕÔÐÚâØàÞÒÐâì" + +msgid "On/Off" +msgstr "" + +msgid "Add" +msgstr "´ÞÑÐÒØâì" + +msgid "Delete" +msgstr "ÃÔÐÛØâì" + +msgid "Remove entry?" +msgstr "ÚÐÝÐÛ?" + +msgid "Name" +msgstr "" + +msgid "Lock active" +msgstr "±ÛÞÚØàÞÒÚÐ ÐÚâØÒÝÐ" + +msgid "Keyword" +msgstr "" + +msgid "Search mode" +msgstr "" + +msgid "Start" +msgstr "" + +msgid "Stop" +msgstr "" + +msgid "Setup your pin code: " +msgstr "" + +msgid "Pin Code: " +msgstr "¿ØÝ ÚÞÔ" + +msgid "Pin code successfully setup" +msgstr "" + +msgid "Code accepted" +msgstr "" + +msgid "Invalid Code !" +msgstr "" + +msgid "Please enter pin code first" +msgstr "" + +msgid "Recording protected, enter pin code first" +msgstr "¿ÞÖÐÛãÙáâÐ ÒÒÕÔØâÕ áÝÐçÐÛÐ ßØÝ ÚÞÔ" + +msgid "channel is protected" +msgstr "ÚÐÝÐÛ ×ÐÑÛÞÚØàÞÒÐÝ" + +msgid "broadcast is protected" +msgstr "àÐÔØÞßÕàÕÔÐçÐ ×ÐÑÛÞÚØàÞÒÐÝÐ" + +msgid "is protected" +msgstr "" + +msgid "Pin code" +msgstr "" + +msgid "Skip protected channel silent" +msgstr "¿àÞßãáâØâì ×ÐéØéÕÝÝëÙ ÚÐÝÐÛ âØåÞ" + +msgid "Hide protected menus" +msgstr "" + +msgid "Hide protected plugins" +msgstr "" + +msgid "Hide protected recordings" +msgstr "" + +msgid "Open menu after pin request" +msgstr "" + +msgid "Pin inactivity time [min]" +msgstr "ÂÐÙÜÕà ÝÕÐÚâØÒÝÞáâØ ßØÝ [ÜØÝãâ]" + +msgid "Autoprotection of recordings" +msgstr "" + +msgid "Log Level [0-5]" +msgstr "" + +msgid "Ignoring invalid pin" +msgstr "¸ÓÝÞàØàÞÒÐâì ÝÕÒÕàÝëÙ ßØÝ" @@ -0,0 +1,77 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 29.01.2006, horchi + */ + +#include <stdio.h> +#include <sys/types.h> +#include <regex.h> + +#include "rep.h" +#include "def.h" + +//************************************************************************** +// Regular Expression Searching +//************************************************************************** + +int rep(const char* string, const char* expression, Option options) +{ + const char* tmpA; + const char* tmpB; + + return rep( string, expression, tmpA, tmpB, options); +} + + +int rep(const char* string, const char* expression, const char*& s_location, + Option options) +{ + const char* tmpA; + + return rep( string, expression, s_location, tmpA, options); +} + + +int rep(const char* string, const char* expression, const char*& s_location, + const char*& e_location, Option options) +{ + regex_t reg; + regmatch_t rm; + int status; + int opt = 0; + + // Vorbereiten von reg fuer die Expressionsuche mit regexec + // Flags: REG_EXTENDED = Use Extended Regular Expressions + // REG_ICASE = Ignore case in match. + + reg.re_nsub = 0; + + // Options umwandeln + if (options & repUseRegularExpression) + opt = opt | REG_EXTENDED; + if (options & repIgnoreCase) + opt = opt | REG_ICASE; + + if (regcomp( ®, expression, opt) != 0) + return fail; + + // Suchen des ersten Vorkommens von reg in string + + status = regexec( ®, string, 1, &rm, 0); + regfree(®); + + if (status != 0) + return fail; + + // Suche erfolgreich => + // Setzen der ermittelten Start- und Endpositionen + + s_location = (char*)(string + rm.rm_so); + e_location = (char*)(string + rm.rm_eo); + + return success; +} + @@ -0,0 +1,31 @@ +/* + * pin.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * Date: 28.01.2006, horchi + */ + +//*************************************************************************** + +#ifndef __REP_H__ +#define __REP_H__ + +//*************************************************************************** + +enum Option +{ + repUseRegularExpression = 1, + repIgnoreCase = 2 +}; + +int rep(const char* string, const char* expression, Option options = repUseRegularExpression); + +int rep(const char* string, const char* expression, + const char*& s_location, Option options = repUseRegularExpression); + +int rep(const char* string, const char* expression, const char*& s_location, + const char*& e_location, Option options = repUseRegularExpression); + +//*************************************************************************** +#endif diff --git a/scripts/cut.sh b/scripts/cut.sh new file mode 100755 index 0000000..3b4a1db --- /dev/null +++ b/scripts/cut.sh @@ -0,0 +1,14 @@ +# +# Copy FSK protection of the PIN plugin when cutting a protected recording +# + +if [ $1 == "edited" ]; then + target_recording="$2" + source_recording=`echo $2 | sed s/"%"/""/ ` + protection_file="$source_recording/protection.fsk" + + if [ -e "$protection_file" ]; then + cp "$protection_file" "$target_recording/" + fi +fi + diff --git a/scripts/fskcheck-demo.sh b/scripts/fskcheck-demo.sh new file mode 100755 index 0000000..02aa17e --- /dev/null +++ b/scripts/fskcheck-demo.sh @@ -0,0 +1,23 @@ + + +./fskcheck check + +case "$?" in + 0) + echo "check went wrong" + ;; + + 1) + echo "not protected" + ;; + + 2) + echo "protected" + ./fskcheck info "Can't execute script due to pin protection" + ;; + + *) + echo "unexpected return code" + ;; + +esac diff --git a/scripts/fskprotect.sh b/scripts/fskprotect.sh new file mode 100755 index 0000000..8e9a78b --- /dev/null +++ b/scripts/fskprotect.sh @@ -0,0 +1,34 @@ + +fskcheck check + +if [ $? != 1 ]; then + fskcheck info "Please enable pin protection first" + exit 1 +fi + +if [ "$1" == "protect" ]; then + + if [ -f $2/protection.fsk ]; then + fskcheck info "Recording was already protected!" + exit 1 + fi + + touch $2/protection.fsk + fskcheck info "Recording now protected!" + +fi + +if [ "$1" == "unprotect" ]; then + + if [ ! -f $2/protection.fsk ]; then + echo fskcheck info "Recording was not protected!" + exit 1 + fi + + rm -f $2/protection.fsk + fskcheck info "Removed protection of recording!" + +fi + +exit 0 + diff --git a/scripts/getSetupMenues b/scripts/getSetupMenues new file mode 100755 index 0000000..ea46edd --- /dev/null +++ b/scripts/getSetupMenues @@ -0,0 +1,8 @@ + +cat $1 | awk 'BEGIN { insidecom=0; } + /[<][!][-][-]/ { insidecom=1; } + /[-][-][>]/ { insidecom=0; } + /^[^-]/ { if (!insidecom) { printf( "%s\n", $0); begin=0 } }' | \ +egrep "<(system|menu|command) " | sed s/"^.* name=\""/""/ | sed s/"\".*"/""/ | sort | uniq | awk '{ printf("%s:no:0000:2359:%s:exact\n", $0, $0) }' + + diff --git a/setupmenu.c b/setupmenu.c new file mode 100644 index 0000000..4d77382 --- /dev/null +++ b/setupmenu.c @@ -0,0 +1,139 @@ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/menuitems.h> +#include "setupmenu.h" +#include <ctype.h> // isdigit + +//*************************************************************************** +// Object +//*************************************************************************** + +PinSetupMenu::PinSetupMenu() +{ + static const char* trProtectionModes[cPinPlugin::apmCount] = { 0 }; + + hidePinCode = yes; + // hidePinCode = no; + + if (hidePinCode) + { + for (int i = 0; i < cPinPlugin::sizePinCode; i++) + pinCode[i] = '*'; + + pinCode[cPinPlugin::sizePinCode] = 0; + } + else + { + strcpy(pinCode, cPinPlugin::pinCode); + } + + skipChannelSilent = cPinPlugin::skipChannelSilent; + pinResetTime = cPinPlugin::pinResetTime; + autoMenuOpen = cPinPlugin::autoMenuOpen; + autoProtectionMode = cPinPlugin::autoProtectionMode; + hideProtectedMenus = cPinPlugin::hideProtectedMenus; + hideProtectedPlugins = cPinPlugin::hideProtectedPlugins; + hideProtectedRecordings = cPinPlugin::hideProtectedRecordings; + + // translate protection modes + + if (!trProtectionModes[0]) + for (int i = 0; i < cPinPlugin::apmCount; i++) + trProtectionModes[i] = tr(cPinPlugin::autoProtectionModes[i]); + + if (hidePinCode) + Add(new cMenuEditStrItem(tr("Pin code"), pinCode, cPinPlugin::sizePinCode+TB, "0123456789*")); + else + Add(new cMenuEditNumItem(tr("Pin code"), pinCode, cPinPlugin::sizePinCode, false)); + + Add(new cMenuEditBoolItem(tr("Skip protected channel silent"), &skipChannelSilent)); + Add(new cMenuEditBoolItem(tr("Hide protected menus"), &hideProtectedMenus)); + Add(new cMenuEditBoolItem(tr("Hide protected plugins"), &hideProtectedPlugins)); + Add(new cMenuEditBoolItem(tr("Hide protected recordings"), &hideProtectedRecordings)); + Add(new cMenuEditBoolItem(tr("Open menu after pin request"), &autoMenuOpen)); + Add(new cMenuEditIntItem(tr("Pin inactivity time [min]"), &pinResetTime, 0, 5*60)); // max 5 hour + Add(new cMenuEditStraItem(tr("Autoprotection of recordings"), &autoProtectionMode, + cPinPlugin::apmCount, trProtectionModes)); + Add(new cMenuEditIntItem(tr("Log Level [0-5]"), &logLevel, 0, 5)); +} + +PinSetupMenu::~PinSetupMenu() +{ + // nothing yet +} + +//*************************************************************************** +// Store +//*************************************************************************** + +void PinSetupMenu::Store(void) +{ + int i = 0; + int pinValid = yes; + + if (hidePinCode) + { + int pinChanged = no; + + // store only numerical pin codes + + for (i = 0; i < cPinPlugin::sizePinCode; i++) + { + if (pinCode[i] != '*') + { + pinChanged = yes; + break; + } + } + + if (pinChanged) + { + i = 0; + + while (pinCode[i]) + { + if (!isdigit(pinCode[i++])) + { + i--; + pinCode[i] = 0; + break; + } + } + + if (i < 2) + { + Skins.Message(mtError, tr("Ignoring invalid pin")); + pinValid = no; + } + } + else + pinValid = no; + } + + if (pinValid) + { + strncpy(cPinPlugin::pinCode, pinCode, cPinPlugin::sizePinCode); + cPinPlugin::pinCode[cPinPlugin::sizePinCode] = 0; + SetupStore("pinCode", cPinPlugin::pinCode); + } + + cPinPlugin::skipChannelSilent = skipChannelSilent; + cPinPlugin::pinResetTime = pinResetTime; + cPinPlugin::autoMenuOpen = autoMenuOpen; + cPinPlugin::autoProtectionMode = autoProtectionMode; + + cPinPlugin::hideProtectedMenus = hideProtectedMenus; + cPinPlugin::hideProtectedPlugins = hideProtectedPlugins; + cPinPlugin::hideProtectedRecordings = hideProtectedRecordings; + + SetupStore("skipChannelSilent", skipChannelSilent); + SetupStore("hideProtectedMenus", hideProtectedMenus); + SetupStore("hideProtectedPlugins", hideProtectedPlugins); + SetupStore("hideProtectedRecordings", hideProtectedRecordings); + SetupStore("pinResetTime", pinResetTime); + SetupStore("autoMenuOpen", autoMenuOpen); + SetupStore("autoProtectionMode", autoProtectionMode); +} diff --git a/setupmenu.h b/setupmenu.h new file mode 100644 index 0000000..7b70944 --- /dev/null +++ b/setupmenu.h @@ -0,0 +1,42 @@ + +#ifndef __PINSETUTMENU_H_ +#define __PINSETUTMENU_H_ + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include <vdr/plugin.h> +#include "pin.h" + +//*************************************************************************** +// Pin Setup Menu +//*************************************************************************** + +class PinSetupMenu : public cMenuSetupPage +{ + + public: + + PinSetupMenu(); + ~PinSetupMenu(); + + protected: + + void Store(void); + + // data + + char pinCode[cPinPlugin::sizePinCode+TB]; + int skipChannelSilent; + int pinResetTime; + int autoMenuOpen; + int autoProtectionMode; + int hidePinCode; + int hideProtectedMenus; + int hideProtectedPlugins; + int hideProtectedRecordings; +}; + +//*************************************************************************** +#endif // __PINSETUTMENU_H_ @@ -0,0 +1,198 @@ + + +#include <sys/msg.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <errno.h> +#include <signal.h> + +#include <vdr/tools.h> + +#include "def.h" +#include "talk.h" + +//*************************************************************************** +// Statics +//*************************************************************************** + +static int fTimeout = no; + +//************************************************************************* +// Timeout-Handler +//************************************************************************* + +void timeoutHandler(...) +{ + fTimeout = true; +} + +//*************************************************************************** +// Object +//*************************************************************************** + +Talk::Talk() +{ + struct msgbuf* theMsg = (struct msgbuf*)buffer; + + header = (Header*)theMsg->mtext; + message = theMsg->mtext + sizeof(Header); + receiverID = na; + msgID = na; + timeout = 30; + opened = no; +} + +Talk::~Talk() +{ + if (opened) + { + if (msgctl(msgID, IPC_RMID, 0) < 0) + tell(eloAlways, "Error: Closing message queue failed, '%s'", strerror(errno)); + } +} + +//*************************************************************************** +// Init +//*************************************************************************** + +int Talk::init() +{ + return success; +} + +//*************************************************************************** +// Open +//*************************************************************************** + +int Talk::open(long port) +{ + if ((msgID = msgget(0xd8000000 + port, IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) + { + tell(eloAlways, "Creating of message queue failed, error was '%s'", strerror(errno)); + + return fail; + } + + opened = yes; + + return success; +} + +//*************************************************************************** +// Wait +//*************************************************************************** + +int Talk::wait() +{ + int result; + int status = success; + struct itimerval oldTimer, newTimer; + struct sigaction oldAction, newAction; + struct msgbuf* theMsg = (struct msgbuf*)buffer; + + // clear message buffer + + memset(buffer, 0, sizeBuffer); + + // set timeout-handler + + if (timeout) + { + // init register + + memset(&newAction, 0, sizeof(newAction)); + memset(&newTimer, 0, sizeof(newTimer)); + + // set timer + + newTimer.it_value.tv_sec = timeout; + setitimer(ITIMER_REAL, &newTimer, &oldTimer); + + // set handler + + newAction.sa_handler = (void(*)(int))timeoutHandler; + sigaction(SIGALRM, &newAction, &oldAction); + + // clear timeout-flag + + fTimeout = no; + } + + // receive auf + + if ((result = msgrcv(msgID, theMsg, sizeBuffer, 0, 0)) < 0) + { + if (!fTimeout) + { + if (errno == EINTR) + return wrnSysInterrupt; + else if (errno == E2BIG) + return errMessageToBig; + else if (errno != ENOMSG) + tell(eloAlways, "Receiving message failed, errno (%d), '%s'", + errno, strerror(errno)); + } + + status = fail; + } + + if (timeout) + { + sigaction(SIGALRM, &oldAction, 0); + setitimer(ITIMER_REAL, &oldTimer,0); + } + + if (status == success) + { + event = header->event; + from = header->sender; + } + + return status; +} + +//*************************************************************************** +// Send +//*************************************************************************** + +int Talk::send(long to, int event, const char* msg) +{ + struct msgbuf* theMsg = (struct msgbuf*)buffer; + int sizeMsg = sizeof(Header); + int receiverID; + + if (!msg) msg = ""; + + if (strlen(msg) > sizeBuffer - sizeof(Header) - sizeof(theMsg->mtype)) + { + tell(eloAlways, "Message to big, aborting"); + return fail; + } + + // try to get the receiver ID + + if ((receiverID = msgget(0xd8000000 + to, 0)) < 0) + { + tell(eloAlways, "Attach to message queue failed, '%s'", strerror(errno)); + return fail; + } + + strcpy(message, msg); + sizeMsg += strlen(message)+1; + + theMsg->mtype = 1; + header->sender = msgID; + header->receiver = receiverID; + header->event = event; + header->type = 0; + + if (msgsnd(header->receiver, theMsg, sizeMsg, 0) < 0) + { + tell(eloAlways, "send failed, '%s'", strerror(errno)); + return fail; + } + + tell(eloAlways, "send to (%ld) succeeded", header->receiver); + + return success; +} @@ -0,0 +1,97 @@ +//*************************************************************************** +/* + * fskcheck.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: talk.h,v 1.1 2007/01/13 07:52:27 root Exp $ + */ +//*************************************************************************** + +//*************************************************************************** +// Includes +//*************************************************************************** + +#include "def.h" + +//*************************************************************************** +// Class Talk +//*************************************************************************** + +class Talk +{ + public: + + // declarations + + enum Error + { + errMessageServiceFirst = -1000, + + errMessageToBig, + + wrnSysInterrupt, + wrnNoMessage + }; + + enum Size + { + sizeBuffer = 1000 + }; + + enum Event + { + evtUnknown = na, + + evtCheck, // = 0 + evtShow, // = 1 + evtAsk, // = 2 + evtConfirm, // = 3 + evtAbort, // = 4 + evtAnswer, // = 5 + evtExit // = 6 + }; + + struct Header + { + long sender; + long receiver; + int event; + int type; // eMessageType + }; + + // object + + Talk(); + ~Talk(); + + // functions + + int wait(); + int init(); + int send(long to, int event, const char* msg = 0); + int open(long port); + + int isOpen() { return opened; } + long getTimeout() { return timeout; } + int getEvent() { return event; } + long getFrom() { return from; } + const char* getMessage() { return message; } + + void setTimeout(long t) { timeout = t; } + + protected: + + // data + + int receiverID; + int msgID; + char buffer[sizeBuffer]; + char* message; + Header* header; + long timeout; + int opened; + + int event; + long from; +}; @@ -0,0 +1,13 @@ +#include "def.h" + + +int main() +{ + char ct[sizeHHMM+TB]; + long theTime = DT::lNow(); + + printf("lNow = '%s'; daylight %d; timezone %ld hours\n", DT::int2Hhmm(theTime, ct), daylight, timezone/tfSecondsPerHour); + + return 0; +} + |