diff options
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | HISTORY | 10 | ||||
-rw-r--r-- | Makefile | 110 | ||||
-rw-r--r-- | README | 24 | ||||
-rw-r--r-- | dataplaylist.c | 663 | ||||
-rw-r--r-- | dataplaylist.h | 155 | ||||
-rw-r--r-- | debian/changelog | 11 | ||||
-rw-r--r-- | debian/control | 12 | ||||
-rw-r--r-- | debian/copyright | 8 | ||||
-rw-r--r-- | debian/dirs | 1 | ||||
-rw-r--r-- | debian/docs | 1 | ||||
-rwxr-xr-x | debian/rules | 79 | ||||
-rw-r--r-- | i18n.c | 1594 | ||||
-rw-r--r-- | i18n.h | 16 | ||||
-rw-r--r-- | menucontrol.c | 391 | ||||
-rw-r--r-- | menucontrol.h | 50 | ||||
-rw-r--r-- | menuitemtext.c | 36 | ||||
-rw-r--r-- | menuitemtext.h | 22 | ||||
-rw-r--r-- | menuplaylist.c | 966 | ||||
-rw-r--r-- | menuplaylist.h | 113 | ||||
-rw-r--r-- | menuplaylists.c | 569 | ||||
-rw-r--r-- | menuplaylists.h | 62 | ||||
-rw-r--r-- | menusetup.c | 303 | ||||
-rw-r--r-- | menusetup.h | 32 | ||||
-rw-r--r-- | playlist.c | 608 | ||||
-rw-r--r-- | playlist.h | 163 | ||||
-rw-r--r-- | vdrtools.c | 217 | ||||
-rw-r--r-- | vdrtools.h | 26 |
28 files changed, 6582 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,10 @@ +VDR Plugin 'playlist' Revision History +-------------------------------------- + +2004-09-23: Version 0.0.1 + +- Initial revision. + +2004-10-08: Version 0.0.2 + +* Bug fixes diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..724b018 --- /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 = playlist + +### 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 += -DPL_Debug1 +#DEFINES += -DPL_Debug2 +#DEFINES += -DPL_Debug3 +#CXXFLAGS += -g + +### The object files (add further files here): + +OBJS = $(PLUGIN).o dataplaylist.o menucontrol.o menuplaylist.o menuplaylists.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,24 @@ +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/playlist + +See the file COPYING for license information. + +playlist-plugin version 0.0.2rc3 + +hier kommt noch was ... + +TODO: + +- Komandozeilenoptionen und Konfigurationsdatei fehlen noch +- Markierung in Aufnameauswahl +- Verschiebung in Liste genauer Prüfen (z.Z. kann man Verzeichnisse verschieben --> ist aber nicht gut!) +- Aufnahmenanzeige nicht im richtigen Verzeichnis bei vorheriger Auswahl eines Verzeichnisses mit Unterverzeichnissen +- Aufnahmenanzeige enthält doppelte Einträge +- auf roter taste standartwert anzeigen +- Option für Wiedergabe im Detail-Ansicht +x neue Playlist ohne inhalt auch namen-dialog schließen +- Wenn nur 1 Verzeichniss in PL -> Name für PL übernehmen
\ No newline at end of file diff --git a/dataplaylist.c b/dataplaylist.c new file mode 100644 index 0000000..d462b5b --- /dev/null +++ b/dataplaylist.c @@ -0,0 +1,663 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: dataplaylist.c 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#include <stdlib.h> +#include <unistd.h> +#include "dataplaylist.h" +#include "playlist.h" +#include "i18n.h" +#include "vdrtools.h" +#include <vdr/keys.h> +#include <vdr/tools.h> +#include <vdr/videodir.h> + +// -- cPlaylistMark ----------------------------------------------------------------- + +cPlaylistMark::cPlaylistMark(char *Filename) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistMark::cPlaylistMark Name=%s", plugin_name, Filename); +#endif + filename = Filename ? strdup(Filename) : NULL; +} + +cPlaylistMark::~cPlaylistMark(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistMark::~cPlaylistMark Name=%s", plugin_name, filename); +#endif + FREENULL(filename); +} + +// -- cPlaylistMarkCol ----------------------------------------------------------------- + +cPlaylistMarkCol PlaylistMark; + +// -- cPlaylistRecord ----------------------------------------------------------------- + +cPlaylistRecord::cPlaylistRecord(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::cPlaylistRecord", plugin_name); +#endif + SetName(NULL); + SetDefaults(); + playlist = NULL; +} + +cPlaylistRecord::cPlaylistRecord(cPlaylist *Playlist, char *Filename) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::cPlaylistRecord Filename=%s", plugin_name, Filename); +#endif + playlist = Playlist; + SetName(Filename); + SetDefaults(); +} + +cPlaylistRecord::cPlaylistRecord(cPlaylist *Playlist, cRecording *Recording, cPlaylistRecord *Parent) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::cPlaylistRecord Parent=%s", plugin_name, Parent ? Parent->name : "(null)"); +#endif + playlist = Playlist; + SetName(Recording->FileName()); + parent = Parent; + SetDefaults(Recording); +} + + +cPlaylistRecord::~cPlaylistRecord(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::~cPlaylistRecord [%s]", plugin_name, name); +#endif + FREENULL(filename); + FREENULL(summary); + FREENULL(title); + FREENULL(path); + parent = NULL; // no delete! +} + +void cPlaylistRecord::SetName(const char *Filename) +{ + if (Filename) + { + char *buffer = strdup(Filename + strlen(VideoDirectory) + 1); + +//suche record .. + + buffer = ExchangeChars(buffer, false); + + char *temp = strrchr(buffer, '~'); + if (temp) + { + *temp = 0; + temp = strrchr(buffer, '~'); + } + if (temp) + strn0cpy(name, temp + 1, MaxFileName); + else + strn0cpy(name, buffer, MaxFileName); + path = strdup(buffer); + free(buffer); + filename = strdup(Filename); + isdir = filename[strlen(filename) - 1] == '/'; + } else + { + name[0] = 0; + filename = NULL; + path = NULL; + isdir = false; + } + parent = NULL; +} + +void cPlaylistRecord::SetDefaults(cRecording *Recording) +{ + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + options[i] = parent ? NoYesDefault_defaultRecordDir : NoYesDefault_defaultPlaylist; // Option_playoption is not use + isdel = false; + isnew = false; + isedited = false; + start = 0; + title = NULL; + summary = NULL; + if (!isdir && filename) + if (!CopyFromRecording(Recording)) + ERROR(tr("Error while accessing recording!")); +} + +bool cPlaylistRecord::CopyFromRecording(cRecording *Recording) +{ + cRecording *recording = Recording ? Recording : Recordings.GetByName(filename); + if (recording) + { + isedited = recording->IsEdited(); + isnew = recording->IsNew(); + start = recording->start; + title = strdup(recording->Title('\t', true, recording->HierarchyLevels())); + char *temp = strrchr(title, '\t'); + if (temp) + *temp = 0; + summary = recording->Summary() ? strdup(recording->Summary()) : NULL; + return true; + } + isdel = true; + return false; +} + +void cPlaylistRecord::CopyOptions(cPlaylistRecord *PlaylistRecord) +{ + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + options[i] = PlaylistRecord->options[i]; +} + +bool cPlaylistRecord::Parse(const char *s) +{ + static cPlaylistRecord *lastdir = NULL; + char *namebuf = NULL; + char *filenamebuf = NULL; + int hasparent = false; + int opt1, opt2, opt3; + int fields = sscanf(s, "%a[^:]:%a[^:]:%d:%d:%d:%d:%d:%d:%d:%d:%d[:%d]", &namebuf, + &filenamebuf, + &hasparent, + &isdel, + &options[Option_confirmdeleterecord], + &options[Option_confirmstartnewrecord], + &options[Option_deletefromlist], + &options[Option_deleterecord], + &options[Option_jumpmark], + &opt1, &opt2, &opt3); +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::Parse fields=%d line=%s*", plugin_name, fields, s); +#endif + if (namebuf) + { + strn0cpy(name, namebuf, sizeof(name)); + free(namebuf); + } + FREENULL(filename); + filename = (filenamebuf && !strcasecmp(filenamebuf, "@null@")) ? NULL : filenamebuf; + strreplace(name, '|', ':'); + if (filename) + { + strreplace(filename, '|', ':'); + char *buffer = strdup(filename + strlen(VideoDirectory) + 1); + buffer = ExchangeChars(buffer, false); + char *temp = strrchr(buffer, '~'); + if (temp) + *temp = 0; + path = strdup(buffer); + free(buffer); + isdir = filename[strlen(filename) - 1] == '/'; + if (isdir) + lastdir = this; + else + { + if (lastdir && hasparent) + { + if (strstr(filename, lastdir->filename) == filename) + parent = lastdir; + } + if (!CopyFromRecording()) + esyslog("%s: Error while accessing recording (deleted from playlist) %s", plugin_name, filename); + } + } + if (fields == 12) + { + options[Option_playonlynew] = opt1; + options[Option_searchnewrecord] = opt2; + options[Option_searchrecordsub] = opt3; + } else + { + options[Option_playonlynew] = isdir ? NoYesDefault_defaultPlaylist : NoYesDefault_defaultRecordDir; + options[Option_searchnewrecord] = opt1; + options[Option_searchrecordsub] = opt2; + } + return fields == 11 || fields == 12; +} + +bool cPlaylistRecord::Save(FILE *f) +{ +dsyslog("%s: cPlaylistRecord::Save", plugin_name); + char *buffer = NULL; + bool result = true; + if (!isdel || parent) + { + strreplace(name, ':', '|'); + if (filename) + strreplace(filename, ':', '|'); + asprintf(&buffer, "%s:%s:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n", + name, + filename ? filename : "@null@", + parent ? true : false, + isdel, + options[Option_confirmdeleterecord], + options[Option_confirmstartnewrecord], + options[Option_deletefromlist], + options[Option_deleterecord], + options[Option_jumpmark], + options[Option_playonlynew], + options[Option_searchnewrecord], + options[Option_searchrecordsub]); + + strreplace(name, '|', ':'); + if (filename) + strreplace(filename, '|', ':'); + result = fputs(buffer, f) > 0; + *(buffer + strlen(buffer) - 1) = 0; + if (verbose.u) + isyslog("%s: write line [%s]", plugin_name, buffer); + } +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::Save buffer=%s result=%s", plugin_name, buffer, result ? "true" : "false"); +#endif + FREENULL(buffer); + return result; +} + +bool cPlaylistRecord::DeleteRecord(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecord::DeleteRecord Name=%s Filename=%s", plugin_name, name, filename); +#endif + DeleteRecording(filename, false); + if (playlist && playlist->RecordCol2()) + { + isdel = true; + playlist->RecordCol2()->SetChange(); + } + return true; +} + +int cPlaylistRecord::IndexRec(void) +{ + if (!playlist) + return -1; + int index = 0; + for (cPlaylistRecord *plr = playlist->First_PLR(); plr; plr = playlist->Next_PLR(plr)) + { + if (!plr->isdir && !plr->isdel) + { + index++; + if (plr == this) + return index; + } + } + return -2; +} + +bool cPlaylistRecord::Option(eOptions Select) +{ + if (Select < Option_confirmdeleterecord || Select >= Option_max) + return false; + switch (options[Select]) + { + case NoYesDefault_no: return false; + case NoYesDefault_yes: return true; + case NoYesDefault_defaultRecordDir: if (parent) + return parent->Option(Select); + // no break + case NoYesDefault_defaultPlaylist: if (playlist) + return playlist->Option(Select); + // no break + case NoYesDefault_defaultPlugin: return PL_options[Select].u; + default: return PL_options[Select].d; + } +} + +bool cPlaylistRecord::operator< (const cListObject &ListObject) +{ + return start == ((cPlaylistRecord *)&ListObject)->start ? strcmp(name, ((cPlaylistRecord *)&ListObject)->name) < 0 : start < ((cPlaylistRecord *)&ListObject)->start; +} + +bool cPlaylistRecord::operator!= (const cPlaylistRecord &PlaylistRecordObject) +{ + bool temp; + if (strlen(PlaylistRecordObject.name)) + if (strlen(name)) + temp = strcmp(name, PlaylistRecordObject.name); + else + temp = true; + else + temp = strlen(name); + if (temp) + return true; + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + if (options[i] != PlaylistRecordObject.options[i]) + return true; + return false; +} + +// -- cPlaylistRecordCol ---------------------------------------------------------------- + +cPlaylistRecordCol::cPlaylistRecordCol(cPlaylist *Parent) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecordCol::cPlaylistRecordCol", plugin_name); +#endif + change = false; + parent = Parent; +} + +cPlaylistRecordCol::~cPlaylistRecordCol(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecordCol::~cPlaylistRecordCol", plugin_name); +#endif + parent = NULL; +} + +void cPlaylistRecordCol::DeleteFile() +{ + if (!access(FileName(), F_OK)) + if (remove(FileName()) < 0) + LOG_ERROR_STR(FileName()); +} + +bool cPlaylistRecordCol::SaveWithFilename() +{ +#ifdef PL_Debug1 + dsyslog("%s: cPlaylistRecordCol::SaveWithFilename playlist=%s", plugin_name, parent ? parent->Name() : "(null)"); +#endif + DeleteFile(); + if (!parent || !*parent->Name()) + return false; + char *tempname = NULL; + asprintf(&tempname, "%s%s%s", "playlists.", parent->Name(), ".conf"); + const char *filenew = PluginPlaylist->ExpandPath(tempname); + free(tempname); + + bool result = true; + cSafeFile f(filenew); + if (f.Open()) + { + for(cPlaylistRecord *plr = First(); plr; plr = Next(plr)) + { + if (!plr->Save((FILE *)f)) + { + result = false; + break; + } + } + if (!f.Close()) + result = false; + } else + result = false; + if (result) +// { +// Load(filenew); + change = false; +// } + return result; +} + +bool cPlaylistRecordCol::SearchRecord(const char *Filename) +{ + bool result = false; + for (cPlaylistRecord *plr = First(); plr; plr = Next(plr)) + { + if (strcasecmp(plr->Filename(), Filename) == 0) + { + result = true; + break; + } + } +#ifdef PL_Debug2 + dsyslog("%s: cPlaylistRecordCol::SearchRecord Filename=%s found=%s", plugin_name, Filename, result ? "true" : "false"); +#endif + return result; +} + + +// -- cPlaylistSortCol ---------------------------------------------------------------- + +cPlaylistSortCol PlaylistSort; + +// -- cPlaylist ---------------------------------------------------------------- + +cPlaylist::cPlaylist(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::cPlaylist", plugin_name); +#endif + name[0] = 0; + lastrecord = NULL; + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + options[i] = NoYesDefault_defaultPlugin; + options[Option_playoption1] = PlayOptions_defaultPlugin; + options[Option_playoption2] = PlayOptions_defaultPlugin; + recordcount = 0; + recordnew = 0; + recordcol = new cPlaylistRecordCol(this); +} + +cPlaylist::~cPlaylist(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::~cPlaylist [%s]", plugin_name, name); +#endif + FREENULL(lastrecord); + if (recordcol) + DELETENULL(recordcol); +} + +bool cPlaylist::Parse(const char *s) +{ + char *namebuf = NULL; + char *lastbuf = NULL; + int opt1, opt2, opt3, opt4; + int fields = sscanf(s, "%a[^:]:%a[^:]:%d:%d:%d:%d:%d:%d:%d:%d[:%d][:%d]", &namebuf, + &lastbuf, + &options[Option_confirmdeleterecord], + &options[Option_confirmstartnewrecord], + &options[Option_deletefromlist], + &options[Option_deleterecord], + &options[Option_jumpmark], + &options[Option_playoption1], + &opt1, &opt2, &opt3, &opt4); +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::Parse fields=%d line=%s*", plugin_name, fields, s); +#endif + if (namebuf) + { + strn0cpy(name, namebuf, sizeof(name)); + free(namebuf); + } + FREENULL(lastrecord); + lastrecord = (lastbuf && !strcasecmp(lastbuf, "@null@")) ? NULL : lastbuf; + strreplace(name, '|', ':'); + if (lastrecord) + strreplace(lastrecord, '|', ':'); + if (fields == 12) + { + options[Option_playoption2] = opt1; + options[Option_playonlynew] = opt2; + options[Option_searchnewrecord] = opt3; + options[Option_searchrecordsub] = opt4; + } else + { + options[Option_playoption2] = PlayOptions_defaultPlugin; + options[Option_playonlynew] = NoYesDefault_defaultPlugin; + options[Option_searchnewrecord] = opt1; + options[Option_searchrecordsub] = opt2; + } + return fields == 10 || fields == 12; +} + +bool cPlaylist::Save(FILE *f) +{ + char *buffer = NULL; + strreplace(name, ':', '|'); + if (lastrecord) + strreplace(lastrecord, ':', '|'); + asprintf(&buffer, "%s:%s:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n", + name, + lastrecord ? lastrecord : "@null@", + options[Option_confirmdeleterecord], + options[Option_confirmstartnewrecord], + options[Option_deletefromlist], + options[Option_deleterecord], + options[Option_jumpmark], + options[Option_playoption1], + options[Option_playoption2], + options[Option_playonlynew], + options[Option_searchnewrecord], + options[Option_searchrecordsub]); + strreplace(name, '|', ':'); + if (lastrecord) + strreplace(lastrecord, '|', ':'); + bool result = fputs(buffer, f) > 0; + if (verbose.u) + isyslog("%s: write line [%s]", plugin_name, buffer); +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::Save buffer=%s result=%s", plugin_name, buffer, result ? "true" : "false"); +#endif + free(buffer); + return result; +} + +bool cPlaylist::SearchRecords(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::SearchRecords start", plugin_name); +#endif + bool modifyplaylist = false; + for (cPlaylistRecord *searchdir = recordcol->First(); searchdir; searchdir = recordcol->Next(searchdir)) + { + if (searchdir->IsDir() && searchdir->Option(Option_searchnewrecord)) + { + PlaylistSort.Clear(); + cPlaylistRecord *plr = NULL; + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) + { + if (strstr(recording->FileName(), searchdir->Filename()) == recording->FileName()) + { + const char *next = NULL; + if (!searchdir->Option(Option_searchrecordsub)) + { + const char *test = recording->FileName() + strlen(searchdir->Filename()); + const char *temp = strchr(test, '/'); + if (temp) + next = strchr(temp + 1, '/'); + } + if ((!next || searchdir->Option(Option_searchrecordsub)) && !recordcol->SearchRecord(recording->FileName())) + { + plr = new cPlaylistRecord(this, recording, searchdir); + PlaylistSort.Add(plr); + } + } + } + if (PlaylistSort.Count()) + { + PlaylistSort.Sort(); + cPlaylistRecord *temp = NULL; + cPlaylistRecord *lastrecord = NULL; + for (cPlaylistRecord *testrecord = recordcol->Next(searchdir); PlaylistSort.Count() && testrecord && testrecord->ParentObj() == searchdir; testrecord = recordcol->Next(testrecord)) + { + lastrecord = testrecord; + temp = PlaylistSort.First(); + if (testrecord->Start() > temp->Start()) + { + PlaylistSort.Del(temp, false); + recordcol->Ins(temp, lastrecord); + modifyplaylist = true; + testrecord = temp; // if more then one recording to insert + } + } + for (plr = PlaylistSort.Last(); plr; plr = temp) + { + temp = PlaylistSort.Prev(plr); + PlaylistSort.Del(plr, false); + recordcol->Add(plr, lastrecord); + modifyplaylist = true; + } + } + } + } + CountRecords(); +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::SearchRecords modified=%s count=%d new=%d", plugin_name, modifyplaylist ? "true" : "false", recordcount, recordnew); +#endif + return modifyplaylist; +} + +void cPlaylist::CountRecords(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPlaylist::CountRecords", plugin_name); +#endif + recordcount = 0; + recordnew = 0; + for (cPlaylistRecord *plr = recordcol->First(); plr; plr = recordcol->Next(plr)) + { + if (!plr->IsDirOrDel()) + { + recordcount++; + if (plr->IsNew()) + recordnew++; + } + } +} + +cPlaylistRecord *cPlaylist::Firstnormal_PLR(void) +{ + if (recordcol) + for (cPlaylistRecord *plr = recordcol->First(); plr; plr = recordcol->Next(plr)) + if (!plr->IsDirOrDel()) + return plr; + return NULL; +} + +cPlaylistRecord *cPlaylist::Firstnew_PLR(void) +{ + if (recordcol) + for (cPlaylistRecord *plr = recordcol->First(); plr; plr = recordcol->Next(plr)) + if (!plr->IsDirOrDel()) + if (plr->IsNew()) + return plr; + return NULL; +} + +cPlaylistRecord *cPlaylist::Lastplayed_PLR(void) +{ + if (recordcol && lastrecord) + for (cPlaylistRecord *plr = recordcol->First(); plr; plr = recordcol->Next(plr)) + if (!plr->IsDirOrDel()) + if (strcmp(lastrecord, plr->Filename()) == 0) + return plr; + FREENULL(lastrecord); + return NULL; +} + +bool cPlaylist::operator!= (const cPlaylist &PlaylistObject) +{ + bool temp; + if (strlen(PlaylistObject.name)) + if (strlen(name)) + temp = strcmp(name, PlaylistObject.name); + else + return true; + else + temp = strlen(name); + if (temp) + return true; + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + if (options[i] != PlaylistObject.options[i]) + return true; + return false; +} + +cPlaylistRecord *SelectPLR = NULL; +cPlaylistRecord *PlayedPLR = NULL; + +// -- cPlaylistCol ---------------------------------------------------------------- + +cPlaylistCol PlaylistCol; diff --git a/dataplaylist.h b/dataplaylist.h new file mode 100644 index 0000000..e5e32fe --- /dev/null +++ b/dataplaylist.h @@ -0,0 +1,155 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: dataplaylist.h 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#ifndef __DATAPLAYLIST_H +#define __DATAPLAYLIST_H + +#include <vdr/tools.h> +#include <vdr/interface.h> +#include "playlist.h" + +class cPlaylistMark : public cListObject { +private: + char *filename; +public: + cPlaylistMark(char *Filename); + virtual ~cPlaylistMark(void); + char *Filename(void) { return filename; } + }; + +class cPlaylistMarkCol : public cList<cPlaylistMark> { +private: +public: + }; + +extern cPlaylistMarkCol PlaylistMark; + +class cPlaylist; + +class cPlaylistRecord : public cListObject { + friend class cMenuRecordingEdit; +private: + char name[MaxFileName]; + char *filename; + char *path; + bool isdir; + int isdel; + bool isnew; // copy from cRecording + time_t start; // copy from cRecording + char *title; // copy from cRecording + bool isedited; // copy from cRecording + char *summary; // copy from cRecording + int options[Option_max]; + cPlaylistRecord *parent; + cPlaylist *playlist; + void SetName(const char *Filename); + void SetDefaults(cRecording *Recording = NULL); + bool CopyFromRecording(cRecording *Recording = NULL); +public: + cPlaylistRecord(void); + cPlaylistRecord(cPlaylist *Playlist, char *Filename); + cPlaylistRecord(cPlaylist *Playlist, cRecording *Recording, cPlaylistRecord *Parent); + virtual ~cPlaylistRecord(void); + virtual bool operator< (const cListObject &ListObject); + virtual bool operator!= (const cPlaylistRecord &PlaylistRecordObject); + void CopyOptions(cPlaylistRecord *PlaylistRecord); + bool Parse(const char *s); + bool Save(FILE *f); + bool DeleteRecord(void); + int IndexRec(void); + const char *Name(void) { return &name[0]; } + char *Filename(void) { return filename; } + bool IsNew(void) { return isnew; } + bool IsEdited(void) { return isedited; } + bool IsDir(void) { return isdir; } + bool IsDel(void) { return isdel; } + bool IsDirOrDel(void) { return isdir || isdel; } + time_t Start(void) { return start; } + const char *Title(void) { return title; } + bool Parent(void) { return parent; } + cPlaylistRecord *ParentObj(void) { return parent; } + cPlaylist *Playlist(void) { return playlist; } + void Playlist(cPlaylist *PlayList) { playlist = PlayList; } + void SetDel(void) { isdel = true; } + void SetNew(bool Value) { isnew = Value; } + bool Option(eOptions Select); + bool OptionInherited(eOptions Select) { return (Select < Option_confirmdeleterecord || Select >= Option_max) ? false : options[Select] > NoYesDefault_yes; } + }; + +class cPlaylistRecordCol : public cConfig<cPlaylistRecord> { +private: + bool change; + cPlaylist *parent; +public: + cPlaylistRecordCol(cPlaylist *Parent); + virtual ~cPlaylistRecordCol(void); + bool GetChange(void) { return change; } + void SetChange(void) { change = true; } + void DeleteFile(); + bool SaveWithFilename(); + bool SearchRecord(const char *Filename); + }; + +class cPlaylistSortCol : public cList<cPlaylistRecord> { +private: +public: + }; + +extern cPlaylistSortCol PlaylistSort; + +class cPlaylist : public cListObject { + friend class cMenuPlaylistEdit; +private: + char name[MaxFileName]; + char *lastrecord; + int options[Option_max]; + int recordcount; + int recordnew; + + cPlaylistRecordCol *recordcol; +public: + cPlaylist(void); + virtual ~cPlaylist(void); + virtual bool operator!= (const cPlaylist &PlaylistObject); + cPlaylistRecordCol *RecordCol2(void) { return recordcol; } + bool Parse(const char *s); + bool Save(FILE *f); + bool SearchRecords(void); + void CountRecords(void); + cPlaylistRecord *First_PLR(void) { return recordcol ? recordcol->First() : NULL; } + cPlaylistRecord *Last_PLR(void) { return recordcol ? recordcol->Last() : NULL; } + cPlaylistRecord *Next_PLR(cPlaylistRecord *PLR) { return recordcol ? recordcol->Next(PLR) : NULL; } + cPlaylistRecord *Prev_PLR(cPlaylistRecord *PLR) { return recordcol ? recordcol->Prev(PLR) : NULL; } + cPlaylistRecord *Firstnormal_PLR(void); + cPlaylistRecord *Firstnew_PLR(void); + cPlaylistRecord *Lastplayed_PLR(void); + void SetChange(void) { if (recordcol) recordcol->SetChange(); } + void SaveRecordCol(void) { if (recordcol && recordcol->GetChange() && (!storeplaylist.u || Interface->Confirm(tr("Question$Save Playlist?")))) recordcol->SaveWithFilename(); } + void SetLastRecord(const char *LastRecord) { FREENULL(lastrecord); lastrecord = strdup(LastRecord); } + char *Name(void) { return &name[0]; } + int RecordCount(bool Refesh = false) { if (Refesh) CountRecords(); return recordcount; } + int RecordNew(void) { return recordnew; } + int Playoption(eOptions Select) { return Select == Option_playoption1 ? (options[Option_playoption1] == PlayOptions_defaultPlugin) ? PL_options[Option_playoption1].u : (options[Option_playoption1] < PlayOptions_defaultPlugin) ? options[Option_playoption1] : PL_options[Option_playoption1].d : Select == Option_playoption2 ? (options[Option_playoption2] == PlayOptions_defaultPlugin) ? PL_options[Option_playoption2].u : (options[Option_playoption2] < PlayOptions_defaultPlugin) ? options[Option_playoption2] : PL_options[Option_playoption2].d : PlayOptions_firstpos; } + bool Option(eOptions Select) { return (Select < Option_confirmdeleterecord || Select >= Option_max) ? false : (options[Select] == NoYesDefault_defaultPlugin) ? PL_options[Select].u : (options[Select] < NoYesDefault_defaultPlugin) ? options[Select] : PL_options[Select].d; } + bool OptionInherited(eOptions Select) { return (Select < Option_confirmdeleterecord || Select >= Option_max) ? false : (Select == Option_playoption1 || Select == Option_playoption2) ? options[Select] == PlayOptions_defaultPlugin : options[Select] > NoYesDefault_yes; } + }; + +//extern cPlaylist *SelectPlaylist; +//extern int Selectplayoption; +//extern int Selectplayposition; +extern cPlaylistRecord *SelectPLR; +extern cPlaylistRecord *PlayedPLR; + +class cPlaylistCol : public cConfig<cPlaylist> { +private: +public: + }; + +extern cPlaylistCol PlaylistCol; + +#endif //__DATAPLAYLIST_H diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..4416d09 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,11 @@ +vdr-plugin-playlist (0.0.2-1) unstable; urgency=low + + * Bug fixes + - + + -- Hardy Flor <HFlor@gmx.de> Fri, 08 Okt 2004 02:34:00 +0200 +vdr-plugin-playlist (0.0.1-1) unstable; urgency=low + + * Initial revision + + -- Hardy Flor <HFlor@gmx.de> Thu, 23 Sep 2004 23:42:32 +0200 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..a124ccd --- /dev/null +++ b/debian/control @@ -0,0 +1,12 @@ +Source: vdr-plugin-playlist +Section: misc +Priority: extra +Maintainer: Hardy Flor <HFlor@gmx.de> +Build-Depends: debhelper (>> 3.0.0), vdr-dev (>= 1.2.6-5) +Standards-Version: 3.5.2 + +Package: vdr-plugin-playlist +Architecture: i386 +Depends: ${shlibs:Depends}, vdr (>= 1.2.6-5) +Description: Plugin for VDR to display playlist for recordings + Patchlevel: ${patchlevel}
\ No newline at end of file diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..6e5458d --- /dev/null +++ b/debian/copyright @@ -0,0 +1,8 @@ +This package was debianized by Hardy Flor on Thu, 23 Sep 2004 23:42:32 +0200. + +Copyright: + + You are free to distribute this software under the terms of + the GNU General Public License. + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL file. diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..aa338f5 --- /dev/null +++ b/debian/dirs @@ -0,0 +1 @@ +usr/lib/vdr/plugins diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..20fd2fe --- /dev/null +++ b/debian/rules @@ -0,0 +1,79 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This is the debhelper compatibility version to use. +export DH_COMPAT=3 + +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) + CFLAGS += -g +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + $(MAKE) all DVBDIR=/usr/include VDRDIR=/usr/include/vdr LIBDIR=. REMOTE=lirc + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + rm -f debian/vdr-plugin-playlist.substvars + rm -f libvdr-*.so* + make clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + cp libvdr-playlist*.so.* $(CURDIR)/debian/vdr-plugin-playlist/usr/lib/vdr/plugins/ + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installdocs + dh_installexamples + dh_installmenu + dh_installcron + dh_installman + dh_installinfo + dh_installchangelogs HISTORY + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + cd debian; mv vdr-plugin-playlist.substvars substvars.old; cat /usr/include/vdr/patchlevel substvars.old > vdr-plugin-playlist.substvars; rm -f substvars.old + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure @@ -0,0 +1,1594 @@ +/* + * playlist: 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/08 02:34:00 hflor Exp $ + */ + +#include "i18n.h" + +const tI18nPhrase Phrases[] = { + { "Add", + "Hinzufügen", + "",// 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à + }, + { "Option", + "Optionen", + "",// 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à + }, + { "Select", + "Auswahl", + "",// 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à + }, + { "UnMark", + "Demakieren", + "",// 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à + }, + { "playlist for recordings", + "Playlisten für 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à + }, + { "Playlist", + "Playlist", + "",// 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à + }, + { "Add selected Record to Playlist?", + "Ausgewählte Aufnahme hinzufügen?", + "",// 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à + }, + { "Delete recording?", + "Aufnahme 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à + }, + { "Discard all changes?", + "Alle Änderungen verwerfen?", + "",// 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$Display Playlist", + "Anzeige Playlist", + "",// 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$Display Playlists", + "Übersicht Playlisten", + "",// 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 playlists 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$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à + }, + { "Edit$Confirm Options", + "Bestätigung der Optionen", + "",// 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à + }, + { "Edit$Create Playlist", + "Erstelle Playlist", + "",// 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à + }, + { "Edit$Edit Playlist", + "Bearbeite Playlist", + "",// 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à + }, + { "Edit$Edit Record", + "Bearbeite Aufnahme", + "",// 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à + }, + { "Edit$Delete Playlist?", + "Löschen der Playlist?", + "",// 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à + }, + { "Edit$Delete Playlistentry?", + "Löschen des Playlist-Eintrags?", + "",// 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$Playlistentry or Record is deleted", + "Playlisteintrag oder Aufnahme ist gelöscht", + "",// 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$Missing playlistentry name!", + "Name für Eintrag in Playlist fehlt!", + "",// 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$Missing playlist name!", + "Name für Playlist fehlt!", + "",// 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$Move between folders and not folders not allowed.", + "Vers. zw. Verzeichniss und normal nicht erlaubt", + "",// 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$Playlistentry is not set", + "Playlist-Eintrag ist fehlerhaft", + "",// 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$Playlist is currently used by played recording", + "Aktuelle Wiedergabe benutzt diese Playliste", + "",// 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$same name of playlist exists!", + "Gleicher Name der Playlist 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à + }, + { "OptionPL$[from Folder]", + "[von Verzeichniss]", + "",// 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à + }, + { "OptionPL$[from Playlist]", + "[von Playlist]", + "",// 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à + }, + { "OptionPL$[from Setup]", + "[von Einstellung]", + "",// 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à + }, + { "OptionPL$first new", + "erste neue", + "",// 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à + }, + { "OptionPL$first pos", + "erste Position", + "",// 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à + }, + { "OptionPL$last played", + "letzte Wiederg.", + "",// 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à + }, + { "OptionPL$last pos", + "letzte Position", + "",// 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à + }, + { "OptionPL$question", + "Frage", + "",// 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à + }, + { "OptionPL$seletced pos", + "ausgewählte", + "",// 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à + }, + { "OptionPL$ Character for folders", + " Zeichen für Verzeichniss", + "",// 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à + }, + { "OptionPL$ Character for normal records", + " Zeichen für normale 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à + }, + { "OptionPL$ Character for records in folders", + " Zeichen für Aufn. im Verzeichnis", + "",// 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à + }, + { "OptionPL$ Confirm delete records", + " Bestätigung löschen 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à + }, + { "OptionPL$ Confirm delete records", + " Bestätigung löschen 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à + }, + { "OptionPL$ Confirm start new record", + " Frage bei Start neue Wiedergabe", + "",// 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à + }, + { "OptionPL$Confirm start new record", + "Frage bei Start neue Wiedergabe", + "",// 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à + }, + { "OptionPL$ Delete records after play", + " Löschen Aufn. nach Wiedergabe", + "",// 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à + }, + { "OptionPL$Delete records after play", + "Löschen Aufn. nach Wiedergabe", + "",// 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à + }, + { "OptionPL$Effective setting is:", + "Aktuelle Einstellung ist:", + "",// 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à + }, + { "OptionPL$In detailview starts play at", + "Wiedergabe bei Playliste startet", + "",// 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à + }, + { "OptionPL$ In detailview starts play at", + " Wiedergabe bei Playliste startet", + "",// 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à + }, + { "OptionPL$In playlistview starts play at", + "Wiedergabe bei Übersicht startet", + "",// 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à + }, + { "OptionPL$ In playlistview starts play at", + " Wiedergabe bei Übersicht startet", + "",// 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à + }, + { "OptionPL$ Jump to first segment of movie", + " Zum ersten Filmteil sprigen", + "",// 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à + }, + { "OptionPL$Jump to first segment of movie", + "Zum ersten Filmteil sprigen", + "",// 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à + }, + { "OptionPL$Name", + "Name", + "",// 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à + }, + { "OptionPL$Play only new Records", + "Nur neue Aufzeichnungen abspielen", + "",// 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à + }, + { "OptionPL$ Play only new Records", + " Nur neue Aufzeichnungen abspielen", + "",// 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à + }, + { "OptionPL$ Remove records after play from list", + " PL-Eintrag n. Wiedergabe streichen", + "",// 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à + }, + { "OptionPL$Remove records after play from list", + "PL-Eintrag n. Wiedergabe streichen", + "",// 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à + }, + { "OptionPL$ Search new records on folders", + " Verzeichnissuche neue 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à + }, + { "OptionPL$Search new records on folders", + "Verzeichnissuche neue 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à + }, + { "OptionPL$ Search new records on subfolders", + " Aufnahmen in Unterverzei. suchen", + "",// 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à + }, + { "OptionPL$Search records on subfolders", + "Aufnahmen in Unterverzei. suchen", + "",// 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à + }, + { "Play$Delete recording:", + "Aufnahme 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à + }, + { "Play$Start next recording:", + "Nächste Aufnahme starten:", + "",// 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à + }, + { "Play$Currently play first Record! Jump to last?", + "Erste Aufnahme wird gespielt! Zur letzten gehen?", + "",// 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à + }, + { "Play$Currently play last Record! Jump to first?", + "Letzte Aufnahme wird gespielt! Zur ersten gehen?", + "",// 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$No new recording found! Play first?", + "Keine neuen Aufnahmen! Erste abspielen?", + "",// 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$Play first new recording?", + "Erste neue Aufnahme abspielen?", + "",// 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$Play last played recording?", + "Zuletzt gespielte Aufnahme abspielen?", + "",// 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$Save Playlist?", + "Playlist speichern?", + "",// 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$after question", + "nach Frage", + "",// 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$automatically", + "automatisch", + "",// 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 last PL", + "Anz. letzte PL", + "",// 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 PL", + "Anzeige PL", + "",// 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$Edit", + "Bearbeitung", + "",// 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$new empty PL", + "leere PL", + "",// 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$Play", + "Wiedergabe", + "",// 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$Play last PL", + "Wiedergabe PL", + "",// 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$Allow delete Records", + "Aufnahmen löschen erlauben", + "",// 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$Change Character for identification", + "Darstellungszeichen ändern", + "",// 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$Change default options for playlist", + "Standardoptionen für Playlist ändern", + "",// 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 playlistentries", + "Frage löschen PL-Eintragungen", + "",// 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$Path for store playlists", + "Speicherpfad für Playlisten", + "",// 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$Press OK in Playlistview starts", + "OK in Playlist-Ansicht startet", + "",// 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$Startoptions for plugin", + "Startoptionen des Plugins", + "",// 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$Store playlist after change", + "Playlist nach Änderung speichern", + "",// 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à + }, + { "Setup$Display playlists now", + "Jetzt Playlisten 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$Play last playlist now", + "Letzte Playlist wiedergeben", + "",// 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$At this position and after no recording found!", + "Dieser Position und danach ist keine Aufnahme", + "",// 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$Play selected recording?", + "Ausgewählte Aufnahme abspielen?", + "",// 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à + }, + { "OptionPL$is:", + "ist:", + "",// 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 @@ +/* + * playlist: 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/09/23 23:42:32 hflor Exp $ + */ + +#ifndef _I18N__H +#define _I18N__H + +#include <vdr/i18n.h> + +extern const tI18nPhrase Phrases[]; + +#endif //_I18N__H diff --git a/menucontrol.c b/menucontrol.c new file mode 100644 index 0000000..4ea34ed --- /dev/null +++ b/menucontrol.c @@ -0,0 +1,391 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menucontrol.c 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#include "menucontrol.h" +#include "menuplaylists.h" +#include "playlist.h" +#include "vdrtools.h" +#include <vdr/recording.h> +#include <vdr/remote.h> +#include <vdr/interface.h> + +// --- cControlPlaylist ----------------------------------------------------------- + +cControlPlaylist::cControlPlaylist(void) +:cControl(NULL) +{ +#ifdef PL_Debug2 + dsyslog("%s: cControlPlaylist::cControlPlaylist", plugin_name); +#endif + + replaycontrol = NULL; + if (SelectPLR) + PlayRecording(SelectPLR); + else + cRemote::Put(kBack); +} + +cControlPlaylist::~cControlPlaylist(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cControlPlaylist::~cControlPlaylist", plugin_name); +#endif + if (replaycontrol) + DELETENULL(replaycontrol); + PlayedPLR = NULL; +#ifdef PL_Debug2 + dsyslog("%s: PlayedPLR=(null)", plugin_name); +#endif +} + +void cControlPlaylist::Hide(void) +{ + if (replaycontrol) + replaycontrol->Hide(); +} + +eOSState cControlPlaylist::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cControlPlaylist::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + + eOSState state = osUnknown; + if (replaycontrol) + state = replaycontrol->ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || state != osUnknown) + { + dsyslog("%s: cControlPlaylist::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + char *temp = NULL; + cPlaylistRecord *plr = PlayedPLR; + cPlaylist *playlist = plr ? plr->Playlist() : NULL; + switch (state) + { + case osUnknown: switch (NORMALKEY(Key)) + { + case k1: if (playlist) + { + if (plr) + plr = playlist->Prev_PLR(plr); + while (plr && (plr->IsDirOrDel())) + plr = playlist->Prev_PLR(plr); + if (!plr && Interface->Confirm(tr("Play$Currently play first Record! Jump to last?"))) + { + plr = playlist->Last_PLR(); + while (plr && (plr->IsDirOrDel())) + plr = playlist->Prev_PLR(plr); + } + } + state = osContinue; + break; + case k3: if (playlist) + { + if (plr) + plr = playlist->Next_PLR(plr); + while (plr && (plr->IsDirOrDel())) + plr = playlist->Next_PLR(plr); + if (!plr && Interface->Confirm(tr("Play$Currently play last Record! Jump to first?"))) + { + plr = playlist->First_PLR(); + while (plr && (plr->IsDirOrDel())) + plr = playlist->Next_PLR(plr); + } + } + state = osContinue; + break; + case kBack: state = osEnd; + break; + default: break; + } + if (state == osContinue && plr) + { + bool visible = replaycontrol ? replaycontrol->Visible() : false; + UpdateRecording(); + state = PlayRecording(plr, visible); + } + break; + case osRecordings: // kBack while playing + UpdateRecording(); + cControl::Shutdown(); + if (ControlMenuIsOpen) + state = osUser8; + else + { + if (playlist) + playlist->SaveRecordCol(); + state = osEnd; + } + break; + case osEnd: // end of playing + { + bool visible = replaycontrol ? replaycontrol->Visible() : false; + UpdateRecording(); + if (playlist) + { + cPlaylistRecord *plr_n = playlist->Next_PLR(plr); + asprintf(&temp, "%s %s", tr("Play$Delete recording:"), plr->Name()); + if (deleterecords.u && plr->Option(Option_deleterecord) && (!plr->Option(Option_confirmdeleterecord) || Interface->Confirm(temp))) + plr->DeleteRecord(); + else if (plr->Option(Option_deletefromlist)) + { + plr->SetDel(); + playlist->SetChange(); + } + FREENULL(temp); + plr = plr_n; + while (plr && (plr->IsDirOrDel() || (plr->Option(Option_playonlynew) && !plr->IsNew()))) + plr = playlist->Next_PLR(plr); + if (plr) + { + asprintf(&temp, "%s %s", tr("Play$Start next recording:"), plr->Name()); + if (!plr->Option(Option_confirmstartnewrecord) || Interface->Confirm(temp)) + state = PlayRecording(plr, visible); + else + plr = NULL; + FREENULL(temp); + } + } else + plr = NULL; + if (!plr) + { + if (playlist) + playlist->SaveRecordCol(); + cControl::Shutdown(); + } + } + break; + default: break; + } +#ifdef PL_Debug3 + if (!noneKey || state != osUnknown) + dsyslog("%s: cControlPlaylist::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} + +eOSState cControlPlaylist::PlayRecording(cPlaylistRecord *PlaylistRecord, bool Visible) +{ +#ifdef PL_Debug1 + dsyslog("%s: cControlPlaylist::PlayRecording Name=%s FileName=%s", plugin_name, PlaylistRecord ? PlaylistRecord->Name() : NULL, PlaylistRecord ? PlaylistRecord->Filename() : NULL); +#endif + + static char title[MaxFileName]; + eOSState state = osEnd; + DELETENULL(replaycontrol); + if (PlaylistRecord) + { + if (PlaylistRecord->IsNew() && !PlaylistRecord->IsEdited() && PlaylistRecord->Option(Option_jumpmark)) + { + cResumeFile *resume = new cResumeFile(PlaylistRecord->Filename()); + int res = resume->Read(); + delete resume; + if (res < 0) // new file + { + cMarks *marks = new cMarks; + if (marks) + { + marks->Load(PlaylistRecord->Filename()); + if (marks->Count()) + { + int mark = marks->First()->position; + if (mark < 100 && marks->Count() > 2) + { + mark = marks->GetNext(mark)->position; + mark = marks->GetNext(mark)->position; + } + cResumeFile *resume = new cResumeFile(PlaylistRecord->Filename()); + if (mark > 0 && resume) + { + resume->Save(mark); + DELETENULL(resume); + } + } + } + } + } + char *buffer; + if (PlaylistRecord->Playlist()) + { + asprintf(&buffer, "%d/%d %s", PlaylistRecord->IndexRec(), PlaylistRecord->Playlist()->RecordCount(true), PlaylistRecord->Name()); + PlaylistRecord->Playlist()->SetLastRecord(PlaylistRecord->Filename()); + PlaylistCol.Save(); + } else + buffer = strdup(PlaylistRecord->Name()); + strn0cpy(title, buffer, MaxFileName); + free(buffer); + if (verbose.u) + dsyslog("%s: start new replay Name=%s Directory=%s", plugin_name, title, PlaylistRecord->Filename()); + cReplayControl::SetRecording(NULL, NULL); + cReplayControl::SetRecording(PlaylistRecord->Filename(), title); + replaycontrol = new cReplayControlPlaylist; + if (replaycontrol) + { + player = replaycontrol->GetPlayerPlaylist(); + if (cDevice::PrimaryDevice()->AttachPlayer(player)) + state = osContinue; + PlayedPLR = PlaylistRecord; +#ifdef PL_Debug2 + dsyslog("%s: PlayedPLR=(null)", plugin_name, PlayedPLR ? PlayedPLR->Name() : "(null)"); +#endif + if (Visible) + replaycontrol->Show(); + if (PlaylistRecord && PlaylistRecord->Playlist()) + strn0cpy(lastplaylist.u, PlaylistRecord->Playlist()->Name(), sizeof(lastplaylist.u)); + else + lastplaylist.u[0] = 0; + if (strcmp(lastplaylist.u, lastplaylist.o)) + { + PluginPlaylist->SetupStore("lastpl", lastplaylist.u); + strcpy(lastplaylist.o, lastplaylist.u); + } + } + } + return state; +} + +void cControlPlaylist::UpdateRecording(void) +{ +#ifdef PL_Debug1 + dsyslog("%s: cControlPlaylist::UpdateRecording PlayedPLR=%s", plugin_name, PlayedPLR ? PlayedPLR->Filename() : "(null)"); +#endif + + DELETENULL(replaycontrol); + cRecording *recording_n = NULL; + if (PlayedPLR) + { + cRecording *recording_o = Recordings.GetByName(PlayedPLR->Filename()); + recording_n = new cRecording(PlayedPLR->Filename()); + if (recording_o && recording_n) + { + Recordings.Add(recording_n, recording_o); + Recordings.Del(recording_o); + } + } + for (cPlaylist *pl = PlaylistCol.First(); pl; pl = PlaylistCol.Next(pl)) + for (cPlaylistRecord *plr = pl->First_PLR(); plr; plr = pl->Next_PLR(plr)) + if (strcasecmp(plr->Filename(), PlayedPLR->Filename()) == 0) +{ + dsyslog("%s: playlist=%s isnew=%s", plugin_name, pl->Name(), recording_n ? recording_n->IsNew() ? "true" : "false" : "(null)"); + if (recording_n) + plr->SetNew(recording_n->IsNew()); + else + plr->SetDel(); +} +} + +// --- cControlMenu ----------------------------------------------------------- + +cControlMenu::cControlMenu(void) +:cOsdObject(true) +{ +#ifdef PL_Debug2 + dsyslog("%s: cControlMenu::cControlMenu Startoption=%d", plugin_name, startoption.u); +#endif + + ControlMenuIsOpen = true; + switch (startoption.u) + { + case Start_DisplayPL: osdmenu = new cMenuPlaylists; + break; + case Start_DisplayLast: osdmenu = new cMenuPlaylists; + if (SelectPLR) + osdmenu->ProcessKey(kUser1); + break; + case Start_PlayLast: osdmenu = new cMenuPlaylists; + if (SelectPLR) + { + if (osdmenu->ProcessKey(kUser2) == osUser9) + { + DELETENULL(osdmenu); + cControl::Shutdown(); + cControl::Launch(new cControlPlaylist); + } + } + break; + case Start_NewEmpty: osdmenu = new cMenuPlaylists; + osdmenu->ProcessKey(kUser3); + break; + } +} + +cControlMenu::~cControlMenu() +{ +#ifdef PL_Debug + dsyslog("%s: cControlMenu::~cControlMenu", plugin_name); +#endif + if (osdmenu) + DELETENULL(osdmenu); + ControlMenuIsOpen = false; +} + +void cControlMenu::Show(void) +{ + if (osdmenu) + osdmenu->Display(); +} + +eOSState cControlMenu::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cControlMenu::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + + eOSState state; + cOsdObject *Interact = osdmenu ? (cOsdObject*)osdmenu : cControl::Control(); + if (Interact) + state = Interact->ProcessKey(Key); + else + state = cOsdObject::ProcessKey(Key); + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cControlMenu::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + switch (state) + { + case osUnknown: switch (NORMALKEY(Key)) + { + case kBack: state = osEnd; + break; + default: break; + } + break; + case osUser8: osdmenu = new cMenuPlaylists; + if (SelectPLR) + osdmenu->ProcessKey(kUser1); + break; + case osUser9: if (SelectPLR) + { + DELETENULL(osdmenu); + cControl::Shutdown(); + cControl::Launch(new cControlPlaylist); + } + state = osContinue; + break; + default: break; + } + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cControlMenu::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} diff --git a/menucontrol.h b/menucontrol.h new file mode 100644 index 0000000..392d696 --- /dev/null +++ b/menucontrol.h @@ -0,0 +1,50 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menucontrol.h 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#ifndef __MENUCONTROL_H +#define __MENUCONTROL_H + +#include "dataplaylist.h" +#include <vdr/menu.h> + + +// --- cReplayControlPlaylist ----------------------------------------------------------- + +class cReplayControlPlaylist : public cReplayControl { +public: + cPlayer *GetPlayerPlaylist() { return cControl::player; } + }; + +// --- cControlPlaylist ----------------------------------------------------------- + +class cControlPlaylist : public cControl { +private: +// cPlaylistRecord *playlistrecord; + cReplayControlPlaylist *replaycontrol; + eOSState PlayRecording(cPlaylistRecord *PlaylistRecord, bool Visible = false); + void UpdateRecording(void); +public: + cControlPlaylist(void); + virtual ~cControlPlaylist(void); + virtual void Hide(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +// --- cControlMenu ----------------------------------------------------------- + +class cControlMenu : public cOsdObject { +private: + cOsdMenu *osdmenu; +public: + cControlMenu(void); + virtual ~cControlMenu(void); + virtual void Show(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +#endif //__MENUCONTROL_H diff --git a/menuitemtext.c b/menuitemtext.c new file mode 100644 index 0000000..9bb0447 --- /dev/null +++ b/menuitemtext.c @@ -0,0 +1,36 @@ +/* + * playlist: 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/09/23 23:42:32 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..b53a0bd --- /dev/null +++ b/menuitemtext.h @@ -0,0 +1,22 @@ +/* + * playlist: 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/09/23 23:42:32 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/menuplaylist.c b/menuplaylist.c new file mode 100644 index 0000000..e87588d --- /dev/null +++ b/menuplaylist.c @@ -0,0 +1,966 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuplaylist.c 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#include "menuplaylist.h" +#include "dataplaylist.h" +#if VDRVERSNUM < 10307 +#include "menuitemtext.h" +#endif +#include "playlist.h" +#include "i18n.h" +#include "vdrtools.h" +#include <vdr/interface.h> +#include <vdr/videodir.h> +#ifdef HAVE_ICONPATCH +#include <vdr/iconpatch.h> +#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()); + ismark = false; +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingSelectItem::cMenuRecordingSelectItem FileName=%s Level=%d Name=%s", plugin_name, filename, Level, name); +#endif +} + +cMenuRecordingSelectItem::~cMenuRecordingSelectItem() +{ +#ifdef PL_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 PL_Debug2 + dsyslog("%s: cMenuRecordingSelectItem::IncrementCounter FileName=%s New=%s Buffer=%s", plugin_name, filename, New ? "true" : "false", buffer); +#endif +} + +// --- cMenuRecordingSelect -------------------------------------------------------- + +cMenuRecordingSelect::cMenuRecordingSelect(const char *Base, int Level, bool OpenSubMenus, bool SingleSelect) +:cOsdMenu(Base ? Base : tr("Recordings"), 6, 6, 6) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingSelect::cMenuRecordingSelect Base=%s Level=%d OpenSubMenus=%s", plugin_name, Base, Level, OpenSubMenus ? "true" : "false"); +#endif +#if VDRVERSNUM < 10311 +#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; + singleselect = SingleSelect; + Display(); + cMenuRecordingSelectItem *LastItem = NULL; + char *LastItemText = NULL; + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.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 (LastSelectedRecord && strncmp(LastSelectedRecord, recording->FileName(), strlen(LastSelectedRecord)) == 0) + SetCurrent(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 PL_Debug2 + dsyslog("%s: cMenuRecordingSelect::~cMenuRecordingSelect Base=%s Level=%d", plugin_name, base, level); +#endif + FREENULL(base); +} + +void cMenuRecordingSelect::SetHelpKeys(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingSelect::SetHelpKeys", plugin_name); +#endif + + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri) + { + if (ri->IsDirectory()) + if (singleselect) + SetHelp(tr("Open")); + else + SetHelp(tr("Add"), ri->IsMark() ? tr("UnMark") : tr("Mark"), NULL, NULL); + else + { + cRecording *recording = GetRecording(ri); + SetHelp(singleselect ? tr("Select") : tr("Add"), singleselect ? NULL : ri->IsMark() ? tr("UnMark") : tr("Mark"), deleterecords.u ? tr("Delete") : NULL, (recording && recording->Summary() && *recording->Summary()) ? tr("Summary") : NULL); + } + } else + { + SetHelp(NULL); + } +} + +cRecording *cMenuRecordingSelect::GetRecording(cMenuRecordingSelectItem *Item) +{ + cRecording *recording = Recordings.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, singleselect)); + FREENULL(buffer); + return osContinue; + } else if (!OpenSubMenus) + return AddPlaylist(); + } + return osUnknown; +} + +eOSState cMenuRecordingSelect::AddPlaylist(void) +{ + FREENULL(LastSelectedRecord); + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri) + { + if (ri->IsDirectory() && singleselect) + return Open(); + LastSelectedRecord = strdup(ri->FileName()); + if (ri->IsDirectory()) + { + char *last = LastSelectedRecord + strlen(VideoDirectory) + 1; + for (int i = level; *last && i >= 0; i--) + { + last = strchr(last, '/'); + if (!last) + break; + last++; + } + if (last) + *last = 0; + } + if (PlaylistMark.Count() && !ri->IsMark() && Interface->Confirm(tr("Add selected Record to Playlist?"))) + { + cPlaylistMark *pm = new cPlaylistMark(LastSelectedRecord); + PlaylistMark.Add(pm); + } + return osUser1; // Add to Playlist in cMenuPlaylist::ProcessKey + } + return osUnknown; +} + +eOSState cMenuRecordingSelect::MarkSel(void) +{ + if (singleselect) + return osContinue; + INFO("kommt noch ...?"); + return osContinue; +} + +eOSState cMenuRecordingSelect::Delete(void) +{ + if (!deleterecords.u || HasSubMenu() || Count() == 0) + return osContinue; + cMenuRecordingSelectItem *ri = (cMenuRecordingSelectItem *)Get(Current()); + if (ri && !ri->IsDirectory() && Interface->Confirm(tr("Delete recording?")) && DeleteRecording(ri->FileName())) + { + 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 PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuRecordingSelect::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuRecordingSelect::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + switch (state) + { + case osUnknown: switch (Key) + { + case kOk: state = Open(); + break; + case kRed: state = AddPlaylist(); + break; + case kGreen: state = MarkSel(); + break; + case kYellow: state = Delete(); + break; + case kBlue: state = Summary(); + break; + default: break; + } + break; + default: break; + } + if (!HasSubMenu() && Key != kNone) + SetHelpKeys(); + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuRecordingSelect::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} + +// --- cMenuRecordingEdit ----------------------------------------------------------- + +cMenuRecordingEdit::cMenuRecordingEdit(cPlaylistRecord *PlaylistRecord, bool ConfirmOptions) +:cOsdMenu(ConfirmOptions ? tr("Edit$Confirm Options") : tr("Edit$Edit Record"), 33) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingEdit::cMenuRecordingEdit Playlistentry=%s ConfirmOptions=%s", plugin_name, PlaylistRecord ? PlaylistRecord->Name() : "(null)", ConfirmOptions ? "true" : "false"); +#endif + playlistrecord = PlaylistRecord; + confirmoptions = ConfirmOptions; +#if VDRVERSNUM >= 10307 + editwidth = DisplayMenu()->EditableWidth(); +#endif + DisplayStatus[0] = 0; + if (playlistrecord) + { + data = *playlistrecord; + Set(); + } + SetHelpKeys(); +} + +cMenuRecordingEdit::~cMenuRecordingEdit() +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingEdit::~cMenuRecordingEdit Playlistentry=%s", plugin_name, playlistrecord ? playlistrecord->Name() : "(null)"); +#endif + data.filename = NULL; + data.summary = NULL; + data.title = NULL; + data.path = NULL; +} + +void cMenuRecordingEdit::SetHelpKeys(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingEdit:SetHelpKeys", plugin_name); +#endif + + char *buffer = NULL; + eOptions display = (Current() >= 0) && (Current() < MAXOptionLines) ? displayoption[Current()] : Option_max; + if (display < Option_max && data.OptionInherited(display)) + asprintf(&buffer, "%s %s", tr("OptionPL$is:"), NoYesDefault[data.Option(display)]); + if (buffer) + { + if (strcmp(DisplayStatus, buffer)) + strn0cpy(DisplayStatus, buffer, MAXOSDTEXTWIDTH); + free(buffer); + } else + if (strlen(DisplayStatus)) + DisplayStatus[0] = 0; + const char *red = strlen(DisplayStatus) ? DisplayStatus : NULL; + if (confirmoptions) + SetHelp(red); + else + SetHelp(red, (data.isdir || data.parent) ? NULL : tr("Select"), tr("Delete"), (data.summary && *data.summary) ? tr("Summary") : NULL); +} + +void cMenuRecordingEdit::Set(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuRecordingEdit::Set Current=%d", plugin_name, Current()); +#endif + for (int i = 0; i < MAXOptionLines; i++) + displayoption[i] = Option_max; + int current = Current(); + Clear(); + + if (data.path) + { + char *buffer = NULL; + asprintf(&buffer, "%s: %s", tr("Path"), data.path); + +#if VDRVERSNUM >= 10307 + cOsdItem *item; + strreplace(buffer, ' ', '|'); + strreplace(buffer, '~', ' '); + cTextWrapper *textwrapper = new cTextWrapper(buffer, cFont::GetFont(fontOsd), editwidth); + for (int i = 0; i < textwrapper->Lines(); i++) + { + char *textbuf = strdup(textwrapper->GetLine(i)); + strreplace(buffer, ' ', '/'); + strreplace(buffer, '|', ' '); + item = new cOsdItem(textbuf); + free(textbuf); + item->SetSelectable(false); + Add(item); + } + delete textwrapper; + item = new cOsdItem(" "); + item->SetSelectable(false); + Add(item); +#else + strreplace(buffer, '~', '/'); + char *pos = buffer; + char *pos_next; + char *pos_last; + char text[MAXOSDWIDTH + 1]; + int textlen; + + while (*pos) + { + pos_next = strchr(pos, '\n'); + if (!pos_next) + pos_next = pos + strlen(pos); + textlen = pos_next - pos; + if (textlen < (Setup.OSDwidth - 1)) + { + strn0cpy(text, pos, textlen + 1); + } else + { + strn0cpy(text, pos, Setup.OSDwidth - 1); + pos_last = strrchr(text, '/'); + if (!pos_last) + pos_last = text + Setup.OSDwidth - 1; + *pos_last = 0; + textlen = pos_last - text; + } + Add(new cOsdItem(text)); + pos += textlen; + if (*pos) pos++; + } + Add(new cOsdItem(" ")); +#endif + free(buffer); + } +#if VDRVERSNUM < 10307 + firstline = Count(); +#endif + + Add(new cMenuEditStrItem(tr("OptionPL$Name"), data.name, sizeof(data.name), tr(FileNameChars))); + if (current < Count()) + current = Count(); + if (data.isdir) + { + displayoption[Count()] = Option_searchnewrecord; + Add(new cMenuEditStraItem(tr("OptionPL$Search new records on folders"), &data.options[Option_searchnewrecord], 4, NoYesDefault)); + displayoption[Count()] = Option_searchrecordsub; + Add(new cMenuEditStraItem(tr("OptionPL$Search records on subfolders"), &data.options[Option_searchrecordsub], 4, NoYesDefault)); + displayoption[Count()] = Option_playonlynew; + Add(new cMenuEditStraItem(tr("OptionPL$Play only new Records"), &data.options[Option_playonlynew], data.parent ? 5 : 4, NoYesDefault)); + } + displayoption[Count()] = Option_jumpmark; + Add(new cMenuEditStraItem(tr("OptionPL$Jump to first segment of movie"), &data.options[Option_jumpmark], data.parent ? 5 : 4, NoYesDefault)); + displayoption[Count()] = Option_confirmstartnewrecord; + Add(new cMenuEditStraItem(tr("OptionPL$Confirm start new record"), &data.options[Option_confirmstartnewrecord], data.parent ? 5 : 4, NoYesDefault)); + displayoption[Count()] = Option_deletefromlist; + Add(new cMenuEditStraItem(tr("OptionPL$Remove records after play from list"), &data.options[Option_deletefromlist], data.parent ? 5 : 4, NoYesDefault)); + displayoption[Count()] = Option_deleterecord; + Add(new cMenuEditStraItem(tr("OptionPL$Delete records after play"), &data.options[Option_deleterecord], data.parent ? 5 : 4, NoYesDefault)); + if (data.options[Option_deleterecord] != NoYesDefault_no) + { + displayoption[Count()] = Option_confirmdeleterecord; + Add(new cMenuEditStraItem(tr("OptionPL$ Confirm delete records"), &data.options[Option_confirmdeleterecord], data.parent ? 5 : 4, NoYesDefault)); + } + SetCurrent(Get(current)); + Display(); +} + +eOSState cMenuRecordingEdit::Summary(void) +{ + if (!HasSubMenu() && !data.isdir && data.summary && *data.summary) +#if VDRVERSNUM >= 10307 + return AddSubMenu(new cMenuText(tr("Summary"), data.summary)); +#else + return AddSubMenu(new cMenuItemText(tr("Summary"), data.summary)); +#endif + + + return osContinue; +} + +eOSState cMenuRecordingEdit::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuRecordingEdit::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + int m_deleterecord = data.options[Option_deleterecord]; + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuRecordingEdit::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (m_deleterecord != data.options[Option_deleterecord]) + Set(); + +#if VDRVERSNUM < 10307 + if (Current() < firstline) + { + DisplayCurrent(false); + SetCurrent(Get(firstline)); + DisplayCurrent(true); + } +#endif + + char *buffer = NULL; + eOptions display = (Current() >= 0) && (Current() < MAXOptionLines) ? displayoption[Current()] : Option_max; +/* if (display < Option_max && data.OptionInherited(display)) + asprintf(&buffer, "%s %s", tr("OptionPL$Effective setting is:"), NoYesDefault[data.Option(display)]); + if (buffer) + { + if (strcmp(DisplayStatus, buffer)) + { + strn0cpy(DisplayStatus, buffer, MAXOSDTEXTWIDTH); + SetStatus(DisplayStatus); + } + free(buffer); + } else + { + if (strlen(DisplayStatus)) + { + DisplayStatus[0] = 0; + SetStatus(NULL); + } + }*/ + + switch (state) + { + case osUnknown: switch (Key) + { + case kOk: strn0cpy(data.name, skipspace(stripspace(data.name)), sizeof(data.name)); + Display(); + if (!strlen(data.name)) + { + ERROR(tr("Error$Missing playlistentry name!")); + break; + } + if (playlistrecord) + { + data.isdel = playlistrecord->isdel; + if (data != *playlistrecord) + { + *playlistrecord = data; + if (playlistrecord->Playlist()) + playlistrecord->Playlist()->SetChange(); + if (verbose.u) + isyslog("%s: playlistentry %d modified (%s)", plugin_name, playlistrecord->Index() + 1, playlistrecord->name); + } + data.filename = NULL; + state = osBack; + } + break; + case kRed: state = osContinue; + break; + case kGreen: LastSelectedRecord = playlistrecord->filename; + state = AddSubMenu(new cMenuRecordingSelect(NULL, 0, true, true)); + break; + case kYellow: state = osUser2; // delete Playlistentry in cMenuPlaylist::ProcessKey + break; + case kBlue: state = Summary(); + break; + default: break; + } + break; + case osUser1: state = CloseSubMenu(); + if (state == osContinue && LastSelectedRecord && *LastSelectedRecord && LastSelectedRecord[strlen(LastSelectedRecord) - 1] != '/') + { + playlistrecord->SetName(LastSelectedRecord); + playlistrecord->CopyFromRecording(); + data = *playlistrecord; + Set(); + } + break; + default: break; + } + if (!HasSubMenu() && Key != kNone) + SetHelpKeys(); + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuRecordingEdit::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} + +// --- cMenuPlaylistItem -------------------------------------------------------- + +cMenuPlaylistItem::cMenuPlaylistItem(cPlaylistRecord *PlaylistRecord) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistItem::cMenuPlaylistItem Playlistentry=%s", plugin_name, PlaylistRecord ? PlaylistRecord->Name() : "(null)"); +#endif + playlistrecord = PlaylistRecord; + Set(); +} + +cMenuPlaylistItem::~cMenuPlaylistItem() +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistItem::~cMenuPlaylistItem Playlistentry=%s", plugin_name, playlistrecord ? playlistrecord->Name() : "(null)"); +#endif +} + +void cMenuPlaylistItem::Set(void) +{ + char *buffer = NULL; + if (playlistrecord) + { + if (playlistrecord->IsDel()) + asprintf(&buffer, "\t%s", tr("Error$Playlistentry or Record is deleted")); + else if (playlistrecord->IsDir()) + asprintf(&buffer, "%c\t%s", charfolder.u, playlistrecord->Name()); + else + asprintf(&buffer, "%c\t%s\t%s", playlistrecord->Parent() ? charentry.u : charrecord.u, playlistrecord->Title(), playlistrecord->Name()); + } else + buffer = strdup(tr("Error$Playlistentry is not set")); + SetText(buffer, false); +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistItem::Set SetText=%s", plugin_name, buffer); +#endif +} + +// --- cMenuPlaylist ----------------------------------------------------------- + +cMenuPlaylist::cMenuPlaylist(cPlaylist *Playlist) +:cOsdMenu(tr("Display$Display Playlist"), 2, 6, 7, 5) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::cMenuPlaylist", plugin_name); +#endif + + playlist = Playlist; + if (playlist) + for (cPlaylistRecord *plr = playlist->First_PLR(); plr; plr = playlist->Next_PLR(plr)) + if (!plr->IsDel()) + Add(new cMenuPlaylistItem(plr)); + addrecords = false; + if (Count()) + { + SetHelpKeys(); + Display(); + } else + AddSubMenu(new cMenuRecordingSelect(NULL, 0, true)); +} + +cMenuPlaylist::~cMenuPlaylist(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::~cMenuPlaylist", plugin_name); +#endif + playlist = NULL; +} + +void cMenuPlaylist::SetHelpKeys(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::SetHelpKeys", plugin_name); +#endif + if (Count()) + SetHelp((playlist && *playlist->Name()) ? tr("Play") : NULL, tr("New"), tr("Delete"), tr("Mark")); + else + SetHelp(NULL, tr("New"), NULL, NULL); +} + +eOSState cMenuPlaylist::Play(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::Play", plugin_name); +#endif + cPlaylistRecord *plr = CurrentPlaylistRecord(); + if (HasSubMenu() || !plr || !playlist || !*playlist->Name()) + return osContinue; + if (verbose.u) + isyslog("%s: start play PlaylistRecord %d Option=%d", plugin_name, plr->Index() + 1, playlist->Playoption(Option_playoption2)); + playlist->SearchRecords(); + cPlaylistRecord *plr_selected = plr; + cPlaylistRecord *plr_firstnomal = playlist->Firstnormal_PLR(); + cPlaylistRecord *plr_firstnew = playlist->Firstnew_PLR(); + cPlaylistRecord *plr_lastplayed = playlist->Lastplayed_PLR(); + while (plr_selected && plr_selected->IsDirOrDel()) + plr_selected = playlist->Next_PLR(plr_selected); + switch (playlist->Playoption(Option_playoption2)) + { + case PlayOptions_selectpos: SelectPLR = plr_selected; + if (!SelectPLR) + ERROR(tr("Error$At this position and after no recording found!")); + break; + case PlayOptions_firstpos: SelectPLR = plr_firstnomal; + break; + case PlayOptions_firstnew: if (plr_firstnew) + SelectPLR = plr_firstnew; + else + SelectPLR = Interface->Confirm(tr("Question$No new recording found! Play first?")) ? plr_firstnomal : NULL; + break; + case PlayOptions_lastplay: if (plr_lastplayed) + { + SelectPLR = plr_lastplayed; + break; + } + // no break! + case PlayOptions_question: if (plr_selected && Interface->Confirm(tr("Question$Play selected recording?"))) + { + SelectPLR = plr_selected; + break; + } + if (plr_lastplayed && Interface->Confirm(tr("Question$Play last played recording?"))) + { + SelectPLR = plr_lastplayed; + break; + } + if (plr_firstnew && plr_firstnew != plr_firstnomal && Interface->Confirm(tr("Question$Play first new recording?"))) + { + SelectPLR = plr_firstnew; + break; + } + SelectPLR = plr_firstnomal; + break; + } + return SelectPLR ? osUser9 : osContinue; // osUSer9 starts play playlist with SelectPLR in cControlMenu::ProcessKey +} + +eOSState cMenuPlaylist::Edit(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::Edit", plugin_name); +#endif + if (HasSubMenu() || !CurrentPlaylistRecord()) + return osContinue; + isyslog("%s: editing Playlistentry %d", plugin_name, CurrentPlaylistRecord()->Index() + 1); + return AddSubMenu(new cMenuRecordingEdit(CurrentPlaylistRecord())); +} + +bool cMenuPlaylist::AddPlaylistentrys() +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::AddPlaylistentrys Add=%s", plugin_name, LastSelectedRecord); +#endif + static cPlaylistRecord *playlistrecord = NULL; + bool iswithdir = LastSelectedRecord && LastSelectedRecord[strlen(LastSelectedRecord) - 1] == '/'; + if (!playlistrecord && iswithdir) + { + playlistrecord = new cPlaylistRecord(NULL,LastSelectedRecord); + AddSubMenu(new cMenuRecordingEdit(playlistrecord, true)); + addrecords = true; + return true; + } + if (!playlist || !playlist->RecordCol2()) + return false; + if (iswithdir) + { + PlaylistSort.Clear(); + cPlaylistRecord *p_plr = new cPlaylistRecord(playlist, LastSelectedRecord); + p_plr->CopyOptions(playlistrecord); + playlist->RecordCol2()->Add(p_plr); + cMenuPlaylistItem *mpli = new cMenuPlaylistItem(p_plr); + Add(mpli); + SetCurrent(mpli); + cPlaylistRecord *plr = NULL; + for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) + { + if (strstr(recording->FileName(), LastSelectedRecord) == recording->FileName()) + { + const char *next = NULL; + if (!p_plr->Option(Option_searchrecordsub)) + { + const char *test = recording->FileName() + strlen(LastSelectedRecord); + const char *temp = strchr(test, '/'); + if (temp) + next = strchr(temp + 1, '/'); + } + if (!next) + { + plr = new cPlaylistRecord(playlist, recording, p_plr); + PlaylistSort.Add(plr); + } + } + } + PlaylistSort.Sort(); + cPlaylistRecord *nplr = NULL; + for (plr = PlaylistSort.First(); plr; plr = nplr) + { + nplr = PlaylistSort.Next(plr); + PlaylistSort.Del(plr, false); + playlist->RecordCol2()->Add(plr); + Add(new cMenuPlaylistItem(plr)); + } + } else + { // one record to add + cPlaylistRecord *plr = new cPlaylistRecord(playlist, LastSelectedRecord); + playlist->RecordCol2()->Add(plr); + cMenuPlaylistItem *mpli = new cMenuPlaylistItem(plr); + Add(mpli); + SetCurrent(mpli); + } + playlist->SetChange(); + addrecords = false; + DELETENULL(playlistrecord); + Display(); + return true; +} + +eOSState cMenuPlaylist::New(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::New", plugin_name); +#endif + if (HasSubMenu()) + return osContinue; + cOsdMenu *menu = new cMenuRecordingSelect(NULL, 0, true); + eOSState state = AddSubMenu(menu); + if (LastSelectedRecord && LastSelectedRecord[strlen(LastSelectedRecord) - 1] == '/') + menu->ProcessKey(kBack); + return state; +} + +eOSState cMenuPlaylist::Delete(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::Delete", plugin_name); +#endif + cPlaylistRecord *plr = CurrentPlaylistRecord(); + if (plr && playlist) + { + if (!confirmdelplentry.u || Interface->Confirm(tr("Edit$Delete Playlistentry?"))) + { + if (verbose.u) + isyslog("%s: Playlistentry %d deleted", plugin_name, plr->Index() + 1); + plr->SetDel(); + playlist->SetChange(); + cOsdMenu::Del(Current()); + Display(); + } + } + return osContinue; +} + +void cMenuPlaylist::Move(int From, int To) +{ +#ifdef PL_Debug1 + dsyslog("%s: cMenuPlaylist::Move from=%d to=%d", plugin_name, From, To); +#endif + if (playlist && playlist->RecordCol2()) + { + cMenuPlaylistItem *temp = (cMenuPlaylistItem *)Get(From); + cPlaylistRecord *plr_f = temp ? temp->PlaylistRecord() : NULL; + temp = (cMenuPlaylistItem *)Get(To); + cPlaylistRecord *plr_t = temp ? temp->PlaylistRecord() : NULL; + cPlaylistRecord *plr_p = NULL; + if (To > 0) + { + temp = (cMenuPlaylistItem *)Get(To - 1); + plr_p = temp ? temp->PlaylistRecord() : NULL; + } + // plr_f --> cPlaylistRecord (Source) + // plr_t --> cPlaylistRecord at Targetposition + // plr_p --> cPlaylistRecord before Targetposition + if (!plr_f || !plr_t) + { + esyslog("%s: Error while get playlistentries in move-function", plugin_name); + return; + } + if (plr_f->Parent() == plr_t->Parent() || (plr_p && plr_f->Parent() == plr_p->Parent())) + { + playlist->RecordCol2()->Move(plr_f->Index(), plr_t->Index()); + playlist->SetChange(); + cOsdMenu::Move(From, To); + Display(); + } else + ERROR(tr("Error$Move between folders and not folders not allowed.")); + } +} + +cPlaylistRecord *cMenuPlaylist::CurrentPlaylistRecord(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylist::CurrentPlaylistRecord", plugin_name); +#endif + cMenuPlaylistItem *item = (cMenuPlaylistItem *)Get(Current()); + return item ? item->PlaylistRecord() : NULL; +} + +eOSState cMenuPlaylist::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuPlaylist::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + int n; + bool hSubMenu = HasSubMenu(); + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuPlaylist::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (!HasSubMenu() && hSubMenu) + { + for (cOsdItem *item = First(); item; item = Next(item)) + item->Set(); + if (addrecords) + AddPlaylistentrys(); // submenu for folder-options is closed + else + Display(); + } + + switch (state) + { + case osUnknown: switch (Key) + { + case k0...k9: n = (Key == k0) ? 10 : (Key - k0); + if (n > Count()) + break; + SetCurrent(Get(--n)); + // no break! + case kOk: state = Edit(); + break; + case kRed: state = Play(); + break; + case kGreen: state = New(); + break; + case kYellow: state = Delete(); + break; + case kBlue: if (!HasSubMenu()) + { + Mark(); + state = osContinue; + } + break; + default: break; + } + break; + case osUser1: state = CloseSubMenu(); + if (state == osContinue) + AddPlaylistentrys(); + break; + case osUser2: state = CloseSubMenu(); + if (state == osContinue) + state = Delete(); + break; + default: break; + } + if (!HasSubMenu() && Key != kNone) + SetHelpKeys(); + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuPlaylist::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} diff --git a/menuplaylist.h b/menuplaylist.h new file mode 100644 index 0000000..697c18b --- /dev/null +++ b/menuplaylist.h @@ -0,0 +1,113 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuplaylist.h 0.1 2004/09/23 23:42:32 hflor Exp $ + */ + +#ifndef __MENUPLAYLIST_H +#define __MENUPLAYLIST_H + +#include "dataplaylist.h" +#include <vdr/menu.h> +#include <vdr/menuitems.h> + +// --- cMenuRecordingSelectItem -------------------------------------------------------- + +class cMenuRecordingSelectItem : public cOsdItem { +private: + char *filename; + char *name; + time_t start; + bool isdir; + bool ismark; + int totalEntries; + int newEntries; +public: + cMenuRecordingSelectItem(cRecording *Recording, int Level); + ~cMenuRecordingSelectItem(); + virtual bool operator< (const cListObject &ListObject); + void IncrementCounter(bool New); + const char *FileName(void) { return filename; } + const char *Name(void) { return name; } + bool IsDirectory(void) { return isdir; } + bool IsMark(void) { return ismark; } + void SetMark(bool Mark) { ismark = Mark; } + }; + +// --- cMenuRecordingSelect -------------------------------------------------------- + +class cMenuRecordingSelect : public cOsdMenu { +private: + char *base; + int level; + bool singleselect; + void SetHelpKeys(void); + cRecording *GetRecording(cMenuRecordingSelectItem *Item); + eOSState Open(bool OpenSubMenus = false); + eOSState AddPlaylist(void); + eOSState MarkSel(void); + eOSState Delete(void); + eOSState Summary(void); +public: + cMenuRecordingSelect(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false, bool SingleSelect = false); + ~cMenuRecordingSelect(); + virtual eOSState ProcessKey(eKeys Key); + }; + +// --- cMenuRecordingEdit -------------------------------------------------------- + +class cMenuRecordingEdit : public cOsdMenu { +private: + cPlaylistRecord *playlistrecord; + cPlaylistRecord data; + bool confirmoptions; + eOptions displayoption[MAXOptionLines]; +#if VDRVERSNUM >= 10307 + int editwidth; +#else + int firstline; +#endif + void SetHelpKeys(void); + eOSState Summary(void); +public: + cMenuRecordingEdit(cPlaylistRecord *PlaylistRecord, bool ConfirmOptions = false); + virtual ~cMenuRecordingEdit(); + virtual void Set(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +// --- cMenuPlaylistItem -------------------------------------------------------- + +class cMenuPlaylistItem : public cOsdItem { +private: + cPlaylistRecord *playlistrecord; +public: + cMenuPlaylistItem(cPlaylistRecord *PlaylistRecord); + virtual ~cMenuPlaylistItem(); + virtual void Set(void); + cPlaylistRecord *PlaylistRecord(void) { return playlistrecord; } + }; + +// --- cMenuPlaylist ----------------------------------------------------------- + +class cMenuPlaylist : public cOsdMenu { +private: + cPlaylist *playlist; + bool addrecords; + void SetHelpKeys(void); + bool AddPlaylistentrys(void); + eOSState Edit(void); + eOSState Play(void); + eOSState New(void); + eOSState Delete(void); + cPlaylistRecord *CurrentPlaylistRecord(void); +public: + cMenuPlaylist(cPlaylist *Playlist); + virtual ~cMenuPlaylist(); + virtual void Move(int From, int To); + virtual eOSState ProcessKey(eKeys Key); + }; + +#endif //__MENUPLAYLIST_H diff --git a/menuplaylists.c b/menuplaylists.c new file mode 100644 index 0000000..aacb9b2 --- /dev/null +++ b/menuplaylists.c @@ -0,0 +1,569 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuplaylists.c 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#include "menuplaylists.h" +#include "dataplaylist.h" +#include "playlist.h" +#include "menuplaylist.h" +#include "i18n.h" +#include "vdrtools.h" +#include <vdr/interface.h> + +// --- cMenuPlaylistEdit ----------------------------------------------------------- + +cMenuPlaylistEdit::cMenuPlaylistEdit(cPlaylist *Playlist, bool New) +:cOsdMenu(New ? tr("Edit$Create Playlist") : tr("Edit$Edit Playlist"), 33) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistEdit::cMenuPlaylistEdit Playlist=%s new=%s", plugin_name, Playlist ? Playlist->Name() : "(null)", New ? "true" : "false"); +#endif + playlist = Playlist; + addIfConfirmed = New; + DisplayStatus[0] = 0; + if (playlist) + { + data = *playlist; + Set(); + } + if (New) + AddSubMenu(new cMenuPlaylist(playlist)); +} + +cMenuPlaylistEdit::~cMenuPlaylistEdit() +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistEdit::~cMenuPlaylistEdit Playlist=%s addIfConfirmed=%s", plugin_name, playlist ? playlist->Name() : "(null)", addIfConfirmed ? "true" : "false"); +#endif + data.lastrecord = NULL; + data.recordcol = NULL; + if (playlist && addIfConfirmed) + delete playlist; // apparently it wasn't confirmed +} + +void cMenuPlaylistEdit::Set(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistEdit::Set Current=%d", plugin_name, Current()); +#endif + for (int i = 0; i < MAXOptionLines; i++) + displayoption[i] = Option_max; + int current = Current(); + Clear(); + Add(new cMenuEditStrItem(tr("OptionPL$Name"), data.name, sizeof(data.name), tr(FileNameChars))); + displayoption[Count()] = Option_playoption1; + Add(new cMenuEditStraItem(tr("OptionPL$In playlistview starts play at"), &data.options[Option_playoption1], PlayOptions_max, PlayOptions)); + displayoption[Count()] = Option_playoption2; + Add(new cMenuEditStraItem(tr("OptionPL$In detailview starts play at"), &data.options[Option_playoption2], PlayOptions_max, PlayOptions)); + displayoption[Count()] = Option_searchnewrecord; + Add(new cMenuEditStraItem(tr("OptionPL$Search new records on folders"), &data.options[Option_searchnewrecord], 3, NoYesDefault)); + displayoption[Count()] = Option_searchrecordsub; + Add(new cMenuEditStraItem(tr("OptionPL$Search records on subfolders"), &data.options[Option_searchrecordsub], 3, NoYesDefault)); + displayoption[Count()] = Option_playonlynew; + Add(new cMenuEditStraItem(tr("OptionPL$Play only new Records"), &data.options[Option_playonlynew], 3, NoYesDefault)); + displayoption[Count()] = Option_jumpmark; + Add(new cMenuEditStraItem(tr("OptionPL$Jump to first segment of movie"), &data.options[Option_jumpmark], 3, NoYesDefault)); + displayoption[Count()] = Option_confirmstartnewrecord; + Add(new cMenuEditStraItem(tr("OptionPL$Confirm start new record"), &data.options[Option_confirmstartnewrecord], 3, NoYesDefault)); + displayoption[Count()] = Option_deletefromlist; + Add(new cMenuEditStraItem(tr("OptionPL$Remove records after play from list"), &data.options[Option_deletefromlist], 3, NoYesDefault)); + displayoption[Count()] = Option_deleterecord; + Add(new cMenuEditStraItem(tr("OptionPL$Delete records after play"), &data.options[Option_deleterecord], 3, NoYesDefault)); + if (data.options[Option_deleterecord] != NoYesDefault_no) + { + displayoption[Count()] = Option_confirmdeleterecord; + Add(new cMenuEditStraItem(tr("OptionPL$ Confirm delete records"), &data.options[Option_confirmdeleterecord], 3, NoYesDefault)); + } + SetCurrent(Get(current)); +} + +eOSState cMenuPlaylistEdit::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuPlaylistEdit::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + int m_searchnewrecord = data.options[Option_searchnewrecord]; + int m_jumpmark = data.options[Option_jumpmark]; + int m_deleterecord = data.options[Option_deleterecord]; + int m_playoption = data.options[Option_playoption1]; + bool hSubMenu = HasSubMenu(); + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuPlaylistEdit::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (m_searchnewrecord != data.options[Option_searchnewrecord] || m_jumpmark != data.options[Option_jumpmark] || m_deleterecord != data.options[Option_deleterecord]) + { + Set(); + Display(); + } else if (m_playoption != data.options[Option_playoption1] && data.options[Option_playoption1] == PlayOptions_selectpos) + { + data.options[Option_playoption1] = m_playoption < PlayOptions_selectpos ? PlayOptions_question : PlayOptions_lastplay; + RefreshCurrent(); + } + + char *buffer = NULL; + eOptions display = (Current() >= 0) && (Current() < MAXOptionLines) ? displayoption[Current()] : Option_max; + if (display < Option_max && data.OptionInherited(display)) + asprintf(&buffer, "%s %s", tr("OptionPL$Effective setting is:"), (display == Option_playoption1 || display == Option_playoption2) ? PlayOptions[data.Playoption(display)] : NoYesDefault[data.Option(display)]); + if (buffer) + { + if (strcmp(DisplayStatus, buffer)) + { + strn0cpy(DisplayStatus, buffer, MAXOSDTEXTWIDTH); + SetStatus(DisplayStatus); + } + free(buffer); + } else + { + if (strlen(DisplayStatus)) + { + DisplayStatus[0] = 0; + SetStatus(NULL); + } + } + if (hSubMenu && !HasSubMenu()) + { + if (playlist && playlist->RecordCol2() && !playlist->RecordCol2()->Count()) + state = osBack; // empty new list +//TODO name + RefreshCurrent(); // name + } + + cPlaylist *tempplaylist = NULL; + bool namefound = false; + switch (state) + { + case osUnknown: switch (Key) + { + case kOk: strn0cpy(data.name, skipspace(stripspace(data.name)), sizeof(data.name)); + Display(); + if (!strlen(data.name)) + { + ERROR(tr("Error$Missing playlist name!")); + break; + } + tempplaylist = PlaylistCol.First(); + while (tempplaylist) + { + if (tempplaylist != playlist && !strcasecmp(tempplaylist->name, data.name)) + { + namefound = true; + break; + } + tempplaylist = PlaylistCol.Next(tempplaylist); + } + if (namefound) + { + ERROR(tr("Error$same name of playlist exists!")); + break; + } + if (playlist) + { + if (data != *playlist) + { + if (strcmp(data.name, playlist->name)) + playlist->SetChange(); + *playlist = data; + if (addIfConfirmed) + PlaylistCol.Add(playlist); + PlaylistCol.Save(); + if (verbose.u) + isyslog("%s: playlist %d %s (%s)", plugin_name, playlist->Index() + 1, addIfConfirmed ? "added" : "modified", playlist->name); + addIfConfirmed = false; + } + state = osBack; + } + break; + case kRed: + case kGreen: + case kYellow: + case kBlue: state = osContinue; + break; + default: break; + } + break; + case osBack: if (playlist && !strlen(playlist->name) && playlist->RecordCol2() && playlist->RecordCol2()->Count() && playlist->RecordCol2()->GetChange() && !Interface->Confirm(tr("Discard all changes?"))) + state = osContinue; + default: break; + } + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuPlaylistEdit::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} + +// --- cMenuPlaylistsItem -------------------------------------------------------- + +cMenuPlaylistsItem::cMenuPlaylistsItem(cPlaylist *Playlist) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistsItem::cMenuPlaylistsItem Playlist=%s", plugin_name, Playlist ? Playlist->Name() : "(null)"); +#endif + playlist = Playlist; + Set(); +} + +cMenuPlaylistsItem::~cMenuPlaylistsItem() +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistsItem::~cMenuPlaylistsItem Playlist=%s", plugin_name, playlist ? playlist->Name() : "(null)"); +#endif +} + +bool cMenuPlaylistsItem::operator< (const cListObject &ListObject) +{ + return strcmp(playlist->Name(), ((cMenuPlaylistsItem *)&ListObject)->playlist->Name()) < 0; +} + +void cMenuPlaylistsItem::Set(void) +{ + char *buffer = NULL; + asprintf(&buffer, "%d\t%d\t%s", playlist->RecordCount(), playlist->RecordNew(), playlist->Name()); + SetText(buffer, false); +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylistsItem::Set SetText=%s", plugin_name, buffer); +#endif +} + +// --- cMenuPlaylists ----------------------------------------------------------- + +cMenuPlaylists::cMenuPlaylists(void) +:cOsdMenu(tr("Display$Display Playlists"), 4, 4) +{ +#ifdef PL_Debug1 + dsyslog("%s: cMenuPlaylists::cMenuPlaylists", plugin_name); +#endif + helpkeys = 1; + +#if VDRVERSNUM >= 10311 + if (Recordings.NeedsUpdate()) + { + STATUS(tr("scanning recordings...")); +#else + if (time(NULL) - LoadTime_Recordings > 3600) + { + LoadTime_Recordings = time(NULL); +#ifdef HAVE_ELCHI + Interface->Status(tr("scanning recordings..."), Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(tr("scanning recordings...")); +#endif + Interface->Flush(); +#endif + if (verbose.u) + isyslog("%s: loading recordings", plugin_name); + Recordings.Load(); + if (verbose.u) + isyslog("%s: %d recordings loaded", plugin_name, Recordings.Count()); + PlaylistSort.Clear(); + PlaylistMark.Clear(); + } else + { +#if VDRVERSNUM < 10311 +#ifdef HAVE_ELCHI + Interface->Status(tr("Display$prepare playlists display..."), Setup.Theme == themeVanilla ? clrBlack : (eDvbColor)fginfofont, Setup.Theme == themeVanilla ? clrCyan : clrInfoLine); +#else + Interface->Status(tr("Display$prepare playlists display...")); +#endif + Interface->Flush(); +#else + STATUS(tr("Display$prepare playlists display...")); +#endif + } + if (verbose.u) + isyslog("%s: loading playlists", plugin_name); + SelectPLR = NULL; + cMenuPlaylistsItem *selitem = NULL; + PlaylistCol.Load(PluginPlaylist->ExpandPath("playlists.conf"), false); + for (cPlaylist *playlist = PlaylistCol.First(); playlist; playlist = PlaylistCol.Next(playlist)) + if (playlist->RecordCol2()) + { + char *tempname = NULL; + asprintf(&tempname, "playlists.%s.conf", playlist->Name()); + playlist->RecordCol2()->Load(PluginPlaylist->ExpandPath(tempname), false); + free(tempname); + cPlaylistRecord *plr_n = NULL; + for (cPlaylistRecord *plr = playlist->First_PLR(); plr; plr = plr_n) + { + plr->Playlist(playlist); + plr_n = playlist->Next_PLR(plr); + if (!plr->IsDir() && plr->Start() == 0) + playlist->RecordCol2()->Del(plr); + } + if (playlist->SearchRecords()) + playlist->RecordCol2()->SaveWithFilename(); + if (verbose.u) + isyslog("%s playlist '%s' contain %d records, %d new", plugin_name, playlist->Name(), playlist->RecordCount(), playlist->RecordNew()); + cMenuPlaylistsItem *item = new cMenuPlaylistsItem(playlist); + Add(item); + if (strcasecmp(playlist->Name(), lastplaylist.u) == 0) + { + selitem = item; + SelectPLR = playlist->First_PLR(); + } + } + Sort(); + SetStatus(NULL); + if (selitem) + SetCurrent(selitem); + SetHelpKeys(); + Display(); +} + +cMenuPlaylists::~cMenuPlaylists(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::~cMenuPlaylists", plugin_name); +#endif +} + +void cMenuPlaylists::SetHelpKeys(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::SetHelpKeys", plugin_name); +#endif + if (Count()) + switch (helpkeys) + { + case 1: SetHelp(okstartplay.u ? tr("Edit") : tr("Play"), tr("New"), tr("Delete"), "-->"); break; + case 2: SetHelp("<--", okstartplay.u ? NULL : tr("Edit"), tr("Option"), NULL); break; + } + else + { + helpkeys = 1; + SetHelp(NULL, tr("New"), NULL, NULL); + } +} + +eOSState cMenuPlaylists::Play(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::Play", plugin_name); +#endif + cPlaylist *playlist = CurrentPlaylist(); + if (HasSubMenu() || !playlist) + return osContinue; + if (verbose.u) + isyslog("%s: start play Playlist %d Option=%d", plugin_name, playlist->Index() + 1, playlist->Playoption(Option_playoption1)); + playlist->SearchRecords(); + cPlaylistRecord *plr_firstnomal = playlist->Firstnormal_PLR(); + cPlaylistRecord *plr_firstnew = playlist->Firstnew_PLR(); + cPlaylistRecord *plr_lastplayed = playlist->Lastplayed_PLR(); + switch (playlist->Playoption(Option_playoption1)) + { + case PlayOptions_selectpos: // select not allow + case PlayOptions_firstpos: SelectPLR = plr_firstnomal; + break; + case PlayOptions_firstnew: if (plr_firstnew) + SelectPLR = plr_firstnew; + else + SelectPLR = Interface->Confirm(tr("Question$No new recording found! Play first?")) ? plr_firstnomal : NULL; + break; + case PlayOptions_lastplay: if (plr_lastplayed) + { + SelectPLR = plr_lastplayed; + break; + } + // no break! + case PlayOptions_question: if (plr_lastplayed && Interface->Confirm(tr("Question$Play last played recording?"))) + { + SelectPLR = plr_lastplayed; + break; + } + if (plr_firstnew && plr_firstnew != plr_firstnomal && Interface->Confirm(tr("Question$Play first new recording?"))) + { + SelectPLR = plr_firstnew; + break; + } + SelectPLR = plr_firstnomal; + break; + } + return SelectPLR ? osUser9 : osContinue; // osUSer9 starts play playlist with SelectPLR in cControlMenu::ProcessKey +} + +eOSState cMenuPlaylists::New(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::New", plugin_name); +#endif + if (HasSubMenu()) + return osContinue; + FREENULL(LastSelectedRecord); + return AddSubMenu(new cMenuPlaylistEdit(new cPlaylist, true)); +} + +eOSState cMenuPlaylists::Delete(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::Delete", plugin_name); +#endif + cPlaylist *playlist = CurrentPlaylist(); + if (PlayedPLR && PlayedPLR->Playlist() == playlist) + { + ERROR(tr("Error$Playlist is currently used by played recording")); + return osContinue; + } + if (playlist && playlist->RecordCol2()) + { + if (Interface->Confirm(tr("Edit$Delete Playlist?"))) + { + if (verbose.u) + isyslog("%s: Playlist %d deleted", plugin_name, playlist->Index() + 1); + playlist->RecordCol2()->DeleteFile(); + PlaylistCol.Del(playlist); + PlaylistCol.Save(); + cOsdMenu::Del(Current()); + Display(); + } + } + return osContinue; +} + +eOSState cMenuPlaylists::EditPlaylist(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::EditPlaylist", plugin_name); +#endif + if (HasSubMenu() || !CurrentPlaylist()) + return osContinue; + isyslog("%s: editing Playlist %d", plugin_name, CurrentPlaylist()->Index() + 1); + cPlaylist *playlist = CurrentPlaylist(); + if (playlist) + playlist->SearchRecords(); + return AddSubMenu(new cMenuPlaylist(playlist)); +} + +eOSState cMenuPlaylists::EditOption(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::EditOption", plugin_name); +#endif + if (HasSubMenu() || !CurrentPlaylist()) + return osContinue; + isyslog("%s: editing option Playlist %d", plugin_name, CurrentPlaylist()->Index() + 1); + return AddSubMenu(new cMenuPlaylistEdit(CurrentPlaylist())); +} + +cPlaylist *cMenuPlaylists::CurrentPlaylist(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuPlaylists::CurrentPlaylist", plugin_name); +#endif + cMenuPlaylistsItem *item = (cMenuPlaylistsItem *)Get(Current()); + return item ? item->Playlist() : NULL; +} + +eOSState cMenuPlaylists::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuPlaylists::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + cOsdItem *Item; + int n; + int nPlaylists = PlaylistCol.Count(); + bool hSubMenu = HasSubMenu(); + + eOSState state = cOsdMenu::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuPlaylists::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (!HasSubMenu() && hSubMenu) + { + if (nPlaylists == PlaylistCol.Count()) + { + Item = Get(Current()); + RefreshCurrent(); + } else + Add((Item = new cMenuPlaylistsItem(PlaylistCol.Get(nPlaylists)))); + Sort(); + SetCurrent(Item); + cPlaylist *playlist = CurrentPlaylist(); + if (playlist) + { + playlist->SearchRecords(); + RefreshCurrent(); + Display(); + playlist->SaveRecordCol(); + } else + { + RefreshCurrent(); + Display(); + } + } + + switch (state) + { + case osUnknown: switch (Key) + { + case k0...k9: n = (Key == k0) ? 10 : (Key - k0); + if (n > Count()) + break; + SetCurrent(Get(--n)); + // no break! + case kOk: state = okstartplay.u ? Play() : EditPlaylist(); + break; + case kRed: switch (helpkeys) + { + case 1: okstartplay.u ? EditPlaylist() : state = Play(); break; + case 2: helpkeys = 1; break; + } + break; + case kGreen: switch (helpkeys) + { + case 1: state = New(); break; + case 2: state = okstartplay.u ? osUnknown : EditPlaylist(); break; + } + break; + case kYellow: switch (helpkeys) + { + case 1: state = Delete(); break; + case 2: state = EditOption(); break; + } + break; + case kBlue: switch (helpkeys) + { + case 1: helpkeys = 2; break; + case 2: break; + } + break; + case kUser1: state = EditPlaylist(); + break; + case kUser2: state = Play(); + break; + case kUser3: state = New(); + break; + default: break; + } + break; + default: break; + } + if (!HasSubMenu() && Key != kNone) + SetHelpKeys(); + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuPlaylists::ProcessKey returned OSState=%s", plugin_name, OSStateName(state)); +#endif + return state; +} diff --git a/menuplaylists.h b/menuplaylists.h new file mode 100644 index 0000000..6bf67d9 --- /dev/null +++ b/menuplaylists.h @@ -0,0 +1,62 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: menuplaylists.h 0.1 2004/09/23 23:42:32 hflor Exp $ + */ + +#ifndef __MENUPLAYLISTS_H +#define __MENUPLAYLISTS_H + +#include "dataplaylist.h" +#include <vdr/osd.h> +#include <vdr/menu.h> + +// --- cMenuPlaylistEdit -------------------------------------------------------- + +class cMenuPlaylistEdit : public cOsdMenu { +private: + cPlaylist *playlist; + cPlaylist data; + bool addIfConfirmed; + eOptions displayoption[MAXOptionLines]; +public: + cMenuPlaylistEdit(cPlaylist *Playlist, bool New = false); + virtual ~cMenuPlaylistEdit(); + virtual void Set(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +// --- cMenuPlaylistsItem -------------------------------------------------------- + +class cMenuPlaylistsItem : public cOsdItem { +private: + cPlaylist *playlist; +public: + cMenuPlaylistsItem(cPlaylist *Playlist); + virtual ~cMenuPlaylistsItem(); + virtual bool operator< (const cListObject &ListObject); + virtual void Set(void); + cPlaylist *Playlist(void) { return playlist; } + }; + +// --- cMenuPlaylists ----------------------------------------------------------- + +class cMenuPlaylists : public cOsdMenu { +private: + int helpkeys; + void SetHelpKeys(void); + eOSState Play(void); + eOSState New(void); + eOSState Delete(void); + eOSState EditPlaylist(void); + eOSState EditOption(void); + cPlaylist *CurrentPlaylist(void); +public: + cMenuPlaylists(void); + virtual ~cMenuPlaylists(); + virtual eOSState ProcessKey(eKeys Key); + }; + +#endif //__MENUPLAYLISTS_H diff --git a/menusetup.c b/menusetup.c new file mode 100644 index 0000000..39eb387 --- /dev/null +++ b/menusetup.c @@ -0,0 +1,303 @@ +/* + * playlist: 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/08 02:34:00 hflor Exp $ + */ + +#include "menusetup.h" +#include "playlist.h" +#include "menuplaylists.h" +#include "menucontrol.h" +#include "i18n.h" +#include "vdrtools.h" +#include <vdr/plugin.h> + +// --- cMenuSetupPlayList ------------------------------------------------------- + +cMenuSetupPlayList::cMenuSetupPlayList(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupPlayList::cMenuSetupPlayList", plugin_name); +#endif + store = false; + changedefault = false; + + #define StoreValue(T) T.o = T.u + #define StoreValueFile(T) strcpy(T.o, T.u) + + // var pos7 + StoreValue (charentry); + StoreValue (charfolder); + StoreValue (charrecord); + StoreValue (commandline_preference); + StoreValueFile (lastplaylist); + StoreValueFile (mainmenu_name); + StoreValue (mainmenu_visible); + StoreValue (confirmdelplentry); + StoreValue (okstartplay); + StoreValue (deleterecords); + StoreValueFile (pathplaylists); + StoreValue (startoption); + StoreValue (storeplaylist); + StoreValue (timeoutreadrecords); + StoreValue (verbose); + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + StoreValue (PL_options[i]); + + #undef StoreValue + #undef StoreValueFile + + Set(); +} + +cMenuSetupPlayList::~cMenuSetupPlayList(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupPlayList::~cMenuSetupPlayList 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 (charentry); + RestoreValue (charfolder); + RestoreValue (charrecord); + RestoreValue (commandline_preference); + RestoreValueFile (lastplaylist); + RestoreValueFile (mainmenu_name); + RestoreValue (mainmenu_visible); + RestoreValue (confirmdelplentry); + RestoreValue (okstartplay); + RestoreValue (deleterecords); + RestoreValueFile (pathplaylists); + RestoreValue (startoption); + RestoreValue (storeplaylist); + RestoreValue (timeoutreadrecords); + RestoreValue (verbose); + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + RestoreValue (PL_options[i]); + + #undef RestoreValue + #undef RestoreValueFile + } +} + +void cMenuSetupPlayList::Store(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupPlayList::Store", plugin_name); +#endif + + #define SaveValue(T, N) if (T.u != T.o) SetupStore(N, T.u); + #define SaveValueChar(T, N) if (T.u != T.o) SetupStore(N, T.u + 256); + #define SaveValueFile(T, N) if (strcmp(T.u, T.o)) SetupStore(N, T.u); + + // var pos9 + SaveValueChar (charentry, "cahre"); + SaveValueChar (charfolder, "charf"); + SaveValueChar (charrecord, "charr"); + SaveValue (commandline_preference, "commandline"); + SaveValueFile (lastplaylist, "lastpl"); + SaveValueFile (mainmenu_name, "name"); + SaveValue (mainmenu_visible, "visible"); + SaveValue (confirmdelplentry, "deletentry"); + SaveValue (okstartplay, "okplay"); + SaveValue (deleterecords, "delete"); + SaveValueFile (pathplaylists, "path"); + SaveValue (startoption, "start"); + SaveValue (storeplaylist, "storepl"); + SaveValue (timeoutreadrecords, "timerecords"); + SaveValue (verbose, "verbose"); + SaveValue (PL_options[Option_confirmdeleterecord], "confdelete"); + SaveValue (PL_options[Option_confirmstartnewrecord], "startnew"); + SaveValue (PL_options[Option_deletefromlist], "deletel"); + SaveValue (PL_options[Option_deleterecord], "deleter"); + SaveValue (PL_options[Option_jumpmark], "jumpmark"); + SaveValue (PL_options[Option_playoption1], "playoption1"); + SaveValue (PL_options[Option_playoption2], "playoption2"); + SaveValue (PL_options[Option_playonlynew], "playonlynew"); + SaveValue (PL_options[Option_searchnewrecord], "searchnew"); + SaveValue (PL_options[Option_searchrecordsub], "searchsub"); + + #undef SaveValue + #undef SaveValueChar + #undef SaveValueFile + + store = true; +} + +void cMenuSetupPlayList::Set(bool sel) +{ +#ifdef PL_Debug2 + dsyslog("%s: cMenuSetupPlayList::Set Current=%d", plugin_name, Current()); +#endif + int current = Current(); + Clear(); + fileitempos = -1; + + #define DisplayLine(T) !T.h && (!commandline_preference.u || !T.c) + + Add(new cOsdItem (tr("Setup$Display playlists now"), osUser6)); + Add(new cOsdItem (tr("Setup$Play last playlist now"), osUser7)); + 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(startoption)) + Add(new cMenuEditStraItem(tr("Setup$Startoptions for plugin"), &startoption.u, 4, StartOptions)); + if (DisplayLine(okstartplay)) + Add(new cMenuEditBoolItem(tr("Setup$Press OK in Playlistview starts"), &okstartplay.u, tr("Setup$Edit"), tr("Setup$Play"))); + if (DisplayLine(storeplaylist)) + Add(new cMenuEditBoolItem(tr("Setup$Store playlist after change"), &storeplaylist.u, tr("Setup$automatically"), tr("Setup$after question"))); + if (DisplayLine(deleterecords)) + Add(new cMenuEditBoolItem(tr("Setup$Allow delete Records"), &deleterecords.u)); + if (DisplayLine(confirmdelplentry)) + Add(new cMenuEditBoolItem(tr("Setup$Confirm delete playlistentries"), &confirmdelplentry.u)); + if (DisplayLine(pathplaylists)) + { + fileitempos = Count(); + Add(new cMenuEditStrItem (tr("Setup$Path for store playlists"), pathplaylists.u, sizeof(pathplaylists.u), FileNameCharsAllowed)); + } + Add(new cMenuEditBoolItem(tr("Setup$Change default options for playlist"), &changedefault)); + if (changedefault) + { + if (DisplayLine(PL_options[Option_playoption1])) + Add(new cMenuEditStraItem(tr("OptionPL$ In playlistview starts play at"), &PL_options[Option_playoption1].u, PlayOptions_max - 1, PlayOptions)); + if (DisplayLine(PL_options[Option_playoption2])) + Add(new cMenuEditStraItem(tr("OptionPL$ In detailview starts play at"), &PL_options[Option_playoption2].u, PlayOptions_max - 1, PlayOptions)); + if (DisplayLine(PL_options[Option_searchnewrecord])) + Add(new cMenuEditBoolItem(tr("OptionPL$ Search new records on folders"), &PL_options[Option_searchnewrecord].u)); + if (DisplayLine(PL_options[Option_searchrecordsub])) + Add(new cMenuEditBoolItem(tr("OptionPL$ Search new records on subfolders"), &PL_options[Option_searchrecordsub].u)); + if (DisplayLine(PL_options[Option_playonlynew])) + Add(new cMenuEditBoolItem(tr("OptionPL$ Play only new Records"), &PL_options[Option_playonlynew].u)); + if (DisplayLine(PL_options[Option_jumpmark])) + Add(new cMenuEditBoolItem(tr("OptionPL$ Jump to first segment of movie"), &PL_options[Option_jumpmark].u)); + if (DisplayLine(PL_options[Option_confirmstartnewrecord])) + Add(new cMenuEditBoolItem(tr("OptionPL$ Confirm start new record"), &PL_options[Option_confirmstartnewrecord].u)); + if (DisplayLine(PL_options[Option_deletefromlist])) + Add(new cMenuEditBoolItem(tr("OptionPL$ Remove records after play from list"), &PL_options[Option_deletefromlist].u)); + if (DisplayLine(PL_options[Option_deleterecord]) && deleterecords.u) + Add(new cMenuEditBoolItem(tr("OptionPL$ Delete records after play"), &PL_options[Option_deleterecord].u)); + if (DisplayLine(PL_options[Option_confirmdeleterecord]) && PL_options[Option_deleterecord].u && deleterecords.u) + Add(new cMenuEditBoolItem(tr("OptionPL$ Confirm delete records"), &PL_options[Option_confirmdeleterecord].u)); + } + Add(new cMenuEditBoolItem(tr("Setup$Change Character for identification"), &changechar)); + if (changechar) + { + if (DisplayLine(charfolder)) + Add(new cMenuEditChrItem(tr("OptionPL$ Character for folders"), &charfolder.u, AllCharsAllowed)); + if (DisplayLine(charentry)) + Add(new cMenuEditChrItem(tr("OptionPL$ Character for records in folders"), &charentry.u, AllCharsAllowed)); + if (DisplayLine(charrecord)) + Add(new cMenuEditChrItem(tr("OptionPL$ Character for normal records"), &charrecord.u, AllCharsAllowed)); + } + if (DisplayLine(verbose)) + Add(new cMenuEditBoolItem(tr("Setup$Verbose Log Mode"), &verbose.u)); + if (sel && changechar) + SetCurrent(Get(Count() - 1)); + + #undef DisplayLine + +#ifdef PL_Debug2 + dsyslog("%s: Count=%d", plugin_name, Count()); +#endif + SetCurrent(Get(current)); +} + +eOSState cMenuSetupPlayList::ProcessKey(eKeys Key) +{ +#ifdef PL_Debug3 + bool noneKey = Key == kNone; + if (!noneKey) + dsyslog("%s: cMenuSetupPlayList::ProcessKey Key=%s", plugin_name, KeyName(Key)); +#endif + static char oldstatus[MAXOSDTEXTWIDTH]; + char status[MAXOSDTEXTWIDTH]; + int pathlen; + + int m_commandline_preference = commandline_preference.u; + int m_mainmenu_visible = mainmenu_visible.u; + int m_deleterecords = deleterecords.u; + int m_changedefault = changedefault; + int m_deleterecord = PL_options[Option_deleterecord].u; + int m_changechar = changechar; + int m_playoption = PL_options[Option_playoption1].u; + + eOSState state = cMenuSetupPage::ProcessKey(Key); +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + { + dsyslog("%s: cMenuSetupPlayList::ProcessKey OSState=%s", plugin_name, OSStateName(state)); + noneKey = false; + } +#endif + + if (m_commandline_preference != commandline_preference.u || m_mainmenu_visible != mainmenu_visible.u || m_deleterecords != deleterecords.u || m_changedefault != changedefault || m_deleterecord != PL_options[Option_deleterecord].u || m_changechar != changechar) + { + Set(m_changechar != changechar); + Display(); + if (!m_changedefault && changedefault) + { + for (int i = 0; i < 5; i++) + CursorDown(); + for (int i = 0; i < 5; i++) + CursorUp(); + } + } else if (m_playoption != PL_options[Option_playoption1].u && PL_options[Option_playoption1].u == PlayOptions_selectpos) + { + PL_options[Option_playoption1].u = m_playoption < PlayOptions_selectpos ? PlayOptions_question : PlayOptions_lastplay; + RefreshCurrent(); + } + if (Current() == fileitempos) + { + const char *temp = PluginPlaylist->ExpandPath("", false); + pathlen = strlen(temp); + if (pathlen > AKTOSDTEXTWIDTH - 10) + sprintf(status, "...%s", temp + pathlen - AKTOSDTEXTWIDTH + 10); + else + strcpy(status, temp); + if (oldstatus != status) + { + SetStatus(status); + strcpy(oldstatus, status); + } + } else if (strlen(oldstatus)) + { + SetStatus(NULL); + oldstatus[0] = 0; + } + switch (state) + { + case osUser6: state = AddSubMenu(new cMenuPlaylists); + break; + case osUser7: { + cMenuPlaylists *menu = new cMenuPlaylists; + if (SelectPLR) + menu->ProcessKey(kUser2); + state = AddSubMenu(menu); + } + break; + case osUser9: if (SelectPLR) + { + cControl::Shutdown(); // Start play (SelectPLR) + cControl::Launch(new cControlPlaylist); + } + state = osEnd; + break; + default: break; + } + +#ifdef PL_Debug3 + if (!noneKey || (state != osUnknown && state != osContinue)) + dsyslog("%s: cMenuSetupPlayList::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..aac738f --- /dev/null +++ b/menusetup.h @@ -0,0 +1,32 @@ +/* + * playlist: 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 2004/10/08 02:34:00 hflor Exp $ + */ + +#ifndef __MENUSETUP_H +#define __MENUSETUP_H + +#include <vdr/menu.h> +#include <vdr/menuitems.h> + +// --- cMenuSetupPlayList ------------------------------------------------------- + +class cMenuSetupPlayList : public cMenuSetupPage { +private: + int store; + int fileitempos; + int changedefault; + int changechar; +protected: + virtual void Store(void); +public: + cMenuSetupPlayList(void); + virtual ~cMenuSetupPlayList(void); + virtual void Set(bool sel = false); + virtual eOSState ProcessKey(eKeys Key); + }; + +#endif //__MENUSETUP_H diff --git a/playlist.c b/playlist.c new file mode 100644 index 0000000..484644a --- /dev/null +++ b/playlist.c @@ -0,0 +1,608 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: playlist.c 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#include "playlist.h" +#include "menuplaylists.h" +#include "menucontrol.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 = "playlist for recordings"; + +/* TODO +option playonlynewrecords +*/ +// Global variables that control the overall behaviour: + +// var pos2 +tParamFile playlistconfigfile = { false, false, false, "playlist.conf", "playlist.conf" }; +#ifdef HAVE_ICONPATCH +tParamChar charentry = { false, false, false, 236 }; +tParamChar charfolder = { false, false, false, 237 }; +tParamChar charrecord = { false, false, false, 249 }; +#else +tParamChar charentry = { false, false, false, 'e' }; +tParamChar charfolder = { false, false, false, 'f' }; +tParamChar charrecord = { false, false, false, 'r' }; +#endif +tParamInt commandline_preference = { false, false, false, true }; +tParamFile lastplaylist = { false, false, false, "" }; +tParamFile mainmenu_name = { false, false, false, "Playlist" }; +tParamInt mainmenu_visible = { false, false, false, true }; +tParamInt confirmdelplentry = { false, false, false, true }; +tParamInt okstartplay = { false, false, false, true }; +tParamInt deleterecords = { false, false, false, true }; +tParamFile pathplaylists = { false, false, false, "" }; +tParamInt startoption = { false, false, false, 0 }; +tParamInt storeplaylist = { false, false, false, 0 }; +tParamInt timeoutreadrecords = { false, false, false, 60 }; +tParamInt verbose = { false, false, false, false, true }; +tParamInt PL_options[Option_max] ={{ false, false, false, true }, // confirmdeleterecord + { false, false, false, false }, // confirmstartnewrecord + { false, false, false, true }, // deletefromlist + { false, false, false, false }, // deleterecord + { false, false, false, true }, // jumpmark + { false, false, false, PlayOptions_firstnew }, // playoption1 + { false, false, false, PlayOptions_selectpos }, // playoption2 + { false, false, false, false }, // playonlynew + { false, false, false, true }, // searchnewrecord + { false, false, false, true }}; // searchrecordsub + +char plugin_name[MaxFileName] = "Playlist"; +char DisplayStatus[MAXOSDTEXTWIDTH] = ""; +const char *NoYesDefault[NoYesDefault_max]; +const char *StartOptions[Start_max]; +const char *PlayOptions[PlayOptions_max]; +char *FileNameCharsAllowed = NULL; +char *AllCharsAllowed = NULL; +char *LastSelectedRecord = NULL; +bool ControlMenuIsOpen = false; +#if VDRVERSNUM < 10311 +cRecordings Recordings; +time_t LoadTime_Recordings; +#endif + +void DisplaySetings(void) +{ + #define WriteSource(T) plugin_name, T.r ? 'r' : ' ', T.c ? 'c' : ' ' + #define IsDefault(T) WriteSource(T), T.u == T.d ? '*' : ' ' + #define IsDefaultChar(T) WriteSource(T), strcmp(T.u, T.d) ? ' ' : '*' + #define BoolValue(T) IsDefault(T), T.u ? "yes" : "no" + + // var pos3 + ExpandEnvironment(&pathplaylists); + 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", IsDefaultChar(mainmenu_name), mainmenu_name.u); + } + +#ifdef PL_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", IsDefaultChar(mainmenu_name), mainmenu_name.u); + } +#endif + + #undef WriteSource + #undef IsDefault + #undef IsDefaultChar + #undef BoolValue +} + +void ExpandEnvironment(tParamFile *FileStruc) +{ +#ifdef PL_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 PL_Debug2 + dsyslog("%s: ExpandEnvironment return=%s", plugin_name, FileStruc->e); +#endif +} + +// --- cPluginPlaylist ---------------------------------------------------------- + +cPluginPlaylist *PluginPlaylist; + +cPluginPlaylist::cPluginPlaylist(void) +{ +#ifdef PL_Debug1 + dsyslog("%s: cPluginPlaylist::cPluginPlaylist", 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! + OSDLanguage = -1; + PluginPlaylist = this; +} + +cPluginPlaylist::~cPluginPlaylist() +{ +#ifdef PL_Debug1 + dsyslog("%s: cPluginPlaylist::~cPluginPlaylist", plugin_name); +#endif + // Clean up after yourself! + FREENULL(FileNameCharsAllowed); + FREENULL(AllCharsAllowed); + FREENULL(LastSelectedRecord); + PluginPlaylist = NULL; +} + +void cPluginPlaylist::TestAndSetOSDLanguage(void) +{ +#ifdef PL_Debug2 + dsyslog("%s: cPluginPlaylist::TestAndSetOSDLanguage OSDLanguage=%d", plugin_name, Setup.OSDLanguage); +#endif + if (OSDLanguage != Setup.OSDLanguage) + { + OSDLanguage = Setup.OSDLanguage; + + StartOptions[Start_DisplayPL] = tr("Setup$Display PL"); + StartOptions[Start_DisplayLast] = tr("Setup$Display last PL"); + StartOptions[Start_PlayLast] = tr("Setup$Play last PL"); + StartOptions[Start_NewEmpty] = tr("Setup$new empty PL"); + NoYesDefault[NoYesDefault_no] = tr("no"); + NoYesDefault[NoYesDefault_yes] = tr("yes"); + NoYesDefault[NoYesDefault_defaultPlugin] = tr("OptionPL$[from Setup]"); + NoYesDefault[NoYesDefault_defaultPlaylist] = tr("OptionPL$[from Playlist]"); + NoYesDefault[NoYesDefault_defaultRecordDir] = tr("OptionPL$[from Folder]"); + PlayOptions[PlayOptions_firstpos] = tr("OptionPL$first pos"); + PlayOptions[PlayOptions_firstnew] = tr("OptionPL$first new"); + PlayOptions[PlayOptions_lastplay] = tr("OptionPL$last played"); + PlayOptions[PlayOptions_selectpos] = tr("OptionPL$seletced pos"); + PlayOptions[PlayOptions_question] = tr("OptionPL$question"); + PlayOptions[PlayOptions_defaultPlugin] = tr("OptionPL$[from Setup]"); + FREENULL(FileNameCharsAllowed); + asprintf(&FileNameCharsAllowed, "%s/$(){}!%%@", tr(FileNameChars)); + if (!AllCharsAllowed) + { + AllCharsAllowed = MALLOC(char, 193); + char *next = AllCharsAllowed; + for (int i = 32; i <= 127; i++) + *next++ = i; + for (int i = 160; i <= 255; i++) + *next++ = i; + *next = 0; + } + } +} + +bool cPluginPlaylist::ProcessArg(int argc, char *argv[]) +{ + int c; + static struct option long_options[] = { + { "delete_begin", no_argument, NULL, 'b' }, + { "nodelete_begin", no_argument, NULL, 'B' }, + { "min_entrys", required_argument, NULL, 'd' }, + { "delete_end", no_argument, NULL, 'e' }, + { "nodelete_end", no_argument, NULL, 'E' }, + { "holdtime_history", required_argument, NULL, 'h' }, + { "visible_in_mainmenu", no_argument, NULL, 'm' }, + { "hide_in_mainmenu", no_argument, NULL, 'M' }, + { "mainmenu_name", required_argument, NULL, 'n' }, + { "holdtime_respones", required_argument, NULL, 'r' }, + { "sort_ascending", no_argument, NULL, 's' }, + { "sort_descending", no_argument, NULL, 'S' }, + { "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 SetvalueChar(T) T.c = true; strn0cpy(T.u, optarg, sizeof(T.u)) + + while ((c = getopt_long(argc, argv, "bBd:eEh:mMn:r:sSvV", long_options, NULL)) != -1) + { + // var pos4 + switch (c) + { + case 1: commandline_preference.h = true; + break; +/* case 'b': Setvalue(delete_b_e) |= 0x1; + break; + case 'B': Setvalue(delete_b_e) &= ~0x1; + break; + case 'd': if (isnumber(optarg)) + { + Setvalue(num_entrys) = atoi(optarg); + Setvalue(delete_b_e) = 0x3; + if (num_entrys.u > 0) break; + } + esyslog("%s: invalid parameter for -d option: %s", plugin_name, optarg); + return false; + case 'e': Setvalue(delete_b_e) |= 0x2; + break; + case 'E': Setvalue(delete_b_e) &= ~0x2; + break; + case 'h': if (isnumber(optarg)) + { + Setvalue(message_in_queue) = atoi(optarg); + if (message_in_queue.u >=5 && message_in_queue.u <= 999) break; + } + esyslog("%s: invalid parameter for -h option: %s range 5-999", plugin_name, optarg); + return false; + case 'm': Setvalue(mainmenu_visible) = true; + break; + case 'M': Setvalue(mainmenu_visible) = false; + break; + case 'n': SetvalueChar(mainmenu_name); + Setvalue(mainmenu_visible) = true; + break; + case 'r': if (isnumber(optarg)) + { + Setvalue(response_in_queue) = atoi(optarg); + if (response_in_queue.u >= 2 && response_in_queue.u <= 199) break; + } + esyslog("%s: invalid parameter for -r option: %s range 2-199", plugin_name, optarg); + return false; + case 's': Setvalue(sortdirection) = true; + break; + case 'S': Setvalue(sortdirection) = false; + break;*/ + case 'v': Setvalue(verbose) = true; + break; + case 'V': Setvalue(verbose) = false; + break; + default: return false; + } + } + + #undef Setvalue + #undef SetvalueChar + + if (optind < argc && argv[optind][0] == '@') + { + strn0cpy(playlistconfigfile.u, &argv[optind][1], sizeof(playlistconfigfile.u)); + optind++; + } + return optind >= argc; +} + +const char *cPluginPlaylist::Version(void) +{ + return VERSION; +} + +const char *cPluginPlaylist::Description(void) +{ + return tr(DESCRIPTION); +} + +const char *cPluginPlaylist::CommandLineHelp(void) +{ + // Return a string that describes all known command line options. + return " -m --visible_in_mainmenu Show the plugin in the mainmenu\n" + " -M --hide_in_mainmenu Hide the plugin in the mainmenu\n" + " -n Name --mainmenu_name=Name Select Name for entry in the mainmenu (set also -m)\n" + " -b --delete_begin Show the delete all messages line at begin of messagelist\n" + " -B --nodelete_begin Hide the delete all messages line at begin of messagelist\n" + " -e --delete_end Show the delete all messages line at end of messagelist\n" + " -E --nodelete_end Hide the delete all messages line at end of messagelist\n" + " -d xx --min_entrys=xx minimum entrys for display delete all messages line at begin and end (include -b and -e)\n" + " -h xx --holdtime_history=xx minimum time (min) for message in historyqueue (OSD-list) 5-999\n" + " -r xx --holdtime_respones=xx minumum time (min) for responses in queue (readable by SAQRESP) 2-199\n" + " -s --sort_ascending sortoption for messagelist (OSD)\n" + " -S --sort_descending sortoption for messagelist (OSD)\n" + " -v --verbose Enable more logging\n" + " -V --noverbose Disable more loggig\n" + " --nosetup_commandline Hide the Preferr Command Line Parameter form setup-menu\n" + " --ns_commandline same as --nosetup_commandline"; + // free: a c f g i j k l o p q t u v w x y z +} + +bool cPluginPlaylist::ProcessArgs(int argc, char *argv[]) +{ + // Implement command line argument processing here if applicable. + return ProcessArg(argc, argv); +} + +#ifdef PL_Debug1 +void TestI18n(char *Test) +{ + Setup.OSDLanguage = 0; + const char *eng = tr(Test); + Setup.OSDLanguage = 1; + const char *deu = tr(Test); + if (eng && deu && strcmp(eng, deu) == 0) + dsyslog("%s: missing: %s", plugin_name, Test); +} +#endif + +bool cPluginPlaylist::Start(void) +{ + // Start any background activities the plugin shall perform. + RegisterI18n(Phrases); + TestAndSetOSDLanguage(); + +#ifdef PL_Debug1 + dsyslog("%s: cPluginPlaylist::Start playlistconfigfile=%s", plugin_name, playlistconfigfile.u); +#endif + + char *p; + char *q = strdup(ConfigDirectory("")); + asprintf(&p, "%s%s%s", q, *(q + strlen(q) - 1) == '/' ? "" : "/", playlistconfigfile.u); + if (!access(playlistconfigfile.u, F_OK) && !access(playlistconfigfile.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(playlistconfigfile.u, F_OK)) + { + f = fopen(playlistconfigfile.u, "r"); +#ifdef PL_Debug2 + dsyslog("%s: cPluginPlaylist::Start open playlistconfigfile=%s", plugin_name, playlistconfigfile.u); +#endif + } else + { + f = fopen(p, "r"); +#ifdef PL_Debug2 + dsyslog("%s: cPluginPlaylist::Start open playlistconfigfile=%s", plugin_name, p); +#endif + } + free(p); + free(q); + if (!f) + { + esyslog("%s: ERROR: cannot open config file: [%s]%s", plugin_name, ConfigDirectory(""), playlistconfigfile.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(""), playlistconfigfile.u); + return false; + } + while(fargc) free(fargv[--fargc]); + } else + { + free(p); + free(q); + if (strcmp(playlistconfigfile.u, playlistconfigfile.d)) + { + esyslog("%s: ERROR: config file not found: [%s]%s", plugin_name, ConfigDirectory(""), playlistconfigfile.u); + return false; + } else if (verbose.u) + isyslog("%s: INFO: config file not found: [%s]%s", plugin_name, ConfigDirectory(""), playlistconfigfile.u); + } + + // 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 (playlistconfigfile); + SetParam (charentry); + SetParam (charfolder); + SetParam (charrecord); + SetParamFile (lastplaylist); + SetParamFile (mainmenu_name); + SetParam (mainmenu_visible); + SetParam (confirmdelplentry); + SetParam (okstartplay); + SetParam (deleterecords); + SetParamFile (pathplaylists); + SetParam (startoption); + SetParam (storeplaylist); + SetParam (timeoutreadrecords); + SetParam (verbose); + for (int i = Option_confirmdeleterecord; i < Option_max; i++) + SetParam (PL_options[i]); + + #undef SetParam + #undef SetParamFile + + if (verbose.u) + isyslog("%s: Start", plugin_name); + DisplaySetings(); + strcpy(lastplaylist.o, lastplaylist.u); + return true; +} + +const char *cPluginPlaylist::MainMenuEntry(void) +{ + return mainmenu_visible.u ? mainmenu_name.u : NULL; +} + +cOsdObject *cPluginPlaylist::MainMenuAction(void) +{ +#ifdef PL_Debug1 + dsyslog("%s: cPluginPlaylist::MainMenuAction", plugin_name); +#endif + TestAndSetOSDLanguage(); + return new cControlMenu; +} + +cMenuSetupPage *cPluginPlaylist::SetupMenu(void) +{ + TestAndSetOSDLanguage(); + return new cMenuSetupPlayList; +} + + +bool cPluginPlaylist::SetupParse(const char *Name, const char *Value) +{ + #define SetParam(T) { T.r = true; T.s = strtol(Value, NULL, 0); } + #define SetParamChar(T) { T.r = true; temp = strtol(Value, NULL, 0); T.s = temp > 255 ? temp - 256 : temp; } + #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 + int temp; + + if (!strcasecmp(Name, "cahre")) SetParamChar (charentry) + else if (!strcasecmp(Name, "charf")) SetParamChar (charfolder) + else if (!strcasecmp(Name, "charr")) SetParamChar (charrecord) + else if (!strcasecmp(Name, "commandline")) SetParam (commandline_preference) + else if (!strcasecmp(Name, "lastpl")) SetParamFile (lastplaylist) + else if (!strcasecmp(Name, "name")) SetParamFile (mainmenu_name) + else if (!strcasecmp(Name, "visible")) SetParam (mainmenu_visible) + else if (!strcasecmp(Name, "deletentry")) SetParam (confirmdelplentry) + else if (!strcasecmp(Name, "okplay")) SetParam (okstartplay) + else if (!strcasecmp(Name, "delete")) SetParam (deleterecords) + else if (!strcasecmp(Name, "path")) SetParamFile (pathplaylists) + else if (!strcasecmp(Name, "start")) SetParam (startoption) + else if (!strcasecmp(Name, "storepl")) SetParam (storeplaylist) + else if (!strcasecmp(Name, "timerecords")) SetParam (timeoutreadrecords) + else if (!strcasecmp(Name, "verbose")) SetParam (verbose) + else if (!strcasecmp(Name, "confdelete")) SetParam (PL_options[Option_confirmdeleterecord]) + else if (!strcasecmp(Name, "startnew")) SetParam (PL_options[Option_confirmstartnewrecord]) + else if (!strcasecmp(Name, "deletel")) SetParam (PL_options[Option_deletefromlist]) + else if (!strcasecmp(Name, "deleter")) SetParam (PL_options[Option_deleterecord]) + else if (!strcasecmp(Name, "jumpmark")) SetParam (PL_options[Option_jumpmark]) + else if (!strcasecmp(Name, "playoption1")) SetParam (PL_options[Option_playoption1]) + else if (!strcasecmp(Name, "playoption2")) SetParam (PL_options[Option_playoption2]) + else if (!strcasecmp(Name, "playonlynew")) SetParam (PL_options[Option_playonlynew]) + else if (!strcasecmp(Name, "searchnew")) SetParam (PL_options[Option_searchnewrecord]) + else if (!strcasecmp(Name, "searchsub")) SetParam (PL_options[Option_searchrecordsub]) + else + return false; + return true; + + #undef SetParam + #undef SetParamChar + #undef SetParamFile +} + +const char *cPluginPlaylist::ExpandPath(const char *Filename, bool CreateDir) +{ + static char path[MaxFileName]; + char *c = strdup(ConfigDirectory("")); + char *p = NULL; + + ExpandEnvironment(&pathplaylists); + if (pathplaylists.e[0] == '/') + asprintf(&p, "%s%s%s", pathplaylists.e, *(pathplaylists.e + strlen(pathplaylists.e) - 1) == '/' ? "" : "/", Filename); + else + asprintf(&p, "%s%s%s%s%s", c, *(c + strlen(c) - 1) == '/' ? "" : "/", pathplaylists.e, strlen(pathplaylists.e) ? *(pathplaylists.e + strlen(pathplaylists.e) - 1) == '/' ? "" : "/" : "", Filename); + if (strlen(p) >= MaxFileName) + esyslog("%s: max length for filename is %d this name is %d [%s]", plugin_name, MaxFileName, strlen(p), p); + strn0cpy(path, p, MaxFileName); + if (CreateDir) + MakeDirs(path, false); + free(c); + free(p); +#ifdef PL_Debug1 + dsyslog("%s: ExpandPath Filename=%s Return=%s", plugin_name, Filename, path); +#endif + return &path[0]; +} + +VDRPLUGINCREATOR(cPluginPlaylist); // Don't touch this! diff --git a/playlist.h b/playlist.h new file mode 100644 index 0000000..bfb7e46 --- /dev/null +++ b/playlist.h @@ -0,0 +1,163 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: playlist.h 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#ifndef __PLAYLIST_H +#define __PLAYLIST_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 + +// Global variables that control the overall behaviour: + +enum eStartOption { + Start_DisplayPL = 0, + Start_DisplayLast, + Start_PlayLast, + Start_NewEmpty, + Start_max }; + +enum eNoYesDefault { + NoYesDefault_no = 0, + NoYesDefault_yes, + NoYesDefault_defaultPlugin, + NoYesDefault_defaultPlaylist, + NoYesDefault_defaultRecordDir, + NoYesDefault_max }; + +enum ePlayOptions { + PlayOptions_firstpos = 0, + PlayOptions_firstnew, + PlayOptions_lastplay, + PlayOptions_selectpos, + PlayOptions_question, + PlayOptions_defaultPlugin, + PlayOptions_max }; + +enum eOptions { + Option_confirmdeleterecord = 0, + Option_confirmstartnewrecord, + Option_deletefromlist, + Option_deleterecord, + Option_jumpmark, + Option_playoption1, + Option_playoption2, + Option_playonlynew, + Option_searchnewrecord, + Option_searchrecordsub, + Option_max }; + +#define MAXOptionLines 20 + +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 tParamChar charentry; +extern tParamChar charfolder; +extern tParamChar charrecord; +extern tParamInt commandline_preference; +extern tParamFile lastplaylist; +extern tParamFile mainmenu_name; +extern tParamInt mainmenu_visible; +extern tParamInt confirmdelplentry; +extern tParamInt okstartplay; +extern tParamInt deleterecords; +extern tParamFile pathplaylists; +extern tParamInt startoption; +extern tParamInt storeplaylist; +extern tParamInt timeoutreadrecords; +extern tParamInt verbose; +extern tParamInt PL_options[]; + +extern char plugin_name[]; +extern char DisplayStatus[]; +extern const char *NoYesDefault[]; +extern const char *StartOptions[]; +extern const char *PlayOptions[]; +extern char *FileNameCharsAllowed; +extern char *AllCharsAllowed; +extern char *LastSelectedRecord; +extern bool ControlMenuIsOpen; +#if VDRVERSNUM < 10311 +extern cRecordings Recordings; +extern time_t LoadTime_Recordings; +#endif + +void ExpandEnvironment(tParamFile *FileStruc); + +// --- cPluginPlaylist ---------------------------------------------------------- + +class cPluginPlaylist : public cPlugin { +private: + // Add any member variables or functions you may need here. + int OSDLanguage; + void TestAndSetOSDLanguage(void); + bool ProcessArg(int argc, char *argv[]); + +public: + cPluginPlaylist(void); + virtual ~cPluginPlaylist(); + 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); + const char *ExpandPath(const char *Filename, bool CreateDir = true); + }; + +extern cPluginPlaylist *PluginPlaylist; + +#endif //__PLAYLIST_H diff --git a/vdrtools.c b/vdrtools.c new file mode 100644 index 0000000..c9a78f0 --- /dev/null +++ b/vdrtools.c @@ -0,0 +1,217 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: vdrtools.c 0.2 2004/10/08 02:34:00 hflor Exp $ + */ + +#include "vdrtools.h" +#include "playlist.h" +#include "dataplaylist.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; +} + +bool DeleteRecording(const char *Filename, bool Confirm) +{ + if (!Confirm || Interface->Confirm(tr("Delete recording?"))) + { + cRecordControl *rc = cRecordControls::GetRecordControl(Filename); + if (rc) + { + if (!Confirm || Interface->Confirm(tr("Timer still recording - really delete?"))) + { + cTimer *timer = rc->Timer(); + if (timer) + { + timer->Skip(); + cRecordControls::Process(time(NULL)); + if (timer->IsSingleEvent()) + { + isyslog("timer %d deleted", timer->Index() + 1); + Timers.Del(timer); + } + Timers.Save(); + } + } else + return false; + } + cRecording *recording = Recordings.GetByName(Filename); + if (recording) + { + if (recording->Delete()) + { + cReplayControl::ClearLastReplayed(Filename); + if (LastSelectedRecord && !strcmp(LastSelectedRecord, Filename)) + FREENULL(LastSelectedRecord); + Recordings.Del(recording); + for (cPlaylist *pl = PlaylistCol.First(); pl; pl = PlaylistCol.Next(pl)) + for (cPlaylistRecord *plr = pl->First_PLR(); plr; plr = pl->Next_PLR(plr)) + if (strcasecmp(plr->Filename(), Filename) == 0) + plr->SetDel(); + return true; + } + } + ERROR(tr("Error while accessing recording!")); + } + return false; +} + + +#ifdef PL_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; + 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..c17ef7a --- /dev/null +++ b/vdrtools.h @@ -0,0 +1,26 @@ +/* + * playlist: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: vdrtools.h 0.2 2004/10/08 02:34:00 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); +bool DeleteRecording(const char *Filename, bool Confirm = true); + +#ifdef PL_Debug1 +const char *KeyName(eKeys Key); +const char *OSStateName(eOSState OSState); +#endif + + +#endif //__VDRTOOLS_H |