summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schirrmacher <vdr.zaphistory@schirrmacher.eu>2013-08-15 21:24:18 +0200
committerMartin Schirrmacher <vdr.zaphistory@schirrmacher.eu>2013-08-15 21:24:18 +0200
commit111b0cc69414d8025a66b3325a65d7286be87df7 (patch)
tree13e4ec5b46e6607456e7015b0aa1365994f35a8e
downloadvdr-plugin-zaphistory-111b0cc69414d8025a66b3325a65d7286be87df7.tar.gz
vdr-plugin-zaphistory-111b0cc69414d8025a66b3325a65d7286be87df7.tar.bz2
initial commit
-rw-r--r--COPYING340
-rw-r--r--HISTORY62
-rw-r--r--Makefile122
-rw-r--r--README22
-rw-r--r--epg_item.c133
-rw-r--r--epg_item.h55
-rw-r--r--menu_reset.c93
-rw-r--r--menu_reset.h29
-rw-r--r--monitor.c31
-rw-r--r--monitor.h22
-rw-r--r--po/de_DE.po114
-rw-r--r--setup-zaphistory.c93
-rw-r--r--setup-zaphistory.h51
-rw-r--r--statistic_item.c62
-rw-r--r--statistic_item.h26
-rw-r--r--zaphistory.c107
-rw-r--r--zaphistory.h38
-rw-r--r--zaphistory_osditem.c19
-rw-r--r--zaphistory_osditem.h23
-rw-r--r--zaphistorychannel.c125
-rw-r--r--zaphistorychannel.h48
-rw-r--r--zaphistoryosd.c279
-rw-r--r--zaphistoryosd.h38
-rw-r--r--zaplist.c124
-rw-r--r--zaplist.h42
25 files changed, 2098 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -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.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..356f526
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,62 @@
+VDR Plugin 'zaphistory' Revision History
+----------------------------------------
+
+2013-08-15: Version 0.9.6 (Martin Schirrmacher)
+- add options to set progress view - old text bar, VDRSymbols, percent
+- remove translations (only eng & ger)
+- remove old i18n implementation
+- new VDR 2.0 Makefile
+- VDR 2.0-compatible release
+
+2006-09-28: Version 0.9.5 (Peter Pinnau)
+
+- VDR 1.4-compatible release
+
+2006-03-28: Version 0.9.4 (Peter Juszack)
+
+- added French translations (thanks to alien2924)
+
+- switched the sort order of this file ;)
+
+2006-03-23: Version 0.9.3 (Peter Juszack)
+
+- removed pointers to VDRs cChannel instances to avoid problems when
+ a VDR-channel is deleted during runtime
+
+
+2006-03-15: Version 0.9.2 (Peter Juszack)
+
+- fixed problems for channels without EPG data
+
+- added Estonian translation (thanks to Arthur Konovalov)
+
+2006-03-13: Version 0.9.1 (Peter Juszack)
+
+- fixed compiling problems with older VDR versions:
+ now works at least with VDR >= 1.3.37
+
+- added Spanish translation (thanks to Luis Palacios)
+
+2006-03-11: Version 0.9.0 (Peter Juszack)
+
+- code rewriting and bugfixing
+- new reset menu
+
+2006-03-10: Version 0.0.3 (Peter Juszack)
+
+- history is stored in file
+- zap and watchtime counter
+- 2 history views: EPG and statistic
+- sorting by latest view, zap count and watchtime
+
+2006-03-04: Version 0.0.2 (Peter Juszack)
+
+- added setup option to hide main menu entry
+- fix: on mulit card systems channels from VDRs background activities
+ (EOG-scan and PID-scan) were displayed in history
+- added i18n for English and German
+- dublicate entries are removed from the history (confugurable in setup)
+
+2005-03-15: Version 0.0.1 (Andreas Kwasnik)
+
+- Initial revision.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1aa6bc9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,122 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id$
+
+# The official name of this plugin.
+# This name will be used in the '-P...' option of VDR to load the plugin.
+# By default the main source file also carries this name.
+
+PLUGIN = zaphistory
+
+### 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 directory environment:
+
+# Use package data if installed...otherwise assume we're under the VDR source directory:
+PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
+LIBDIR = $(call PKGCFG,libdir)
+LOCDIR = $(call PKGCFG,locdir)
+PLGCFG = $(call PKGCFG,plgcfg)
+#
+TMPDIR ?= /tmp
+
+### The compiler options:
+
+export CFLAGS = $(call PKGCFG,cflags)
+export CXXFLAGS = $(call PKGCFG,cxxflags)
+
+### The version number of VDR's plugin API:
+
+APIVERSION = $(call PKGCFG,apiversion)
+
+### Allow user defined options to overwrite defaults:
+
+-include $(PLGCFG)
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### The name of the shared object file:
+
+SOFILE = libvdr-$(PLUGIN).so
+
+### Includes and Defines (add further entries here):
+
+INCLUDES +=
+
+DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = epg_item.o menu_reset.o monitor.o setup-zaphistory.o statistic_item.o zaphistorychannel.o zaphistoryosd.o zaphistory_osditem.o zaplist.o $(PLUGIN).o
+
+### The main target:
+
+all: $(SOFILE) i18n
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
+
+### Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Internationalization (I18N):
+
+PODIR = po
+I18Npo = $(wildcard $(PODIR)/*.po)
+I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file))))
+I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
+I18Npot = $(PODIR)/$(PLUGIN).pot
+
+%.mo: %.po
+ msgfmt -c -o $@ $<
+
+$(I18Npot): $(wildcard *.c)
+ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
+
+%.po: $(I18Npot)
+ msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
+ @touch $@
+
+$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
+ install -D -m644 $< $@
+
+.PHONY: i18n
+i18n: $(I18Nmo) $(I18Npot)
+
+install-i18n: $(I18Nmsgs)
+
+### Targets:
+
+$(SOFILE): $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
+
+install-lib: $(SOFILE)
+ install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
+
+install: install-lib install-i18n
+
+dist: $(I18Npo) clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+ @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
diff --git a/README b/README
new file mode 100644
index 0000000..77e3eb5
--- /dev/null
+++ b/README
@@ -0,0 +1,22 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Martin Schirrmacher <vdr.zaphistory@schirrmacher.eu>
+ Andreas Kwasnik <>
+ Peter Juszack <vdr@unterbrecher.de>
+
+Project's homepage:
+
+Latest version available at:
+
+See the file COPYING for license information.
+
+Description:
+
+Originally the plugins provided a history of the latest viewed channels.
+Since version 0.0.3 statistics (zaps and watchtime) are collected for
+each channel.
+History can be sorted by latest viewed, zap count and watch time. The idea
+is a self-learning favourites list.
+The history provides a channel name + EPG view and a channel name + statistics
+view.
+Statistics and history entries can be deleted or reseted from the menu.
diff --git a/epg_item.c b/epg_item.c
new file mode 100644
index 0000000..8ce25bb
--- /dev/null
+++ b/epg_item.c
@@ -0,0 +1,133 @@
+/*
+ * epg_item.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include <string>
+#include <math.h>
+#include <vdr/menu.h>
+#include <locale.h>
+#include <langinfo.h>
+#include "epg_item.h"
+
+#define HOURS(x) ((x)/100)
+#define MINUTES(x) ((x)%100)
+
+#define SHORTTEXT(EVENT) \
+ ((EVENT) && !isempty((EVENT)->ShortText())) ? " ~ ":"", \
+((EVENT) && !isempty((EVENT)->ShortText())) ? (EVENT)->ShortText():""
+
+//extern int exitToMainMenu;
+
+// --- Icons ------------------------------------------------------------------
+bool Icons::IsUTF8 = false;
+
+void Icons::InitCharSet()
+{
+ // Taken from VDR's vdr.c
+ char *CodeSet = NULL;
+ if(setlocale(LC_CTYPE, ""))
+ CodeSet = nl_langinfo(CODESET);
+ else
+ {
+ char *LangEnv = getenv("LANG"); // last resort in case locale stuff isn't installed
+ if(LangEnv)
+ {
+ CodeSet = strchr(LangEnv,'.');
+ if( CodeSet )
+ CodeSet++; // skip the dot
+ }
+ }
+
+ if( CodeSet && strcasestr(CodeSet,"UTF-8") != 0 )
+ IsUTF8 = true;
+}
+
+
+// --- cMenuMyScheduleItem ------------------------------------------------------
+ cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, cZapHistoryChannel *Channel, int Progress)
+:cZapHistoryOsdItem(Channel)
+{
+ event = Event;
+ progress = Progress;
+ timerMatch = tmNone;
+ Update(true);
+}
+
+bool cMenuMyScheduleItem::Update(bool Force)
+{
+ bool result = false;
+ const cChannel* channel = zapChannel->GetChannel();
+
+ eTimerMatch OldTimerMatch = timerMatch;
+ cTimer* hasMatch = NULL;
+
+ if (event)
+ hasMatch = Timers.GetMatch(event, &timerMatch);
+
+ if (Force || timerMatch != OldTimerMatch)
+ {
+ char szChannelpart[20] = "";
+ if (channel)
+ snprintf(szChannelpart, 20, "%s\t", channel->Name() );
+
+ char szProgressPart[50] = "";
+ if (progress > 0 && channel && event )
+ {
+ strcpy(szProgressPart, "\t");
+
+ if( ZapHistorySetup.ProgressView == 1 ) { // VDRSymbols
+ std::string ProgressBar;
+ ProgressBar += Icons::ProgressStart();
+ int frac = (int)roundf( (float)(time(NULL) - event->StartTime()) / (float)(event->Duration()) * 10.0 );
+ frac = min(10,max(0, frac));
+ for(int i=0;i < 10;i++)
+ {
+ if(i < frac)
+ ProgressBar += Icons::ProgressFilled();
+ else
+ ProgressBar += Icons::ProgressEmpty();
+ }
+ ProgressBar += Icons::ProgressEnd();
+ sprintf(szProgressPart, "%s\t", ProgressBar.c_str());
+ } else if( ZapHistorySetup.ProgressView == 0 ) {
+ char szProgress[9] = "";
+ int frac = (int)roundf( (float)(time(NULL) - event->StartTime()) / (float)(event->Duration()) * 8.0 );
+ frac = min(8,max(0, frac));
+
+ for(int i = 0; i < frac; i++)
+ szProgress[i] = (progress == 1 ? '|' : 127);
+ szProgress[frac]=0;
+ sprintf(szProgressPart, "%c%-8s%c\t", progress==1?'[':128, szProgress, progress==1?']':129);
+ } else {
+ float frac = (int)roundf( (float)(time(NULL) - event->StartTime()) / (float)(event->Duration()) * 100.0 );
+ sprintf(szProgressPart, "%3.0f%%", frac);
+ }
+ }
+
+ char t = event && hasMatch ? (timerMatch == tmFull) ? 'T' : 't' : ' ';
+ char v = event && event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' ';
+ char r = event && event->IsRunning() ? '*' : ' ';
+
+ char szEventDescr[100] = "";
+ snprintf(szEventDescr, 100, "%s%s%s",
+ event?event->Title():tr("no info"),
+ SHORTTEXT(event) );
+
+ char *buffer = NULL;
+ if (channel) // menu "What's on"
+ asprintf(&buffer, "%s%s\t%s %c%c%c \t%s",
+ szChannelpart,
+ event?*(event->GetTimeString() ):"",
+ szProgressPart,
+ t, v, r,
+ szEventDescr);
+
+ SetText(buffer, false);
+ return true;
+ }
+ return result;
+}
diff --git a/epg_item.h b/epg_item.h
new file mode 100644
index 0000000..091f27e
--- /dev/null
+++ b/epg_item.h
@@ -0,0 +1,55 @@
+#ifndef __ZAPHISTORY_EPGITEM_H
+#define __ZAPHISTORY_EPGITEM_H
+
+/* cMenuMyScheduleItem
+
+ Provides a menu item with channel name and EPG information.
+ Basically taken from the epgsearch plugin
+ */
+
+#include <vdr/menuitems.h>
+#include "zaphistorychannel.h"
+#include "zaphistory_osditem.h"
+
+// --- cMenuMyScheduleItem ------------------------------------------------------
+
+class cMenuMyScheduleItem : public cZapHistoryOsdItem {
+ private:
+ const cEvent *event;
+
+ int progress;
+ eTimerMatch timerMatch;
+
+ public:
+
+ cMenuMyScheduleItem(const cEvent *Event, cZapHistoryChannel *Channel, int iProgress=0);
+ bool Update(bool Force = false);
+};
+
+
+class Icons
+{
+ private:
+ static bool IsUTF8;
+ public:
+ static void InitCharSet();
+ static const char* Continue(){return IsUTF8?"\ue000":"\x80";}
+ static const char* DVD(){return IsUTF8?"\ue001":"\x81";}
+ static const char* Directory(){return IsUTF8?"\ue002":"\x82";}
+ static const char* FixedBlank(){return IsUTF8?"\ue003":"\x83";}
+ static const char* Scissor(){return IsUTF8?"\ue004":"\x84";}
+ static const char* MovingRecording(){return IsUTF8?"\ue005":"\x85";}
+ static const char* MovingDirectory(){return IsUTF8?"\ue006":"\x86";}
+ static const char* ProgressStart(){return IsUTF8?"\ue007":"\x87";}
+ static const char* ProgressFilled(){return IsUTF8?"\ue008":"\x88";}
+ static const char* ProgressEmpty(){return IsUTF8?"\ue009":"\x89";}
+ static const char* ProgressEnd(){return IsUTF8?"\ue00a":"\x8a";}
+ static const char* Recording(){return IsUTF8?"\ue00b":"\x8b";}
+ static const char* AlarmClock(){return IsUTF8?"\ue00c":"\x8c";}
+ static const char* TVScrambled(){return IsUTF8?"\ue00d":"\x8d";}
+ static const char* Radio(){return IsUTF8?"\ue00e":"\x8e";}
+ static const char* TV(){return IsUTF8?"\ue00f":"\x8f";}
+ static const char* New(){return IsUTF8?"\ue010":"\x90";}
+};
+
+#endif
diff --git a/menu_reset.c b/menu_reset.c
new file mode 100644
index 0000000..96f305f
--- /dev/null
+++ b/menu_reset.c
@@ -0,0 +1,93 @@
+/* * menu_reset.c: The actual menu implementations
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id:
+ */
+
+#include "menu_reset.h"
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+
+#include <vdr/menu.h>
+#include <vdr/interface.h>
+
+cMenuHistoryReset::cMenuHistoryReset(cZapHistoryChannel *zapChan)
+ :cOsdMenu(tr("Reset history") )
+{
+ zapChannel = zapChan;
+ Setup();
+}
+
+void cMenuHistoryReset::Setup() {
+ Clear(); // Remove old menuitems
+
+ char *buffer = NULL;
+
+ // Items to operate on the complete history
+ Add( new cOsdItem( tr("Delete all entries") ) );
+ Add( new cOsdItem( tr("Reset all statistics") ) );
+
+ // if a channel has been passed, add menuitems for operations on that channel
+ if (zapChannel != NULL) {
+ asprintf(&buffer, "%s%s %s", tr("Delete entry"), ":", zapChannel->GetChannel()->Name() );
+ Add( new cOsdItem( buffer ) );
+ free(buffer);
+
+ asprintf(&buffer, "%s%s %s", tr("Reset statistics for"), ":", zapChannel->GetChannel()->Name() );
+ Add( new cOsdItem( buffer ) );
+ free(buffer);
+ }
+
+ // Buttons
+ SetHelp(tr("Button$Ok"), 0, 0, tr("Button$Back") );
+
+ Display();
+}
+
+eOSState cMenuHistoryReset::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kBlue: // Close reset menu
+ return osBack;
+ case kRed:
+ case kOk: // Execute operation
+ // Validate index of selected item
+ switch ( Current() ) {
+ case 0: // Delete all entries
+ if (Interface->Confirm(tr("Delete complete history?") ) ) {
+ ZapHistory.Reset(NULL, false);
+ return osBack;
+ }
+ break;
+ case 1: // Reset complete statistisc
+ if (Interface->Confirm(tr("Reset all?") ) ) {
+ ZapHistory.Reset(NULL);
+ return osBack;
+ }
+ break;
+ case 2: // Delete entry XYZ
+ if (zapChannel != NULL && Interface->Confirm(tr("Delete entry?") ) ) {
+ ZapHistory.Reset(zapChannel, false);
+ return osBack;
+ }
+ break;
+ case 3: // Reset statistics for XYZ
+ if (zapChannel != NULL && Interface->Confirm(tr("Reset entry?") ) ) {
+ ZapHistory.Reset(zapChannel);
+ return osBack;
+ }
+ break;
+ }
+ return osContinue;
+
+ default: return osContinue;
+ }
+ }
+
+ return state;
+}
diff --git a/menu_reset.h b/menu_reset.h
new file mode 100644
index 0000000..bfa1955
--- /dev/null
+++ b/menu_reset.h
@@ -0,0 +1,29 @@
+/*
+ * zap_reset.h: The actual menu implementations
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * Provides a menu for reseting opertaions against the zaphistory
+ */
+
+#ifndef __MENU_RESET_H
+#define __MENU_RESET_H
+
+#include <vdr/osdbase.h>
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+
+class cMenuHistoryReset : public cOsdMenu {
+ private:
+ void Setup(void);
+
+ cZapHistoryChannel *zapChannel;
+ protected:
+ eOSState Switch(void);
+ public:
+ cMenuHistoryReset( cZapHistoryChannel *zapChan);
+ virtual eOSState ProcessKey(eKeys Key);
+};
+
+#endif
diff --git a/monitor.c b/monitor.c
new file mode 100644
index 0000000..f24a406
--- /dev/null
+++ b/monitor.c
@@ -0,0 +1,31 @@
+/*
+ * monitor.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include <vdr/eitscan.h>
+#include <vdr/channels.h>
+
+#include "monitor.h"
+#include "setup-zaphistory.h"
+#include "zaphistory.h"
+
+void cZapHistoryMonitor::ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView)
+{
+ // Inform history, that channel has been switched
+ if (ChannelNumber > 0 && Device->IsPrimaryDevice() && LiveView )
+ {
+ ZapHistory.ChannelSwitch( Channels.GetByNumber (ChannelNumber) );
+ }
+}
+
+void cZapHistoryMonitor::Replaying(const cControl *Control, const char *Name, const char *FileName, bool On) {
+ // Inform history, that live viewing has been started/stopped
+ if (On)
+ ZapHistory.ViewInterrupted();
+ else
+ ZapHistory.ViewContinue();
+}
diff --git a/monitor.h b/monitor.h
new file mode 100644
index 0000000..768708f
--- /dev/null
+++ b/monitor.h
@@ -0,0 +1,22 @@
+/*
+ * monitor.h: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * Provides a cStatus derived monitor to be informed about VDR activities like
+ * channel switch, replay start/stop
+ */
+
+#ifndef __MONITOR_H
+#define __MONITOR_H
+
+#include <vdr/status.h>
+
+class cZapHistoryMonitor : public cStatus {
+ public:
+ void ChannelSwitch( const cDevice *Device, int ChannelNumber, bool LiveView);
+
+ void Replaying( const cControl *Control, const char *Name, const char *FileName, bool On);
+};
+
+#endif
diff --git a/po/de_DE.po b/po/de_DE.po
new file mode 100644
index 0000000..718f6c2
--- /dev/null
+++ b/po/de_DE.po
@@ -0,0 +1,114 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-zaphistory 0.9.5\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2013-08-13 20:23+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "no info"
+msgstr "keine Info"
+
+msgid "Reset history"
+msgstr "History zurücksetzen"
+
+msgid "Delete all entries"
+msgstr "Alle Einträge löschen"
+
+msgid "Reset all statistics"
+msgstr "Reset der kompletten Statistik"
+
+msgid "Delete entry"
+msgstr "Lösche Eintrag"
+
+msgid "Reset statistics for"
+msgstr "Reset Statistik für"
+
+msgid "Button$Ok"
+msgstr "Ok"
+
+msgid "Button$Back"
+msgstr "Zurück"
+
+msgid "Delete complete history?"
+msgstr "Gesamte History löschen?"
+
+msgid "Reset all?"
+msgstr "Alle zurücksetzen?"
+
+msgid "Delete entry?"
+msgstr "Eintrag entfernen?"
+
+msgid "Reset entry?"
+msgstr "Eintrag zurücksetzen?"
+
+msgid "Latest view"
+msgstr "Zuletzt eingeschaltet"
+
+msgid "Zap count"
+msgstr "Wie oft Eingeschaltet"
+
+msgid "View time"
+msgstr "Gesamtzeit"
+
+msgid "Button$Schedule"
+msgstr "EPG Übersicht"
+
+msgid "Button$Statistic"
+msgstr "Statistik"
+
+msgid "old text bar"
+msgstr "Text Balken"
+
+msgid "VDRSymbols"
+msgstr "VDRSymbols"
+
+msgid "Percent"
+msgstr "Prozent"
+
+msgid "Zaphistory"
+msgstr "Zaphistorie"
+
+msgid "Number of entries"
+msgstr "Anzahl der Einträge"
+
+msgid "Hide mainmenu entry"
+msgstr "Hauptmenüeintrag verstecken"
+
+msgid "Default view"
+msgstr "Standard-Ansicht"
+
+msgid "Default sort"
+msgstr "Standard-Sortierung"
+
+msgid "Progress view"
+msgstr "Fortschrittsanzeige"
+
+msgid "Zapping History"
+msgstr "Letzte Kanäle"
+
+msgid "Sorted by"
+msgstr "Geordnet nach"
+
+msgid "Button$Sort"
+msgstr "Sortieren"
+
+msgid "Button$Reset"
+msgstr "Reset"
+
+msgid "Button$Info"
+msgstr "Info"
+
+msgid "Channel"
+msgstr "Kanal"
diff --git a/setup-zaphistory.c b/setup-zaphistory.c
new file mode 100644
index 0000000..93ba52e
--- /dev/null
+++ b/setup-zaphistory.c
@@ -0,0 +1,93 @@
+/*
+ * ZapHistory Player plugin for VDR
+ *
+ * This code is distributed under the terms and conditions of the
+ * GNU GENERAL PUBLIC LICENSE. Read the file COPYING for details.
+ */
+
+#include "zaphistory.h"
+#include "setup-zaphistory.h"
+#ifdef __QNXNTO__
+#include <strings.h>
+#include <vdr/channels.h>
+
+#endif
+
+cZapHistorySetup ZapHistorySetup;
+
+// --- cZapHistorySetup -----------------------------------------------------------
+cZapHistorySetup::cZapHistorySetup(void)
+{
+ // set default values
+ HideMainMenu = 0;
+ DefaultView = historyView;
+ DefaultSort = historySort;
+ EntryCount = 10;
+
+ ProgressView = 0;
+}
+
+void cZapHistorySetup::IntToEnum() {
+ // Convert int-dummy values to enum
+ switch (DummyDefaultView) {
+ case 0: DefaultView = historyView; break;
+ case 1: DefaultView = statisticView; break;
+ }
+
+ switch (DummyDefaultSort) {
+ case 0: DefaultSort = historySort; break;
+ case 1: DefaultSort = zapcountSort; break;
+ case 2: DefaultSort = watchtimeSort; break;
+ }
+}
+
+bool cZapHistorySetup::SetupParse(const char *Name, const char *Value)
+{
+ // Parse your own setup parameters and store their values.
+ if (!strcasecmp(Name, "HideMainMenu")) HideMainMenu = atoi(Value);
+ else if (!strcasecmp(Name, "EntryCount")) EntryCount = atoi(Value);
+ else if (!strcasecmp(Name, "DefaultView")) { DummyDefaultView = atoi(Value); IntToEnum(); }
+ else if (!strcasecmp(Name, "DefaultSort")) { DummyDefaultSort = atoi(Value); IntToEnum(); }
+ else if (!strcasecmp(Name, "ProgressView")) { ProgressView = atoi(Value); }
+ else
+ return false;
+ return true;
+}
+
+// --- cMenuSetupZapHistory --------------------------------------------------------
+
+cMenuSetupZapHistory::cMenuSetupZapHistory(void)
+{
+ // init sort option strings
+ sortStrs[0] = tr("Latest view");
+ sortStrs[1] = tr("Zap count");
+ sortStrs[2] = tr("View time");
+
+ // init view option strings
+ viewStrs[0] = tr("Button$Schedule");
+ viewStrs[1] = tr("Button$Statistic");
+
+ ProgressViewtStrs[0] = tr("old text bar");
+ ProgressViewtStrs[1] = tr("VDRSymbols");
+ ProgressViewtStrs[2] = tr("Percent");
+
+ // add menu items
+ SetSection(tr("Zaphistory"));
+ Add(new cMenuEditIntItem(tr("Number of entries"), &ZapHistorySetup.EntryCount, 0, Channels.Count() ));
+ Add(new cMenuEditBoolItem(tr("Hide mainmenu entry"), &ZapHistorySetup.HideMainMenu));
+ Add(new cMenuEditStraItem(tr("Default view"), &ZapHistorySetup.DummyDefaultView, 2, viewStrs));
+ Add(new cMenuEditStraItem(tr("Default sort"), &ZapHistorySetup.DummyDefaultSort, 3, sortStrs));
+ Add(new cMenuEditStraItem(tr("Progress view"), &ZapHistorySetup.ProgressView, 3, ProgressViewtStrs));
+}
+
+void cMenuSetupZapHistory::Store(void)
+{
+ // store setup
+ ZapHistorySetup.IntToEnum();
+
+ SetupStore("HideMainMenu", ZapHistorySetup.HideMainMenu );
+ SetupStore("EntryCount", ZapHistorySetup.EntryCount );
+ SetupStore("DefaultView", ZapHistorySetup.DummyDefaultView );
+ SetupStore("DefaultSort", ZapHistorySetup.DummyDefaultSort );
+ SetupStore("ProgressView", ZapHistorySetup.ProgressView );
+}
diff --git a/setup-zaphistory.h b/setup-zaphistory.h
new file mode 100644
index 0000000..9f947a4
--- /dev/null
+++ b/setup-zaphistory.h
@@ -0,0 +1,51 @@
+/*
+ * ZapHistory plugin for VDR
+ *
+ * This code is distributed under the terms and conditions of the
+ * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
+ *
+ * Setup data structure and setup menu
+ *
+ */
+
+#ifndef __SETUP_ZapHistory_H
+#define __SETUP_ZapHistory_H
+
+#include <vdr/menuitems.h>
+
+enum cZapHistoryView { historyView, statisticView };
+enum cZapHistorySortMode { historySort, zapcountSort, watchtimeSort };
+
+class cZapHistorySetup {
+ public:
+ int HideMainMenu;
+ int EntryCount;
+ cZapHistoryView DefaultView;
+ cZapHistorySortMode DefaultSort;
+
+ // Dummy fields to convert enum fields to int
+ int DummyDefaultView;
+ int DummyDefaultSort;
+
+ int ProgressView; // 0 = textbar; 1 = VDRSymbols; 2 = percent
+
+ public:
+ cZapHistorySetup(void);
+ void IntToEnum();
+ bool SetupParse(const char *Name, const char *Value);
+};
+
+class cMenuSetupZapHistory : public cMenuSetupPage {
+ private:
+ const char* viewStrs[2];
+ const char* sortStrs[3];
+ const char* ProgressViewtStrs[3];
+ protected:
+ virtual void Store(void);
+ public:
+ cMenuSetupZapHistory(void);
+};
+
+extern cZapHistorySetup ZapHistorySetup;
+
+#endif // __SETUP_ZapHistory_H
diff --git a/statistic_item.c b/statistic_item.c
new file mode 100644
index 0000000..7541900
--- /dev/null
+++ b/statistic_item.c
@@ -0,0 +1,62 @@
+/* * statistic_item.h: The actual menu implementations
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id:
+ */
+
+#include "zaphistoryosd.h"
+#include "zaphistory.h"
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+#include "statistic_item.h"
+
+#include "epg_item.h"
+
+#include <vdr/channels.h>
+#include <vdr/menu.h>
+#include <vdr/interface.h>
+
+cZapHistoryChannelItem::cZapHistoryChannelItem(cZapHistoryChannel *Channel):cZapHistoryOsdItem(Channel)
+{
+ if (Channel->GetChannel()->GroupSep())
+ SetSelectable(false);
+ Set();
+}
+
+void cZapHistoryChannelItem::Set(void)
+{
+ char *buffer = NULL;
+
+ char *timeBuffer = NULL;
+ char *zapCountBuffer = NULL;
+
+ int hours = zapChannel->GetWatchTime() / 3600;
+ int minutes = (int) ( (zapChannel->GetWatchTime() % 3600) / 60 );
+
+ // build watch time string: e.g. --42:17
+ if (hours >= 1000)
+ asprintf( &timeBuffer, "%d:%02d" , hours, minutes );
+ else if (hours >= 100)
+ asprintf( &timeBuffer, "-%d:%02d" , hours, minutes );
+ else if (hours >= 10)
+ asprintf( &timeBuffer, "--%d:%02d" , hours, minutes );
+ else
+ asprintf( &timeBuffer, "---%d:%02d" , hours, minutes );
+
+ // build counter string: e.g. --58
+ if (zapChannel->GetZapCount() >= 1000)
+ asprintf( &zapCountBuffer, "%ld", zapChannel->GetZapCount() );
+ else if (zapChannel->GetZapCount() >= 100)
+ asprintf( &zapCountBuffer, "-%ld", zapChannel->GetZapCount() );
+ else if (zapChannel->GetZapCount() >= 10)
+ asprintf( &zapCountBuffer, "--%ld", zapChannel->GetZapCount() );
+ else
+ asprintf( &zapCountBuffer, "---%ld", zapChannel->GetZapCount() );
+
+ // build all data into one string
+ asprintf(&buffer, "%s\t %s\t %s", zapChannel->GetChannel()->Name(), zapCountBuffer, timeBuffer );
+
+ SetText(buffer, false);
+}
diff --git a/statistic_item.h b/statistic_item.h
new file mode 100644
index 0000000..3491781
--- /dev/null
+++ b/statistic_item.h
@@ -0,0 +1,26 @@
+/* * statistic_item.h: The actual menu implementations
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * Provides a menuitem to display channel name and statistics
+ */
+
+#include "zaphistoryosd.h"
+#include "zaphistory.h"
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+#include "zaphistory_osditem.h"
+
+#include "epg_item.h"
+
+#include <vdr/channels.h>
+#include <vdr/menu.h>
+#include <vdr/interface.h>
+
+class cZapHistoryChannelItem : public cZapHistoryOsdItem {
+
+ public:
+ cZapHistoryChannelItem(cZapHistoryChannel *Channel);
+ virtual void Set(void);
+};
diff --git a/zaphistory.c b/zaphistory.c
new file mode 100644
index 0000000..4b28399
--- /dev/null
+++ b/zaphistory.c
@@ -0,0 +1,107 @@
+/*
+ * zaphistory.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include "zaphistory.h"
+#include "setup-zaphistory.h"
+#include "zaphistoryosd.h"
+#include "epg_item.h"
+
+static const char *VERSION = "0.9.6";
+static const char *MAINMENUENTRY = "Zapping history";
+static const char *DESCRIPTION = "History of the last zapped channels";
+
+const char *cPluginZaphistory::Version(void) {
+ return VERSION;
+}
+
+const char *cPluginZaphistory::Description(void) {
+ return tr(DESCRIPTION);
+}
+
+cPluginZaphistory::cPluginZaphistory(void)
+{
+ // Initialize any member variables here.
+ // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
+ // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
+ monitor = NULL;
+}
+
+cPluginZaphistory::~cPluginZaphistory()
+{
+ // Clean up after yourself!
+}
+
+const char *cPluginZaphistory::CommandLineHelp(void)
+{
+ // Return a string that describes all known command line options.
+ return NULL;
+}
+
+bool cPluginZaphistory::ProcessArgs(int argc, char *argv[])
+{
+ // Implement command line argument processing here if applicable.
+ return true;
+}
+
+bool cPluginZaphistory::Initialize(void)
+{
+ // Initialize any background activities the plugin shall perform.
+ return true;
+}
+
+const char *cPluginZaphistory::MainMenuEntry(void) {
+ if ( ZapHistorySetup.HideMainMenu == 1 )
+ return NULL;
+
+ return tr( tr(MAINMENUENTRY) );
+}
+
+bool cPluginZaphistory::Start(void)
+{
+ Icons::InitCharSet();
+ // Load stored history
+ ZapHistory.Load( AddDirectory( ConfigDirectory(), "zaphistory.conf" ));
+
+ monitor = new cZapHistoryMonitor();
+
+ return true;
+}
+
+void cPluginZaphistory::Stop(void)
+{
+ // Save history
+ ZapHistory.UpdateWatchTime();
+ ZapHistory.Save();
+ // Stop any background activities the plugin shall perform.
+ delete monitor;
+}
+
+void cPluginZaphistory::Housekeeping(void)
+{
+ // Perform any cleanup or other regular tasks.
+}
+
+cOsdObject *cPluginZaphistory::MainMenuAction(void)
+{
+ // Perform the action when selected from the main VDR menu.
+ return new cMenuZappedChannels();
+}
+
+cMenuSetupPage *cPluginZaphistory::SetupMenu(void)
+{
+ // Return a setup menu in case the plugin supports one.
+ return new cMenuSetupZapHistory();
+}
+
+bool cPluginZaphistory::SetupParse(const char *Name, const char *Value)
+{
+ // Parse your own setup parameters and store their values.
+ return ZapHistorySetup.SetupParse(Name, Value);
+}
+
+VDRPLUGINCREATOR(cPluginZaphistory); // Don't touch this!
diff --git a/zaphistory.h b/zaphistory.h
new file mode 100644
index 0000000..3b56031
--- /dev/null
+++ b/zaphistory.h
@@ -0,0 +1,38 @@
+/*
+ * zaphistory.h: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#ifndef __ZAPHISTORY_H
+#define __ZAPHISTORY_H
+
+#include <vdr/plugin.h>
+#include "zaplist.h"
+#include "monitor.h"
+
+
+class cPluginZaphistory : public cPlugin {
+private:
+ // Add any member variables or functions you may need here.
+ cZapHistoryMonitor *monitor;
+public:
+ cPluginZaphistory(void);
+ virtual ~cPluginZaphistory();
+ virtual const char *Version(void);
+ virtual const char *Description(void);
+ virtual const char *CommandLineHelp(void);
+ virtual bool ProcessArgs(int argc, char *argv[]);
+ virtual bool Initialize(void);
+ virtual bool Start(void);
+ virtual void Stop(void);
+ virtual void Housekeeping(void);
+ virtual const char *MainMenuEntry(void);
+ virtual cOsdObject *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ };
+
+#endif
diff --git a/zaphistory_osditem.c b/zaphistory_osditem.c
new file mode 100644
index 0000000..3bd98d6
--- /dev/null
+++ b/zaphistory_osditem.c
@@ -0,0 +1,19 @@
+/*
+ * zaphistory_osditem.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include "zaphistory_osditem.h"
+
+// --- cZapHistoryOsdItem ------------------------------------------------------
+cZapHistoryOsdItem::cZapHistoryOsdItem(cZapHistoryChannel *Channel)
+{
+ zapChannel = Channel;
+}
+
+cZapHistoryChannel* cZapHistoryOsdItem::Channel() {
+ return zapChannel;
+}
diff --git a/zaphistory_osditem.h b/zaphistory_osditem.h
new file mode 100644
index 0000000..7d60c38
--- /dev/null
+++ b/zaphistory_osditem.h
@@ -0,0 +1,23 @@
+#ifndef __ZAPHISTORY_OSDITEM_H
+#define __ZAPHISTORY_OSDITEM_H
+
+/* cZapHistoryOsdItem
+
+ Base class for history menu items to display a channel
+ */
+
+#include <vdr/menuitems.h>
+#include "zaphistorychannel.h"
+
+// --- cMenuMyScheduleItem ------------------------------------------------------
+
+class cZapHistoryOsdItem : public cOsdItem {
+ protected:
+ cZapHistoryChannel *zapChannel;
+
+ public:
+ cZapHistoryOsdItem(cZapHistoryChannel *Channel);
+ cZapHistoryChannel *Channel();
+};
+
+#endif
diff --git a/zaphistorychannel.c b/zaphistorychannel.c
new file mode 100644
index 0000000..1049f7e
--- /dev/null
+++ b/zaphistorychannel.c
@@ -0,0 +1,125 @@
+/*
+ * zaphistorychannel.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include <vdr/channels.h>
+
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+#include "zaphistorychannel.h"
+
+cZapHistoryChannel::cZapHistoryChannel() {
+ // init members
+ //channelID = tChannelID.tChannelID();
+ watchTime = 0;
+ zapCount = 0;
+}
+
+// Getter/Setter for wrapped cChannel
+const cChannel *cZapHistoryChannel::GetChannel() {
+ return Channels.GetByChannelID(channelID);
+}
+
+tChannelID cZapHistoryChannel::GetChannelID() {
+ return channelID;
+}
+
+void cZapHistoryChannel::SetChannelID(tChannelID id) {
+ channelID = id;
+}
+
+// Reset statistics
+void cZapHistoryChannel::Reset() {
+ watchTime = 0;
+ zapCount = 0;
+}
+
+// Getter for statistics
+time_t cZapHistoryChannel::GetWatchTime() {
+ return watchTime;
+}
+
+// Getter for statistics
+long cZapHistoryChannel::GetZapCount() {
+ return zapCount;
+}
+
+// Increases zap count
+void cZapHistoryChannel::IncreaseZapCount() {
+ zapCount++;
+}
+
+// Increases watch time
+void cZapHistoryChannel::AddWatchTime( time_t t) {
+ watchTime += t;
+}
+
+// Getter for position in history
+int cZapHistoryChannel::GetHistoryPos() {
+ return historyPos;
+}
+
+// Setter for position in history
+void cZapHistoryChannel::SetHistoryPos(int p) {
+ historyPos = p;
+}
+
+// Compares this instance to another cZapHistoryChannel
+int cZapHistoryChannel::Compare(const cListObject &ListObject) const {
+ // Comparison depends on current sort mode of history
+ switch( ZapHistory.GetSortMode() ) {
+ case historySort:
+ if ( historyPos == ((cZapHistoryChannel&) ListObject).GetHistoryPos() )
+ return 0;
+ if ( historyPos > ((cZapHistoryChannel&) ListObject).GetHistoryPos() )
+ return 1;
+
+ return -1;
+ case zapcountSort:
+ if ( zapCount == ((cZapHistoryChannel&) ListObject).GetZapCount() )
+ return 0;
+ if ( zapCount > ((cZapHistoryChannel&) ListObject).GetZapCount() )
+ return -1;
+
+ return 1;
+ case watchtimeSort:
+ if ( watchTime == ((cZapHistoryChannel&) ListObject).GetWatchTime() )
+ return 0;
+ if ( watchTime > ((cZapHistoryChannel&) ListObject).GetWatchTime() )
+ return -1;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+bool cZapHistoryChannel::Parse( char *s ) {
+ char *channelbuffer = NULL;
+
+ // Parse line from zaphistory.conf
+ if ( sscanf( s, "%a[^:]:%d:%ld:%ld", &channelbuffer, &historyPos, &zapCount, &watchTime) == 4) {
+ // get channel ID
+ channelID = tChannelID::FromString(channelbuffer);
+ // free buffer
+ free(channelbuffer);
+
+ // if invalid channel do not add to history
+ if (GetChannel() == NULL)
+ return false;
+
+ // parsed successful
+ return true;
+ }
+
+ // could not parse
+ return false;
+}
+
+bool cZapHistoryChannel::Save( FILE *f ) {
+ return fprintf(f, "%s:%d:%ld:%ld\n", *channelID.ToString(), GetHistoryPos(), GetZapCount(), GetWatchTime() );
+}
diff --git a/zaphistorychannel.h b/zaphistorychannel.h
new file mode 100644
index 0000000..ae70e11
--- /dev/null
+++ b/zaphistorychannel.h
@@ -0,0 +1,48 @@
+/*
+ * zaplist.h: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * Channel entry for the zaphistory. Class wraps a VDR cChannel-instance and adds
+ * additionally data like statistics
+ */
+
+#ifndef __ZAPHISTORYCHANNEL_H
+#define __ZAPHISTORYCHANNEL_H
+
+#include <vdr/channels.h>
+
+#include "setup-zaphistory.h"
+
+class cZapHistoryChannel : public cListObject {
+ private:
+ // VDRs Channel ID
+ tChannelID channelID;
+
+ time_t watchTime;
+ long zapCount;
+ int historyPos;
+ public:
+ cZapHistoryChannel();
+
+ const cChannel *GetChannel();
+ tChannelID GetChannelID();
+ void SetChannelID(tChannelID id);
+
+ long GetWatchTime();
+ long GetZapCount();
+ int GetHistoryPos();
+
+ void IncreaseZapCount();
+ void AddWatchTime( time_t t );
+ void SetHistoryPos(int p);
+
+ bool Parse(char *s);
+ bool Save( FILE *f );
+
+ void Reset();
+
+ virtual int Compare(const cListObject &ListObject) const;
+};
+
+#endif
diff --git a/zaphistoryosd.c b/zaphistoryosd.c
new file mode 100644
index 0000000..95ee375
--- /dev/null
+++ b/zaphistoryosd.c
@@ -0,0 +1,279 @@
+/* zaphistoryosd.c: The actual menu implementations
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id:
+ */
+
+#include "zaphistoryosd.h"
+#include "zaphistory.h"
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+#include "statistic_item.h"
+#include "menu_reset.h"
+#include "epg_item.h"
+
+#include <vdr/channels.h>
+#include <vdr/menu.h>
+#include <vdr/interface.h>
+
+cMenuZappedChannels::cMenuZappedChannels()
+ :cOsdMenu(tr("Zapping History") )
+{
+ // Init members
+
+ // Start with view mode from setup
+ viewMode = ZapHistorySetup.DefaultView;
+
+ // Start with sort mode from setup
+ ZapHistory.SetSortMode( ZapHistorySetup.DefaultSort );
+
+ inResetMode = false;
+
+ // Build the menu
+ Setup();
+}
+
+void cMenuZappedChannels::Setup() {
+ Clear(); // Remove old menuitems
+ ZapHistory.UpdateWatchTime(); // calculate watchtime in history and refresh channel instances
+
+ // Sort history
+ ZapHistory.Sort();
+
+ switch(viewMode) { // build menu
+ case historyView:
+ SetupEPGView();
+ break;
+ case statisticView:
+ SetupStatisticView();
+ break;
+ }
+
+ Display();
+}
+
+// Builds a non-selectable menu item to display current sort mode
+void cMenuZappedChannels::SortInfoItem() {
+ char *buffer = NULL;
+ const char *sortField = NULL;
+
+ switch (ZapHistory.GetSortMode() ) {
+ case historySort:
+ sortField = tr("Latest view");
+ break;
+ case zapcountSort:
+ sortField = tr("Zap count");
+ break;
+ case watchtimeSort:
+ sortField = tr("View time");
+ break;
+ }
+
+ asprintf(&buffer, "--- %s '%s' -----------------------------------------------------", tr("Sorted by"), sortField );
+ Add( new cOsdItem( buffer, osUnknown, false));
+ free(buffer);
+}
+
+// Builds the EPG based view
+void cMenuZappedChannels::SetupEPGView() {
+ // Get schedules to retrieve EPG data
+ cSchedulesLock *schedLock = new cSchedulesLock();
+ const cSchedules *schedules = cSchedules::Schedules( *schedLock );
+
+ // schedules not available
+ if (schedules == NULL) {
+ esyslog("ZAPHISTORY: could not get schedules - switching to statistic view");
+ SetupStatisticView();
+ return;
+ }
+
+ // Set tab-stops for menu columns
+ SetCols( 10, 6, 6, 4);
+
+ SortInfoItem();
+
+ // Init history counter
+ int historyPosition = 1;
+ const cEvent *event = NULL;
+
+ // Loop history objects
+ for (cZapHistoryChannel *zapChannel = ZapHistory.First(); zapChannel; zapChannel = ZapHistory.Next(zapChannel)) {
+ if (zapChannel->GetChannel() == NULL) {
+ esyslog("ZAPHISTORY: history item with channel=NULL - ignoring" );
+ continue;
+ }
+
+ // As long as history counter as not greater that maxEntry from setup
+ if (ZapHistorySetup.EntryCount == 0 || historyPosition <= ZapHistorySetup.EntryCount) {
+ // get schedule for history item
+#if VDRVERSNUM >= 10338
+ const cSchedule *schedule = schedules->GetSchedule( zapChannel->GetChannel() );
+#else
+ const cSchedule *schedule = schedules->GetSchedule( zapChannel->GetChannelID() );
+#endif
+ if (schedule == NULL) {
+ event = NULL;
+ } else {
+ event = schedule->GetEventAround(time(NULL));
+ }
+
+ // add menuitem
+ Add( new cMenuMyScheduleItem( event, zapChannel, 1 ));
+ } else // output complete
+ break;
+ historyPosition++;
+ }
+
+ // release schedules
+ delete schedLock;
+
+ // buttons
+ SetHelp(tr("Button$Sort"), tr("Button$Statistic"), tr("Button$Reset"), tr("Button$Info") );
+}
+
+// Builds the statistic view
+void cMenuZappedChannels::SetupStatisticView(void)
+{
+ // Set tab-stops for menu columns
+ SetCols( 25, 10, 10);
+
+ SortInfoItem();
+
+ char *buffer = NULL;
+ asprintf(&buffer, "%s\t%s\t%s", tr("Channel"), tr("Zap count"), tr("View time") );
+
+ Add( new cOsdItem( buffer, osUnknown, false));
+ free(buffer);
+
+ // Init history counter
+ int historyPosition = 1;
+ // Loop history objects
+ for (cZapHistoryChannel *zapChannel = ZapHistory.First(); zapChannel; zapChannel = ZapHistory.Next(zapChannel)) {
+ if (ZapHistorySetup.EntryCount == 0 || historyPosition <= ZapHistorySetup.EntryCount) {
+ // add menuitem
+ Add( new cZapHistoryChannelItem( zapChannel ));
+ } else
+ break;
+
+ historyPosition++;
+ }
+
+ // buttons
+ SetHelp(tr("Button$Sort"), tr("Button$Schedule"), tr("Button$Reset"), tr("Button$Info") );
+}
+
+// Returns the currently selcted channel
+cZapHistoryChannel *cMenuZappedChannels::GetChannel(int Index)
+{
+ if (viewMode == historyView && Index < 1)
+ return NULL;
+ else if (viewMode == statisticView && Index < 2)
+ return NULL;
+
+
+ cZapHistoryOsdItem *selected = (cZapHistoryOsdItem*) Get(Index);
+
+ if (selected == NULL)
+ return NULL;
+
+ return selected->Channel();
+}
+
+eOSState cMenuZappedChannels::Switch(void)
+{
+ cZapHistoryChannel *zapChan = GetChannel(Current());
+ if (zapChan && zapChan->GetChannel() ) {
+ return cDevice::PrimaryDevice()->SwitchChannel(zapChan->GetChannel(), true) ? osEnd : osContinue;
+ return osEnd;
+ }
+
+ return osUnknown;
+}
+
+eOSState cMenuZappedChannels::ShowInfo() {
+ if (HasSubMenu())
+ return osUnknown;
+
+ cZapHistoryChannel *channel = GetChannel(Current());
+
+ if (channel == NULL || channel->GetChannel() == NULL)
+ return osUnknown;
+
+ // Get schedules to retrieve EPG data
+ cSchedulesLock *schedLock = new cSchedulesLock();
+ const cSchedules *schedules = cSchedules::Schedules( *schedLock );
+
+#if VDRVERSNUM >= 10338
+ const cSchedule *schedule = schedules->GetSchedule( channel->GetChannel() );
+#else
+ const cSchedule *schedule = schedules->GetSchedule( channel->GetChannel()->GetChannelID() );
+#endif
+ delete schedLock;
+
+ if (schedule == NULL)
+ return osUnknown;
+
+ return AddSubMenu( new cMenuEvent(schedule->GetEventAround(time(NULL)) ) );
+
+}
+
+eOSState cMenuZappedChannels::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kBlue: // Show EPG info
+ ShowInfo(); break;
+
+ case kOk: // Switch channel
+ return Switch();
+
+ case kGreen: // switch view mode
+ switch( viewMode ) {
+ case historyView:
+ viewMode = statisticView;
+ break;
+ case statisticView:
+ viewMode = historyView;
+ break;
+ }
+
+ Setup(); // rebuild menu
+ break;
+
+ case kYellow:
+ AddSubMenu( new cMenuHistoryReset( GetChannel( Current() ) ) );
+ inResetMode = true;
+ break;
+ case kRed: // sorting
+ // TODO: menu
+ switch( ZapHistory.GetSortMode() ) {
+ case historySort:
+ ZapHistory.SetSortMode( zapcountSort );
+ break;
+ case zapcountSort:
+ ZapHistory.SetSortMode( watchtimeSort );
+ break;
+ case watchtimeSort:
+ ZapHistory.SetSortMode( historySort );
+ break;
+ }
+
+ Setup();
+ break;
+
+ default: break;
+ }
+ }
+
+ // Rebuild after returning from Reset menu
+ if (inResetMode && !HasSubMenu()) {
+ Setup();
+ inResetMode = false;
+ }
+
+ return state;
+}
diff --git a/zaphistoryosd.h b/zaphistoryosd.h
new file mode 100644
index 0000000..1d62b67
--- /dev/null
+++ b/zaphistoryosd.h
@@ -0,0 +1,38 @@
+/*
+ * zaphistoryosd.h: The actual menu implementations
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * Provides the zaphistory menu
+ */
+
+#ifndef __ZAPHISTORYOSD_H
+#define __ZAPHISTORYOSD_H
+
+#include <vdr/osdbase.h>
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+
+class cMenuZappedChannels : public cOsdMenu {
+ private:
+ void Setup(void);
+ void SetupEPGView();
+ void SetupStatisticView();
+ void SortInfoItem();
+ eOSState ShowInfo();
+
+ cZapHistoryChannel *GetChannel(int Index);
+ void Propagate(void);
+
+ cZapHistoryView viewMode;
+
+ bool inResetMode;
+ protected:
+ eOSState Switch(void);
+ public:
+ cMenuZappedChannels();
+ virtual eOSState ProcessKey(eKeys Key);
+};
+
+#endif
diff --git a/zaplist.c b/zaplist.c
new file mode 100644
index 0000000..0d3ebec
--- /dev/null
+++ b/zaplist.c
@@ -0,0 +1,124 @@
+/*
+ * zaplist.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include <vdr/channels.h>
+
+#include "zaplist.h"
+#include "setup-zaphistory.h"
+
+cZapHistory ZapHistory;
+
+cZapHistoryChannel* cZapHistory::FindChannel(cChannel *channel) {
+ if (channel == NULL)
+ return NULL;
+
+ cZapHistoryChannel *returnVal = NULL;
+
+ // Look for channel
+ for ( cZapHistoryChannel *zapChan = First(); zapChan; zapChan = Next( zapChan ) ) {
+ if ( zapChan->GetChannelID() == channel->GetChannelID() ) {
+ returnVal = zapChan;
+ break;
+ }
+ }
+
+ return returnVal;
+}
+
+void cZapHistory::Reset( cZapHistoryChannel *zapChan, bool statisticOnly ) {
+ if (zapChan != NULL) { // Operate on ONE channel
+ if (statisticOnly) { // reset statistics
+ zapChan->Reset();
+ } else { // delete entry
+ if (zapChan == currentChannel)
+ currentChannel = NULL;
+ Del(zapChan);
+ }
+ } else { // operate in complete history
+ if (statisticOnly) { // reset statistics
+ for ( cZapHistoryChannel *zapChan = First(); zapChan; zapChan = Next( zapChan ) ) {
+ zapChan->Reset();
+ }
+ } else { // clear history
+ currentChannel = NULL;
+
+ while (First() != NULL) {
+ Del( First() );
+ }
+ }
+ }
+
+ Save();
+}
+
+void cZapHistory::UpdateHistory(cZapHistoryChannel *zapChan) {
+ for ( cZapHistoryChannel *chan = First(); chan; chan = Next( chan ) ) {
+ chan->SetHistoryPos( chan->GetHistoryPos() + 1);
+ }
+
+ zapChan->IncreaseZapCount();
+ zapChan->SetHistoryPos(1);
+ UpdateWatchTime();
+}
+
+cZapHistory::cZapHistory() {
+ currentChannel = NULL;
+ lastSwitch = time(NULL);
+ sortMode = historySort;
+}
+
+void cZapHistory::ViewInterrupted() {
+ // Add view time to current channel before playback of st. is started
+ UpdateWatchTime();
+
+ lastSwitch = -1;
+}
+
+cZapHistorySortMode cZapHistory::GetSortMode() {
+ return sortMode;
+}
+
+void cZapHistory::SetSortMode( cZapHistorySortMode mode ) {
+ sortMode = mode;
+}
+
+void cZapHistory::UpdateWatchTime() {
+ if (currentChannel == NULL || lastSwitch == -1)
+ return;
+
+ // Add wiew time since last switch
+ currentChannel->AddWatchTime( time(NULL) - lastSwitch );
+
+ lastSwitch = time(NULL);
+}
+
+void cZapHistory::ViewContinue() {
+ lastSwitch = time(NULL);
+}
+
+void cZapHistory::ChannelSwitch( cChannel *channel ) {
+ cZapHistoryChannel *zapChan = FindChannel( channel );
+
+ // Channel not in history management
+ if ( zapChan == NULL ) {
+ // Create new history channel
+ zapChan = new cZapHistoryChannel();
+ zapChan->SetChannelID( channel->GetChannelID() );
+ // Add channel to history
+ Ins( zapChan );
+ UpdateHistory(zapChan);
+ } else if (currentChannel != zapChan) { // Channel already in history management and
+ // a real switch (another channel)
+ UpdateHistory(zapChan);
+ }
+
+ currentChannel = zapChan;
+
+ // Write history to file
+ ZapHistory.Save();
+}
diff --git a/zaplist.h b/zaplist.h
new file mode 100644
index 0000000..e48f836
--- /dev/null
+++ b/zaplist.h
@@ -0,0 +1,42 @@
+/*
+ * zaplist.h: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#ifndef __ZAPLIST_H
+#define __ZAPLIST_H
+
+#include <vdr/channels.h>
+#include <vdr/status.h>
+
+#include "setup-zaphistory.h"
+#include "zaphistorychannel.h"
+
+class cZapHistory;
+
+extern cZapHistory ZapHistory;
+
+class cZapHistory : public cConfig<cZapHistoryChannel> {
+ private:
+ cZapHistoryChannel *currentChannel;
+ time_t lastSwitch;
+
+ cZapHistoryChannel* FindChannel( cChannel *channel );
+ cZapHistorySortMode sortMode;
+
+ void UpdateHistory( cZapHistoryChannel *zapChan);
+ public:
+ cZapHistory();
+ void ChannelSwitch( cChannel *channel );
+ void ViewInterrupted();
+ void ViewContinue();
+ void UpdateWatchTime();
+ cZapHistorySortMode GetSortMode();
+ void SetSortMode( cZapHistorySortMode mode );
+ void Reset(cZapHistoryChannel *zapChan = NULL, bool statisticOnly = true);
+};
+
+#endif