diff options
-rw-r--r-- | HISTORY | 12 | ||||
-rw-r--r-- | PLUGINS.html | 33 | ||||
-rw-r--r-- | PLUGINS/src/epgtableid0/COPYING | 340 | ||||
-rw-r--r-- | PLUGINS/src/epgtableid0/HISTORY | 6 | ||||
-rw-r--r-- | PLUGINS/src/epgtableid0/Makefile | 114 | ||||
-rw-r--r-- | PLUGINS/src/epgtableid0/README | 19 | ||||
-rw-r--r-- | PLUGINS/src/epgtableid0/epgtableid0.c | 98 | ||||
-rw-r--r-- | eit.c | 80 | ||||
-rw-r--r-- | epg.c | 154 | ||||
-rw-r--r-- | epg.h | 67 | ||||
-rw-r--r-- | vdr.5 | 4 | ||||
-rw-r--r-- | vdr.c | 3 |
12 files changed, 878 insertions, 52 deletions
@@ -6960,7 +6960,7 @@ Video Disk Recorder Revision History which was made in version 1.1.10, so please report if this has any unwanted side effects. -2012-03-08: Version 1.7.26 +2012-03-10: Version 1.7.26 - Now checking for NULL in cOsd::AddPixmap() (suggested by Christoph Haubrich). - Fixed the German translation of "VDR will shut down in %s minutes" (thanks to @@ -6999,3 +6999,13 @@ Video Disk Recorder Revision History is selected, but it works at any time (and is more obvious). - Revoked "If the first event in a schedule has a table id of 0x00, any incoming EIT data for that schedule from the DVB stream will be completely ignored". +- Added a new plugin interface for implementing EPG handlers. + + A plugin can implement an EPG handler by creating an object derived from + cEpgHandler and implementing the necessary member functions. + + The special handling of events with table id 0x00 has been dropped. + For backwards compatibility EPG events with table ids lower than 0x4E will + be treated as if they had a table id of 0x4E, and the new plugin 'epgtableid0' + can be used to have them handled like in previous versions. + + The default table id for a newly created cEvent has been changed to 0xFF, + which is higher than any normal table id that is broadcast in the EIT data. + See PLUGINS.html, section "Electronic Program Guide" for more information. diff --git a/PLUGINS.html b/PLUGINS.html index 4d939430..82164bff 100644 --- a/PLUGINS.html +++ b/PLUGINS.html @@ -102,6 +102,7 @@ structures and allows it to hook itself into specific areas to perform special a <li><a href="#Audio">Audio</a> <li><a href="#Remote Control">Remote Control</a> <li><a href="#Conditional Access">Conditional Access</a> +<li><modified><a href="#Electronic Program Guide">Electronic Program Guide</modified></a> </ul> </ul> @@ -2212,5 +2213,37 @@ virtual bool Assign(cDevice *Device, bool Query = false); See the description of this function in <tt>ci.h</tt> for details. +<div class="modified"> +<hr><h2><a name="Electronic Program Guide">Electronic Program Guide</a></h2> + +<div class="blurb">The grass is always greener on the other side...</div><p> + +In case the <i>Electronic Program Guide (EPG)</i> provided by the broadcaster +isn't sufficient for your taste, you can implement a <tt>cEpgHandler</tt> to +improve it from external sources. For instance, to replace the description +of the broadcaster's EPG with one from some external database, you could do: + +<p><table><tr><td class="code"><pre> +#include <vdr/epg.h> + +class cMyEpgHandler : public cEpgHandler { +public: + virtual bool SetDescription(cEvent *Event, const char *Description); + }; + +bool cMyEpgHandler::SetDescription(cEvent *Event, const char *Description) +{ + Event->SetDescription(DescriptionFromDatabase(Event)); + return true; +} +</pre></td></tr></table><p> + +where <tt>DescriptionFromDatabase()</tt> would derive the description of the + given event from some external source. Note that the function returns <tt>true</tt> +to signal VDR that no other EPG handlers shall be queried after this one. +<p> +See <tt>VDR/epg.h</tt> for details. +</div modified> + </body> </html> diff --git a/PLUGINS/src/epgtableid0/COPYING b/PLUGINS/src/epgtableid0/COPYING new file mode 100644 index 00000000..f90922ee --- /dev/null +++ b/PLUGINS/src/epgtableid0/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General +Public License instead of this License. diff --git a/PLUGINS/src/epgtableid0/HISTORY b/PLUGINS/src/epgtableid0/HISTORY new file mode 100644 index 00000000..7f732add --- /dev/null +++ b/PLUGINS/src/epgtableid0/HISTORY @@ -0,0 +1,6 @@ +VDR Plugin 'epgtableid0' Revision History +----------------------------------------- + +2012-03-10: Version 0.0.1 + +- Initial revision. diff --git a/PLUGINS/src/epgtableid0/Makefile b/PLUGINS/src/epgtableid0/Makefile new file mode 100644 index 00000000..5653e28e --- /dev/null +++ b/PLUGINS/src/epgtableid0/Makefile @@ -0,0 +1,114 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id: Makefile 1.1 2012/03/10 14:23:58 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. +# IMPORTANT: the presence of this macro is important for the Make.config +# file. So it must be defined, even if it is not used here! +# +PLUGIN = epgtableid0 + +### 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 ?= -g -O3 -Wall -Woverloaded-virtual -Wno-parentheses + +### The directory environment: + +VDRDIR ?= ../../.. +LIBDIR ?= ../../lib +TMPDIR ?= /tmp + +### Make sure that necessary options are included: + +include $(VDRDIR)/Make.global + +### Allow user defined options to overwrite defaults: + +-include $(VDRDIR)/Make.config + +### The version number of VDR's plugin API (taken from VDR's "config.h"): + +APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h) + +### The name of the distribution archive: + +ARCHIVE = $(PLUGIN)-$(VERSION) +PACKAGE = vdr-$(ARCHIVE) + +### Includes and Defines (add further entries here): + +INCLUDES += -I$(VDRDIR)/include + +DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' + +### The object files (add further files here): + +OBJS = $(PLUGIN).o + +### The main target: + +all: libvdr-$(PLUGIN).so i18n + +### Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< + +### Dependencies: + +MAKEDEP = $(CXX) -MM -MG +DEPFILE = .dependencies +$(DEPFILE): Makefile + @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +### Internationalization (I18N): + +PODIR = po +LOCALEDIR = $(VDRDIR)/locale +I18Npo = $(wildcard $(PODIR)/*.po) +I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(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 $@ $^ + +%.po: $(I18Npot) + msgmerge -U --no-wrap --no-location --backup=none -q $@ $< + @touch $@ + +$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo + @mkdir -p $(dir $@) + cp $< $@ + +.PHONY: i18n +i18n: $(I18Nmsgs) $(I18Npot) + +### Targets: + +libvdr-$(PLUGIN).so: $(OBJS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@ + @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION) + +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 $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot diff --git a/PLUGINS/src/epgtableid0/README b/PLUGINS/src/epgtableid0/README new file mode 100644 index 00000000..8c2436dd --- /dev/null +++ b/PLUGINS/src/epgtableid0/README @@ -0,0 +1,19 @@ +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Klaus Schmidinger <kls@tvdr.de> + +Project's homepage: http://www.tvdr.de + +Latest version available at: http://www.tvdr.de + +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. +See the file COPYING for more information. + +Description: + +The special handling of EPG events with table id 0x00 has been dropped +in VDR version 1.7.26, and replaced by a more felxible "EPG Handler" +concept. You can use this plugin to get the previous functionality back. diff --git a/PLUGINS/src/epgtableid0/epgtableid0.c b/PLUGINS/src/epgtableid0/epgtableid0.c new file mode 100644 index 00000000..d400b48c --- /dev/null +++ b/PLUGINS/src/epgtableid0/epgtableid0.c @@ -0,0 +1,98 @@ +/* + * epgtableid0.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: epgtableid0.c 1.1 2012/03/10 15:10:43 kls Exp $ + */ + +#include <vdr/epg.h> +#include <vdr/plugin.h> + +static const char *VERSION = "0.0.1"; +static const char *DESCRIPTION = "EPG handler for events with table id 0x00"; + +// --- cTable0Handler -------------------------------------------------------- + +class cTable0Handler : public cEpgHandler { +private: + bool Ignore(cEvent *Event) { return Event->TableID() == 0x00; } +public: + virtual bool SetEventID(cEvent *Event, tEventID EventID); + virtual bool SetStartTime(cEvent *Event, time_t StartTime); + virtual bool SetDuration(cEvent *Event, int Duration); + virtual bool SetTitle(cEvent *Event, const char *Title); + virtual bool SetShortText(cEvent *Event, const char *ShortText); + virtual bool SetDescription(cEvent *Event, const char *Description); + virtual bool SetContents(cEvent *Event, uchar *Contents); + virtual bool SetParentalRating(cEvent *Event, int ParentalRating); + virtual bool SetVps(cEvent *Event, time_t Vps); + virtual bool FixEpgBugs(cEvent *Event); + }; + +bool cTable0Handler::SetEventID(cEvent *Event, tEventID EventID) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetStartTime(cEvent *Event, time_t StartTime) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetDuration(cEvent *Event, int Duration) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetTitle(cEvent *Event, const char *Title) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetShortText(cEvent *Event, const char *ShortText) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetDescription(cEvent *Event, const char *Description) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetContents(cEvent *Event, uchar *Contents) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetParentalRating(cEvent *Event, int ParentalRating) +{ + return Ignore(Event); +} + +bool cTable0Handler::SetVps(cEvent *Event, time_t Vps) +{ + return Ignore(Event); +} + +bool cTable0Handler::FixEpgBugs(cEvent *Event) +{ + return Ignore(Event); +} + +// --- cPluginEpgtableid0 ---------------------------------------------------- + +class cPluginEpgtableid0 : public cPlugin { +public: + virtual const char *Version(void) { return VERSION; } + virtual const char *Description(void) { return DESCRIPTION; } + virtual bool Initialize(void); + }; + +bool cPluginEpgtableid0::Initialize(void) +{ + new cTable0Handler; + return true; +} + +VDRPLUGINCREATOR(cPluginEpgtableid0); // Don't touch this! @@ -8,7 +8,7 @@ * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>. * - * $Id: eit.c 2.14 2012/03/08 15:05:45 kls Exp $ + * $Id: eit.c 2.15 2012/03/10 14:43:52 kls Exp $ */ #include "eit.h" @@ -36,12 +36,13 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo cChannel *channel = Channels.GetByChannelID(channelID, true); if (!channel) return; // only collect data for known channels + if (EpgHandlers.IgnoreChannel(channel)) + return; cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true); bool Empty = true; bool Modified = false; - bool HasExternalData = false; time_t SegmentStart = 0; time_t SegmentEnd = 0; time_t Now = time(NULL); @@ -53,7 +54,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo SI::EIT::Event SiEitEvent; for (SI::Loop::Iterator it; eventLoop.getNext(SiEitEvent, it); ) { - bool ExternalData = false; + if (EpgHandlers.HandleEitEvent(pSchedule, &SiEitEvent, Tid, getVersionNumber())) + continue; // an EPG handler has done all of the processing time_t StartTime = SiEitEvent.getStartTime(); int Duration = SiEitEvent.getDuration(); // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number. @@ -72,23 +74,17 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo // If we don't have that event yet, we create a new one. // Otherwise we copy the information into the existing event anyway, because the data might have changed. pEvent = newEvent = new cEvent(SiEitEvent.getEventId()); - if (!pEvent) - continue; + newEvent->SetStartTime(StartTime); + newEvent->SetDuration(Duration); + pSchedule->AddEvent(newEvent); } else { // We have found an existing event, either through its event ID or its start time. pEvent->SetSeen(); - // If the existing event has a zero table ID it was defined externally and shall - // not be overwritten. - uchar TableID = pEvent->TableID(); - if (TableID == 0x00) { - if (pEvent->Version() == getVersionNumber()) - continue; - HasExternalData = ExternalData = true; - } + uchar TableID = max(pEvent->TableID(), uchar(0x4E)); // for backwards compatibility, table ids less than 0x4E are treated as if they were "present" // If the new event has a higher table ID, let's skip it. // The lower the table ID, the more "current" the information. - else if (Tid > TableID) + if (Tid > TableID) continue; // If the new event comes from the same table and has the same version number // as the existing one, let's skip it to avoid unnecessary work. @@ -98,21 +94,20 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers. else if (Tid == TableID && pEvent->Version() == getVersionNumber()) continue; + EpgHandlers.SetEventID(pEvent, SiEitEvent.getEventId()); // unfortunately some stations use different event ids for the same event in different tables :-( + EpgHandlers.SetStartTime(pEvent, StartTime); + EpgHandlers.SetDuration(pEvent, Duration); } - if (!ExternalData) { - pEvent->SetEventID(SiEitEvent.getEventId()); // unfortunately some stations use different event ids for the same event in different tables :-( + if (pEvent->TableID() > 0x4E) // for backwards compatibility, table ids less than 0x4E are never overwritten pEvent->SetTableID(Tid); - pEvent->SetStartTime(StartTime); - pEvent->SetDuration(Duration); - } - if (newEvent) - pSchedule->AddEvent(newEvent); if (Tid == 0x4E) { // we trust only the present/following info on the actual TS if (SiEitEvent.getRunningStatus() >= SI::RunningStatusNotRunning) pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus(), channel); } - if (OnlyRunningStatus) + if (OnlyRunningStatus) { + pEvent->SetVersion(0xFF); // we have already changed the table id above, so set the version to an invalid value to make sure the next full run will be executed continue; // do this before setting the version, so that the full update can be done later + } pEvent->SetVersion(getVersionNumber()); int LanguagePreferenceShort = -1; @@ -124,10 +119,6 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo cLinkChannels *LinkChannels = NULL; cComponents *Components = NULL; for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) { - if (ExternalData && d->getDescriptorTag() != SI::ComponentDescriptorTag) { - delete d; - continue; - } switch (d->getDescriptorTag()) { case SI::ExtendedEventDescriptorTag: { SI::ExtendedEventDescriptor *eed = (SI::ExtendedEventDescriptor *)d; @@ -164,7 +155,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo NumContents++; } } - pEvent->SetContents(Contents); + EpgHandlers.SetContents(pEvent, Contents); } break; case SI::ParentalRatingDescriptorTag: { @@ -183,7 +174,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo case 0x13: ParentalRating = 16; break; default: ParentalRating = 0; } - pEvent->SetParentalRating(ParentalRating); + EpgHandlers.SetParentalRating(pEvent, ParentalRating); } } } @@ -202,7 +193,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec t.tm_year--; time_t vps = mktime(&t); - pEvent->SetVps(vps); + EpgHandlers.SetVps(pEvent, vps); } break; case SI::TimeShiftedEventDescriptorTag: { @@ -213,9 +204,9 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo rEvent = (cEvent *)rSchedule->GetEvent(tsed->getReferenceEventId()); if (!rEvent) break; - pEvent->SetTitle(rEvent->Title()); - pEvent->SetShortText(rEvent->ShortText()); - pEvent->SetDescription(rEvent->Description()); + EpgHandlers.SetTitle(pEvent, rEvent->Title()); + EpgHandlers.SetShortText(pEvent, rEvent->ShortText()); + EpgHandlers.SetDescription(pEvent, rEvent->Description()); } break; case SI::LinkageDescriptorTag: { @@ -273,30 +264,30 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo if (!rEvent) { if (ShortEventDescriptor) { char buffer[Utf8BufSize(256)]; - pEvent->SetTitle(ShortEventDescriptor->name.getText(buffer, sizeof(buffer))); - pEvent->SetShortText(ShortEventDescriptor->text.getText(buffer, sizeof(buffer))); + EpgHandlers.SetTitle(pEvent, ShortEventDescriptor->name.getText(buffer, sizeof(buffer))); + EpgHandlers.SetShortText(pEvent, ShortEventDescriptor->text.getText(buffer, sizeof(buffer))); } - else if (!HasExternalData) { - pEvent->SetTitle(NULL); - pEvent->SetShortText(NULL); + else { + EpgHandlers.SetTitle(pEvent, NULL); + EpgHandlers.SetShortText(pEvent, NULL); } if (ExtendedEventDescriptors) { char buffer[Utf8BufSize(ExtendedEventDescriptors->getMaximumTextLength(": ")) + 1]; - pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": ")); + EpgHandlers.SetDescription(pEvent, ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": ")); } - else if (!HasExternalData) - pEvent->SetDescription(NULL); + else + EpgHandlers.SetDescription(pEvent, NULL); } delete ExtendedEventDescriptors; delete ShortEventDescriptor; pEvent->SetComponents(Components); - if (!HasExternalData) - pEvent->FixEpgBugs(); + EpgHandlers.FixEpgBugs(pEvent); if (LinkChannels) channel->SetLinkChannels(LinkChannels); Modified = true; + EpgHandlers.HandleEvent(pEvent); } if (Tid == 0x4E) { if (Empty && getSectionNumber() == 0) @@ -307,9 +298,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo if (OnlyRunningStatus) return; if (Modified) { - pSchedule->Sort(); - if (!HasExternalData) - pSchedule->DropOutdated(SegmentStart, SegmentEnd, Tid, getVersionNumber()); + EpgHandlers.SortSchedule(pSchedule); + EpgHandlers.DropOutdated(pSchedule, SegmentStart, SegmentEnd, Tid, getVersionNumber()); Schedules->SetModified(pSchedule); } } @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * - * $Id: epg.c 2.11 2012/02/13 14:58:19 kls Exp $ + * $Id: epg.c 2.12 2012/03/10 13:14:27 kls Exp $ */ #include "epg.h" @@ -114,7 +114,7 @@ cEvent::cEvent(tEventID EventID) { schedule = NULL; eventID = EventID; - tableID = 0; + tableID = 0xFF; // actual table ids are 0x4E..0x60 version = 0xFF; // actual version numbers are 0..31 runningStatus = SI::RunningStatusUndefined; title = NULL; @@ -1296,3 +1296,153 @@ void cEpgDataReader::Action(void) { cSchedules::Read(); } + +// --- cEpgHandler ----------------------------------------------------------- + +cEpgHandler::cEpgHandler(void) +{ + EpgHandlers.Add(this); +} + +cEpgHandler::~cEpgHandler() +{ + EpgHandlers.Del(this, false); +} + +// --- cEpgHandlers ---------------------------------------------------------- + +cEpgHandlers EpgHandlers; + +bool cEpgHandlers::IgnoreChannel(const cChannel *Channel) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->IgnoreChannel(Channel)) + return true; + } + return false; +} + +bool cEpgHandlers::HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->HandleEitEvent(Schedule, EitEvent, TableID, Version)) + return true; + } + return false; +} + +void cEpgHandlers::SetEventID(cEvent *Event, tEventID EventID) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetEventID(Event, EventID)) + return; + } + Event->SetEventID(EventID); +} + +void cEpgHandlers::SetTitle(cEvent *Event, const char *Title) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetTitle(Event, Title)) + return; + } + Event->SetTitle(Title); +} + +void cEpgHandlers::SetShortText(cEvent *Event, const char *ShortText) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetShortText(Event, ShortText)) + return; + } + Event->SetShortText(ShortText); +} + +void cEpgHandlers::SetDescription(cEvent *Event, const char *Description) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetDescription(Event, Description)) + return; + } + Event->SetDescription(Description); +} + +void cEpgHandlers::SetContents(cEvent *Event, uchar *Contents) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetContents(Event, Contents)) + return; + } + Event->SetContents(Contents); +} + +void cEpgHandlers::SetParentalRating(cEvent *Event, int ParentalRating) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetParentalRating(Event, ParentalRating)) + return; + } + Event->SetParentalRating(ParentalRating); +} + +void cEpgHandlers::SetStartTime(cEvent *Event, time_t StartTime) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetStartTime(Event, StartTime)) + return; + } + Event->SetStartTime(StartTime); +} + +void cEpgHandlers::SetDuration(cEvent *Event, int Duration) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetDuration(Event, Duration)) + return; + } + Event->SetDuration(Duration); +} + +void cEpgHandlers::SetVps(cEvent *Event, time_t Vps) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SetVps(Event, Vps)) + return; + } + Event->SetVps(Vps); +} + +void cEpgHandlers::FixEpgBugs(cEvent *Event) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->FixEpgBugs(Event)) + return; + } + Event->FixEpgBugs(); +} + +void cEpgHandlers::HandleEvent(cEvent *Event) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->HandleEvent(Event)) + break; + } +} + +void cEpgHandlers::SortSchedule(cSchedule *Schedule) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->SortSchedule(Schedule)) + return; + } + Schedule->Sort(); +} + +void cEpgHandlers::DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->DropOutdated(Schedule, SegmentStart, SegmentEnd, TableID, Version)) + return; + } + Schedule->DropOutdated(SegmentStart, SegmentEnd, TableID, Version); +} @@ -7,13 +7,14 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * - * $Id: epg.h 2.7 2012/02/26 13:58:26 kls Exp $ + * $Id: epg.h 2.8 2012/03/10 13:50:10 kls Exp $ */ #ifndef __EPG_H #define __EPG_H #include "channels.h" +#include "libsi/section.h" #include "thread.h" #include "tools.h" @@ -221,4 +222,68 @@ public: void ReportEpgBugFixStats(bool Reset = false); +class cEpgHandler : public cListObject { +public: + cEpgHandler(void); + ///< Constructs a new EPG handler and adds it to the list of EPG handlers. + ///< Whenever an event is received from the EIT data stream, the EPG + ///< handlers are queried in the order they have been created. + ///< As soon as one of the EPG handlers returns true in a member function, + ///< none of the remaining handlers will be queried. If none of the EPG + ///< handlers returns true in a particular call, the default processing + ///< will take place. + ///< EPG handlers will be deleted automatically at the end of the program. + virtual ~cEpgHandler(); + virtual bool IgnoreChannel(const cChannel *Channel) { return false; } + ///< Before any EIT data for the given Channel is processed, the EPG handlers + ///< are asked whether this Channel shall be completely ignored. If any of + ///< the EPG handlers returns true in this function, no EIT data at all will + ///< be processed for this Channel. + virtual bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version) { return false; } + ///< Before the raw EitEvent for the given Schedule is processed, the + ///< EPG handlers are queried to see if any of them would like to do the + ///< complete processing by itself. TableID and Version are from the + ///< incoming section data. + virtual bool SetEventID(cEvent *Event, tEventID EventID) { return false; } + virtual bool SetTitle(cEvent *Event, const char *Title) { return false; } + virtual bool SetShortText(cEvent *Event, const char *ShortText) { return false; } + virtual bool SetDescription(cEvent *Event, const char *Description) { return false; } + virtual bool SetContents(cEvent *Event, uchar *Contents) { return false; } + virtual bool SetParentalRating(cEvent *Event, int ParentalRating) { return false; } + virtual bool SetStartTime(cEvent *Event, time_t StartTime) { return false; } + virtual bool SetDuration(cEvent *Event, int Duration) { return false; } + virtual bool SetVps(cEvent *Event, time_t Vps) { return false; } + virtual bool FixEpgBugs(cEvent *Event) { return false; } + ///< Fixes some known problems with EPG data. + virtual bool HandleEvent(cEvent *Event) { return false; } + ///< After all modifications of the Event have been done, the EPG handler + ///< can take a final look at it. + virtual bool SortSchedule(cSchedule *Schedule) { return false; } + ///< Sorts the Schedule after the complete table has been processed. + virtual bool DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version) { return false; } + ///< Takes a look at all EPG events between SegmentStart and SegmentEnd and + ///< drops outdated events. + }; + +class cEpgHandlers : public cList<cEpgHandler> { +public: + bool IgnoreChannel(const cChannel *Channel); + bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version); + void SetEventID(cEvent *Event, tEventID EventID); + void SetTitle(cEvent *Event, const char *Title); + void SetShortText(cEvent *Event, const char *ShortText); + void SetDescription(cEvent *Event, const char *Description); + void SetContents(cEvent *Event, uchar *Contents); + void SetParentalRating(cEvent *Event, int ParentalRating); + void SetStartTime(cEvent *Event, time_t StartTime); + void SetDuration(cEvent *Event, int Duration); + void SetVps(cEvent *Event, time_t Vps); + void FixEpgBugs(cEvent *Event); + void HandleEvent(cEvent *Event); + void SortSchedule(cSchedule *Schedule); + void DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version); + }; + +extern cEpgHandlers EpgHandlers; + #endif //__EPG_H @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 2.28 2012/02/27 11:05:15 kls Exp $ +.\" $Id: vdr.5 2.29 2012/03/10 14:56:01 kls Exp $ .\" .TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files" .SH NAME @@ -861,7 +861,7 @@ l l. <event id> @is a 32 bit unsigned int, uniquely identifying this event <start time> @is the time (as a time_t integer) in UTC when this event starts <duration> @is the time (in seconds) that this event will take -<table id> @is a hex number that indicates the table this event is contained in (if this is left empty or 0 this event will not be overwritten or modified by data that comes from the DVB stream) +<table id> @is a hex number that indicates the table this event is contained in (if this is left empty it will be set to 0x00; and value less than 0x4E it will be treated as if it were 0x4E) <version> @is a hex number that indicates the event's version number inside its table (optional, ignored when reading EPG data) <title> @is the title of the event <short text> @is the short text of the event (typically the name of the episode etc.) @@ -22,7 +22,7 @@ * * The project's page is at http://www.tvdr.de * - * $Id: vdr.c 2.33 2012/03/08 09:51:52 kls Exp $ + * $Id: vdr.c 2.34 2012/03/09 09:55:15 kls Exp $ */ #include <getopt.h> @@ -1300,6 +1300,7 @@ Exit: Setup.Save(); } cDevice::Shutdown(); + EpgHandlers.Clear(); PluginManager.Shutdown(true); cSchedules::Cleanup(true); ReportEpgBugFixStats(); |