diff options
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | HISTORY | 13 | ||||
-rw-r--r-- | Makefile | 110 | ||||
-rw-r--r-- | README | 26 | ||||
-rw-r--r-- | i18n.c | 456 | ||||
-rw-r--r-- | i18n.h | 16 | ||||
-rw-r--r-- | menuitemtext.c | 36 | ||||
-rw-r--r-- | menuitemtext.h | 22 | ||||
-rw-r--r-- | menusetup.c | 169 | ||||
-rw-r--r-- | menusetup.h | 29 | ||||
-rw-r--r-- | menuundelete.c | 545 | ||||
-rw-r--r-- | menuundelete.h | 67 | ||||
-rw-r--r-- | undelete.c | 485 | ||||
-rw-r--r-- | undelete.h | 107 | ||||
-rw-r--r-- | vdrtools.c | 173 | ||||
-rw-r--r-- | vdrtools.h | 25 |
16 files changed, 2619 insertions, 0 deletions
@@ -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,13 @@ +VDR Plugin 'playlist' Revision History +-------------------------------------- + +2004-10-08: Version 0.0.1 + +- Initial revision. + +2004-10-10: Version 0.0.2 + +* Bug fixes +- TriggerUpdate for VDR > 1.3.11 (thanks to Brougs78@vdrportal.de) +- Update counter in listviews +- Confirm options diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..42360c6 --- /dev/null +++ b/Makefile @@ -0,0 +1,110 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id: Makefile 1.8 2002/12/13 14:54:14 kls 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 = undelete + +### The version number of this plugin (taken from the main source file): + +VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g') + +### The C++ compiler and options: + +CXX ?= g++ +CXXFLAGS ?= -O2 -Wall -Woverloaded-virtual + +### Allow user defined options to overwrite defaults: + +-include $(VDRDIR)/Make.config + +### The directory environment: + +DVBDIR = ../../../../DVB +VDRDIR = ../../.. +LIBDIR = ../../lib +TMPDIR = /tmp + +### The version number of VDR (taken from VDR's "config.h"): + +VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g') +VDRVERSNUM = $(shell grep 'define VDRVERSNUM ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g') + +### DEFINES += -DVDRVERSNUM=$(VDRVERSNUM) + +### 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 += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' +DEFINES += -D_GNU_SOURCE + +### Test Elchi + +#ELCHIVERSION = $(shell grep 'define ELCHIAIOVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g') + +ifeq ($(shell test -f $(VDRDIR)/theme.h ; echo $$?),0) + DEFINES += -DHAVE_ELCHI +endif + +### Test wareagle-patch + +ifeq ($(shell test -f $(VDRDIR)/iconpatch.h ; echo $$?),0) + DEFINES += -DHAVE_ICONPATCH +endif + +#for more debug lines +DEFINES += -DUND_Debug1 +DEFINES += -DUND_Debug2 +DEFINES += -DUND_Debug3 +CXXFLAGS += -g + +### The object files (add further files here): + +OBJS = $(PLUGIN).o menuundelete.o menusetup.o i18n.o vdrtools.o + +ifeq ($(shell test $(VDRVERSNUM) -lt 10307 ; echo $$?),0) + OBJS += menuitemtext.o +endif + +### 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) + +### Targets: + +all: libvdr-$(PLUGIN).so + +libvdr-$(PLUGIN).so: $(OBJS) + $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ + @cp $@ $(LIBDIR)/$@.$(VDRVERSION) + +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 $(OBJS) $(DEPFILE) *.so *.tgz core* *~ @@ -0,0 +1,26 @@ +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Hardy Flor <HFlor@web.de> + +Project's homepage (vdr): www.cadsoft.de/people/kls/vdr +Project's homepage (playlist): www.fast-info.de/vdr/undelete + +See the file COPYING for license information. + +undelete-plugin version 0.0.2 + +This plugin allow the undelete from deleted recordings for a short time + +If the VDR idle then erase all deleted recordings! + +Handling: + +You can build the list from plugin-setup (by 'Display deleted recordings now') or is the +mainmenuentry visible from then mainmenu. + +red - open a directory (if a directory selected) +green - salvage a recording +yellow - purge a recording +blue - show summary (if a recording with summary selected) + +back - close the menu @@ -0,0 +1,456 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: i18n.c 0.2 2004/10/10 12:23:20 hflor Exp $ + */ + +#include "i18n.h" + +const tI18nPhrase Phrases[] = { + { " -m --visible_in_mainmenu Show the plugin in the mainmenu\n -M --hide_in_mainmenu Hide the plugin in the mainmenu\n You can start the Plugin in the setupmenu\n -n Name --mainmenu_name=Name Select Name for entry in the mainmenu\n (set also -m)\n -c --confirm_del_rec show confirmation for delete recording\n -C --not_confirm_del_rec delete recording without confirmation\n -d --confirm_del_dir show confirmation for delete directory\n -D --not_confirm_del_dir delete directory without confirmation\n -s --confirm_undel_rec show confirmation for undelete recording\n -S --not_confirm_undel_rec undelete recording without confirmation\n -t --confirm_undel_dir show confirmation for undelete directory\n -T --not_confirm_undel_dir undelete directory without confirmation\n -v --verbose Enable more logging\n -V --noverbose Disable more loggig\n --nosetup_commandline Hide the 'Preferr Command Line Parameter'\n form setup-menu\n @config-file Read also parameters from this file\n note: recording means deleted recordings (there not show in VDR)", + " -m --visible_in_mainmenu Plugin wird im Hautmenü angezeigt\n -M --hide_in_mainmenu kein Eintrag im Hauptmenü für das Plugin\n es kann über das Setup-Menü gestartet werden\n -n Name --mainmenu_name=Name Name für den Eintrag im Hauptmenü\n (diese Option setzt auch -m)\n -c --confirm_del_rec Bestätigung für das Löschen von Aufnahmen\n -C --not_confirm_del_rec keine Bestätigung (löschen Aufnahmen)\n -d --confirm_del_dir Bestätigung beim Löschen von Verzeichnissen\n -D --not_confirm_del_dir keine Bestätigung (löschen Verzeichnissen)\n -s --confirm_undel_rec Bestätigung Wiederherstellung von Aufnahmen\n -S --not_confirm_undel_rec keine Best. Wiederherstellung von Aufnahmen\n -t --confirm_undel_dir Bestätigung Wiederherstellung von Verzei.\n -T --not_confirm_undel_dir keine Best. Wiederherstellung von Verzei.\n -v --verbose erweiterte Protokollierung aktivieren\n -V --noverbose keine erweiterte Protokollierung\n --nosetup_commandline Option 'Kommandozeile hat Vorrang'\n im Setup-Menü verbergen\n @config-file Komandozeilenoptionen auch aus der angegebenen\n Datei lesen\n\n Hinweis: Mit Aufnahmen sind hier die gelöschten Aufnahmen gemeint", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + + { "Undelete", + "Wiederherst.", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Deleted Recordings", + "Gelöschte Aufnahmen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "undelete for recordings", + "Wiederherstellung gelöschter Aufnahmen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "DelRec", + "Löschung", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "HelpKeys", + "Hilfstasten", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "UnDelRec", + "Wiederherstellung", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "unknow", + "unbekannt", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Display$please wait ...", + "bitte warten ...", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Display$prepare recording display...", + "Listenanzeige wird vorbereitet...", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Display$remove empty directories...", + "Entferne leere Verzeichnisse...", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Error$Recording with the same name exists!", + "Aufnahme mit selben Namen ist vorhanden!", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Menu$Undelete recordings", + "Aufnahmen wiederherstellen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Question$Delete recording definitive?", + "Aufnahme endgültig löschen?", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Question$Delete recordings in diretory definitive?", + "Aufnahmen in Verzeichnis endgültig löschen?", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Question$Undelete recording?", + "Aufnahme wiederherstellen?", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Question$Undelete recordings in directory?", + "Aufnahmen in Verzeichnis wiederherstellen?", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Confirm delete deleted recordings", + "Aufnahme löschen bestätigen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Confirm delete directories", + "Verzeichnisse löschen bestätigen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Confirm undelete deleted recordings", + "Wiederherstellung Aufn. bestätigen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Confirm undelete directories", + "Wiederherstellung Verz. bestätigen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Display deleted recordings now", + "Gelöschte Aufnahmen jetzt anzeigen", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$ Name for Mainmenu", + " Eintragname im Hauptmenü", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Preferr Command Line Parameter", + "Kommandozeile hat Vorrang", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Verbose Log Mode", + "Ausführliche Protokollierung", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { "Setup$Visible in Mainmenu", + "Im Hauptmenü sichtbar", + "",// TODO Slovenski + "",// TODO Italiano + "",// TODO Nederlands + "",// TODO Português + "",// TODO Français + "",// TODO Norsk + "",// TODO suomi + "",// TODO Polski + "",// TODO Español + "",// TODO Ellinika + "",// TODO Svenska + "",// TODO Romaneste + "",// TODO Magyar + "",// TODO Català + }, + { NULL } + }; @@ -0,0 +1,16 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: i18n.h 0.1 2004/10/08 02:03:31 hflor Exp $ + */ + +#ifndef _I18N__H +#define _I18N__H + +#include <vdr/i18n.h> + +extern const tI18nPhrase Phrases[]; + +#endif //_I18N__H diff --git a/menuitemtext.c b/menuitemtext.c new file mode 100644 index 0000000..e093086 --- /dev/null +++ b/menuitemtext.c @@ -0,0 +1,36 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuitemtext.c 0.1 2004/10/08 02:03:31 hflor Exp $ + */ + +#include "menuitemtext.h" +#include <vdr/menuitems.h> + +// --- cMenuText ------------------------------------------------------------- + +cMenuItemText::cMenuItemText(const char *Title, const char *Text, eDvbFont Font) +:cOsdMenu(Title) +{ + Add(new cMenuTextItem(Text, 1, 2, Setup.OSDwidth - 2, MAXOSDITEMS, clrWhite, clrBackground, Font)); +} + +eOSState cMenuItemText::ProcessKey(eKeys Key) +{ + eOSState state = cOsdMenu::ProcessKey(Key); + + switch (state) + { + case osUnknown: switch (NORMALKEY(Key)) + { + case kOk: state = osBack; + break; + default: break; + } + break; + default: break; + } + return state; +} diff --git a/menuitemtext.h b/menuitemtext.h new file mode 100644 index 0000000..8217f95 --- /dev/null +++ b/menuitemtext.h @@ -0,0 +1,22 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuitemtext.h 0.1 2004/10/08 02:03:31 hflor Exp $ + */ + +#ifndef __MENUITEMTEXT_H +#define __MENUITEMTEXT_H + +#include <vdr/osd.h> + +// --- cMenuText ------------------------------------------------------------- + +class cMenuItemText : public cOsdMenu { +public: + cMenuItemText(const char *Title, const char *Text, eDvbFont Font = fontOsd); + virtual eOSState ProcessKey(eKeys Key); + }; + +#endif // __MENUITEMTEXT_H diff --git a/menusetup.c b/menusetup.c new file mode 100644 index 0000000..ddf9613 --- /dev/null +++ b/menusetup.c @@ -0,0 +1,169 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menusetup.c 0.2 2004/10/10 12:23:20 hflor Exp $ + */ + +#include "menusetup.h" +#include "undelete.h" +#include "menuundelete.h" +#include "i18n.h" +#include "vdrtools.h" +#include <vdr/plugin.h> + +// --- cMenuSetupUndelete ------------------------------------------------------- + +cMenuSetupUndelete::cMenuSetupUndelete(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupUndelete::cMenuSetupUndelete", plugin_name); +#endif + store = false; + + #define StoreValue(T) T.o = T.u + #define StoreValueFile(T) strcpy(T.o, T.u) + + // var pos7 + StoreValue (commandline_preference); + StoreValue (confirmdel); + StoreValue (confirmdeldir); + StoreValue (confirmundel); + StoreValue (confirmundeldir); + StoreValueFile (mainmenu_name); + StoreValue (mainmenu_visible); + StoreValue (verbose); + + #undef StoreValue + #undef StoreValueFile + + Set(); +} + +cMenuSetupUndelete::~cMenuSetupUndelete(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupUndelete::~cMenuSetupUndelete store=%s", plugin_name, store ? "true" : "false"); +#endif + if (!store) + { + + #define RestoreValue(T) T.u = T.o + #define RestoreValueFile(T) strcpy(T.u, T.o) + + // var pos8 + RestoreValue (commandline_preference); + RestoreValue (confirmdel); + RestoreValue (confirmdeldir); + RestoreValue (confirmundel); + RestoreValue (confirmundeldir); + RestoreValueFile (mainmenu_name); + RestoreValue (mainmenu_visible); + RestoreValue (verbose); + + #undef RestoreValue + #undef RestoreValueFile + } +} + +void cMenuSetupUndelete::Store(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupUndelete::Store", plugin_name); +#endif + + #define SaveValue(T, N) if (T.u != T.o) SetupStore(N, T.u); + #define SaveValueFile(T, N) if (strcmp(T.u, T.o)) SetupStore(N, T.u); + + // var pos9 + SaveValue (commandline_preference, "commandline"); + SaveValue (confirmdel, "confdel"); + SaveValue (confirmdeldir, "confdeldir"); + SaveValue (confirmundel, "confundel"); + SaveValue (confirmundeldir, "confundeldir"); + SaveValueFile (mainmenu_name, "name"); + SaveValue (mainmenu_visible, "visible"); + SaveValue (verbose, "verbose"); + + #undef SaveValue + #undef SaveValueFile + + store = true; +} + +void cMenuSetupUndelete::Set(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupUndelete::Set Current=%d", plugin_name, Current()); +#endif + int current = Current(); + Clear(); + + #define DisplayLine(T) !T.h && (!commandline_preference.u || !T.c) + + Add(new cOsdItem (tr("Setup$Display deleted recordings now"), osUser1)); + if (DisplayLine(commandline_preference)) + Add(new cMenuEditBoolItem(tr("Setup$Preferr Command Line Parameter"), &commandline_preference.u)); + if (DisplayLine(mainmenu_visible)) + Add(new cMenuEditBoolItem(tr("Setup$Visible in Mainmenu"), &mainmenu_visible.u)); + if (DisplayLine(mainmenu_name) && mainmenu_visible.u) + Add(new cMenuEditStrItem (tr("Setup$ Name for Mainmenu"), mainmenu_name.u, sizeof(mainmenu_name.u), tr(FileNameChars))); + if (DisplayLine(confirmdel)) + Add(new cMenuEditBoolItem(tr("Setup$Confirm delete deleted recordings"), &confirmdel.u)); + if (DisplayLine(confirmdeldir)) + Add(new cMenuEditBoolItem(tr("Setup$Confirm delete directories"), &confirmdeldir.u)); + if (DisplayLine(confirmundel)) + Add(new cMenuEditBoolItem(tr("Setup$Confirm undelete deleted recordings"), &confirmundel.u)); + if (DisplayLine(confirmundeldir)) + Add(new cMenuEditBoolItem(tr("Setup$Confirm undelete directories"), &confirmundeldir.u)); + if (DisplayLine(verbose)) + Add(new cMenuEditBoolItem(tr("Setup$Verbose Log Mode"), &verbose.u)); + + #undef DisplayLine + +#ifdef PL_Debug2 + dsyslog("%s: Count=%d", plugin_name, Count()); +#endif + SetCurrent(Get(current)); +} + +eOSState cMenuSetupUndelete::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuSetupUndelete::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + + int m_commandline_preference = commandline_preference.u; + int m_mainmenu_visible = mainmenu_visible.u; + + eOSState state = cMenuSetupPage::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuSetupUndelete::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (m_commandline_preference != commandline_preference.u || m_mainmenu_visible != mainmenu_visible.u) + { + Set(); + Display(); + } + + switch (state) + { + case osUser1: state = AddSubMenu(new cMenuUndelete); + break; + default: break; + } + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuSetupUndelete::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} diff --git a/menusetup.h b/menusetup.h new file mode 100644 index 0000000..3d052b4 --- /dev/null +++ b/menusetup.h @@ -0,0 +1,29 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menusetup.h 0.2 0.1 2004/10/08 02:03:31 hflor Exp $ + */ + +#ifndef __MENUSETUP_H +#define __MENUSETUP_H + +#include <vdr/menu.h> +#include <vdr/menuitems.h> + +// --- cMenuSetupUndelete ------------------------------------------------------- + +class cMenuSetupUndelete : public cMenuSetupPage { +private: + int store; +protected: + virtual void Store(void); +public: + cMenuSetupUndelete(void); + virtual ~cMenuSetupUndelete(void); + virtual void Set(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +#endif //__MENUSETUP_H diff --git a/menuundelete.c b/menuundelete.c new file mode 100644 index 0000000..e059797 --- /dev/null +++ b/menuundelete.c @@ -0,0 +1,545 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuundelete.c 0.2 2004/10/10 12:23:20 hflor Exp $ + */ + +#include "menuundelete.h" +#if VDRVERSNUM < 10307 +#include "menuitemtext.h" +#endif +#include "undelete.h" +#include "i18n.h" +#include "vdrtools.h" +#include <vdr/interface.h> +#include <vdr/videodir.h> +#include <vdr/remote.h> +#include <vdr/recording.h> +#ifdef HAVE_ICONPATCH +#include <vdr/iconpatch.h> +#endif + +#ifndef RECEXT +#define RECEXT ".rec" +#define DELEXT ".del" +#endif + +// --- cMenuRecordingSelectItem -------------------------------------------------------- + +cMenuRecordingSelectItem::cMenuRecordingSelectItem(cRecording *Recording, int Level) +{ + filename = strdup(Recording->FileName()); + totalEntries = newEntries = 0; + start = Recording->start; + SetText(Recording->Title('\t', true, Level)); + if ((isdir = (*Text() == '\t'))) + name = strdup(Text() + 2); + else + name = strdup(Recording->Name()); + level = Level; +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelectItem::cMenuRecordingSelectItem FileName=%s Level=%d Name=%s", plugin_name, filename, level, name); +#endif +} + +cMenuRecordingSelectItem::~cMenuRecordingSelectItem() +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelectItem::~cMenuRecordingSelectItem FileName=%s Name=%s", plugin_name, filename, name); +#endif + FREENULL(filename); + FREENULL(name); +} + +bool cMenuRecordingSelectItem::operator< (const cListObject &ListObject) +{ + cMenuRecordingSelectItem *temp = (cMenuRecordingSelectItem *)&ListObject; + if (isdir != temp->isdir) + return isdir; + if (isdir) + return strcasecmp(name, temp->name) < 0; + return start < temp->start; +} + +void cMenuRecordingSelectItem::IncrementCounter(bool New) +{ + totalEntries++; + if (New) + newEntries++; + char *buffer = NULL; + asprintf(&buffer, "%d\t%d\t%s", totalEntries, newEntries, name); + SetText(buffer, false); +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelectItem::IncrementCounter FileName=%s New=%s Buffer=%s", plugin_name, filename, New ? "true" : "false", buffer); +#endif +} + +void cMenuRecordingSelectItem::RefreshCounter(void) +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelectItem::RefeshCounter FileName=%s", plugin_name, filename); +#endif + if (isdir) + { + char *dirname = DirName(); + if (dirname) + { + totalEntries = 0; + newEntries = 0; + for (cRecording *recording = DeletedRecordings.First(); recording; recording = DeletedRecordings.Next(recording)) + if (strncmp(recording->FileName(), dirname, strlen(dirname)) == 0) + IncrementCounter(recording->IsNew()); + free(dirname); + } + } +} + +char *cMenuRecordingSelectItem::DirName(void) +{ + if (isdir) + { + char *temp = strdup(filename); + char *last = temp + strlen(VideoDirectory) + 1; + for (int i = level; *last && i >= 0; i--) + { + last = strchr(last, '/'); + if (!last) + break; + last++; + } + if (last) + *last = 0; + return temp; + } else + return NULL; +} + +// --- cMenuRecordingSelect -------------------------------------------------------- + +cMenuRecordingSelect::cMenuRecordingSelect(const char *Base, int Level, bool OpenSubMenus) +:cOsdMenu(Base ? Base : tr("Deleted Recordings"), 6, 6, 6) +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelect::cMenuRecordingSelect Base=%s Level=%d OpenSubMenus=%s", plugin_name, Base, Level, OpenSubMenus ? "true" : "false"); +#endif +#if VDRVERSNUM < 10307 +#ifdef HAVE_ELCHI + Interface->Status(tr("Display$prepare recording display..."), Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(tr("Display$prepare recording display...")); +#endif + Interface->Flush(); +#else + STATUS(tr("Display$prepare recording display...")); +#endif + base = Base ? strdup(Base) : NULL; + level = Level; + Display(); + cMenuRecordingSelectItem *LastItem = NULL; + char *LastItemText = NULL; + for (cRecording *recording = DeletedRecordings.First(); recording; recording = DeletedRecordings.Next(recording)) + { + if (!Base || (strstr(recording->Name(), Base) == recording->Name() && recording->Name()[strlen(Base)] == '~')) + { + cMenuRecordingSelectItem *Item = new cMenuRecordingSelectItem(recording, level); + if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) + { + Add(Item); + LastItem = Item; + FREENULL(LastItemText); + LastItemText = strdup(LastItem->Text()); + } else + delete Item; + if (LastItem) + { + if (LastItem->IsDirectory()) + LastItem->IncrementCounter(recording->IsNew()); + } + } + } + free(LastItemText); + LastItem = Current() < 0 ? NULL : (cMenuRecordingSelectItem *)Get(Current()); + Sort(); + if (LastItem) + { + SetCurrent(LastItem); + if (OpenSubMenus && Open(true) == osContinue) + return; + } else + SetCurrent(First()); + SetHelpKeys(); +} + +cMenuRecordingSelect::~cMenuRecordingSelect() +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelect::~cMenuRecordingSelect Base=%s Level=%d", plugin_name, base, level); +#endif + FREENULL(base); +} + +void cMenuRecordingSelect::SetHelpKeys(void) +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuRecordingSelect::SetHelpKeys", plugin_name); +#endif + + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri) + { + if (ri->IsDirectory()) + SetHelp(tr("Open"), tr("Undelete"), tr("Delete"), NULL); + else + { + cRecording *recording = GetRecording(ri); + SetHelp(NULL, tr("Undelete"), tr("Delete"), (recording && recording->Summary() && *recording->Summary()) ? tr("Summary") : NULL); + } + } else + { + SetHelp(NULL); + } +} + +cRecording *cMenuRecordingSelect::GetRecording(cMenuRecordingSelectItem *Item) +{ + cRecording *recording = DeletedRecordings.GetByName(Item->FileName()); + if (!recording) + ERROR(tr("Error while accessing recording!")); + return recording; +} + +eOSState cMenuRecordingSelect::Open(bool OpenSubMenus) +{ + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri) + { + if (ri->IsDirectory()) + { + const char *t = ri->Name(); + char *buffer = NULL; + if (base) + { + asprintf(&buffer, "%s~%s", base, t); + t = buffer; + } + AddSubMenu(new cMenuRecordingSelect(t, level + 1, OpenSubMenus)); + FREENULL(buffer); + return osContinue; + } + } + return osUnknown; +} + +eOSState cMenuRecordingSelect::UnDelete(void) +{ + if (HasSubMenu() || Count() == 0) + return osContinue; + if (WorkFilename) + { + esyslog("%s: Error previous jobs not completed (%s)", plugin_name, WorkFilename); + return osContinue; + } + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri && ((!ri->IsDirectory() && (!confirmundel.u || Interface->Confirm(tr("Question$Undelete recording?")))) || (ri->IsDirectory() && (!confirmundeldir.u || Interface->Confirm(tr("Question$Undelete recordings in directory?")))))) + { + if (ri->IsDirectory()) + WorkFilename = ri->DirName(); // WorkFilename is NULL see up + else + WorkFilename = strdup(ri->FileName()); + cRemote::Put((eKeys)kUnDelRec); + cOsdMenu::Del(Current()); + Display(); + if (!Count()) + return osBack; + } + return osContinue; +} + +eOSState cMenuRecordingSelect::Delete(void) +{ + if (HasSubMenu() || Count() == 0) + return osContinue; + if (WorkFilename) + { + esyslog("%s: Error previous jobs not completed (%s)", plugin_name, WorkFilename); + return osContinue; + } + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri && ((!ri->IsDirectory() && (!confirmdel.u || Interface->Confirm(tr("Question$Delete recording definitive?")))) || (ri->IsDirectory() && (!confirmdeldir.u || Interface->Confirm(tr("Question$Delete recordings in diretory definitive?")))))) + { + if (ri->IsDirectory()) + WorkFilename = ri->DirName(); // WorkFilename is NULL see up + else + WorkFilename = strdup(ri->FileName()); + cRemote::Put((eKeys)kDelRec); + cOsdMenu::Del(Current()); + Display(); + if (!Count()) + return osBack; + } + return osContinue; +} + +eOSState cMenuRecordingSelect::Summary(void) +{ + if (HasSubMenu() || Count() == 0) + return osContinue; + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri && !ri->IsDirectory()) + { + cRecording *recording = GetRecording(ri); + if (recording && recording->Summary() && *recording->Summary()) +#if VDRVERSNUM >= 10307 + return AddSubMenu(new cMenuText(tr("Summary"), recording->Summary())); +#else + return AddSubMenu(new cMenuItemText(tr("Summary"), recording->Summary())); +#endif + } + return osContinue; +} + +eOSState cMenuRecordingSelect::ProcessKey(eKeys Key) +{ +#ifdef UND_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuRecordingSelect::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + bool hSubMenu = HasSubMenu(); + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef UND_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuRecordingSelect::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + + if (hSubMenu && !HasSubMenu()) + { + if (Key == kYellow || Key == kGreen) + { + cOsdMenu::Del(Current()); + if (!Count()) + state = osBack; + } + if (state == osContinue) + { + for (cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)First(); ri; ri = (cMenuRecordingSelectItem *)Next(ri)) + ri->RefreshCounter(); + Display(); + } + } + + switch (state) + { + case osUnknown: switch (Key) + { + case kBack: state = osBack; + case kOk: + case kRed: state = Open(); + break; + case kGreen: state = UnDelete(); + break; + case kYellow: state = Delete(); + break; + case kBlue: state = Summary(); + break; + default: break; + } + break; + default: break; + } + if (!HasSubMenu() && Key != kNone && !WorkFilename) + { + SetHelpKeys(); + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri) + { + ri->RefreshCounter(); + RefreshCurrent(); + } + } + +#ifdef UND_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuRecordingSelect::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} + +// --- cMenuUndelete -------------------------------------------------------- + +cMenuUndelete::cMenuUndelete(void) +:cOsdMenu(tr("Deleted Recordings"), 6, 6) +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuUndelete::cMenuUndelete", plugin_name); +#endif +#if VDRVERSNUM < 10307 +#ifdef HAVE_ELCHI + Interface->Status(tr("Display$prepare recording display..."), Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(tr("Display$prepare recording display...")); +#endif + Interface->Flush(); +#else + STATUS(tr("Display$prepare recording display...")); +#endif +#if VDRVERSNUM >= 10311 + DeletedRecordings.Load(); +#else + DeletedRecordings.Load(true); +#endif + AddSubMenu(new cMenuRecordingSelect); + PurgeRecording = false; + SalvageRecording = false; +} + +cMenuUndelete::~cMenuUndelete() +{ +#ifdef UND_Debug2 + dsyslog("%s: cMenuUndelete::~cMenuUndelete", plugin_name); +#endif + if (PurgeRecording) + { +#if VDRVERSNUM < 10307 +#ifdef HAVE_ELCHI + Interface->Status(tr("Display$remove empty directories..."), Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(tr("Display$remove empty directories...")); +#endif + Interface->Flush(); +#else + STATUS(tr("Display$remove empty directories...")); +#endif + RemoveEmptyVideoDirectories(); + } + DeletedRecordings.Clear(); + +#if VDRVERSNUM >= 10311 + if (SalvageRecording) + Recordings.TriggerUpdate(); +#endif +} + +eOSState cMenuUndelete::ProcessKey(eKeys Key) +{ +#ifdef UND_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuUndelete::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef UND_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuUndelete::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (state == osUnknown) + { + cRecording *recording = NULL; + bool processrecording = false; + if (WorkFilename && (Key == kDelRec || Key == kUnDelRec)) + { +#if VDRVERSNUM < 10307 +#ifdef HAVE_ELCHI + Interface->Status(tr("Display$please wait ..."), Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(tr("Display$please wait ...")); +#endif + Interface->Flush(); +#else + STATUS(tr("Display$please wait ...")); +#endif + } + switch (Key) + { + case kUnDelRec: state = osContinue; + if (WorkFilename) + { + for (recording = DeletedRecordings.First(); recording; recording = DeletedRecordings.Next(recording)) + if (strncmp(recording->FileName(), WorkFilename, strlen(WorkFilename)) == 0) + { + if (verbose.u) + isyslog("%s: undelete recording=%s", plugin_name, recording->FileName()); + char *NewName = strdup(recording->FileName()); + char *ext = strrchr(NewName, '.'); + if (strcmp(ext, DELEXT) == 0) + { + strncpy(ext, RECEXT, strlen(ext)); + if (access(NewName, F_OK) == 0) + { + ERROR(tr("Error$Recording with the same name exists!")); + if (verbose.u) + isyslog("%s: Recording with the same name exists!", plugin_name); + } else + { + if (!RenameVideoFile(recording->FileName(), NewName)) + esyslog("%s: Error while rename deleted recording (%s) to (%s)", plugin_name, recording->FileName(), NewName); + SalvageRecording = true; + } + } + free(NewName); + cRemote::Put((eKeys)kUnDelRec); + DeletedRecordings.Del(recording); + processrecording = true; + break; + } + } + break; + case kDelRec: state = osContinue; + if (WorkFilename) + { + for (recording = DeletedRecordings.First(); recording; recording = DeletedRecordings.Next(recording)) + if (strncmp(recording->FileName(), WorkFilename, strlen(WorkFilename)) == 0) + { + if (verbose.u) + isyslog("%s: purge deleted recording=%s", plugin_name, recording->FileName()); + if (!RemoveVideoFile(recording->FileName())) + esyslog("%s: Error while remove deleted recording (%s)", plugin_name, recording->FileName()); + PurgeRecording = true; + cRemote::Put((eKeys)kDelRec); + DeletedRecordings.Del(recording); + processrecording = true; + break; + } + } + break; + case kHelpKeys: if (!HasSubMenu()) + state = osBack; + default: break; + } + if (WorkFilename && !processrecording) + { + FREENULL(WorkFilename); // restore Helpkeys in cMenuRecordingSelect::ProcessKey +#if VDRVERSNUM < 10307 +#ifdef HAVE_ELCHI + Interface->Status(NULL, Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(NULL); +#endif + Interface->Flush(); +#else + STATUS(NULL); +#endif + cRemote::Put((eKeys)kHelpKeys); + } + } + if (!WorkFilename && !HasSubMenu()) + state = osBack; + +#ifdef UND_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuUndelete::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} diff --git a/menuundelete.h b/menuundelete.h new file mode 100644 index 0000000..9373d37 --- /dev/null +++ b/menuundelete.h @@ -0,0 +1,67 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuundelete.h 0.2 2004/10/10 12:23:20 hflor Exp $ + */ + +#ifndef __MENUUNDELETE_H +#define __MENUUNDELETE_H + +#include <vdr/menu.h> +#include <vdr/menuitems.h> + +// --- cMenuRecordingSelectItem -------------------------------------------------------- + +class cMenuRecordingSelectItem : public cOsdItem { +private: + char *filename; + char *name; + int level; + time_t start; + bool isdir; + int totalEntries; + int newEntries; +public: + cMenuRecordingSelectItem(cRecording *Recording, int Level); + ~cMenuRecordingSelectItem(void); + virtual bool operator< (const cListObject &ListObject); + void IncrementCounter(bool New); + void RefreshCounter(void); + const char *FileName(void) { return filename; } + char *DirName(void); + const char *Name(void) { return name; } + bool IsDirectory(void) { return isdir; } + }; + +// --- cMenuRecordingSelect -------------------------------------------------------- + +class cMenuRecordingSelect : public cOsdMenu { +private: + char *base; + int level; + void SetHelpKeys(void); + cRecording *GetRecording(cMenuRecordingSelectItem *Item); + eOSState Open(bool OpenSubMenus = false); + eOSState UnDelete(void); + eOSState Delete(void); + eOSState Summary(void); +public: + cMenuRecordingSelect(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false); + ~cMenuRecordingSelect(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +// --- cMenuUndelete -------------------------------------------------------- + +class cMenuUndelete : public cOsdMenu { +private: +public: + cMenuUndelete(void); + ~cMenuUndelete(void); + virtual eOSState ProcessKey(eKeys Key); + }; + + +#endif //__MENUUNDELETE_H diff --git a/undelete.c b/undelete.c new file mode 100644 index 0000000..386fe6e --- /dev/null +++ b/undelete.c @@ -0,0 +1,485 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: undelete.c 0.2 2004/10/10 12:23:20 hflor Exp $ + */ + +#include "undelete.h" +#include "menuundelete.h" +#include "menusetup.h" +#include "i18n.h" +#include "vdrtools.h" +#include <getopt.h> +#include <ctype.h> +#include <vdr/recording.h> + +static const char *VERSION = "0.0.2"; +static const char *DESCRIPTION = "undelete for recordings"; + +// Global variables that control the overall behaviour: + +// var pos2 +tParamFile undeleteconfigfile = { false, false, false, "undelete.conf", "undelete.conf" }; +tParamInt commandline_preference = { false, false, false, true }; +tParamInt confirmdel = { false, false, false, true }; +tParamInt confirmdeldir = { false, false, false, true }; +tParamInt confirmundel = { false, false, false, true }; +tParamInt confirmundeldir = { false, false, false, true }; +tParamFile mainmenu_name = { false, false, false, "Undelete recordings" }; +tParamInt mainmenu_visible = { false, false, false, false }; +tParamInt verbose = { false, false, false, false, true }; + +char plugin_name[MaxFileName] = "Undelete"; +bool PurgeRecording = false; +bool SalvageRecording = false; +#if VDRVERSNUM >= 10311 +cRecordings DeletedRecordings(true); +#else +cRecordings DeletedRecordings; +#endif +char *WorkFilename = NULL; + +void DisplaySetings(void) +{ + #define WriteSource(T) plugin_name, T.r ? 'r' : ' ', T.c ? 'c' : ' ' + #define IsDefault(T) WriteSource(T), T.u == T.d ? '*' : ' ' + #define IsDefaultFile(T) WriteSource(T), strcmp(T.u, T.d) ? ' ' : '*' + #define BoolValue(T) IsDefault(T), T.u ? "yes" : "no" + + // var pos3 + if (verbose.u) + { + isyslog("%s: commandline_preference = [ %c%c%c ] %s", BoolValue(commandline_preference)); + isyslog("%s: mainmenu_visible = [ %c%c%c ] %s", BoolValue(mainmenu_visible)); + if (mainmenu_visible.u) + isyslog("%s: mainmenu_name = [ %c%c%c ] %s", IsDefaultFile(mainmenu_name), mainmenu_name.u); + isyslog("%s: confirm undelete = [ %c%c%c ] %s", BoolValue(confirmundel)); + isyslog("%s: confirm undelete directory = [ %c%c%c ] %s", BoolValue(confirmundeldir)); + isyslog("%s: confirm delete = [ %c%c%c ] %s", BoolValue(confirmdel)); + isyslog("%s: confirm delete directory = [ %c%c%c ] %s", BoolValue(confirmdeldir)); + isyslog("%s: verbose = [ %c%c%c ] %s", BoolValue(verbose)); + } + +#ifdef UND_Debug1 + if (!verbose.u) + { + dsyslog("%s: commandline_preference = [ %c%c%c ] %s", BoolValue(commandline_preference)); + dsyslog("%s: mainmenu_visible = [ %c%c%c ] %s", BoolValue(mainmenu_visible)); + if (mainmenu_visible.u) + dsyslog("%s: mainmenu_name = [ %c%c%c ] %s", IsDefaultFile(mainmenu_name), mainmenu_name.u); + dsyslog("%s: confirm undelete = [ %c%c%c ] %s", BoolValue(confirmundel)); + dsyslog("%s: confirm undelete directory = [ %c%c%c ] %s", BoolValue(confirmundeldir)); + dsyslog("%s: confirm delete = [ %c%c%c ] %s", BoolValue(confirmdel)); + dsyslog("%s: confirm delete directory = [ %c%c%c ] %s", BoolValue(confirmdeldir)); + dsyslog("%s: verbose = [ %c%c%c ] %s", BoolValue(verbose)); + } +#endif + + #undef WriteSource + #undef IsDefault + #undef IsDefaultFile + #undef BoolValue +} + +void ExpandEnvironment(tParamFile *FileStruc) +{ +#ifdef UND_Debug2 + dsyslog("%s: ExpandEnvironment text=%s", plugin_name, FileStruc->u); +#endif + char *s; + char *p; + strn0cpy(FileStruc->e, FileStruc->u, sizeof(FileStruc->e)); + while ((s = strstr(FileStruc->e, "$(")) || (s = strstr(FileStruc->e, "${"))) + { + char c = *(s + 1) == '(' ? ')' : '}'; + p = strchr(s, c); // search closing ) or } + if (p) + { + *p++ = 0; + *s = 0; + s += 2; + char *e = getenv(s); + if (e) + { + char *buffer = NULL; + asprintf(&buffer, "%s%s%s", FileStruc->e, e, p); + strn0cpy(FileStruc->e, buffer, sizeof(FileStruc->e)); + FREENULL(buffer); + } else + { + esyslog("%s: environmentvariable '%s' not found path=%s", plugin_name, s, FileStruc->u); + FileStruc->e[0] = 0; + } + } else + { + esyslog("%s: missing ')' after '$(' path=%s", plugin_name, FileStruc->u); + FileStruc->e[0] = 0; + } + } + while ((p = strstr(FileStruc->e, "//"))) + strcpy(p, p + 1); +#ifdef UND_Debug2 + dsyslog("%s: ExpandEnvironment return=%s", plugin_name, FileStruc->e); +#endif +} + +// --- cPluginUndelete ---------------------------------------------------------- + +cPluginUndelete::cPluginUndelete(void) +{ +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::cPluginUndelete", plugin_name); +#endif + // Initialize any member variables here. + // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL + // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! +} + +cPluginUndelete::~cPluginUndelete() +{ +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::~cPluginUndelete", plugin_name); +#endif + // Clean up after yourself! +} + +bool cPluginUndelete::ProcessArg(int argc, char *argv[]) +{ + int c; + static struct option long_options[] = { + { "confirm_del_rec", no_argument, NULL, 'c' }, + { "not_confirm_del_rec", no_argument, NULL, 'C' }, + { "confirm_del_dir", no_argument, NULL, 'd' }, + { "not_confirm_del_dir", no_argument, NULL, 'D' }, + { "visible_in_mainmenu", no_argument, NULL, 'm' }, + { "hide_in_mainmenu", no_argument, NULL, 'M' }, + { "mainmenu_name", required_argument, NULL, 'n' }, + { "confirm_undel_rec", no_argument, NULL, 's' }, + { "not_confirm_undel_rec", no_argument, NULL, 'S' }, + { "confirm_undel_dir", no_argument, NULL, 't' }, + { "not_confirm_undel_dir", no_argument, NULL, 'T' }, + { "verbose", no_argument, NULL, 'v' }, + { "noverbose", no_argument, NULL, 'V' }, + { "nosetup_commandline", no_argument, NULL, 1 }, + { "ns_commandline", no_argument, NULL, 1 }, + { NULL } + }; + + if (argc >= 1) + strn0cpy(plugin_name, argv[0], sizeof(plugin_name)); + + for (c = 1; c < argc; c++) + dsyslog("%s: parameter%d=%s", plugin_name, c, argv[c]); + + #define Setvalue(T) T.c = true; T.u + #define SetvalueFile(T) T.c = true; strn0cpy(T.u, optarg, sizeof(T.u)) + + while ((c = getopt_long(argc, argv, "cCdDmMn:sStTvV", long_options, NULL)) != -1) + { + // var pos4 + switch (c) + { + case 1: commandline_preference.h = true; + break; + case 'c': Setvalue(confirmdel) = true; + break; + case 'C': Setvalue(confirmdel) = false; + break; + case 'd': Setvalue(confirmdeldir) = true; + break; + case 'D': Setvalue(confirmdeldir) = false; + break; + case 'm': Setvalue(mainmenu_visible) = true; + break; + case 'M': Setvalue(mainmenu_visible) = false; + break; + case 'n': SetvalueFile(mainmenu_name); + Setvalue(mainmenu_visible) = true; + break; + case 's': Setvalue(confirmundel) = true; + break; + case 'S': Setvalue(confirmundel) = false; + break; + case 't': Setvalue(confirmundeldir) = true; + break; + case 'T': Setvalue(confirmundeldir) = false; + break; + case 'v': Setvalue(verbose) = true; + break; + case 'V': Setvalue(verbose) = false; + break; + default: return false; + } + } + + #undef Setvalue + #undef SetvalueFile + + if (optind < argc && argv[optind][0] == '@') + { + strn0cpy(undeleteconfigfile.u, &argv[optind][1], sizeof(undeleteconfigfile.u)); + optind++; + } + return optind >= argc; +} + +const char *cPluginUndelete::Version(void) +{ + return VERSION; +} + +const char *cPluginUndelete::Description(void) +{ + return tr(DESCRIPTION); +} + +const char *cPluginUndelete::CommandLineHelp(void) +{ + // Return a string that describes all known command line options. column 80 --> | + return tr(" -m --visible_in_mainmenu Show the plugin in the mainmenu\n" + " -M --hide_in_mainmenu Hide the plugin in the mainmenu\n" + " You can start the Plugin in the setupmenu\n" + " -n Name --mainmenu_name=Name Select Name for entry in the mainmenu\n" + " (set also -m)\n" + " -c --confirm_del_rec show confirmation for delete recording\n" + " -C --not_confirm_del_rec delete recording without confirmation\n" + " -d --confirm_del_dir show confirmation for delete directory\n" + " -D --not_confirm_del_dir delete directory without confirmation\n" + " -s --confirm_undel_rec show confirmation for undelete recording\n" + " -S --not_confirm_undel_rec undelete recording without confirmation\n" + " -t --confirm_undel_dir show confirmation for undelete directory\n" + " -T --not_confirm_undel_dir undelete directory without confirmation\n" + " -v --verbose Enable more logging\n" + " -V --noverbose Disable more loggig\n" + " --nosetup_commandline Hide the 'Preferr Command Line Parameter'\n" + " form setup-menu\n" + " @config-file Read also parameters from this file" + "\n" + " note: recording means deleted recordings (there not show in VDR)"); + +/* only for translation: + " -m --visible_in_mainmenu Plugin wird im Hautmenü angezeigt\n" + " -M --hide_in_mainmenu kein Eintrag im Hauptmenü für das Plugin\n" + " es kann über das Setup-Menü gestartet werden\n" + " -n Name --mainmenu_name=Name Name für den Eintrag im Hauptmenü\n" + " (diese Option setzt auch -m)\n" + " -c --confirm_del_rec Bestätigung für das Löschen von Aufnahmen\n" + " -C --not_confirm_del_rec keine Bestätigung (löschen Aufnahmen)\n" + " -d --confirm_del_dir Bestätigung beim Löschen von Verzeichnissen\n" + " -D --not_confirm_del_dir keine Bestätigung (löschen Verzeichnissen)\n" + " -s --confirm_undel_rec Bestätigung Wiederherstellung von Aufnahmen\n" + " -S --not_confirm_undel_rec keine Best. Wiederherstellung von Aufnahmen\n" + " -t --confirm_undel_dir Bestätigung Wiederherstellung von Verzei.\n" + " -T --not_confirm_undel_dir keine Best. Wiederherstellung von Verzei.\n" + " -v --verbose erweiterte Protokollierung aktivieren\n" + " -V --noverbose keine erweiterte Protokollierung\n" + " --nosetup_commandline Option 'Kommandozeile hat Vorrang'\n" + " im Setup-Menü verbergen\n" + " @config-file Komandozeilenoptionen auch aus der angegebenen\n" + " Datei lesen\n" + "\n" + " Hinweis: Mit Aufnahmen sind hier die gelöschten Aufnahmen gemeint" +*/ + // free: a b e f g h i j k l o p q r u w x y z +} + +bool cPluginUndelete::ProcessArgs(int argc, char *argv[]) +{ + // Implement command line argument processing here if applicable. + return ProcessArg(argc, argv); +} + +bool cPluginUndelete::Start(void) +{ + // Start any background activities the plugin shall perform. + RegisterI18n(Phrases); + +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::Start undeleteconfigfile=%s", plugin_name, undeleteconfigfile.u); +#endif + + char *p; + char *q = strdup(ConfigDirectory("")); + asprintf(&p, "%s%s%s", q, *(q + strlen(q) - 1) == '/' ? "" : "/", undeleteconfigfile.u); + if (!access(undeleteconfigfile.u, F_OK) && !access(undeleteconfigfile.u, R_OK) || !access(p, F_OK) && !access(p, R_OK)) + { + #define MAXARGS 100 + int fargc = 1; + char *fargv[MAXARGS]; + char buffer[MAXPARSEBUFFER]; + bool done; + FILE *f; + + if (!access(undeleteconfigfile.u, F_OK)) + { + f = fopen(undeleteconfigfile.u, "r"); +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::Start open undeleteconfigfile=%s", plugin_name, undeleteconfigfile.u); +#endif + } else + { + f = fopen(p, "r"); +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::Start open undeleteconfigfile=%s", plugin_name, p); +#endif + } + free(p); + free(q); + if (!f) + { + esyslog("%s: ERROR: cannot open config file: [%s]%s", plugin_name, ConfigDirectory(""), undeleteconfigfile.u); + return false; + } + while (fgets(buffer, sizeof(buffer), f) > 0) + { + p = skipspace(stripspace(buffer)); + q = NULL; + done = false; + while (!done) + { + if (!q) + q = p; + switch (*p) + { + case '\\': strcpy(p, p + 1); + if (*p) + p++; + else + { + esyslog("%s: ERROR: missing character after \\", plugin_name); + return false; + } + break; + case '"': + case '\'': if ((p = SkipQuote(p)) == NULL) + return false; + break; + default: if (!*p || isspace(*p)) + { + done = !*p; + *p = 0; + if (q) + { + if (fargc < MAXARGS - 1) + { + if (*q != '#') + fargv[fargc++] = strdup(q); + } else + { + esyslog("%s: ERROR: plugin argument list too long", plugin_name); + return false; + } + q = NULL; + } + } + if (!done) + p = *p ? p + 1 : skipspace(p + 1); + } + } + } + fclose(f); + fargv[0] = strdup(plugin_name); + fargv[fargc] = NULL; + optind = 0; // to reset the getopt() data + if (fargc > 1) + if (!ProcessArg(fargc, fargv)) + { + esyslog("%s: ERROR: cannot parse config file: [%s]%s", plugin_name, ConfigDirectory(""), undeleteconfigfile.u); + return false; + } + while(fargc) free(fargv[--fargc]); + } else + { + free(p); + free(q); + if (strcmp(undeleteconfigfile.u, undeleteconfigfile.d)) + { + esyslog("%s: ERROR: config file not found: [%s]%s", plugin_name, ConfigDirectory(""), undeleteconfigfile.u); + return false; + } else if (verbose.u) + isyslog("%s: INFO: config file not found: [%s]%s", plugin_name, ConfigDirectory(""), undeleteconfigfile.u); + } + + strn0cpy(mainmenu_name.d, tr("Menu$Undelete recordings"), sizeof(mainmenu_name.d)); + + // default parameter --> d_ + // read parameter from commandline --> c_ (data in u_) + // value parameter from config-file --> s_ + // read parameter from config-file --> r_ + // paramater used --> u_ + + #define SetParam(T) { if (!T.c || (!commandline_preference.u && T.r)) T.u = (!T.c && !T.r) ? T.d : T.s; } + #define SetParamFile(T) { if (!T.c || (!commandline_preference.u && T.r)) strcpy(T.u, (!T.c && !T.r) ? T.d : T.s); } + + commandline_preference.u = commandline_preference.r ? commandline_preference.s : commandline_preference.d; + + // var pos5 + SetParamFile (undeleteconfigfile); + SetParam (confirmdel); + SetParam (confirmdeldir); + SetParam (confirmundel); + SetParam (confirmundeldir); + SetParamFile (mainmenu_name); + SetParam (mainmenu_visible); + SetParam (verbose); + + #undef SetParam + #undef SetParamFile + + if (verbose.u) + isyslog("%s: Start", plugin_name); + DisplaySetings(); + return true; +} + +const char *cPluginUndelete::MainMenuEntry(void) +{ + return mainmenu_visible.u ? mainmenu_name.u : NULL; +} + +cOsdObject *cPluginUndelete::MainMenuAction(void) +{ +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::MainMenuAction", plugin_name); +#endif + return new cMenuUndelete; +} + +cMenuSetupPage *cPluginUndelete::SetupMenu(void) +{ +#ifdef UND_Debug1 + dsyslog("%s: cPluginUndelete::SetupMenu", plugin_name); +#endif + return new cMenuSetupUndelete; +} + + +bool cPluginUndelete::SetupParse(const char *Name, const char *Value) +{ + #define SetParam(T) { T.r = true; T.s = strtol(Value, NULL, 0); } + #define SetParamFile(T) { T.r = true; strn0cpy(T.s, Value, sizeof(T.s)); } + + // Parse your own setup parameters and store their values. + dsyslog("%s: Setupparameter %s=%s", plugin_name, Name, Value); + // var pos6 + + if (!strcasecmp(Name, "commandline")) SetParam (commandline_preference) + else if (!strcasecmp(Name, "confdel")) SetParam (confirmdel) + else if (!strcasecmp(Name, "confdeldir")) SetParam (confirmdeldir) + else if (!strcasecmp(Name, "confundel")) SetParam (confirmundel) + else if (!strcasecmp(Name, "confundeldir")) SetParam (confirmundeldir) + else if (!strcasecmp(Name, "name")) SetParamFile (mainmenu_name) + else if (!strcasecmp(Name, "visible")) SetParam (mainmenu_visible) + else if (!strcasecmp(Name, "verbose")) SetParam (verbose) + else + return false; + return true; + + #undef SetParam + #undef SetParamChar + #undef SetParamFile +} + +VDRPLUGINCREATOR(cPluginUndelete); // Don't touch this! diff --git a/undelete.h b/undelete.h new file mode 100644 index 0000000..0a5aca7 --- /dev/null +++ b/undelete.h @@ -0,0 +1,107 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: undelete.h 0.2 2004/10/10 12:23:20 hflor Exp $ + */ + +#ifndef __UNDELETE_H +#define __UNDELETE_H + +#include <vdr/config.h> +#include <vdr/recording.h> +#include <vdr/plugin.h> + +#define FREENULL(T) { if (T) { free(T); T = NULL; } } +#if VDRVERSNUM >= 10307 +#define MAXOSDTEXTWIDTH 45 +#define AKTOSDTEXTWIDTH 45 +#define ERROR(E) Skins.Message(mtError, E) +#define INFO(I) Skins.Message(mtInfo, I) +#define STATUS(S) Skins.Message(mtStatus, S) +#else +#define MAXOSDTEXTWIDTH MAXOSDWIDTH +#define AKTOSDTEXTWIDTH Setup.OSDwidth +#define ERROR(E) Interface->Error(E) +#define INFO(I) Interface->Info(I) +#endif + +#define kUnDelRec (kNone + 110) +#define kDelRec (kNone + 111) +#define kHelpKeys (kNone + 112) + +// Global variables that control the overall behaviour: + +struct tParamInt { + bool c; // read command line + bool r; // read config file + bool h; // hide in setup menu + int d; // default + int u; // used + int s; // config file + int o; // old value for setup menu + }; + +struct tParamChar { + bool c; // read command line + bool r; // read config file + bool h; // hide in setup menu + char d; // default + char u; // used + char s; // config file + char o; // old value for setup menu + }; + +struct tParamFile { + bool c; // read command line + bool r; // read config file + bool h; // hide in setup menu + char d[MaxFileName]; // default + char u[MaxFileName]; // used + char s[MaxFileName]; // config file + char o[MaxFileName]; // old value for setup menu + char e[MaxFileName]; // expanded name (environment) + }; + +// var pos1 + +extern tParamInt commandline_preference; +extern tParamInt confirmdel; +extern tParamInt confirmdeldir; +extern tParamInt confirmundel; +extern tParamInt confirmundeldir; +extern tParamFile mainmenu_name; +extern tParamInt mainmenu_visible; +extern tParamInt verbose; + +extern char plugin_name[]; +extern bool PurgeRecording; +extern bool SalvageRecording; +extern cRecordings DeletedRecordings; +extern char *WorkFilename; + +void ExpandEnvironment(tParamFile *FileStruc); + +// --- cPluginUndelete ---------------------------------------------------------- + +class cPluginUndelete : public cPlugin { +private: + // Add any member variables or functions you may need here. + bool ProcessArg(int argc, char *argv[]); + +public: + cPluginUndelete(void); + virtual ~cPluginUndelete(); + virtual const char *Version(void); + virtual const char *Description(void); + virtual const char *CommandLineHelp(void); + virtual bool ProcessArgs(int argc, char *argv[]); + virtual bool Start(void); + virtual const char *MainMenuEntry(void); + virtual cOsdObject *MainMenuAction(void); + virtual cMenuSetupPage *SetupMenu(void); + virtual bool SetupParse(const char *Name, const char *Value); + }; + +#endif //__UNDELETE_H diff --git a/vdrtools.c b/vdrtools.c new file mode 100644 index 0000000..84c1d9b --- /dev/null +++ b/vdrtools.c @@ -0,0 +1,173 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: vdrtools.c 0.1 2004/10/08 02:03:31 hflor Exp $ + */ + +#include "vdrtools.h" +#include "undelete.h" +#include "i18n.h" +#include <vdr/menu.h> +#include <vdr/interface.h> + +char *SkipQuote(char *s) +{ + char c = *s; + strcpy(s, s + 1); + while (*s && *s != c) + { + if (*s == '\\') + strcpy(s, s + 1); + if (*s) + s++; + } + if (*s) + { + strcpy(s, s + 1); + return s; + } + esyslog("ERROR: missing closing %c", c); + return NULL; +} + +char *ExchangeChars(char *s, bool ToFileSystem) +{ +// ToFileSystem is not use, only for comatibility with 'ExchangeChars' from 'recording.c' + char *p = s; + while (*p) + { + switch (*p) + { + // mapped characters: + case '_': *p = ' '; + break; + case '/': *p = '~'; + break; + // encodes characters: + case '#': if (strlen(p) > 2) + { + char buf[3]; + sprintf(buf, "%c%c", *(p + 1), *(p + 2)); + unsigned char c = strtol(buf, NULL, 16); + *p = c; + memmove(p + 1, p + 3, strlen(p) - 2); + } + break; + // backwards compatibility: + case '\x01': *p = '\''; + break; + case '\x02': *p = '/'; + break; + case '\x03': *p = ':'; + break; + } + p++; + } + return s; +} + +#ifdef UND_Debug1 +const char *KeyName(eKeys Key) +{ + switch (RAWKEY(Key)) + { + case kUp: return tr("Up"); break; + case kDown: return tr("Down"); break; + case kMenu: return tr("Menu"); break; + case kOk: return tr("Ok"); break; + case kBack: return tr("Back"); break; + case kLeft: return tr("Left"); break; + case kRight: return tr("Right"); break; + case kRed: return tr("Red"); break; + case kGreen: return tr("Green"); break; + case kYellow: return tr("Yellow"); break; + case kBlue: return tr("Blue"); break; + case k0: return "0"; break; + case k1: return "1"; break; + case k2: return "2"; break; + case k3: return "3"; break; + case k4: return "4"; break; + case k5: return "5"; break; + case k6: return "6"; break; + case k7: return "7"; break; + case k8: return "8"; break; + case k9: return "9"; break; + case kPlay: return tr("Play"); break; + case kPause: return tr("Pause"); break; + case kStop: return tr("Stop"); break; + case kRecord: return tr("Record"); break; + case kFastFwd: return tr("FastFwd"); break; + case kFastRew: return tr("FastRew"); break; + case kPower: return tr("Power"); break; + case kChanUp: return tr("ChanUp"); break; + case kChanDn: return tr("ChanDn"); break; + case kVolUp: return tr("VolUp"); break; + case kVolDn: return tr("VolDn"); break; + case kMute: return tr("Mute"); break; + case kSchedule: return tr("Schedule"); break; + case kChannels: return tr("Channels"); break; + case kTimers: return tr("Timers"); break; + case kRecordings: return tr("Recordings"); break; + case kSetup: return tr("Setup"); break; + case kCommands: return tr("Commands"); break; + case kUser1: return tr("User1"); break; + case kUser2: return tr("User2"); break; + case kUser3: return tr("User3"); break; + case kUser4: return tr("User4"); break; + case kUser5: return tr("User5"); break; + case kUser6: return tr("User6"); break; + case kUser7: return tr("User7"); break; + case kUser8: return tr("User8"); break; + case kUser9: return tr("User9"); break; + case kNone: return tr("none"); break; + case kKbd: return tr("Kbd"); break; + case kUnDelRec: return tr("UnDelRec"); break; + case kDelRec: return tr("DelRec"); break; + case kHelpKeys: return tr("HelpKeys"); break; + default: return tr("unknow"); break; + } +} + +const char *OSStateName(eOSState OSState) +{ + switch (OSState) + { + case osUnknown: return "osUnknown"; + case osContinue: return "osContinue"; + case osSchedule: return "osSchedule"; + case osChannels: return "osChannels"; + case osTimers: return "osTimers"; + case osRecordings: return "osRecordings"; + case osPlugin: return "osPlugin"; + case osSetup: return "osSetup"; + case osCommands: return "osCommands"; + case osPause: return "osPause"; + case osRecord: return "osRecord"; + case osReplay: return "osReplay"; + case osStopRecord: return "osStopRecord"; + case osStopReplay: return "osStopReplay"; + case osCancelEdit: return "osCancelEdit"; + case osSwitchDvb: return "osSwitchDvb"; + case osBack: return "osBack"; + case osEnd: return "osEnd"; + case os_User: return "os_User"; + case osUser1: return "osUser1"; + case osUser2: return "osUser2"; + case osUser3: return "osUser3"; + case osUser4: return "osUser4"; + case osUser5: return "osUser5"; + case osUser6: return "osUser6"; + case osUser7: return "osUser7"; + case osUser8: return "osUser8"; + case osUser9: return "osUser9"; + case osUser10: return "osUser10"; +#if VDRVERSNUM < 10307 + case osUser11: return "osUser11"; +#endif + default: return "unknow"; + } + return ""; +} +#endif diff --git a/vdrtools.h b/vdrtools.h new file mode 100644 index 0000000..9f97735 --- /dev/null +++ b/vdrtools.h @@ -0,0 +1,25 @@ +/* + * undelete: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: vdrtools.h 0.1 2004/10/08 02:03:31 hflor Exp $ + */ + +#ifndef __VDRTOOLS_H +#define __VDRTOOLS_H + +#include <vdr/keys.h> +#include <vdr/osd.h> +#include <vdr/osdbase.h> + +char *SkipQuote(char *s); +char *ExchangeChars(char *s, bool ToFileSystem); + +#ifdef UND_Debug1 +const char *KeyName(eKeys Key); +const char *OSStateName(eOSState OSState); +#endif + + +#endif //__VDRTOOLS_H |