mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	Version 1.1.0
- Begin of the 1.1 development branch. THIS IS NOT A STABLE VERSION! The current stable version for every day use is still the 1.0 branch. - First step towards a universal plugin interface. See the file PLUGINS.html for a detailed description. The man page vdr(1) describes the new options '-L' and '-P' used to load plugins. This first step implements the complete "outer" shell for plugins. The "inner" access to VDR data structures will follow. - The VDR version number is now displayed in the title line of the "Setup" menu.
This commit is contained in:
		
							
								
								
									
										55
									
								
								CONTRIBUTORS
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								CONTRIBUTORS
									
									
									
									
									
								
							@@ -1,4 +1,7 @@
 | 
			
		||||
Thanks go to the following people for patches and contributions:
 | 
			
		||||
Tons of suggestions, bugreports, patches and other contributions have been
 | 
			
		||||
provided by the people on the 'linux-dvb' and 'vdr' mailing lists.
 | 
			
		||||
Special thanks go to the following individuals (if your name is missing here,
 | 
			
		||||
please send an email to kls@cadsoft.de):
 | 
			
		||||
 | 
			
		||||
Carsten Koch <Carsten.Koch@icem.de>
 | 
			
		||||
 for adding LIRC support
 | 
			
		||||
@@ -9,6 +12,7 @@ Carsten Koch <Carsten.Koch@icem.de>
 | 
			
		||||
 for implementing the 'new recording' indicator
 | 
			
		||||
 for suggesting that the "Back" button in replay mode should bring up the "Recordings" menu
 | 
			
		||||
 for fixing the watchdog timer if the program hangs in OSD activities
 | 
			
		||||
 for his support in keeping the Premiere World channels up to date in 'channels.conf'
 | 
			
		||||
 | 
			
		||||
Plamen Ganev <pganev@com-it.net>
 | 
			
		||||
 for fixing the frequency offset for Hotbird channels
 | 
			
		||||
@@ -28,7 +32,7 @@ Guido Fiala <gfiala@s.netic.de>
 | 
			
		||||
 now does these things itself)
 | 
			
		||||
 for making the replay progress display avoid unnecessary code execution
 | 
			
		||||
 | 
			
		||||
Robert Schneider <Robert.Schneider@lotus.com>
 | 
			
		||||
Robert Schneider <Robert.Schneider@de.ibm.com>
 | 
			
		||||
 for implementing EIT support for displaying the current/next info
 | 
			
		||||
 for extending EIT support to implement a complete EPG
 | 
			
		||||
 | 
			
		||||
@@ -117,6 +121,13 @@ Stefan Huelswitt <huels@iname.com>
 | 
			
		||||
 for implementing backtracing for fast forward/rewind
 | 
			
		||||
 for implementing the replay mode display
 | 
			
		||||
 for fixing a crash when replaying with DEBUG_OSD=1
 | 
			
		||||
 for fixing a crash when selecting the "Jump" function directly after setting
 | 
			
		||||
 an editing mark
 | 
			
		||||
 for reporting a possible endless loop in shifting recordings between DVB cards
 | 
			
		||||
 for making it no longer setting PIDs 0x1FFF, which apparently fixes problems
 | 
			
		||||
 with CAMs and AC3 sound only working the first time
 | 
			
		||||
 for making the main loop take an active video cutting process into account when
 | 
			
		||||
 doing shutdown or housekeeping
 | 
			
		||||
 | 
			
		||||
Ulrich R<>der <roeder@efr-net.de>
 | 
			
		||||
 for pointing out that there are channels that have a symbol rate higher than
 | 
			
		||||
@@ -157,6 +168,8 @@ Werner Fink <werner@suse.de>
 | 
			
		||||
 for helping to debug leftover 'zombie' processes when closing a pipe
 | 
			
		||||
 for making the Dolby Digital thread start only if the recording actually
 | 
			
		||||
 contains Dolby Digital data
 | 
			
		||||
 for improving thread locking in the ring buffer to avoid possible race conditions
 | 
			
		||||
 under heavy load
 | 
			
		||||
 | 
			
		||||
Rolf Hakenes <hakenes@hippomi.de>
 | 
			
		||||
 for providing 'libdtv' and adapting the EIT mechanisms to it
 | 
			
		||||
@@ -185,7 +198,7 @@ Thomas Heiligenmann <thomas@heiligenmann.de>
 | 
			
		||||
Norbert Schmidt <nschmidt-nrw@t-online.de>
 | 
			
		||||
 for filling in some missing teletext PIDs
 | 
			
		||||
 | 
			
		||||
Thilo Wunderlich <tw@ubcom.net>
 | 
			
		||||
Thilo Wunderlich <wunderlich@speedway.org>
 | 
			
		||||
 for his help in keeping 'channels.conf' up to date
 | 
			
		||||
 for reporting a problem with accessing the epg.data file before it is fully written
 | 
			
		||||
 | 
			
		||||
@@ -202,6 +215,8 @@ Sergei Haller <Sergei.Haller@math.uni-giessen.de>
 | 
			
		||||
 for adding the TPID to Hessen-3 in 'channels.conf'
 | 
			
		||||
 for suggesting that the EPG scan should skip channels with their 'Ca' parameter
 | 
			
		||||
 explicitly set to an other DVB card
 | 
			
		||||
 for implementing enhanced string editing with upper-/lowercase, insert/overwrite
 | 
			
		||||
 and delete
 | 
			
		||||
 | 
			
		||||
Andreas Gebel <andreas@xcapenet.de>
 | 
			
		||||
 for his help in keeping 'channels.conf' up to date
 | 
			
		||||
@@ -280,3 +295,37 @@ Dirk Wiebel <dirk@wiebel.de>
 | 
			
		||||
Gerald Raaf <graaf@attglobal.net>
 | 
			
		||||
 for helping to fix the still picture workaround in case the progress display
 | 
			
		||||
 is active
 | 
			
		||||
 for his support in keeping the Premiere World channels up to date in 'channels.conf'
 | 
			
		||||
 | 
			
		||||
Andreas Roedl <flood@flood-net.de>
 | 
			
		||||
 for adding some DVB-T channels for Berlin (Germany) to channels.conf.terr
 | 
			
		||||
 | 
			
		||||
Jean Martin <mac_j_fr@hotmail.com>
 | 
			
		||||
 for pointing out a problem with OSD color palette handling on "big endian" systems
 | 
			
		||||
 | 
			
		||||
Steffen Koch <Steffen.Koch@koch-enterprises.de>
 | 
			
		||||
 for reporting a crash when selecting the "Jump" function directly after setting
 | 
			
		||||
 an editing mark
 | 
			
		||||
 | 
			
		||||
Matthias Hilbig <hilbig@upb.de>
 | 
			
		||||
 for fixing some missing ',' in i18n.c
 | 
			
		||||
 | 
			
		||||
Simon Dean <linux-dvb@sickhack.com>
 | 
			
		||||
 for reporting a problem with '.' at the end of a directory name in case of VFAT=1
 | 
			
		||||
 (Windows can't handle these)
 | 
			
		||||
 | 
			
		||||
Dimitrios Dimitrakos <mail@dimitrios.de>
 | 
			
		||||
 for translating OSD texts to the Greek language
 | 
			
		||||
 | 
			
		||||
Marcus Kuba <marcus@kuba4u.de>
 | 
			
		||||
 for reporting a bug in the unit of the "SVDRP timeout" setup parameter
 | 
			
		||||
 | 
			
		||||
Ulrich Petri <ulope@gmx.de>
 | 
			
		||||
 for his help in debugging a crash on systems with disks that have a block size
 | 
			
		||||
 larger than 1MB
 | 
			
		||||
 | 
			
		||||
Oliver Lorei <oliverlorei@cityweb.de>
 | 
			
		||||
 for his support in keeping the Premiere World channels up to date in 'channels.conf.cable'
 | 
			
		||||
 | 
			
		||||
Andreas B<>ttger <fboettger@t-online.de>
 | 
			
		||||
 for reporting a bug in skipping forward in time shift mode near the end of the recording
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								HISTORY
									
									
									
									
									
								
							@@ -1,7 +1,9 @@
 | 
			
		||||
Video Disk Recorder Revision History
 | 
			
		||||
------------------------------------
 | 
			
		||||
 | 
			
		||||
2000-02-19: Version 0.01 (Initial revision).
 | 
			
		||||
2000-02-19: Version 0.01
 | 
			
		||||
 | 
			
		||||
- Initial revision.
 | 
			
		||||
 | 
			
		||||
2000-03-11: Version 0.02
 | 
			
		||||
 | 
			
		||||
@@ -1190,3 +1192,65 @@ Video Disk Recorder Revision History
 | 
			
		||||
- Fixed a bug in the editing process in case a previously edited file with the
 | 
			
		||||
  same name was manually deleted on a system with more than one video directory
 | 
			
		||||
  (thanks to Dirk Wiebel for reporting this one).
 | 
			
		||||
 | 
			
		||||
2002-04-21: Version 1.0.1
 | 
			
		||||
 | 
			
		||||
- Added some DVB-T channels for Berlin (Germany) to channels.conf.terr (thanks to
 | 
			
		||||
  Andreas Roedl).
 | 
			
		||||
- Implemented enhanced string editing with upper-/lowercase, insert/overwrite
 | 
			
		||||
  and delete (thanks to Sergei Haller).
 | 
			
		||||
- Fixed color palette handling on "big endian" systems (thanks to Jean Martin
 | 
			
		||||
  for pointing out this one).
 | 
			
		||||
- Updated the "Blue Movie" channels to the new "Premiere Erotik" (thanks to
 | 
			
		||||
  Thilo Wunderlich). NOTE: this adds a new channel to 'channels.conf', so that
 | 
			
		||||
  any timers referencing a channel with a number higher than 102 should be
 | 
			
		||||
  checked and adapted if necessary (this only applies if you are using the default
 | 
			
		||||
  'channels.conf').
 | 
			
		||||
- Improved thread locking in the ring buffer to avoid possible race conditions
 | 
			
		||||
  under heavy load (thanks to Werner Fink).
 | 
			
		||||
- Fixed a crash when selecting the "Jump" function directly after setting an
 | 
			
		||||
  editing mark (thanks to Steffen Koch for reporting and Stefan Huelswitt for
 | 
			
		||||
  fixing this one).
 | 
			
		||||
- Fixed some missing ',' in i18n.c (thanks to Matthias Hilbig).
 | 
			
		||||
- Fixed a possible endless loop in shifting recordings between DVB cards (thanks
 | 
			
		||||
  to Stefan Huelswitt for reporting this one).
 | 
			
		||||
- Updated the Premiere World Formula 1 channels in 'channels.conf' (thanks to Mel
 | 
			
		||||
  Sch<63>chner).
 | 
			
		||||
- No longer setting PIDs 0x1FFF, which apparently fixes problems with CAMs and
 | 
			
		||||
  AC3 sound only working the first time (thanks to Stefan Huelswitt).
 | 
			
		||||
- Now encoding '.' at the end of a directory name in case of VFAT=1, since Windows
 | 
			
		||||
  can't handle these (thanks to Simon Dean for reporting this one).
 | 
			
		||||
 | 
			
		||||
2002-05-05: Version 1.0.2
 | 
			
		||||
 | 
			
		||||
- Now taking an active video cutting process into account when doing shutdown or
 | 
			
		||||
  housekeeping (thanks to Stefan Huelswitt).
 | 
			
		||||
- The default duration of an instant recording has been increased to 3 hours and
 | 
			
		||||
  is now configurable in the "Setup/Recording" menu.
 | 
			
		||||
- Added Greek language texts (thanks to Dimitrios Dimitrakos).
 | 
			
		||||
- Fixed the unit of the "SVDRP timeout" setup parameter (thanks to Marcus Kuba
 | 
			
		||||
  for reporting this one).
 | 
			
		||||
- Fixed a crash on systems with disks that have a block size larger than 1MB
 | 
			
		||||
  (thanks to Ulrich Petri for helping to debug this one).
 | 
			
		||||
- Updated 'channels.conf' for the new PW settings (thanks to Andreas Share,
 | 
			
		||||
  Carsten Koch, Gerald Raaf and Mel Sch<63>chner). Note that all channels with numbers
 | 
			
		||||
  over 50 may have moved, so you should carefully check any timers you have set!
 | 
			
		||||
- Updated 'channels.conf.cable' for the new PW settings (thanks to Oliver Lorei
 | 
			
		||||
  Stephan Schreiber and Uwe Scheffler). Note that all channels may have moved, so
 | 
			
		||||
  you should carefully check any timers you have set!
 | 
			
		||||
  For future updates of this file somebody with digital cable should take the role
 | 
			
		||||
  of the "maintainer" and send me updated versions based on the file that comes
 | 
			
		||||
  with the most recent version of VDR. I will then simply replace the entire file
 | 
			
		||||
  'channels.conf.cable' whenever a new version is sent to me.
 | 
			
		||||
- Fixed skipping forward in time shift mode near the end of the recording (thanks
 | 
			
		||||
  to Andreas B<>ttger for reporting this one).
 | 
			
		||||
 | 
			
		||||
2002-05-09: Version 1.1.0
 | 
			
		||||
 | 
			
		||||
- Begin of the 1.1 development branch. THIS IS NOT A STABLE VERSION!
 | 
			
		||||
  The current stable version for every day use is still the 1.0 branch.
 | 
			
		||||
- First step towards a universal plugin interface. See the file PLUGINS.html
 | 
			
		||||
  for a detailed description. The man page vdr(1) describes the new options '-L'
 | 
			
		||||
  and '-P' used to load plugins. This first step implements the complete "outer"
 | 
			
		||||
  shell for plugins. The "inner" access to VDR data structures will follow.
 | 
			
		||||
- The VDR version number is now displayed in the title line of the "Setup" menu.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								MANUAL
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								MANUAL
									
									
									
									
									
								
							@@ -17,9 +17,9 @@ Video Disk Recorder User's Manual
 | 
			
		||||
  Ok      Ch display  Select       Switch     Edit       Accept        Play        Progress disp.
 | 
			
		||||
  Menu    Menu on     Menu off     Menu off   Menu off   Menu off      Menu off    Menu on
 | 
			
		||||
  Back    -           Menu off     VDR menu   VDR menu   Discard       VDR menu    Recordings menu
 | 
			
		||||
  Red     -           Record       Edit       Edit       -             Play        Jump
 | 
			
		||||
  Green   -           Language     New        New        -             Rewind      Skip -60s
 | 
			
		||||
  Yellow  -           -            Delete     Delete     -             Delete      Skip +60s
 | 
			
		||||
  Red     -           Record       Edit       Edit       ABC/abc       Play        Jump
 | 
			
		||||
  Green   -           Language     New        New        Ins/Ovr       Rewind      Skip -60s
 | 
			
		||||
  Yellow  -           -            Delete     Delete     Delete        Delete      Skip +60s
 | 
			
		||||
  Blue    -           Stop/Resume  Mark       On/Off(1)  -             Summary     Stop
 | 
			
		||||
  0..9    Ch select   -            -          -          Numeric inp.  -           Editing
 | 
			
		||||
 | 
			
		||||
@@ -58,11 +58,10 @@ Video Disk Recorder User's Manual
 | 
			
		||||
  by pressing the "Right" button (which puts brackets around the current
 | 
			
		||||
  character as in "[R]TL"), selecting the desired character position with
 | 
			
		||||
  "Left" and "Right", and changing the character with the "Up" and "Down"
 | 
			
		||||
  keys. "Ok" then confirms the changes. The special character '^' can be used
 | 
			
		||||
  to "cut off" a string at this position. When this character is visible in the
 | 
			
		||||
  brackets (as in abc[^]), the next press to the "Left" or "Ok" button will
 | 
			
		||||
  actually cut off the string. Using "Up" and/or "Down" brings back the
 | 
			
		||||
  original rest of the string (unless you have pressed "Left" or "Ok").
 | 
			
		||||
  keys. "Ok" then confirms the changes. The "Red" key toggles between
 | 
			
		||||
  upper- and lowercase characters, while the "Green" key switches between
 | 
			
		||||
  insert and overwrite mode. The "Yellow" key deletes the current character
 | 
			
		||||
  (or the one to the right of the cursor in insert mode).
 | 
			
		||||
 | 
			
		||||
  The "Red", "Green", "Yellow" and "Blue" buttons have special meanings
 | 
			
		||||
  in various menus and are listed at the bottom of the on-screen-display.
 | 
			
		||||
@@ -519,6 +518,12 @@ Video Disk Recorder User's Manual
 | 
			
		||||
                         If this parameter is empty, the channel name will be used
 | 
			
		||||
                         by default.
 | 
			
		||||
 | 
			
		||||
  Instant rec. time = 180
 | 
			
		||||
                         Defines the duration of an instant recording in minutes.
 | 
			
		||||
                         Default is 180 minutes (3 hours). The stop time of an
 | 
			
		||||
                         instant recording can be modified at any time by editing
 | 
			
		||||
                         the respective timer in the "Timers" menu.
 | 
			
		||||
 | 
			
		||||
  Record Dolby Digital = yes
 | 
			
		||||
                         Turns recording of the Dolby Digital audio channels on
 | 
			
		||||
                         or off. This may be useful if you don't have the equipment
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								Makefile
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
# See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
# how to reach the author.
 | 
			
		||||
#
 | 
			
		||||
# $Id: Makefile 1.33 2002/04/01 12:50:48 kls Exp $
 | 
			
		||||
# $Id: Makefile 1.34 2002/05/09 09:35:05 kls Exp $
 | 
			
		||||
 | 
			
		||||
.DELETE_ON_ERROR:
 | 
			
		||||
 | 
			
		||||
@@ -13,15 +13,17 @@ DTVDIR   = ./libdtv
 | 
			
		||||
MANDIR   = /usr/local/man
 | 
			
		||||
BINDIR   = /usr/local/bin
 | 
			
		||||
 | 
			
		||||
PLUGINDIR= ./PLUGINS
 | 
			
		||||
 | 
			
		||||
VIDEODIR = /video
 | 
			
		||||
 | 
			
		||||
INCLUDES = -I$(DVBDIR)/ost/include
 | 
			
		||||
 | 
			
		||||
DTVLIB   = $(DTVDIR)/libdtv.a
 | 
			
		||||
 | 
			
		||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o osd.o\
 | 
			
		||||
       recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\
 | 
			
		||||
       videodir.o
 | 
			
		||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o\
 | 
			
		||||
       menuitems.o osd.o plugin.o recording.o remote.o remux.o ringbuffer.o\
 | 
			
		||||
       svdrp.o thread.o tools.o vdr.o videodir.o
 | 
			
		||||
 | 
			
		||||
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
 | 
			
		||||
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
 | 
			
		||||
@@ -69,7 +71,7 @@ include $(DEPFILE)
 | 
			
		||||
# The main program:
 | 
			
		||||
 | 
			
		||||
vdr: $(OBJS) $(DTVLIB)
 | 
			
		||||
	g++ -g -O2 $(OBJS) $(NCURSESLIB) -ljpeg -lpthread $(LIBDIRS) $(DTVLIB) -o vdr
 | 
			
		||||
	g++ -g -O2 -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(DTVLIB) -o vdr
 | 
			
		||||
 | 
			
		||||
# The font files:
 | 
			
		||||
 | 
			
		||||
@@ -88,6 +90,21 @@ genfontfile: genfontfile.c
 | 
			
		||||
$(DTVLIB) $(DTVDIR)/libdtv.h:
 | 
			
		||||
	make -C $(DTVDIR) all
 | 
			
		||||
 | 
			
		||||
# The 'include' directory (for plugins):
 | 
			
		||||
 | 
			
		||||
include-dir:
 | 
			
		||||
	@mkdir -p include/vdr
 | 
			
		||||
	@(cd include/vdr; for i in ../../*.h; do ln -fs $$i .; done)
 | 
			
		||||
 | 
			
		||||
# Plugins:
 | 
			
		||||
 | 
			
		||||
plugins: include-dir
 | 
			
		||||
	@for i in `ls $(PLUGINDIR)/SRC | grep -v '[^a-z0-9]'`; do make -C "$(PLUGINDIR)/SRC/$$i" all; done
 | 
			
		||||
 | 
			
		||||
plugins-clean:
 | 
			
		||||
	@for i in `ls $(PLUGINDIR)/SRC | grep -v '[^a-z0-9]'`; do make -C "$(PLUGINDIR)/SRC/$$i" clean; done
 | 
			
		||||
	@-rm -f $(PLUGINDIR)/lib/*
 | 
			
		||||
 | 
			
		||||
# Install the files:
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
@@ -104,6 +121,7 @@ install:
 | 
			
		||||
clean:
 | 
			
		||||
	make -C $(DTVDIR) clean
 | 
			
		||||
	-rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~
 | 
			
		||||
	-rm -rf include
 | 
			
		||||
fontclean:
 | 
			
		||||
	-rm -f fontfix.c fontosd.c
 | 
			
		||||
CLEAN: clean fontclean
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										620
									
								
								PLUGINS.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										620
									
								
								PLUGINS.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,620 @@
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<title>The VDR Plugin System</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body bgcolor="white">
 | 
			
		||||
 | 
			
		||||
<h1>The VDR Plugin System</h1>
 | 
			
		||||
 | 
			
		||||
VDR provides an easy to use plugin interface that allows additional functionality
 | 
			
		||||
to be added to the program by implementing a dynamically loadable library file.
 | 
			
		||||
This interface allows programmers to develop additional functionality for VDR completely
 | 
			
		||||
separate from the core VDR source, without the need of patching the original
 | 
			
		||||
VDR code (and all the problems of correlating various patches).
 | 
			
		||||
<p>
 | 
			
		||||
This document describes the "outside" interface of the plugin system.
 | 
			
		||||
It handles everything necessary for a plugin to get hooked into the core
 | 
			
		||||
VDR program and present itself to the user.
 | 
			
		||||
 | 
			
		||||
<!--<p>TODO: Link to the document about VDR base classes to use when implementing actual functionality (yet to be written).-->
 | 
			
		||||
 | 
			
		||||
<hr><h2>Quick start</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Can't wait, can't wait!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
Actually you should read this entire document before starting to work with VDR plugins,
 | 
			
		||||
but you probably want to see something happening right away <tt>;-)</tt>
 | 
			
		||||
<p>
 | 
			
		||||
So, for a quick demonstration of the plugin system, there is a demo plugin called
 | 
			
		||||
"hello" that comes with the VDR source. To test drive this one, do the following:
 | 
			
		||||
<ul>
 | 
			
		||||
<li>change into the VDR source directory
 | 
			
		||||
<li><b><tt>make</tt></b> the VDR program with your usual <tt>REMOTE=...</tt> (and maybe other) options
 | 
			
		||||
<li>do <b><tt>make plugins</tt></b> to build the demo plugin
 | 
			
		||||
<li>run VDR with <b><tt>vdr -V</tt></b> to see the version information
 | 
			
		||||
<li>run VDR with <b><tt>vdr -h</tt></b> to see the command line options
 | 
			
		||||
<li>run VDR with <b><tt>vdr -Phello</tt></b>
 | 
			
		||||
<li>open VDR's main menu and select the <i>Hello</i> item
 | 
			
		||||
<li>open the <i>Setup</i> menu from VDR's main menu and select <i>Plugins</i>
 | 
			
		||||
</ul>
 | 
			
		||||
If you enjoyed this brief glimpse into VDR plugin handling, read through the rest of
 | 
			
		||||
this document and eventually write your own VDR plugin.
 | 
			
		||||
 | 
			
		||||
<hr><h2>The name of the plugin</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Give me some I.D.!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
One of the first things to consider when writing a VDR plugin is giving the thing
 | 
			
		||||
a proper name. This name will be used in the VDR command line in order to load
 | 
			
		||||
the plugin, and will also be the name of the plugin's source directory, as well
 | 
			
		||||
as part of the final library name.
 | 
			
		||||
<p>
 | 
			
		||||
The plugin's name should typically be as short as possible. Three letter
 | 
			
		||||
abbreviations like <b><tt>dvd</tt></b> (for a DVD player) or <b><tt>mp3</tt></b>
 | 
			
		||||
(for an MP3 player) would be good choices. It is also recommended that the name
 | 
			
		||||
consists of only lowercase letters and digits.
 | 
			
		||||
No other characters should be used here.
 | 
			
		||||
<p>
 | 
			
		||||
A plugin can access its name through the (non virtual) member function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
const char *Name(void);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The actual name is derived from the plugin's library file name, as defined in the
 | 
			
		||||
next chapter.
 | 
			
		||||
 | 
			
		||||
<a name="The plugin directory structure"><hr><h2>The plugin directory structure</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Where is everybody?</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
By default plugins are located in a directory named <tt>PLUGINS</tt> below the
 | 
			
		||||
VDR source directory. Inside this directory the following subdirectory structure
 | 
			
		||||
is used:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
VDR/PLUGINS/SRC
 | 
			
		||||
VDR/PLUGINS/SRC/demo
 | 
			
		||||
VDR/PLUGINS/SRC/hello
 | 
			
		||||
VDR/PLUGINS/lib
 | 
			
		||||
VDR/PLUGINS/lib/libvdr-demo.so.1.1.0
 | 
			
		||||
VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The <tt>SRC</tt> directory contains one subdirectory for each plugin, which carries
 | 
			
		||||
the name of that plugin (in the above example that would be <tt>demo</tt> and
 | 
			
		||||
<tt>hello</tt>, respectively). What's inside the individual source directory of a
 | 
			
		||||
plugin is entirely up to the author of that plugin. The only prerequisites are
 | 
			
		||||
that there is a <tt>Makefile</tt> that provides the targets <tt>all</tt> and
 | 
			
		||||
<tt>clean</tt>, and that a call to <tt>make all</tt> actually produces a dynamically
 | 
			
		||||
loadable library file for that plugin (we'll get to the details later).
 | 
			
		||||
<p>
 | 
			
		||||
The <tt>lib</tt> directory contains the dynamically loadable libraries of all
 | 
			
		||||
available plugins. Note that the names of these files are created by concatenating
 | 
			
		||||
<p>
 | 
			
		||||
<table border=2>
 | 
			
		||||
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>demo</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1.1.0</tt></b></td></tr>
 | 
			
		||||
<tr><td align=center><font size=-1>VDR plugin<br>library prefix</font></td><td align=center><font size=-1>name of<br>the plugin</font></td><td align=center><font size=-1>shared object<br>indicator</font></td><td align=center><font size=-1>VDR version number<br>this plugin was<br>compiled for</font></td></tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p>
 | 
			
		||||
The plugin library files can be stored in any directory. If the default organization
 | 
			
		||||
is not used, the path to the plugin directory has be be given to VDR through the
 | 
			
		||||
<b><tt>-L</tt></b> option.
 | 
			
		||||
<p>
 | 
			
		||||
The VDR <tt>Makefile</tt> contains the target <tt>plugins</tt>, which calls
 | 
			
		||||
<tt>make all</tt> in every directory found under <tt>VDR/PLUGINS/SRC</tt>,
 | 
			
		||||
plus the target <tt>plugins-clean</tt>, which calls <tt>make clean</tt> in
 | 
			
		||||
each of these directories.
 | 
			
		||||
<p>
 | 
			
		||||
If you download a plugin <a href="#Building the distribution package">package</a>
 | 
			
		||||
from the web, it will typically have a name like
 | 
			
		||||
<p>
 | 
			
		||||
<tt>vdr-demo-0.0.1.tgz</tt>
 | 
			
		||||
<p>
 | 
			
		||||
and will unpack into a directory named
 | 
			
		||||
<p>
 | 
			
		||||
<tt>vdr-demo-0.0.1</tt>
 | 
			
		||||
<p>
 | 
			
		||||
To use the <tt>plugins</tt> and <tt>plugins-clean</tt> targets from the VDR <tt>Makefile</tt>
 | 
			
		||||
you need to unpack such an archive into the <tt>VDR/PLUGINS/SRC</tt> directory and
 | 
			
		||||
create a symbolic link with the basic plugin name, as in
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
ln -s vdr-demo-0.0.1 demo
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
Since the VDR <tt>Makefile</tt> only searches for directories with names consisting
 | 
			
		||||
of only lowercase characters and digits, it will only follow the symbolic links, which
 | 
			
		||||
should lead to the current version of the plugin you want to use. This way you can
 | 
			
		||||
have several different versions of a plugin source (like <tt>vdr-demo-0.0.1</tt> and
 | 
			
		||||
<tt>vdr-demo-0.0.2</tt>) and define which one to actually use through the symbolic link.
 | 
			
		||||
 | 
			
		||||
<a name="Initializing a new plugin directory"><hr><h2>Initializing a new plugin directory</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>A room with a view</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
Call the Perl script <tt>newplugin</tt> from the VDR source directory to create
 | 
			
		||||
a new plugin directory with a <tt>Makefile</tt> and a main source file implementing
 | 
			
		||||
the basic derived plugin class.
 | 
			
		||||
You will also find a <tt>README</tt> file there with some inital text, where you
 | 
			
		||||
should fill in actual information about your project.
 | 
			
		||||
A <tt>HISTORY</tt> file is set up with an "Initial revision" entry. As your project
 | 
			
		||||
evolves, you should add the changes here with date and version number.
 | 
			
		||||
<p>
 | 
			
		||||
<tt>newplugin</tt> also creates a copy of the GPL license file <tt>COPYING</tt>,
 | 
			
		||||
assuming that you will release your work under that license. Change this if you
 | 
			
		||||
have other plans.
 | 
			
		||||
<p>
 | 
			
		||||
Add further files and maybe subdirectories to your plugin source directory as
 | 
			
		||||
necessary. Don't forget to adapt the <tt>Makefile</tt> appropriately.
 | 
			
		||||
 | 
			
		||||
<hr><h2>The actual implementation</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Use the source, Luke!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
A newly initialized plugin doesn't really do very much yet.
 | 
			
		||||
If you <a href="#Loading plugins into VDR">load it into VDR</a> you will find a new
 | 
			
		||||
entry in the main menu, with the same name as your plugin (where the first character
 | 
			
		||||
has been converted to uppercase). There will also be a new entry named "Plugins" in
 | 
			
		||||
the "Setup" menu, which will bring up a list of all loaded plugins, through which you
 | 
			
		||||
can access each plugin's own setup parameters (if it provides any).
 | 
			
		||||
<p>
 | 
			
		||||
To implement actual functionality into your plugin you need to edit the source file
 | 
			
		||||
that was generated as <tt>PLUGINS/SRC/name.c</tt>. Read the comments in that file
 | 
			
		||||
to see where you can bring in your own code. The following sections of this document
 | 
			
		||||
will walk you through the individual member functions of the plugin class.
 | 
			
		||||
<p>
 | 
			
		||||
Depending on what your plugin shall do, you may or may not need all of the given
 | 
			
		||||
member functions. Except for the <tt>MainMenuEntry()</tt> function they all by default
 | 
			
		||||
return values that will result in no actual functionality. You can either completely
 | 
			
		||||
delete unused functions from your source file, or just leave them as they are.
 | 
			
		||||
If your plugin shall not be accessible through VDR's main menu, simply remove
 | 
			
		||||
(or comment out) the line implementing the <tt>MainMenuEntry()</tt> function.
 | 
			
		||||
<p>
 | 
			
		||||
At the end of the plugin's source file you will find a line that looks like this:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
VDRPLUGINCREATOR(cPluginDemo);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
This is the "magic" hook that allows VDR to actually load the plugin into
 | 
			
		||||
its memory. You don't need to worry about the details behind all this.
 | 
			
		||||
<p>
 | 
			
		||||
If your plugin requires additional source files, simply add them to your plugin's
 | 
			
		||||
source directory and adjust the <tt>Makefile</tt> accordingly.
 | 
			
		||||
 | 
			
		||||
<hr><h2>Construction and Destruction</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>What goes up, must come down...</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
The constructor and destructor of a plugin are defined as
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
cPlugin(void);
 | 
			
		||||
virtual ~cPlugin();
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The <b>constructor</b> shall initialize any member variables the plugin defines, but
 | 
			
		||||
<b>must not access any global structures of VDR</b>.
 | 
			
		||||
It also must not create any threads or other large data structures. These things
 | 
			
		||||
are done in the <a href="#Getting started"><tt>Start()</tt></a> function later.
 | 
			
		||||
Constructing a plugin object shall not have any side effects or produce any output,
 | 
			
		||||
since VDR, for instance, has to create the plugin objects in order to get their
 | 
			
		||||
command line help - and after that immediately destroys them again.
 | 
			
		||||
<p>
 | 
			
		||||
The <b>destructor</b> has to clean up any data created by the plugin, and has to
 | 
			
		||||
take care that any threads the plugin may have created will be stopped.
 | 
			
		||||
<p>
 | 
			
		||||
Of course, if your plugin doesn't define any member variables that need to be
 | 
			
		||||
initialized (and deleted), you don't need to implement either of these functions.
 | 
			
		||||
 | 
			
		||||
<hr><h2>Version number</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Which incarnation is this?</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
Every plugin must have a version number of its own, which does not necessarily
 | 
			
		||||
have to be in any way related to the VDR version number.
 | 
			
		||||
VDR requests a plugin's version number through a call to the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual const char *Version(void) = 0;
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
Since this is a "pure" virtual function, any derived plugin class <b>must</b>
 | 
			
		||||
implement it. The returned string should identify this version of the plugin.
 | 
			
		||||
Typically this would be something like "0.0.1", but it may also contain other
 | 
			
		||||
information, like for instance "0.0.1pre2" or the like. The string should only
 | 
			
		||||
be as long as really necessary, and shall not contain the plugin's name itself.
 | 
			
		||||
Here's an example:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
static const char *VERSION = "0.0.1";
 | 
			
		||||
 | 
			
		||||
...
 | 
			
		||||
 | 
			
		||||
const char *cPluginDemo::Version(void)
 | 
			
		||||
{
 | 
			
		||||
  return VERSION;
 | 
			
		||||
}
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
Note that the definition of the version number is expected to be located in the
 | 
			
		||||
main source file, and must be written as
 | 
			
		||||
<pre>
 | 
			
		||||
static const char *VERSION = ...
 | 
			
		||||
</pre>
 | 
			
		||||
just like shown in the above example. This is a convention that allows the <tt>Makefile</tt>
 | 
			
		||||
to extract the version number when generating the file name for the distribution archive.
 | 
			
		||||
<p>
 | 
			
		||||
A new plugin project should start with version number <tt>0.0.1</tt> and should reach
 | 
			
		||||
version <tt>1.0.0</tt> once it is completely operative and well tested. Following the
 | 
			
		||||
Linux kernel version numbering scheme, versions with <i>even</i> release numbers
 | 
			
		||||
(like <tt>1.0.x</tt>, <tt>1.2.x</tt>, <tt>1.4.x</tt>...) should be stable releases,
 | 
			
		||||
while those with <i>odd</i> release numbers (like <tt>1.1.x</tt>, <tt>1.3.x</tt>,
 | 
			
		||||
<tt>1.5.x</tt>...) are usually considered "under development". The three parts of
 | 
			
		||||
a version number are not limited to single digits, so a version number of <tt>1.2.15</tt>
 | 
			
		||||
would be acceptable.
 | 
			
		||||
 | 
			
		||||
<hr><h2>Description</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>What is it that you do?</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
In order to tell the user what exactly a plugin does, it must implement the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual const char *Description(void) = 0;
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
which returns a short, one line description of the plugin's purpose.
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual const char *Description(void)
 | 
			
		||||
{
 | 
			
		||||
  return "A simple demo plugin";
 | 
			
		||||
}
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
<hr><h2>Command line arguments</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Taking orders</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
A VDR plugin can have command line arguments just like any normal program.
 | 
			
		||||
If a plugin wants to react on command line arguments, it needs to implement
 | 
			
		||||
the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual bool ProcessArgs(int argc, char *argv[]);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The parameters <tt>argc</tt> and <tt>argv</tt> have exactly the same meaning
 | 
			
		||||
as in a normal C program's <tt>main()</tt> function.
 | 
			
		||||
<tt>argv[0]</tt> contains the name of the plugin (as given in the <b><tt>-P</tt></b>
 | 
			
		||||
option of the <tt>vdr</tt> call).
 | 
			
		||||
<p>
 | 
			
		||||
Each plugin has its own set of command line options, which are totally independent
 | 
			
		||||
from those of any other plugin or VDR itself.
 | 
			
		||||
<p>
 | 
			
		||||
You can use the <tt>getopt()</tt> or <tt>getopt_long()</tt> function to process
 | 
			
		||||
these arguments. As with any normal C program, the strings pointed to by <tt>argv</tt>
 | 
			
		||||
will survive the entire lifetime of the plugin, so it is safe to store pointers to
 | 
			
		||||
these values inside the plugin. Here's an example:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
bool cPluginDemo::ProcessArgs(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  static struct option long_options[] = {
 | 
			
		||||
      { "aaa",      required_argument, NULL, 'a' },
 | 
			
		||||
      { "bbb",      no_argument,       NULL, 'b' },
 | 
			
		||||
      { NULL }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  int c;
 | 
			
		||||
  while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
 | 
			
		||||
        switch (c) {
 | 
			
		||||
          case 'a': fprintf(stderr, "option -a = %s\n", optarg);
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'b': fprintf(stderr, "option -b\n");
 | 
			
		||||
                    break;
 | 
			
		||||
          default:  return false;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The return value must be <i>true</i> if all options have been processed
 | 
			
		||||
correctly, or <i>false</i> in case of an error. The first plugin that returns
 | 
			
		||||
<i>false</i> from a call to its <tt>ProcessArgs()</tt> function will cause VDR
 | 
			
		||||
to exit.
 | 
			
		||||
 | 
			
		||||
<hr><h2>Command line help</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Tell me about it...</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If a plugin accepts command line options, it should implement the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual const char *CommandLineHelp(void);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
which will be called if the user enters the <b><tt>-h</tt></b> option when starting VDR.
 | 
			
		||||
The returned string should contain the command line help for this plugin, formatted
 | 
			
		||||
in the same way as done by VDR itself:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
const char *cPluginDemo::CommandLineHelp(void)
 | 
			
		||||
{
 | 
			
		||||
  return "  -a ABC,   --aaa=ABC      do something nice with ABC\n"
 | 
			
		||||
         "  -b,       --bbb          activate 'plan B'\n";
 | 
			
		||||
}
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
This command line help will be printed directly below VDR's help texts (separated
 | 
			
		||||
by a line indicating the plugin's name, version and description), so if you use the
 | 
			
		||||
same formatting as shown here it will line up nicely.
 | 
			
		||||
Note that all lines should be terminated with a newline character, and should
 | 
			
		||||
be shorter than 80 characters.
 | 
			
		||||
 | 
			
		||||
<a name="Getting started"><hr><h2>Getting started</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Let's get ready to rumble!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If a plugin implements a function that runs in the background (presumably in a
 | 
			
		||||
thread of its own), or wants to make use of <a href="#Internationalization">internationalization</a>,
 | 
			
		||||
it needs to implement the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual void Start(void);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
which is called once for each plugin at program startup.
 | 
			
		||||
Inside this function the plugin must set up everything necessary to perform
 | 
			
		||||
its task. This may, for instance, be a thread that collects data from the DVB
 | 
			
		||||
stream, which is later presented to the user via a function that is available
 | 
			
		||||
from the main menu.
 | 
			
		||||
<p>
 | 
			
		||||
If the plugin doesn't implement any background functionality or internationalized
 | 
			
		||||
texts, it doesn't need to implement this function.
 | 
			
		||||
 | 
			
		||||
<hr><h2>Main menu entry</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Today's special is...</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If the plugin implements a feature that the user shall be able to access
 | 
			
		||||
from VDR's main menu, it needs to implement the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual const char *MainMenuEntry(void);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The default implementation returns a <tt>NULL</tt> pointer, which means that
 | 
			
		||||
this plugin will not have an item in the main menu. Here's an example of a
 | 
			
		||||
plugin that will have a main menu item:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
const char *cPluginDemo::MainMenuEntry(void)
 | 
			
		||||
{
 | 
			
		||||
  return "Demo";
 | 
			
		||||
}
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The menu entries of all plugins will be inserted into VDR's main menu right
 | 
			
		||||
after the <i>Recordings</i> item, in the same sequence as they were given
 | 
			
		||||
in the call to VDR.
 | 
			
		||||
 | 
			
		||||
<hr><h2>User interaction</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>It's showtime!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If the user selects the main menu entry of a plugin, VDR calls the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual cOsdMenu *MainMenuAction(void);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
which can do one of two things:
 | 
			
		||||
<ul>
 | 
			
		||||
<li>Return a pointer to a <tt>cOsdMenu</tt> object which will be displayed
 | 
			
		||||
    as a submenu of the main menu (just like the <i>Recordings</i> menu, for instance).
 | 
			
		||||
    That menu can then implement further functionality and, for instance, could
 | 
			
		||||
    eventually start a custom player to replay a file other than a VDR recording.
 | 
			
		||||
<li>Perform a specific action and return <tt>NULL</tt>. In that case the main menu
 | 
			
		||||
    will be closed after calling <tt>MainMenuAction()</tt>.
 | 
			
		||||
</ul>
 | 
			
		||||
<b>
 | 
			
		||||
It is very important that a call to <tt>MainMenuAction()</tt> returns as soon
 | 
			
		||||
as possible! As long as the program stays inside this function, no other user
 | 
			
		||||
interaction is possible. If a specific action takes longer than a few seconds,
 | 
			
		||||
the plugin should launch a separate thread to do this.
 | 
			
		||||
</b>
 | 
			
		||||
 | 
			
		||||
<hr><h2>Setup parameters</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Remember me...</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If a plugin requires its own setup parameters, it needs to implement the following
 | 
			
		||||
functions to handle these parameters:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
virtual cMenuSetupPage *SetupMenu(void);
 | 
			
		||||
virtual bool SetupParse(const char *Name, const char *Value);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The <tt>SetupMenu()</tt> function shall return the plugin's "Setup" menu
 | 
			
		||||
page, where the user can adjust all the parameters known to this plugin.
 | 
			
		||||
<p>
 | 
			
		||||
<tt>SetupParse()</tt> will be called for each parameter the plugin has
 | 
			
		||||
previously stored in the global setup data (see below). It shall return
 | 
			
		||||
<i>true</i> if the parameter was parsed correctly, <i>false</i> in case of
 | 
			
		||||
an error. If <i>false</i> is returned, an error message will be written to
 | 
			
		||||
the log file (and program execution will continue).
 | 
			
		||||
<p>
 | 
			
		||||
The plugin's setup parameters are stored in the same file as VDR's parameters.
 | 
			
		||||
In order to allow each plugin (and VDR itself) to have its own set of parameters,
 | 
			
		||||
the <tt>Name</tt> of each parameter will be preceeded with the plugin's
 | 
			
		||||
name, as in
 | 
			
		||||
<p>
 | 
			
		||||
<tt>demo.SomeParameter = 123</tt>
 | 
			
		||||
<p>
 | 
			
		||||
The prefix will be handled by the core VDR setup code, so the individual
 | 
			
		||||
plugins need not worry about this.
 | 
			
		||||
<p>
 | 
			
		||||
To store its values in the global setup, a plugin has to call the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
void SetupStore(const char *Name, <i>type</i> Value);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
where <tt>Name</tt> is the name of the parameter (<tt>"SomeParameter"</tt> in the above
 | 
			
		||||
example, without the prefix <tt>"demo."</tt>) and <tt>Value</tt> is a simple data type (like
 | 
			
		||||
<tt>char *</tt>, <tt>int</tt> etc).
 | 
			
		||||
Note that this is not a function that the individual plugin class needs to implement!
 | 
			
		||||
<tt>SetupStore()</tt> is a non-virtual member function of the <tt>cPlugin</tt> class.
 | 
			
		||||
<p>
 | 
			
		||||
To remove a parameter from the setup data, call <tt>SetupStore()</tt> with the appropriate
 | 
			
		||||
name and without any value, as in
 | 
			
		||||
<p>
 | 
			
		||||
<tt>SetupStore("SomeParameter");</tt>
 | 
			
		||||
<p>
 | 
			
		||||
The VDR menu "Setup/Plugins" will list all loaded plugins with their name,
 | 
			
		||||
version number and description. Selecting an item in this list will bring up
 | 
			
		||||
the plugin's "Setup" menu if that plugin has implemented the <tt>SetupMenu()</tt>
 | 
			
		||||
function.
 | 
			
		||||
<p>
 | 
			
		||||
Finally, a plugin doesn't have to implement the <tt>SetupMenu()</tt> if it only
 | 
			
		||||
needs setup parameters that are not directly user adjustable. It can use
 | 
			
		||||
<tt>SetupStore()</tt> and <tt>SetupParse()</tt> without presenting these
 | 
			
		||||
parameters to the user.
 | 
			
		||||
 | 
			
		||||
<a name="Internationalization"><hr><h2>Internationalization</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Welcome to Babylon!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If a plugin displays texts to the user, it should implement internationalized
 | 
			
		||||
versions of these texts and call the function
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
void RegisterI18n(const tI18nPhrase * const Phrases);
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
to register them with VDR's internationalization mechanism.
 | 
			
		||||
<p>
 | 
			
		||||
The call to this function must be done in the <a href="#Getting started"><tt>Start()</tt></a> function of the plugin:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
const tI18nPhrase Phrases[] = {
 | 
			
		||||
  { "Hello world!",
 | 
			
		||||
    "Hallo Welt!",
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
  },
 | 
			
		||||
  { NULL }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
void cPluginDemo::Start(void)
 | 
			
		||||
{
 | 
			
		||||
  RegisterI18n(Phrases);
 | 
			
		||||
}
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
Each entry of type <tt>tI18nPhrase</tt> must have exactly as many members as defined
 | 
			
		||||
by the constant <tt>I18nNumLanguages</tt> in the file <tt>VDR/i18n.h</tt>, and the
 | 
			
		||||
sequence of the various languages must be the same as defined in <tt>VDR/i18n.c</tt>.<br>
 | 
			
		||||
<b>It is very important that the array is terminated with a <tt>{ NULL }</tt>
 | 
			
		||||
entry!</b>.
 | 
			
		||||
<p>
 | 
			
		||||
Usually you won't be able to fill in all the different translations by yourself, so
 | 
			
		||||
you may want to contact the maintainers of these languages (listed in the file
 | 
			
		||||
<tt>VDR/i18n.c</tt>) and ask them to provide the additional translations.
 | 
			
		||||
<p>
 | 
			
		||||
The actual runtime selection of the texts corresponding to the selected language
 | 
			
		||||
is done by wrapping each internationalized text with the <tt>tr()</tt> macro:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
const char *s = tr("Hello world!");
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
The text given here must be the first one defined in the related <i>Phrases</i>
 | 
			
		||||
entry (which is the English version), and the returned pointer is either a translated
 | 
			
		||||
version (if available) or the original string. In the latter case a message will be
 | 
			
		||||
written to the log file, indicating that a translation is missing.
 | 
			
		||||
Texts are first searched for in the <i>Phrases</i> registered for this plugin (if any)
 | 
			
		||||
and then in the global VDR texts. So a plugin can make use of texts defined by the
 | 
			
		||||
core VDR code.
 | 
			
		||||
 | 
			
		||||
<a name="Loading plugins into VDR"><hr><h2>Loading plugins into VDR</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Saddling up!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
Plugins are loaded into VDR using the command line option <b><tt>-P</tt></b>, as in
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
vdr -Pdemo
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
If the plugin accepts command line options, they are given as part of the argument
 | 
			
		||||
to the <b><tt>-P</tt></b> option, which then has to be enclosed in quotes:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
vdr -P"demo -a abc -b"
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
Any number of plugins can be loaded this way, each with its own <b><tt>-P</tt></b> option:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
vdr -P"demo -a abc -b" -Pdvd -Pmp3
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
If you are not starting VDR from the VDR source directory (and thus your plugins
 | 
			
		||||
cannot be found at their default location) you need to tell VDR the location of
 | 
			
		||||
the plugins through the <b><tt>-L</tt></b> option:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
vdr -L/usr/lib/vdr -Pdemo
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
There can be any number of <b><tt>-L</tt></b> options, and each of them will apply to the
 | 
			
		||||
<b><tt>-P</tt></b> options following it.
 | 
			
		||||
<p>
 | 
			
		||||
When started with the <b><tt>-h</tt></b> or <b><tt>-V</tt></b> option (for <i>help</i>
 | 
			
		||||
or <i>version</i> information, respectively), VDR will automatically load all plugins
 | 
			
		||||
in the default or given directory that match the VDR plugin
 | 
			
		||||
<a href="#The plugin directory structure">naming convention</a>,
 | 
			
		||||
and display their help and/or version information in addition to its own output.
 | 
			
		||||
 | 
			
		||||
<a name="Building the distribution package"><hr><h2>Building the distribution package</h2>
 | 
			
		||||
 | 
			
		||||
<center><i><b>Let's get this show on the road!</b></i></center><p>
 | 
			
		||||
 | 
			
		||||
If you want to make your plugin available to other VDR users, you'll need to
 | 
			
		||||
make a package that can be easily distributed.
 | 
			
		||||
The <tt>Makefile</tt> that has been created by the call to
 | 
			
		||||
<a href="#Initializing a new plugin directory"><tt>newplugin</tt></a>
 | 
			
		||||
provides the target <tt>package</tt>, which does this for you.
 | 
			
		||||
<p>
 | 
			
		||||
Simply change into your source directory and execute <tt>make package</tt>:
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
cd VDR/PLUGINS/SRC/demo
 | 
			
		||||
make package
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
After this you should find a file named like
 | 
			
		||||
 | 
			
		||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
 | 
			
		||||
vdr-demo-0.0.1.tgz
 | 
			
		||||
</pre></td></tr></table><p>
 | 
			
		||||
 | 
			
		||||
in your source directory, where <tt>demo</tt> will be replaced with your actual
 | 
			
		||||
plugin's name, and <tt>0.0.1</tt> will be your plugin's current version number.
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										340
									
								
								PLUGINS/SRC/hello/COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								PLUGINS/SRC/hello/COPYING
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,340 @@
 | 
			
		||||
		    GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
		       Version 2, June 1991
 | 
			
		||||
 | 
			
		||||
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 | 
			
		||||
                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 Everyone is permitted to copy and distribute verbatim copies
 | 
			
		||||
 of this license document, but changing it is not allowed.
 | 
			
		||||
 | 
			
		||||
			    Preamble
 | 
			
		||||
 | 
			
		||||
  The licenses for most software are designed to take away your
 | 
			
		||||
freedom to share and change it.  By contrast, the GNU General Public
 | 
			
		||||
License is intended to guarantee your freedom to share and change free
 | 
			
		||||
software--to make sure the software is free for all its users.  This
 | 
			
		||||
General Public License applies to most of the Free Software
 | 
			
		||||
Foundation's software and to any other program whose authors commit to
 | 
			
		||||
using it.  (Some other Free Software Foundation software is covered by
 | 
			
		||||
the GNU Library General Public License instead.)  You can apply it to
 | 
			
		||||
your programs, too.
 | 
			
		||||
 | 
			
		||||
  When we speak of free software, we are referring to freedom, not
 | 
			
		||||
price.  Our General Public Licenses are designed to make sure that you
 | 
			
		||||
have the freedom to distribute copies of free software (and charge for
 | 
			
		||||
this service if you wish), that you receive source code or can get it
 | 
			
		||||
if you want it, that you can change the software or use pieces of it
 | 
			
		||||
in new free programs; and that you know you can do these things.
 | 
			
		||||
 | 
			
		||||
  To protect your rights, we need to make restrictions that forbid
 | 
			
		||||
anyone to deny you these rights or to ask you to surrender the rights.
 | 
			
		||||
These restrictions translate to certain responsibilities for you if you
 | 
			
		||||
distribute copies of the software, or if you modify it.
 | 
			
		||||
 | 
			
		||||
  For example, if you distribute copies of such a program, whether
 | 
			
		||||
gratis or for a fee, you must give the recipients all the rights that
 | 
			
		||||
you have.  You must make sure that they, too, receive or can get the
 | 
			
		||||
source code.  And you must show them these terms so they know their
 | 
			
		||||
rights.
 | 
			
		||||
 | 
			
		||||
  We protect your rights with two steps: (1) copyright the software, and
 | 
			
		||||
(2) offer you this license which gives you legal permission to copy,
 | 
			
		||||
distribute and/or modify the software.
 | 
			
		||||
 | 
			
		||||
  Also, for each author's protection and ours, we want to make certain
 | 
			
		||||
that everyone understands that there is no warranty for this free
 | 
			
		||||
software.  If the software is modified by someone else and passed on, we
 | 
			
		||||
want its recipients to know that what they have is not the original, so
 | 
			
		||||
that any problems introduced by others will not reflect on the original
 | 
			
		||||
authors' reputations.
 | 
			
		||||
 | 
			
		||||
  Finally, any free program is threatened constantly by software
 | 
			
		||||
patents.  We wish to avoid the danger that redistributors of a free
 | 
			
		||||
program will individually obtain patent licenses, in effect making the
 | 
			
		||||
program proprietary.  To prevent this, we have made it clear that any
 | 
			
		||||
patent must be licensed for everyone's free use or not licensed at all.
 | 
			
		||||
 | 
			
		||||
  The precise terms and conditions for copying, distribution and
 | 
			
		||||
modification follow.
 | 
			
		||||
 | 
			
		||||
		    GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
			
		||||
 | 
			
		||||
  0. This License applies to any program or other work which contains
 | 
			
		||||
a notice placed by the copyright holder saying it may be distributed
 | 
			
		||||
under the terms of this General Public License.  The "Program", below,
 | 
			
		||||
refers to any such program or work, and a "work based on the Program"
 | 
			
		||||
means either the Program or any derivative work under copyright law:
 | 
			
		||||
that is to say, a work containing the Program or a portion of it,
 | 
			
		||||
either verbatim or with modifications and/or translated into another
 | 
			
		||||
language.  (Hereinafter, translation is included without limitation in
 | 
			
		||||
the term "modification".)  Each licensee is addressed as "you".
 | 
			
		||||
 | 
			
		||||
Activities other than copying, distribution and modification are not
 | 
			
		||||
covered by this License; they are outside its scope.  The act of
 | 
			
		||||
running the Program is not restricted, and the output from the Program
 | 
			
		||||
is covered only if its contents constitute a work based on the
 | 
			
		||||
Program (independent of having been made by running the Program).
 | 
			
		||||
Whether that is true depends on what the Program does.
 | 
			
		||||
 | 
			
		||||
  1. You may copy and distribute verbatim copies of the Program's
 | 
			
		||||
source code as you receive it, in any medium, provided that you
 | 
			
		||||
conspicuously and appropriately publish on each copy an appropriate
 | 
			
		||||
copyright notice and disclaimer of warranty; keep intact all the
 | 
			
		||||
notices that refer to this License and to the absence of any warranty;
 | 
			
		||||
and give any other recipients of the Program a copy of this License
 | 
			
		||||
along with the Program.
 | 
			
		||||
 | 
			
		||||
You may charge a fee for the physical act of transferring a copy, and
 | 
			
		||||
you may at your option offer warranty protection in exchange for a fee.
 | 
			
		||||
 | 
			
		||||
  2. You may modify your copy or copies of the Program or any portion
 | 
			
		||||
of it, thus forming a work based on the Program, and copy and
 | 
			
		||||
distribute such modifications or work under the terms of Section 1
 | 
			
		||||
above, provided that you also meet all of these conditions:
 | 
			
		||||
 | 
			
		||||
    a) You must cause the modified files to carry prominent notices
 | 
			
		||||
    stating that you changed the files and the date of any change.
 | 
			
		||||
 | 
			
		||||
    b) You must cause any work that you distribute or publish, that in
 | 
			
		||||
    whole or in part contains or is derived from the Program or any
 | 
			
		||||
    part thereof, to be licensed as a whole at no charge to all third
 | 
			
		||||
    parties under the terms of this License.
 | 
			
		||||
 | 
			
		||||
    c) If the modified program normally reads commands interactively
 | 
			
		||||
    when run, you must cause it, when started running for such
 | 
			
		||||
    interactive use in the most ordinary way, to print or display an
 | 
			
		||||
    announcement including an appropriate copyright notice and a
 | 
			
		||||
    notice that there is no warranty (or else, saying that you provide
 | 
			
		||||
    a warranty) and that users may redistribute the program under
 | 
			
		||||
    these conditions, and telling the user how to view a copy of this
 | 
			
		||||
    License.  (Exception: if the Program itself is interactive but
 | 
			
		||||
    does not normally print such an announcement, your work based on
 | 
			
		||||
    the Program is not required to print an announcement.)
 | 
			
		||||
 | 
			
		||||
These requirements apply to the modified work as a whole.  If
 | 
			
		||||
identifiable sections of that work are not derived from the Program,
 | 
			
		||||
and can be reasonably considered independent and separate works in
 | 
			
		||||
themselves, then this License, and its terms, do not apply to those
 | 
			
		||||
sections when you distribute them as separate works.  But when you
 | 
			
		||||
distribute the same sections as part of a whole which is a work based
 | 
			
		||||
on the Program, the distribution of the whole must be on the terms of
 | 
			
		||||
this License, whose permissions for other licensees extend to the
 | 
			
		||||
entire whole, and thus to each and every part regardless of who wrote it.
 | 
			
		||||
 | 
			
		||||
Thus, it is not the intent of this section to claim rights or contest
 | 
			
		||||
your rights to work written entirely by you; rather, the intent is to
 | 
			
		||||
exercise the right to control the distribution of derivative or
 | 
			
		||||
collective works based on the Program.
 | 
			
		||||
 | 
			
		||||
In addition, mere aggregation of another work not based on the Program
 | 
			
		||||
with the Program (or with a work based on the Program) on a volume of
 | 
			
		||||
a storage or distribution medium does not bring the other work under
 | 
			
		||||
the scope of this License.
 | 
			
		||||
 | 
			
		||||
  3. You may copy and distribute the Program (or a work based on it,
 | 
			
		||||
under Section 2) in object code or executable form under the terms of
 | 
			
		||||
Sections 1 and 2 above provided that you also do one of the following:
 | 
			
		||||
 | 
			
		||||
    a) Accompany it with the complete corresponding machine-readable
 | 
			
		||||
    source code, which must be distributed under the terms of Sections
 | 
			
		||||
    1 and 2 above on a medium customarily used for software interchange; or,
 | 
			
		||||
 | 
			
		||||
    b) Accompany it with a written offer, valid for at least three
 | 
			
		||||
    years, to give any third party, for a charge no more than your
 | 
			
		||||
    cost of physically performing source distribution, a complete
 | 
			
		||||
    machine-readable copy of the corresponding source code, to be
 | 
			
		||||
    distributed under the terms of Sections 1 and 2 above on a medium
 | 
			
		||||
    customarily used for software interchange; or,
 | 
			
		||||
 | 
			
		||||
    c) Accompany it with the information you received as to the offer
 | 
			
		||||
    to distribute corresponding source code.  (This alternative is
 | 
			
		||||
    allowed only for noncommercial distribution and only if you
 | 
			
		||||
    received the program in object code or executable form with such
 | 
			
		||||
    an offer, in accord with Subsection b above.)
 | 
			
		||||
 | 
			
		||||
The source code for a work means the preferred form of the work for
 | 
			
		||||
making modifications to it.  For an executable work, complete source
 | 
			
		||||
code means all the source code for all modules it contains, plus any
 | 
			
		||||
associated interface definition files, plus the scripts used to
 | 
			
		||||
control compilation and installation of the executable.  However, as a
 | 
			
		||||
special exception, the source code distributed need not include
 | 
			
		||||
anything that is normally distributed (in either source or binary
 | 
			
		||||
form) with the major components (compiler, kernel, and so on) of the
 | 
			
		||||
operating system on which the executable runs, unless that component
 | 
			
		||||
itself accompanies the executable.
 | 
			
		||||
 | 
			
		||||
If distribution of executable or object code is made by offering
 | 
			
		||||
access to copy from a designated place, then offering equivalent
 | 
			
		||||
access to copy the source code from the same place counts as
 | 
			
		||||
distribution of the source code, even though third parties are not
 | 
			
		||||
compelled to copy the source along with the object code.
 | 
			
		||||
 | 
			
		||||
  4. You may not copy, modify, sublicense, or distribute the Program
 | 
			
		||||
except as expressly provided under this License.  Any attempt
 | 
			
		||||
otherwise to copy, modify, sublicense or distribute the Program is
 | 
			
		||||
void, and will automatically terminate your rights under this License.
 | 
			
		||||
However, parties who have received copies, or rights, from you under
 | 
			
		||||
this License will not have their licenses terminated so long as such
 | 
			
		||||
parties remain in full compliance.
 | 
			
		||||
 | 
			
		||||
  5. You are not required to accept this License, since you have not
 | 
			
		||||
signed it.  However, nothing else grants you permission to modify or
 | 
			
		||||
distribute the Program or its derivative works.  These actions are
 | 
			
		||||
prohibited by law if you do not accept this License.  Therefore, by
 | 
			
		||||
modifying or distributing the Program (or any work based on the
 | 
			
		||||
Program), you indicate your acceptance of this License to do so, and
 | 
			
		||||
all its terms and conditions for copying, distributing or modifying
 | 
			
		||||
the Program or works based on it.
 | 
			
		||||
 | 
			
		||||
  6. Each time you redistribute the Program (or any work based on the
 | 
			
		||||
Program), the recipient automatically receives a license from the
 | 
			
		||||
original licensor to copy, distribute or modify the Program subject to
 | 
			
		||||
these terms and conditions.  You may not impose any further
 | 
			
		||||
restrictions on the recipients' exercise of the rights granted herein.
 | 
			
		||||
You are not responsible for enforcing compliance by third parties to
 | 
			
		||||
this License.
 | 
			
		||||
 | 
			
		||||
  7. If, as a consequence of a court judgment or allegation of patent
 | 
			
		||||
infringement or for any other reason (not limited to patent issues),
 | 
			
		||||
conditions are imposed on you (whether by court order, agreement or
 | 
			
		||||
otherwise) that contradict the conditions of this License, they do not
 | 
			
		||||
excuse you from the conditions of this License.  If you cannot
 | 
			
		||||
distribute so as to satisfy simultaneously your obligations under this
 | 
			
		||||
License and any other pertinent obligations, then as a consequence you
 | 
			
		||||
may not distribute the Program at all.  For example, if a patent
 | 
			
		||||
license would not permit royalty-free redistribution of the Program by
 | 
			
		||||
all those who receive copies directly or indirectly through you, then
 | 
			
		||||
the only way you could satisfy both it and this License would be to
 | 
			
		||||
refrain entirely from distribution of the Program.
 | 
			
		||||
 | 
			
		||||
If any portion of this section is held invalid or unenforceable under
 | 
			
		||||
any particular circumstance, the balance of the section is intended to
 | 
			
		||||
apply and the section as a whole is intended to apply in other
 | 
			
		||||
circumstances.
 | 
			
		||||
 | 
			
		||||
It is not the purpose of this section to induce you to infringe any
 | 
			
		||||
patents or other property right claims or to contest validity of any
 | 
			
		||||
such claims; this section has the sole purpose of protecting the
 | 
			
		||||
integrity of the free software distribution system, which is
 | 
			
		||||
implemented by public license practices.  Many people have made
 | 
			
		||||
generous contributions to the wide range of software distributed
 | 
			
		||||
through that system in reliance on consistent application of that
 | 
			
		||||
system; it is up to the author/donor to decide if he or she is willing
 | 
			
		||||
to distribute software through any other system and a licensee cannot
 | 
			
		||||
impose that choice.
 | 
			
		||||
 | 
			
		||||
This section is intended to make thoroughly clear what is believed to
 | 
			
		||||
be a consequence of the rest of this License.
 | 
			
		||||
 | 
			
		||||
  8. If the distribution and/or use of the Program is restricted in
 | 
			
		||||
certain countries either by patents or by copyrighted interfaces, the
 | 
			
		||||
original copyright holder who places the Program under this License
 | 
			
		||||
may add an explicit geographical distribution limitation excluding
 | 
			
		||||
those countries, so that distribution is permitted only in or among
 | 
			
		||||
countries not thus excluded.  In such case, this License incorporates
 | 
			
		||||
the limitation as if written in the body of this License.
 | 
			
		||||
 | 
			
		||||
  9. The Free Software Foundation may publish revised and/or new versions
 | 
			
		||||
of the General Public License from time to time.  Such new versions will
 | 
			
		||||
be similar in spirit to the present version, but may differ in detail to
 | 
			
		||||
address new problems or concerns.
 | 
			
		||||
 | 
			
		||||
Each version is given a distinguishing version number.  If the Program
 | 
			
		||||
specifies a version number of this License which applies to it and "any
 | 
			
		||||
later version", you have the option of following the terms and conditions
 | 
			
		||||
either of that version or of any later version published by the Free
 | 
			
		||||
Software Foundation.  If the Program does not specify a version number of
 | 
			
		||||
this License, you may choose any version ever published by the Free Software
 | 
			
		||||
Foundation.
 | 
			
		||||
 | 
			
		||||
  10. If you wish to incorporate parts of the Program into other free
 | 
			
		||||
programs whose distribution conditions are different, write to the author
 | 
			
		||||
to ask for permission.  For software which is copyrighted by the Free
 | 
			
		||||
Software Foundation, write to the Free Software Foundation; we sometimes
 | 
			
		||||
make exceptions for this.  Our decision will be guided by the two goals
 | 
			
		||||
of preserving the free status of all derivatives of our free software and
 | 
			
		||||
of promoting the sharing and reuse of software generally.
 | 
			
		||||
 | 
			
		||||
			    NO WARRANTY
 | 
			
		||||
 | 
			
		||||
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 | 
			
		||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 | 
			
		||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 | 
			
		||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 | 
			
		||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 | 
			
		||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 | 
			
		||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 | 
			
		||||
REPAIR OR CORRECTION.
 | 
			
		||||
 | 
			
		||||
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
			
		||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 | 
			
		||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 | 
			
		||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 | 
			
		||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 | 
			
		||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 | 
			
		||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 | 
			
		||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 | 
			
		||||
POSSIBILITY OF SUCH DAMAGES.
 | 
			
		||||
 | 
			
		||||
		     END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
	    How to Apply These Terms to Your New Programs
 | 
			
		||||
 | 
			
		||||
  If you develop a new program, and you want it to be of the greatest
 | 
			
		||||
possible use to the public, the best way to achieve this is to make it
 | 
			
		||||
free software which everyone can redistribute and change under these terms.
 | 
			
		||||
 | 
			
		||||
  To do so, attach the following notices to the program.  It is safest
 | 
			
		||||
to attach them to the start of each source file to most effectively
 | 
			
		||||
convey the exclusion of warranty; and each file should have at least
 | 
			
		||||
the "copyright" line and a pointer to where the full notice is found.
 | 
			
		||||
 | 
			
		||||
    <one line to give the program's name and a brief idea of what it does.>
 | 
			
		||||
    Copyright (C) <year>  <name of author>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Also add information on how to contact you by electronic and paper mail.
 | 
			
		||||
 | 
			
		||||
If the program is interactive, make it output a short notice like this
 | 
			
		||||
when it starts in an interactive mode:
 | 
			
		||||
 | 
			
		||||
    Gnomovision version 69, Copyright (C) year name of author
 | 
			
		||||
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
			
		||||
    This is free software, and you are welcome to redistribute it
 | 
			
		||||
    under certain conditions; type `show c' for details.
 | 
			
		||||
 | 
			
		||||
The hypothetical commands `show w' and `show c' should show the appropriate
 | 
			
		||||
parts of the General Public License.  Of course, the commands you use may
 | 
			
		||||
be called something other than `show w' and `show c'; they could even be
 | 
			
		||||
mouse-clicks or menu items--whatever suits your program.
 | 
			
		||||
 | 
			
		||||
You should also get your employer (if you work as a programmer) or your
 | 
			
		||||
school, if any, to sign a "copyright disclaimer" for the program, if
 | 
			
		||||
necessary.  Here is a sample; alter the names:
 | 
			
		||||
 | 
			
		||||
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 | 
			
		||||
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 | 
			
		||||
 | 
			
		||||
  <signature of Ty Coon>, 1 April 1989
 | 
			
		||||
  Ty Coon, President of Vice
 | 
			
		||||
 | 
			
		||||
This General Public License does not permit incorporating your program into
 | 
			
		||||
proprietary programs.  If your program is a subroutine library, you may
 | 
			
		||||
consider it more useful to permit linking proprietary applications with the
 | 
			
		||||
library.  If this is what you want to do, use the GNU Library General
 | 
			
		||||
Public License instead of this License.
 | 
			
		||||
							
								
								
									
										6
									
								
								PLUGINS/SRC/hello/HISTORY
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								PLUGINS/SRC/hello/HISTORY
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
VDR Plugin 'hello' Revision History
 | 
			
		||||
-----------------------------------
 | 
			
		||||
 | 
			
		||||
2002-05-09: Version 0.0.1
 | 
			
		||||
 | 
			
		||||
- Initial revision.
 | 
			
		||||
							
								
								
									
										78
									
								
								PLUGINS/SRC/hello/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								PLUGINS/SRC/hello/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#
 | 
			
		||||
# Makefile for a Video Disk Recorder plugin
 | 
			
		||||
#
 | 
			
		||||
# $Id: Makefile 1.1 2002/05/09 15:17:44 kls Exp $
 | 
			
		||||
 | 
			
		||||
# The official name of this plugin.
 | 
			
		||||
# This name will be used in the '-P...' option of VDR to load the plugin.
 | 
			
		||||
# By default the main source file also carries this name.
 | 
			
		||||
#
 | 
			
		||||
PLUGIN = hello
 | 
			
		||||
 | 
			
		||||
### The version number of this plugin (taken from the main source file):
 | 
			
		||||
 | 
			
		||||
VERSION = `grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g'`
 | 
			
		||||
 | 
			
		||||
### The directory environment:
 | 
			
		||||
 | 
			
		||||
DVBDIR = ../../../../DVB/ost/include
 | 
			
		||||
VDRDIR = ../../..
 | 
			
		||||
VDRINC = $(VDRDIR)/include
 | 
			
		||||
LIBDIR = ../../lib
 | 
			
		||||
TMPDIR = /tmp
 | 
			
		||||
 | 
			
		||||
### The version number of VDR (taken from VDR's "config.h"):
 | 
			
		||||
 | 
			
		||||
VDRVERSION = `grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g'`
 | 
			
		||||
 | 
			
		||||
### The name of the distribution archive:
 | 
			
		||||
 | 
			
		||||
ARCHIVE = vdr-$(PLUGIN)-$(VERSION)
 | 
			
		||||
 | 
			
		||||
### Includes and Defines (add further entries here):
 | 
			
		||||
 | 
			
		||||
INCLUDES = -I$(VDRINC) -I$(DVBDIR)
 | 
			
		||||
 | 
			
		||||
DEFINES = -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
 | 
			
		||||
 | 
			
		||||
### The object files (add further files here):
 | 
			
		||||
 | 
			
		||||
OBJS = $(PLUGIN).o i18n.o
 | 
			
		||||
 | 
			
		||||
### The C++ compiler and options:
 | 
			
		||||
 | 
			
		||||
CXX      = g++
 | 
			
		||||
CXXFLAGS = -O2 -Wall -Woverloaded-virtual -m486
 | 
			
		||||
 | 
			
		||||
### Implicit rules:
 | 
			
		||||
 | 
			
		||||
%.o: %.c
 | 
			
		||||
	$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
 | 
			
		||||
 | 
			
		||||
# Dependencies:
 | 
			
		||||
 | 
			
		||||
MAKEDEP = g++ -MM -MG
 | 
			
		||||
DEPFILE = .dependencies
 | 
			
		||||
$(DEPFILE): Makefile
 | 
			
		||||
	@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
 | 
			
		||||
 | 
			
		||||
include $(DEPFILE)
 | 
			
		||||
 | 
			
		||||
### Targets:
 | 
			
		||||
 | 
			
		||||
all: libvdr-$(PLUGIN).so
 | 
			
		||||
 | 
			
		||||
libvdr-$(PLUGIN).so: $(OBJS)
 | 
			
		||||
	$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
 | 
			
		||||
	@cp $@ $(LIBDIR)/$@.$(VDRVERSION)
 | 
			
		||||
 | 
			
		||||
package: clean
 | 
			
		||||
	@-rm -rf $(TMPDIR)/$(ARCHIVE)
 | 
			
		||||
	@mkdir $(TMPDIR)/$(ARCHIVE)
 | 
			
		||||
	@cp -a * $(TMPDIR)/$(ARCHIVE)
 | 
			
		||||
	@tar czf $(ARCHIVE).tgz -C $(TMPDIR) $(ARCHIVE)
 | 
			
		||||
	@-rm -rf $(TMPDIR)/$(ARCHIVE)
 | 
			
		||||
	@echo Distribution archive created as $(ARCHIVE).tgz
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
 | 
			
		||||
							
								
								
									
										11
									
								
								PLUGINS/SRC/hello/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								PLUGINS/SRC/hello/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
This is a "plugin" for the Video Disk Recorder (VDR).
 | 
			
		||||
 | 
			
		||||
Written by:                  Klaus Schmidinger <kls@cadsoft.de>
 | 
			
		||||
 | 
			
		||||
Project's homepage:          www.cadsoft.de/people/kls/vdr
 | 
			
		||||
 | 
			
		||||
Latest version available at: www.cadsoft.de/people/kls/vdr/software.htm
 | 
			
		||||
 | 
			
		||||
See the file COPYING for license information.
 | 
			
		||||
 | 
			
		||||
Description: This is a small demo of the VDR plugin interface.
 | 
			
		||||
							
								
								
									
										105
									
								
								PLUGINS/SRC/hello/hello.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								PLUGINS/SRC/hello/hello.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
/*
 | 
			
		||||
 * hello.c: A plugin for the Video Disk Recorder
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: hello.c 1.1 2002/05/09 15:28:51 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <vdr/interface.h>
 | 
			
		||||
#include <vdr/plugin.h>
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
static const char *VERSION        = "0.0.1";
 | 
			
		||||
static const char *DESCRIPTION    = "A friendly greeting";
 | 
			
		||||
static const char *MAINMENUENTRY  = "Hello";
 | 
			
		||||
 | 
			
		||||
class cPluginHello : public cPlugin {
 | 
			
		||||
private:
 | 
			
		||||
  // Add any member variables or functions you may need here.
 | 
			
		||||
  const char *option_a;
 | 
			
		||||
  bool option_b;
 | 
			
		||||
public:
 | 
			
		||||
  cPluginHello(void);
 | 
			
		||||
  virtual ~cPluginHello();
 | 
			
		||||
  virtual const char *Version(void) { return VERSION; }
 | 
			
		||||
  virtual const char *Description(void) { return tr(DESCRIPTION); }
 | 
			
		||||
  virtual const char *CommandLineHelp(void);
 | 
			
		||||
  virtual bool ProcessArgs(int argc, char *argv[]);
 | 
			
		||||
  virtual void Start(void);
 | 
			
		||||
  virtual const char *MainMenuEntry(void) { return tr(MAINMENUENTRY); }
 | 
			
		||||
  virtual cOsdMenu *MainMenuAction(void);
 | 
			
		||||
  virtual cMenuSetupPage *SetupMenu(void);
 | 
			
		||||
  virtual bool SetupParse(const char *Name, const char *Value);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cPluginHello::cPluginHello(void)
 | 
			
		||||
{
 | 
			
		||||
  // Initialize any member varaiables here.
 | 
			
		||||
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
 | 
			
		||||
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
 | 
			
		||||
  option_a = NULL;
 | 
			
		||||
  option_b = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cPluginHello::~cPluginHello()
 | 
			
		||||
{
 | 
			
		||||
  // Clean up after yourself!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cPluginHello::CommandLineHelp(void)
 | 
			
		||||
{
 | 
			
		||||
  // Return a string that describes all known command line options.
 | 
			
		||||
  return "  -a ABC,   --aaa=ABC      do something nice with ABC\n"
 | 
			
		||||
         "  -b,       --bbb          activate 'plan B'\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPluginHello::ProcessArgs(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  // Implement command line argument processing here if applicable.
 | 
			
		||||
  static struct option long_options[] = {
 | 
			
		||||
       { "aaa",      required_argument, NULL, 'a' },
 | 
			
		||||
       { "bbb",      no_argument,       NULL, 'b' },
 | 
			
		||||
       { NULL }
 | 
			
		||||
     };
 | 
			
		||||
 | 
			
		||||
  int c;
 | 
			
		||||
  while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
 | 
			
		||||
        switch (c) {
 | 
			
		||||
          case 'a': option_a = optarg;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'b': option_b = true;
 | 
			
		||||
                    break;
 | 
			
		||||
          default:  return false;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPluginHello::Start(void)
 | 
			
		||||
{
 | 
			
		||||
  // Start any background activities the plugin shall perform.
 | 
			
		||||
  RegisterI18n(Phrases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cOsdMenu *cPluginHello::MainMenuAction(void)
 | 
			
		||||
{
 | 
			
		||||
  // Perform the action when selected from the main VDR menu.
 | 
			
		||||
  Interface->Info(tr("Hello world!"));
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuSetupPage *cPluginHello::SetupMenu(void)
 | 
			
		||||
{
 | 
			
		||||
  // Return a setup menu in case the plugin supports one.
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPluginHello::SetupParse(const char *Name, const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  // Parse your own setup parameters and store their values.
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VDRPLUGINCREATOR(cPluginHello); // Don't touch this!
 | 
			
		||||
							
								
								
									
										52
									
								
								PLUGINS/SRC/hello/i18n.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								PLUGINS/SRC/hello/i18n.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * i18n.c: Internationalization
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: i18n.c 1.1 2002/05/09 15:13:31 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
const tI18nPhrase Phrases[] = {
 | 
			
		||||
  { "Hello",
 | 
			
		||||
    "Hallo",
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
  },
 | 
			
		||||
  { "Hello world!",
 | 
			
		||||
    "Hallo Welt!",
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
  },
 | 
			
		||||
  { "A friendly greeting",
 | 
			
		||||
    "Ein freundlicher Gru<72>",
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
    "",// TODO
 | 
			
		||||
  },
 | 
			
		||||
  { NULL }
 | 
			
		||||
  };
 | 
			
		||||
							
								
								
									
										11
									
								
								PLUGINS/SRC/hello/i18n.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								PLUGINS/SRC/hello/i18n.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
/*
 | 
			
		||||
 * i18n.h: Internationalization
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: i18n.h 1.1 2002/05/09 15:15:49 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <vdr/i18n.h>
 | 
			
		||||
 | 
			
		||||
extern const tI18nPhrase Phrases[];
 | 
			
		||||
							
								
								
									
										125
									
								
								channels.conf
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								channels.conf
									
									
									
									
									
								
							@@ -48,83 +48,68 @@ ORB:12110:h:0:27500:501:502:504:0:28205
 | 
			
		||||
B1:12110:h:0:27500:601:602:604:0:28206
 | 
			
		||||
ARD Online-Kanal:12722:h:0:22000:0:701:0:0:0
 | 
			
		||||
:Premiere World
 | 
			
		||||
Premiere World:11797:h:0:27500:255:256:32:0:8
 | 
			
		||||
Premiere 1:11797:h:0:27500:511:512:0:101:10
 | 
			
		||||
Premiere 2:11797:h:0:27500:1791:1792:0:101:11
 | 
			
		||||
Premiere Start:11797:h:0:27500:255:256:0:101:8
 | 
			
		||||
Premiere 1:11797:h:0:27500:511:512,513;515:0:101:10
 | 
			
		||||
Premiere 2:11797:h:0:27500:1791:1792,1793;1795:0:101:11
 | 
			
		||||
Premiere 3:11797:h:0:27500:2303:2304:0:101:43
 | 
			
		||||
Premiere One:12032:h:0:27500:3071:3072:0:101:51
 | 
			
		||||
Premiere Star:11797:h:0:27500:767:768:0:101:9
 | 
			
		||||
Premiere Sci-Fi:11797:h:0:27500:1535:1536:0:101:41
 | 
			
		||||
Premiere Action:11797:h:0:27500:1023:1024:0:101:20
 | 
			
		||||
Premiere X-Action:11798:h:0:27500:2047:2048:0:101:50
 | 
			
		||||
Premiere Comedy:11797:h:0:27500:1279:1280:0:101:29
 | 
			
		||||
13th Street:12031:h:0:27500:2303:2304:0:101:42
 | 
			
		||||
Premiere 4:11797:h:0:27500:767:768:0:101:9
 | 
			
		||||
Premiere 5:11797:h:0:27500:1279:1280:0:101:29
 | 
			
		||||
Premiere 6:11797:h:0:27500:1535:1536:0:101:41
 | 
			
		||||
Premiere 7:11797:h:0:27500:1023:1024:0:101:20
 | 
			
		||||
13th Street:11758:h:0:27500:2303:2304:0:101:42
 | 
			
		||||
Studio Universal:12090:V:0:27500:255:256:0:101:36
 | 
			
		||||
Filmpalast:12031:h:0:27500:2559:2560:0:101:516
 | 
			
		||||
Heimatkanal:12031:h:0:27500:2815:2816:0:101:517
 | 
			
		||||
Discovery Channel:12031:h:0:27500:1791:1792:0:101:14
 | 
			
		||||
Planet:12090:V:0:27500:1279:1280:0:101:13
 | 
			
		||||
Fox Kids:12031:h:0:27500:1279:1280:0:101:28
 | 
			
		||||
Fox Kids T<>rkce:11914:H:0:27500:767:768:8191:101:54
 | 
			
		||||
Junior:12031:h:0:27500:255:256:0:101:19
 | 
			
		||||
K-Toon:12031:h:0:27500:511:512:0:101:12
 | 
			
		||||
Premiere Serie:12031:h:0:27500:1023:1024:0:101:16
 | 
			
		||||
Disney Channel:12090:V:0:27500:767:768:0:101:34
 | 
			
		||||
Sunset:12031:h:0:27500:1023:1024:0:101:16
 | 
			
		||||
Premiere Nostalgie:12031:h:0:27500:2559:2560:0:101:516
 | 
			
		||||
Discovery Channel:12031:h:0:27500:1791:1792:0:101:14
 | 
			
		||||
Planet:12090:v:0:27500:1279:1280:0:101:13
 | 
			
		||||
Fox Kids:11758:h:0:27500:1279:1280:0:101:28
 | 
			
		||||
Junior:11758:h:0:27500:255:256:0:101:19
 | 
			
		||||
K-Toon:11758:h:0:27500:511:512:0:101:12
 | 
			
		||||
Krimi&Co:12031:h:0:27500:1535:1536:0:101:23
 | 
			
		||||
Goldstar TV:12031:h:0:27500:3839:3840:0:101:518
 | 
			
		||||
Classica:12031:h:0:27500:767:768:0:101:15
 | 
			
		||||
Seasons:12090:V:0:27500:511:512:0:101:33
 | 
			
		||||
:Cinedom
 | 
			
		||||
Cinedom Deluxe:11758:h:0:27500:255:256,257;259:0:101:189
 | 
			
		||||
Cinedom 1A:11758:h:0:27500:511:512,513:0:101:190
 | 
			
		||||
Cinedom 1B:12070:h:0:27500:1535:1536,1537:0:101:178
 | 
			
		||||
Cinedom 1C:11720:h:0:27500:511:512,513:0:101:180
 | 
			
		||||
Cinedom 1D:11720:h:0:27500:1535:1536,1537:0:101:176
 | 
			
		||||
Cinedom 2A:11758:h:0:27500:1023:1024,1025:0:101:193
 | 
			
		||||
Cinedom 2B:11720:h:0:27500:1279:1280:0:101:183
 | 
			
		||||
Cinedom 2C:12070:h:0:27500:1791:1792:0:101:179
 | 
			
		||||
Cinedom 2D:12070:h:0:27500:511:512:0:101:184
 | 
			
		||||
Cinedom 2E:12070:h:0:27500:1279:1280:0:101:188
 | 
			
		||||
Cinedom 3A:11758:h:0:27500:2559:2560:0:101:192
 | 
			
		||||
Cinedom 3B:11758:h:0:27500:1535:1536:0:101:195
 | 
			
		||||
Cinedom 3C:12070:h:0:27500:767:768:0:101:185
 | 
			
		||||
Cinedom 3D:11720:h:0:27500:1023:1024:0:101:182
 | 
			
		||||
Cinedom 4A:11758:h:0:27500:767:768:0:101:191
 | 
			
		||||
Cinedom 4B:11720:h:0:27500:767:768:0:101:181
 | 
			
		||||
Cinedom 4C:12070:h:0:27500:2047:2048:0:101:187
 | 
			
		||||
Cinedom 5A:11758:h:0:27500:1279:1280:0:101:194
 | 
			
		||||
Cinedom 5B:11720:h:0:27500:1791:1792:0:101:177
 | 
			
		||||
Cinedom 5C:12070:h:0:27500:1023:1024:0:101:186
 | 
			
		||||
Goldstar TV:11758:h:0:27500:3839:3840:0:101:518
 | 
			
		||||
Classica:11758:h:0:27500:767:768:0:101:15
 | 
			
		||||
Sonnenklar TV:12090:V:0:27500:1023:1024:0:0:32
 | 
			
		||||
:Premiere Direkt
 | 
			
		||||
Premiere Direkt 1A:12031:h:0:27500:511:512,513;515:0:101:177
 | 
			
		||||
Premiere Direkt 1B:11719:h:0:27500:1023:1024,1025;1027:0:101:182
 | 
			
		||||
Premiere Direkt 2A:12031:h:0:27500:255:256;259:0:101:176
 | 
			
		||||
Premiere Direkt 2B:11719:h:0:27500:767:768;769:0:101:181
 | 
			
		||||
Premiere Direkt 3A:11719:h:0:27500:511:512;515:0:101:180
 | 
			
		||||
Premiere Direkt 3B:11719:h:0:27500:1279:1280;1283:0:101:183
 | 
			
		||||
Premiere Direkt 4A:12031:h:0:27500:2815:2816:0:101:18
 | 
			
		||||
Premiere Direkt 4B:12070:h:0:27500:1535:1536:0:101:216
 | 
			
		||||
:PW Erotic
 | 
			
		||||
Beate-Uhse.TV:11758:h:0:27500:1023:1024:0:101:21
 | 
			
		||||
Premiere Erotik 1:12031:h:0:27500:1279:1280:0:101:513
 | 
			
		||||
Premiere Erotik 2:11719:h:0:27500:1535:1536:0:101:778
 | 
			
		||||
Premiere Erotik 3:11719:h:0:27500:1791:1792:0:101:779
 | 
			
		||||
Premiere Erotik 4:11719:h:0:27500:3583:3584:0:101:780
 | 
			
		||||
:Sportsworld
 | 
			
		||||
Premiere Sport 1:11720:h:0:27500:255:256,257:0:101:17
 | 
			
		||||
Premiere Sport 2:12031:h:0:27500:3839:3840:0:101:27
 | 
			
		||||
:Formel 1
 | 
			
		||||
Supersignal:12070:h:0:27500:255:256:0:101:211
 | 
			
		||||
Cockpitkanal:12070:h:0:27500:511:512:0:101:212
 | 
			
		||||
Boxengasse:12070:h:0:27500:767:768:0:101:213
 | 
			
		||||
Verfolgerfeld:12070:h:0:27500:1023:1024:0:101:214
 | 
			
		||||
Infokanal:12070:h:0:27500:1279:1280:0:101:215
 | 
			
		||||
Multikanal:11720:h:0:27500:255:256:0:101:17
 | 
			
		||||
:Beta Digital
 | 
			
		||||
N24:12480:v:0:27500:2047:2048:0:0:47
 | 
			
		||||
CNBC:11954:h:0:27500:510:520:0:0:28010
 | 
			
		||||
Liberty TV.com:12610:V:0:22000:941:943,942:0:0:12199
 | 
			
		||||
:PW Erotic
 | 
			
		||||
Beate-Uhse.TV:11758:h:0:27500:3839:3840:0:101:21
 | 
			
		||||
Blue Movie 1:11758:h:0:27500:1791:1792:0:101:513
 | 
			
		||||
Blue Movie 2:11758:h:0:27500:2047:2048:0:101:514
 | 
			
		||||
Blue Movie 3:11758:h:0:27500:2303:2304:0:101:515
 | 
			
		||||
:Sportsworld
 | 
			
		||||
Premiere Sport 1:11720:h:0:27500:255:256,257:0:101:17
 | 
			
		||||
Premiere Sport 2:12070:h:0:27500:3839:3840:0:101:27
 | 
			
		||||
Premiere Sport 3:12070:h:0:27500:255:256:0:101:26
 | 
			
		||||
:Formel 1
 | 
			
		||||
Infokanal:11720:h:0:27500:3071:3072:0:101:244
 | 
			
		||||
Multikanal:11720:h:0:27500:2815:2816:0:101:243
 | 
			
		||||
Supersignal:11720:h:0:27500:255:256:0:101:17
 | 
			
		||||
Verfolgerfeld:11720:h:0:27500:2303:2304:0:101:241
 | 
			
		||||
Cockpitkanal:11720:h:0:27500:2559:2560:0:101:242
 | 
			
		||||
Boxengasse:11720:h:0:27500:2047:2048:0:101:240
 | 
			
		||||
:Premiere World Bundesliga
 | 
			
		||||
Superdom:11758:h:0:27500:2815:8192:0:101:18
 | 
			
		||||
BuLi-Konferenz:11758:h:0:27500:3327:3328,3329:0:101:215
 | 
			
		||||
BuLi-Spiel 1:11720:h:0:27500:255:256,257:0:101:17
 | 
			
		||||
BuLi-Spiel 2:11720:h:0:27500:2047:2048,2049:0:101:240
 | 
			
		||||
BuLi-Spiel 3:11720:h:0:27500:2303:2304,2305:0:101:241
 | 
			
		||||
BuLi-Spiel 4:11720:h:0:27500:2559:2560,2561:0:101:242
 | 
			
		||||
BuLi-Spiel 5:11720:h:0:27500:2815:2816,2817:0:101:243
 | 
			
		||||
BuLi-Spiel 6:11720:h:0:27500:3071:3072,3073:0:101:244
 | 
			
		||||
BuLi-Spiel 7:11758:h:0:27500:3071:3072,3073:0:101:214
 | 
			
		||||
:Premiere Bundesliga
 | 
			
		||||
BL-Konferenz:12031:h:0:27500:2303:2304,2305:0:101:210
 | 
			
		||||
BuLi 1:11719:h:0:27500:255:256,257:0:101:17
 | 
			
		||||
BuLi 2:11719:h:0:27500:2047:2048,2049:0:101:240
 | 
			
		||||
BuLi 3:11719:h:0:27500:2303:2304,2305:0:101:241
 | 
			
		||||
BuLi 4:11719:h:0:27500:2559:2560,2561:0:101:242
 | 
			
		||||
BuLi 5:11719:h:0:27500:2815:2816,2817:0:101:243
 | 
			
		||||
BuLi 6:11719:h:0:27500:3071:3072,3073:0:101:244
 | 
			
		||||
BuLi 7:11719:h:0:27500:3327:3328,3329:0:101:245
 | 
			
		||||
BuLi 8:12031:h:0:27500:3071:3072,3073:0:101:208
 | 
			
		||||
BuLi 9:12031:h:0:27500:3327:3328,3329:0:101:209
 | 
			
		||||
:
 | 
			
		||||
TV Niepokalanow:11876:h:0:27500:305:321:0:0:20601
 | 
			
		||||
Mosaico:11934:v:0:27500:165:100:0:0:29010
 | 
			
		||||
@@ -168,7 +153,7 @@ ESC 1:12363:v:0:27500:163:104:0:0:0
 | 
			
		||||
TV5 Europe:12363:v:0:27500:164:112:0:0:0
 | 
			
		||||
TV7 Tunisia:12363:v:0:27500:166:128:0:0:0
 | 
			
		||||
ARTE:12363:v:0:27500:167:137:0:0:0
 | 
			
		||||
RAI Uno:12363:v:0:27500:289:290:0:0:8904
 | 
			
		||||
RAI Uno:10788:v:0:22000:289:290:0:0:9004
 | 
			
		||||
RTP International:12363:v:0:27500:300:301:0:0:0
 | 
			
		||||
Fashion TV:12402:v:0:27500:163:92:0:0:0
 | 
			
		||||
VideoService:12422:h:0:27500:255:256:0:0:0
 | 
			
		||||
 
 | 
			
		||||
@@ -1,184 +1,165 @@
 | 
			
		||||
:verschl<68>sselte Fernsehprogramm
 | 
			
		||||
PREMIERE ONE:378:h:0:6900:3071:3072:0:1:51
 | 
			
		||||
PREMIERE MOVIE 1:370:h:0:6900:511:512;515:0:1:10
 | 
			
		||||
PREMIERE MOVIE 2:370:h:0:6900:1791:1792:0:1:11
 | 
			
		||||
PREMIERE MOVIE 3:370:h:0:6900:2303:2304:0:1:43
 | 
			
		||||
PREMIERE ACTION:370:h:0:6900:1023:1024,1025:0:1:20
 | 
			
		||||
PREMIERE X-ACTION:370:h:0:6900:2047:2048,2049:0:1:50
 | 
			
		||||
PREMIERE SCI-FI:370:h:0:6900:1535:1536:0:1:41
 | 
			
		||||
PREMIERE STAR:370:h:0:6900:767:768:0:1:9
 | 
			
		||||
PREMIERE COMEDY:370:h:0:6900:1279:1280:0:1:29
 | 
			
		||||
13 TH STREET:378:h:0:6900:2303:2304,2305:0:1:42
 | 
			
		||||
KRIMI &CO:378:h:0:6900:1535:1536:0:1:23
 | 
			
		||||
STUDIO UNIVERSAL:402:h:0:6900:1050:1054:0:1:36
 | 
			
		||||
DISCOVERY CHANNEL:378:h:0:6900:1791:1792:0:1:14
 | 
			
		||||
FILMPALAST:378:h:0:6900:2559:2560:0:1:516
 | 
			
		||||
DISNEY CHANNEL:402:h:0:6900:1030:1034:0:1:34
 | 
			
		||||
SUNSET:378:h:0:6900:1023:1024:0:1:16
 | 
			
		||||
PLANET:402:h:0:6900:1100:1104:0:1:13
 | 
			
		||||
CLASSICA:378:h:0:6900:767:768:0:1:15
 | 
			
		||||
GOLDSTAR TV:378:h:0:6900:3839:3840:0:1:518
 | 
			
		||||
HEIMATKANAL:378:h:0:6900:2815:2816:0:1:517
 | 
			
		||||
K-TOON:378:h:0:6900:511:512:0:1:12
 | 
			
		||||
FOX KIDS:378:h:0:6900:1279:1280:0:1:28
 | 
			
		||||
KiKa:394:h:0:6900:310:320:330:0:28008
 | 
			
		||||
JUNIOR:378:h:0:6900:255:256:0:1:19
 | 
			
		||||
:Fernsehprogramme
 | 
			
		||||
Das Erste:410:h:0:6900:101:102,88:104:0:28106
 | 
			
		||||
ZDF:394:h:0:6900:110:120,121:130:0:28006
 | 
			
		||||
Das Erste:410:h:0:6900:101:102:111:0:28106
 | 
			
		||||
ZDF:394:h:0:6900:110:120:130:0:28006
 | 
			
		||||
3sat:394:h:0:6900:210:220:230:0:28007
 | 
			
		||||
arte:410:h:0:6900:401:402:404:0:28109
 | 
			
		||||
EuroNews:394:h:0:6900:2221:2233:768:0:28015
 | 
			
		||||
ZDF.info:394:h:0:6900:610:620:0:0:28011
 | 
			
		||||
ZDF.doku:394:h:0:6900:660:670:0:0:28014
 | 
			
		||||
ZDF Theaterkanal:394:h:0:6900:1110:1120:130:0:28016
 | 
			
		||||
EinsExtra:426:h:0:6900:101:102:0:0:28201
 | 
			
		||||
EinsFestival:426:h:0:6900:201:202:0:0:28202
 | 
			
		||||
EinsMuXx:426:h:0:6900:301:302:0:0:28203
 | 
			
		||||
3sat:394:h:0:6900:210:220:230:0:28007
 | 
			
		||||
arte:410:h:0:6900:401:402:404:0:28109
 | 
			
		||||
EuroNews:394:h:0:6900:2221:2233:768:0:28015
 | 
			
		||||
Phoenix:410:h:0:6900:901:902:0:0:28114
 | 
			
		||||
Eurosport:394:h:0:6900:410:420:430:0:28009
 | 
			
		||||
DW-tv:610:h:0:6900:634:632:0:0:6101
 | 
			
		||||
CNBC:394:h:0:6900:510:520:530:0:28010
 | 
			
		||||
:Regionalprogramme
 | 
			
		||||
WDR FERNSEHEN:410:h:0:6900:601:602:604:0:28111
 | 
			
		||||
B1 Berlin:426:h:0:6900:601:602,603:604:0:28206
 | 
			
		||||
ORB-Fernsehen:426:h:0:6900:501:502:504:0:28205
 | 
			
		||||
MDR FERNSEHEN:426:h:0:6900:401:402:404:0:28204
 | 
			
		||||
SR Fernsehen Suedwest:410:h:0:6900:501:502:504:0:28110
 | 
			
		||||
SuedWest BW:410:h:0:6900:801:802:804:0:28113
 | 
			
		||||
SuedWest RP:426:h:0:6900:3101:3102:3104:0:28231
 | 
			
		||||
BR-alpha:410:h:0:6900:701:702:704:0:28112
 | 
			
		||||
B1 Berlin:426:h:0:6900:601:602:604:0:28206
 | 
			
		||||
N3:426:h:0:6900:2401:2402:2404:0:28224
 | 
			
		||||
ORB-Fernsehen:426:h:0:6900:501:502:504:0:28205
 | 
			
		||||
hessen fernsehen:410:h:0:6900:301:302:304:0:28108
 | 
			
		||||
Bayerisches FS:410:h:0:6900:201:202:204:0:28107
 | 
			
		||||
Test-R:410:h:0:6900:901:902:104:0:28130
 | 
			
		||||
:Premiere Hauptprogramme
 | 
			
		||||
Premiere START:370:C:0:6900:255:256:32:101:8
 | 
			
		||||
Premiere 1:370:C:0:6900:511:512:0:101:10
 | 
			
		||||
Premiere 2:370:C:0:6900:1791:1792:0:101:11
 | 
			
		||||
Premiere 3:370:C:0:6900:2303:2304:0:101:43
 | 
			
		||||
Premiere 4:370:C:0:6900:767:768:0:101:9
 | 
			
		||||
Premiere 5:370:C:0:6900:1279:1280:0:101:29
 | 
			
		||||
Premiere 6:370:C:0:6900:1535:1536:0:101:41
 | 
			
		||||
Premiere 7:370:C:0:6900:1023:1024:0:101:20
 | 
			
		||||
Premiere SERIE:378:C:0:6900:1023:1024:0:101:16
 | 
			
		||||
Premiere Nostalgie:378:C:0:6900:2559:2560:0:101:516
 | 
			
		||||
13 TH STREET:354:C:0:6900:2303:2304:0:101:42
 | 
			
		||||
Stundio Universal:402:C:0:6900:1050:1054:0:101:36
 | 
			
		||||
Krimi &Co:378:C:0:6900:1535:1536:0:101:23
 | 
			
		||||
Disney Channel:402:C:0:6900:1030:1034:0:101:34
 | 
			
		||||
Discovery Channel:378:C:0:6900:1791:1792:0:101:14
 | 
			
		||||
Fox Kids:354:C:0:6900:1279:1280:0:101:28
 | 
			
		||||
Junior:354:C:0:6900:255:256:0:101:19
 | 
			
		||||
K-TOON:354:C:0:6900:0:0:0:101:12
 | 
			
		||||
GOLDSTAR TV:354:C:0:6900:3839:3840:0:101:518
 | 
			
		||||
CLASSICA:354:C:0:6900:767:768:0:101:15
 | 
			
		||||
:Mediavision
 | 
			
		||||
Extreme Sport:346:h:0:6900:801:802:0:1:50700
 | 
			
		||||
Bloomberg:346:h:0:6900:811:812:0:1:50701
 | 
			
		||||
Single TV:346:h:0:6900:621:622:0:1:50706
 | 
			
		||||
Fashion TV:346:h:0:6900:821:822:0:1:50702
 | 
			
		||||
BET ON JAZZ:346:h:0:6900:841:842:0:1:50704
 | 
			
		||||
LANDSCAPE:346:h:0:6900:831:832:0:1:50703
 | 
			
		||||
Einstein:346:h:0:6900:623:624:0:1:50719
 | 
			
		||||
Bloomberg:346:h:0:6900:811:812:0:101:50701
 | 
			
		||||
Fashion TV:346:h:0:6900:821:822:0:101:50702
 | 
			
		||||
Einstein:346:h:0:6900:623:624:0:101:50719
 | 
			
		||||
Extreme Sport:346:h:0:6900:801:802:0:101:50700
 | 
			
		||||
LANDSCAPE:346:h:0:6900:831:832:0:101:50703
 | 
			
		||||
Single TV:346:h:0:6900:621:622:0:101:50706
 | 
			
		||||
Leitseite:346:h:0:6900:2254:0:0:0:5004
 | 
			
		||||
Via 1 - Sch<63>ner Reisen:346:h:0:6900:611:612:0:0:50705
 | 
			
		||||
Parlamentsfernsehen:610:h:0:6900:33:36:47:0:6100
 | 
			
		||||
Vh1 - Classic:610:h:0:6900:604:603:0:0:6106
 | 
			
		||||
BET ON JAZZ:346:h:0:6900:841:842:0:101:50704
 | 
			
		||||
:Digit. Bouquet"Kabel Berlin"
 | 
			
		||||
Parlamentsfernsehen:610:C:0:6900:33:36:47:0:6100
 | 
			
		||||
DW-tv:610:C:0:6900:634:632:0:0:6101
 | 
			
		||||
Kanal 7:610:C:0:6900:49:52:0:101:6103
 | 
			
		||||
Euronews:610:C:0:6900:597:592,591:0:101:6104
 | 
			
		||||
Vh1 - Classic:610:h:0:6900:604:603:0:101:6106
 | 
			
		||||
Travel:610:C:0:6900:595:594:0:101:6105
 | 
			
		||||
Nuvolari:618:C:0:6900:1011:1012:0:101:50101
 | 
			
		||||
Marco Polo:618:C:0:6900:1021:1022:0:101:50102
 | 
			
		||||
Alice:618:C:0:6900:1031:1032:0:101:50103
 | 
			
		||||
Leonardo:618:C:0:6900:1041:1042:0:101:50104
 | 
			
		||||
Club:618:C:0:6900:1051:1052:0:101:50105
 | 
			
		||||
Avante:618:C:0:6900:1061:1062:0:101:50106
 | 
			
		||||
Expo 24*7:618:C:0:6900:1071:1072:0:101:50107
 | 
			
		||||
Innergy:618:C:0:6900:0:0:0:101:50108
 | 
			
		||||
BBC Prime:618:C:0:6900:1091:1092:0:101:50109
 | 
			
		||||
Eurosport News:618:C:0:6900:1101:1102:0:101:50110
 | 
			
		||||
:Diverse TV-Sender
 | 
			
		||||
TV Polonia:434:h:0:6900:641:642:0:1:53204
 | 
			
		||||
Kanal D:434:h:0:6900:651:652:0:1:53205
 | 
			
		||||
RTP international:434:h:0:6900:661:662:0:1:53206
 | 
			
		||||
ERT-Sat:434:h:0:6900:691:692:0:1:53209
 | 
			
		||||
CNE:434:h:0:6900:4056:4057:0:1:53208
 | 
			
		||||
ZEE TV:442:h:0:6900:517:773:0:1:53301
 | 
			
		||||
NTV i:442:h:0:6900:514:515:0:1:53302
 | 
			
		||||
TV Polonia:434:h:0:6900:641:642:0:101:53204
 | 
			
		||||
Kanal D:434:h:0:6900:651:652:0:101:53205
 | 
			
		||||
RTP international:434:h:0:6900:661:662:0:101:53206
 | 
			
		||||
ERT-Sat:434:h:0:6900:691:692:0:101:53209
 | 
			
		||||
CNE:434:h:0:6900:4056:4057:0:101:53208
 | 
			
		||||
ZEE TV:442:h:0:6900:517:773:0:101:53301
 | 
			
		||||
NTV i:442:h:0:6900:514:515:0:101:53302
 | 
			
		||||
ATV:434:h:0:6900:631:632:0:0:53203
 | 
			
		||||
TW1:610:h:0:6900:6106:6107:0:0:6106
 | 
			
		||||
PREMIERE WORLD:370:h:0:6900:255:256:32:0:8
 | 
			
		||||
:Premiere World Bundesliga
 | 
			
		||||
Superdom:362:h:0:6900:255:256:0:1:26
 | 
			
		||||
Spiel 1:362:h:0:6900:255:256,257:0:1:17
 | 
			
		||||
Spiel 2:362:h:0:6900:2047:2048,2049:0:1:240
 | 
			
		||||
BuLi-Konferenz:362:h:0:6900:3071:3072,3073:0:1:208
 | 
			
		||||
BuLi-Spiel 1:362:h:0:6900:3327:3328,3329:0:1:209
 | 
			
		||||
BuLi-Spiel 2:362:h:0:6900:2303:2304,2305:0:1:210
 | 
			
		||||
BuLi-Spiel 3:362:h:0:6900:3583:3584,3585:0:1:211
 | 
			
		||||
BuLi-Spiel 4:362:h:0:6900:2559:2560,2561:0:1:212
 | 
			
		||||
BuLi-Spiel 5:362:h:0:6900:2815:2816,2817:0:1:213
 | 
			
		||||
:Premiere Sport
 | 
			
		||||
PREMIERE SPORT 1:362:h:0:6900:255:256:0:1:17
 | 
			
		||||
PREMIERE SPORT 2:362:h:0:6900:3327:3328:0:1:27
 | 
			
		||||
PREMIERE SPORT 3:354:h:0:6900:2815:2816:0:1:18
 | 
			
		||||
:Premiere Formel 1
 | 
			
		||||
F1 Studio:362:h:0:6900:255:256:0:1:17
 | 
			
		||||
F1 Box:362:h:0:6900:2047:2048:0:1:240
 | 
			
		||||
F1 Verfolger:362:h:0:6900:2303:2304:0:1:241
 | 
			
		||||
F1 Cockpit:362:h:0:6900:2559:2560:0:1:242
 | 
			
		||||
F1 Multi:362:h:0:6900:2815:2816:0:1:243
 | 
			
		||||
F1 Info:362:h:0:6900:3071:3072:0:1:244
 | 
			
		||||
:Premiere Cinedom 1
 | 
			
		||||
Cinedom 1A:362:h:0:6900:1535:1536,1537:0:1:176
 | 
			
		||||
Cinedom 1B:386:h:0:6900:1535:1536,1537:0:1:178
 | 
			
		||||
Cinedom 1C:362:h:0:6900:511:512,513:0:1:180
 | 
			
		||||
Cinedom 1D:354:h:0:6900:511:512,513:0:1:190
 | 
			
		||||
:Premiere Cinedom 2
 | 
			
		||||
Cinedom 2A:386:h:0:6900:1791:1792,1793:0:1:179
 | 
			
		||||
Cinedom 2B:362:h:0:6900:1279:1280,1281:0:1:183
 | 
			
		||||
Cinedom 2C:386:h:0:6900:511:512:0:1:184
 | 
			
		||||
Cinedom 2D:386:h:0:6900:1279:1280:0:1:188
 | 
			
		||||
Cinedom 2E:354:h:0:6900:1023:1024:0:1:193
 | 
			
		||||
: Premiere Cinedom 3
 | 
			
		||||
Cinedom 3A:362:h:0:6900:1023:1024,1025:0:1:182
 | 
			
		||||
Cinedom 3B:386:h:0:6900:767:768:0:1:185
 | 
			
		||||
Cinedom 3C:354:h:0:6900:2559:2560:0:1:192
 | 
			
		||||
Cinedom 3D:354:h:0:6900:1535:1536:0:1:195
 | 
			
		||||
: Premiere Cinedom 4
 | 
			
		||||
Cinedom 4A:362:h:0:6900:767:768,769:0:1:181
 | 
			
		||||
Cinedom 4B:386:h:0:6900:2047:2048:0:1:187
 | 
			
		||||
Cinedom 4C:354:h:0:6900:767:768:0:1:191
 | 
			
		||||
: Premiere Cinedom 5
 | 
			
		||||
Cinedom 5A:386:h:0:6900:1023:1024,1025:0:1:186
 | 
			
		||||
Cinedom 5B:354:h:0:6900:1279:1280,1281:0:1:194
 | 
			
		||||
: Premiere Cinedom Deluxe
 | 
			
		||||
CINEDOM DELUXE:354:h:0:6900:255:256,257:0:1:189
 | 
			
		||||
:Premiere Erotic
 | 
			
		||||
BEATE-UHSE.TV:354:h:0:6900:3839:3840:0:1:21
 | 
			
		||||
BLUE MOVIE 1:354:h:0:6900:1791:1792:0:1:513
 | 
			
		||||
BLUE MOVIE 2:354:h:0:6900:2047:2048:0:1:514
 | 
			
		||||
BLUE MOVIE 3:354:h:0:6900:2303:2304:0:1:515
 | 
			
		||||
PREMIERE SPORT 1:362:C:0:6900:255:256,257:0:101:17
 | 
			
		||||
PREMIERE SPORT 2:378:C:0:6900:3839:3840,3841:0:101:27
 | 
			
		||||
:Premiere Direkt 1
 | 
			
		||||
PREMIERE DIREKT 1A:362:C:0:6900:1023:1024,1025:0:101:182
 | 
			
		||||
PREMIERE DIREKT 1B:378:C:0:6900:511:512,513:0:101:177
 | 
			
		||||
:Premiere Direkt 2
 | 
			
		||||
PREMIERE DIREKT 2A:378:C:0:6900:255:256,257:0:101:176
 | 
			
		||||
PREMIERE DIREKT 2B:362:C:0:6900:767:768,769:0:101:181
 | 
			
		||||
:Premiere Direkt 3
 | 
			
		||||
PREMIERE DIREKT 3A:362:C:0:6900:511:512,513:0:101:180
 | 
			
		||||
PREMIERE DIREKT 3B:362:C:0:6900:1279:1280,1281:0:101:183
 | 
			
		||||
:Premiere Direkt 4
 | 
			
		||||
PREMIERE DIREKT 4A:378:C:0:6900:2815:2816,2817:0:101:18
 | 
			
		||||
PREMIERE DIREKT 4B:386:C:0:6900:1535:1536,1537:0:101:216
 | 
			
		||||
:Premiere Erotik
 | 
			
		||||
BEATE-UHSE.TV:354:C:0:6900:1023:1024:0:101:21
 | 
			
		||||
PREMIERE EROTIK 1:378:C:0:6900:1279:1280:0:101:513
 | 
			
		||||
PREMIERE EROTIK 2:362:C:0:6900:1535:1536:0:101:778
 | 
			
		||||
PREMIERE EROTIK 3:362:C:0:6900:1791:1792:0:101:779
 | 
			
		||||
PREMIERE EROTIK 4:362:C:0:6900:3583:3584:0:101:780
 | 
			
		||||
:Radioprogramme
 | 
			
		||||
Fritz:426:h:0:6900:0:901:0:0:28209
 | 
			
		||||
HR XXL:410:h:0:6900:0:3501:0:0:28125
 | 
			
		||||
JUMP:426:h:0:6900:0:1001:0:0:28210
 | 
			
		||||
SPUTNIK:426:h:0:6900:0:1201:0:0:28212
 | 
			
		||||
RADIOmultikulti:426:h:0:6900:0:1301:0:0:28213
 | 
			
		||||
DLR-Berlin:394:h:0:6900:0:710:0:0:28012
 | 
			
		||||
DLF-K<>ln:394:h:0:6900:0:810:0:0:28013
 | 
			
		||||
<EFBFBD>sterreich 1:394:h:0:6900:0:169:0:0:28017
 | 
			
		||||
100,6:354:h:0:6900:0:1312:0:0:161
 | 
			
		||||
Bayern 4 Klassik:410:h:0:6900:0:3001:0:0:28120
 | 
			
		||||
B5 aktuell:410:h:0:6900:0:3101:0:0:28121
 | 
			
		||||
Bremen 2:410:h:0:6900:0:3801:0:0:28128
 | 
			
		||||
Bayern 1:410:h:0:6900:0:3601:0:0:28126
 | 
			
		||||
NDR 4 Info:410:h:0:6900:0:3701:0:0:28127
 | 
			
		||||
SR 1:410:h:0:6900:0:3901:0:0:28129
 | 
			
		||||
hr-klassik:410:h:0:6900:0:3401:0:0:28124
 | 
			
		||||
hr2:410:h:0:6900:0:3301:0:0:28123
 | 
			
		||||
hr-chronos:410:h:0:6900:0:3201:0:0:28122
 | 
			
		||||
Radio 3:426:h:0:6900:0:701:0:0:28207
 | 
			
		||||
MDR KULTUR:426:h:0:6900:0:801:0:0:28208
 | 
			
		||||
MDR info:426:h:0:6900:0:1101:0:0:28211
 | 
			
		||||
SWR-2:426:h:0:6900:0:1401:0:0:28214
 | 
			
		||||
WDR3:426:h:0:6900:0:1501:0:0:28215
 | 
			
		||||
WDR Radio 5:426:h:0:6900:0:1601:0:0:28216
 | 
			
		||||
Fritz:426:h:0:6900:1:901:0:0:28209
 | 
			
		||||
HR XXL:410:h:0:6900:1:3501:0:0:28125
 | 
			
		||||
JUMP:426:h:0:6900:1:1001:0:0:28210
 | 
			
		||||
SPUTNIK:426:h:0:6900:1:1201:0:0:28212
 | 
			
		||||
RADIOmultikulti:426:h:0:6900:1:1301:0:0:28213
 | 
			
		||||
DLR-Berlin:394:h:0:6900:1:710:0:0:28012
 | 
			
		||||
DLF-K<>ln:394:h:0:6900:1:810:0:0:28013
 | 
			
		||||
<EFBFBD>sterreich 1:394:h:0:6900:1:169:0:0:28017
 | 
			
		||||
100,6:354:h:0:6900:1:1312:0:0:161
 | 
			
		||||
Bayern 4 Klassik:410:h:0:6900:1:3001:0:0:28120
 | 
			
		||||
B5 aktuell:410:h:0:6900:1:3101:0:0:28121
 | 
			
		||||
Bremen 2:410:h:0:6900:1:3801:0:0:28128
 | 
			
		||||
Bayern 1:410:h:0:6900:1:3601:0:0:28126
 | 
			
		||||
NDR 4 Info:410:h:0:6900:1:3701:0:0:28127
 | 
			
		||||
SR 1:410:h:0:6900:1:3901:0:0:28129
 | 
			
		||||
hr-klassik:410:h:0:6900:1:3401:0:0:28124
 | 
			
		||||
hr2:410:h:0:6900:1:3301:0:0:28123
 | 
			
		||||
hr-chronos:410:h:0:6900:1:3201:0:0:28122
 | 
			
		||||
Radio 3:426:h:0:6900:1:701:0:0:28207
 | 
			
		||||
MDR KULTUR:426:h:0:6900:1:801:0:0:28208
 | 
			
		||||
MDR info:426:h:0:6900:1:1101:0:0:28211
 | 
			
		||||
SWR-2:426:h:0:6900:1:1401:0:0:28214
 | 
			
		||||
WDR3:426:h:0:6900:1:1501:0:0:28215
 | 
			
		||||
WDR Radio 5:426:h:0:6900:1:1601:0:0:28216
 | 
			
		||||
:verschl<68>sselte Radioprogramme
 | 
			
		||||
ALTERNATIVE ROCK:378:h:0:6900:1:800:0:1:151
 | 
			
		||||
HITLISTE:378:h:0:6900:1:784:0:1:150
 | 
			
		||||
DANCE:378:h:0:6900:1:816:0:1:152
 | 
			
		||||
EASY LISTENING:402:h:0:6900:1:1201:0:1:162
 | 
			
		||||
CLASSIC ROCK:378:h:0:6900:1:544:0:1:154
 | 
			
		||||
Cristal New Age:442:h:0:6900:1:536:0:0:53351
 | 
			
		||||
Movie Sounds:442:h:0:6900:1:537:0:1:53352
 | 
			
		||||
LOVE SONGS:402:h:0:6900:1:1191:0:1:163
 | 
			
		||||
KLASSIK POPUL<55>R:378:h:0:6900:1:592:0:1:145
 | 
			
		||||
KLASS. SYMPHONIEN:378:h:0:6900:1:608:0:1:146
 | 
			
		||||
OPER & VOKALMUSIK:378:h:0:6900:1:624:0:1:147
 | 
			
		||||
BAROCKMUSIK:378:h:0:6900:1:640:0:1:148
 | 
			
		||||
JAZZ:378:h:0:6900:1:656:0:1:149
 | 
			
		||||
COUNTRY:378:h:0:6900:1:352:0:1:153
 | 
			
		||||
FILMMUSIK:378:h:0:6900:1:368:0:1:155
 | 
			
		||||
DEUTSCHE HITS:402:h:0:6900:1:1156:0:1:156
 | 
			
		||||
SOUL CLASSICS:402:h:0:6900:1:1161:0:1:157
 | 
			
		||||
T<EFBFBD>RK M<>ZIGI:402:h:0:6900:1:1166:0:1:158
 | 
			
		||||
GOLD:402:h:0:6900:1:1171:0:1:159
 | 
			
		||||
MUSICALS:402:h:0:6900:1:1196:0:1:164
 | 
			
		||||
OLD GOLD:402:h:0:6900:1:1186:0:1:165
 | 
			
		||||
SCHLAGER:402:h:0:6900:1:1176:0:1:166
 | 
			
		||||
VOLKSMUSIK:402:h:0:6900:1:1181:0:1:167
 | 
			
		||||
All Jazz:442:h:0:6900:1:535:0:1:53350
 | 
			
		||||
Sinfonica:442:h:0:6900:1:538:0:1:53353
 | 
			
		||||
Opernfestival:442:h:0:6900:1:539:0:1:53354
 | 
			
		||||
Barock Fantasie:442:h:0:6900:1:540:0:1:53355
 | 
			
		||||
Musica Camerata:442:h:0:6900:1:541:0:1:53356
 | 
			
		||||
Musica Antica:442:h:0:6900:1:542:0:1:53357
 | 
			
		||||
Adagio:442:h:0:6900:1:543:0:1:53358
 | 
			
		||||
Jazz Legends:442:h:0:6900:1:544:0:1:53359
 | 
			
		||||
ALTERNATIVE ROCK:370:C:0:6900:1:800:0:101:151
 | 
			
		||||
CLASSIC ROCK:370:C:0:6900:1:544:0:101:154
 | 
			
		||||
DANCE:370:C:0:6900:1:816:0:101:152
 | 
			
		||||
LOVE SONGS:370:C:0:6900:1:352:0:101:163
 | 
			
		||||
GOLD:370:C:0:6900:1:576:0:101:159
 | 
			
		||||
OLD GOLD:370:C:0:6900:1:304:0:101:165
 | 
			
		||||
SOUL CLASSICS:370:C:0:6900:1:400:0:101:157
 | 
			
		||||
EASY LISTENING:370:C:0:6900:1:384:0:101:162
 | 
			
		||||
DEUTSCHE HITS:370:C:0:6900:1:592:0:101:156
 | 
			
		||||
SCHLAGER:370:C:0:6900:1:320:0:101:166
 | 
			
		||||
VOLKSMUSIK:362:C:0:6900:1:336:0:101:167
 | 
			
		||||
COUNTRY:362:C:0:6900:1:352:0:101:153
 | 
			
		||||
FILMMUSIK:362:C:0:6900:1:368:0:101:155
 | 
			
		||||
MUSICALS:362:C:0:6900:1:384:0:101:164
 | 
			
		||||
JAZZ:362:C:0:6900:1:656:0:101:149
 | 
			
		||||
KLASSIK POPUL04R:378:C:0:6900:1:592:0:101:145
 | 
			
		||||
ORCHESTRALE WERKE:378:C:0:6900:1:608:0:101:146
 | 
			
		||||
BAROCK:378:C:0:6900:1:640:0:101:148
 | 
			
		||||
OPER:378:C:0:6900:1:624:0:101:147
 | 
			
		||||
T<EFBFBD>RK M<>ZIGI:378:C:0:6900:1:560:0:101:158
 | 
			
		||||
HITLISTE:370:C:0:6900:1:784:0:101:150
 | 
			
		||||
Radio GoldStar:354:C:0:6900:1:368:0:101:171
 | 
			
		||||
All Jazz:442:C:0:6900:1:535:0:101:53350
 | 
			
		||||
Cristal New Age:442:C:0:6900:1:536:0:101:53351
 | 
			
		||||
Movie Sounds:442:C:0:6900:1:537:0:101:53352
 | 
			
		||||
Sinfonica:442:C:0:6900:1:538:0:101:53353
 | 
			
		||||
Opernfestival:442:C:0:6900:1:539:0:101:53354
 | 
			
		||||
Barock Fantasie:442:C:0:6900:1:540:0:101:53355
 | 
			
		||||
Musica Camerata:442:C:0:6900:1:541:0:101:53356
 | 
			
		||||
Musica Antica:442:C:0:6900:1:542:0:101:53357
 | 
			
		||||
Adagio:442:C:0:6900:1:543:0:101:53358
 | 
			
		||||
Jazz legends:442:C:0:6900:1:544:0:101:53359
 | 
			
		||||
 
 | 
			
		||||
@@ -9,3 +9,12 @@ BBC CHOICE:505833:0:0:0:620:621:0:0:4351
 | 
			
		||||
BBC NEWS 24:505833:0:0:0:640:641:0:0:4415
 | 
			
		||||
BBC Knowledge:505833:0:0:0:630:631:0:0:4607
 | 
			
		||||
Shop!:561833:0:0:0:6049:6050:0:0:13120
 | 
			
		||||
: DVB-T Berlin Germany
 | 
			
		||||
RTL 1:778000:V:0:27500:160:80:0:1:1
 | 
			
		||||
RTL 2:778000:V:0:27500:161:82:0:1:2
 | 
			
		||||
Super RTL:778000:V:0:27500:162:84:0:1:3
 | 
			
		||||
VOX:778000:V:0:27500:165:81:0:1:4
 | 
			
		||||
SAT 1:714000:V:0:27500:160:80:0:1:18
 | 
			
		||||
PRO 7:714000:V:0:27500:161:82:0:1:19
 | 
			
		||||
KABEL 1:714000:V:0:27500:162:84:0:1:20
 | 
			
		||||
N24:714000:V:0:27500:163:86:0:1:21
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										373
									
								
								config.c
									
									
									
									
									
								
							
							
						
						
									
										373
									
								
								config.c
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: config.c 1.97 2002/04/02 21:56:51 kls Exp $
 | 
			
		||||
 * $Id: config.c 1.99 2002/05/05 09:10:00 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
#include "dvbapi.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
#include "interface.h"
 | 
			
		||||
#include "plugin.h"
 | 
			
		||||
 | 
			
		||||
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
 | 
			
		||||
// format characters in order to allow any number of blanks after a numeric
 | 
			
		||||
@@ -332,7 +333,8 @@ cTimer::cTimer(bool Instant)
 | 
			
		||||
  struct tm *now = localtime_r(&t, &tm_r);
 | 
			
		||||
  day = now->tm_mday;
 | 
			
		||||
  start = now->tm_hour * 100 + now->tm_min;
 | 
			
		||||
  stop = start + 200; // "instant recording" records 2 hours by default
 | 
			
		||||
  stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
 | 
			
		||||
  stop = (stop / 60) * 100 + (stop % 60);
 | 
			
		||||
  if (stop >= 2400)
 | 
			
		||||
     stop -= 2400;
 | 
			
		||||
//TODO VPS???
 | 
			
		||||
@@ -386,11 +388,12 @@ cTimer& cTimer::operator= (const cTimer &Timer)
 | 
			
		||||
  return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cTimer::operator< (const cTimer &Timer)
 | 
			
		||||
bool cTimer::operator< (const cListObject &ListObject)
 | 
			
		||||
{
 | 
			
		||||
  cTimer *ti = (cTimer *)&ListObject;
 | 
			
		||||
  time_t t1 = StartTime();
 | 
			
		||||
  time_t t2 = (*(cTimer *)&Timer).StartTime();
 | 
			
		||||
  return t1 < t2 || (t1 == t2 && priority > Timer.priority);
 | 
			
		||||
  time_t t2 = ti->StartTime();
 | 
			
		||||
  return t1 < t2 || (t1 == t2 && priority > ti->priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cTimer::ToText(cTimer *Timer)
 | 
			
		||||
@@ -916,12 +919,76 @@ const cCaDefinition *cCaDefinitions::Get(int Number)
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -- cSetupLine -------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cSetupLine::cSetupLine(void)
 | 
			
		||||
{
 | 
			
		||||
  plugin = name = value = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cSetupLine::cSetupLine(const char *Name, const char *Value, const char *Plugin)
 | 
			
		||||
{
 | 
			
		||||
  name = strdup(Name);
 | 
			
		||||
  value = strdup(Value);
 | 
			
		||||
  plugin = Plugin ? strdup(Plugin) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cSetupLine::~cSetupLine()
 | 
			
		||||
{
 | 
			
		||||
  delete plugin;
 | 
			
		||||
  delete name;
 | 
			
		||||
  delete value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetupLine::operator< (const cListObject &ListObject)
 | 
			
		||||
{
 | 
			
		||||
  const cSetupLine *sl = (cSetupLine *)&ListObject;
 | 
			
		||||
  if (!plugin && !sl->plugin)
 | 
			
		||||
     return strcasecmp(name, sl->name) < 0; 
 | 
			
		||||
  if (!plugin)
 | 
			
		||||
     return true;
 | 
			
		||||
  if (!sl->plugin)
 | 
			
		||||
     return false;
 | 
			
		||||
  int result = strcasecmp(plugin, sl->plugin);
 | 
			
		||||
  if (result == 0)
 | 
			
		||||
     result = strcasecmp(name, sl->name);
 | 
			
		||||
  return result < 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetupLine::Parse(char *s)
 | 
			
		||||
{
 | 
			
		||||
  char *p = strchr(s, '=');
 | 
			
		||||
  if (p) {
 | 
			
		||||
     *p = 0;
 | 
			
		||||
     char *Name  = compactspace(s);
 | 
			
		||||
     char *Value = compactspace(p + 1);
 | 
			
		||||
     if (*Name && *Value) {
 | 
			
		||||
        p = strchr(Name, '.');
 | 
			
		||||
        if (p) {
 | 
			
		||||
           *p = 0;
 | 
			
		||||
           char *Plugin = compactspace(Name);
 | 
			
		||||
           Name = compactspace(p + 1);
 | 
			
		||||
           if (!(*Plugin && *Name))
 | 
			
		||||
              return false;
 | 
			
		||||
           plugin = strdup(Plugin);
 | 
			
		||||
           }
 | 
			
		||||
        name = strdup(Name);
 | 
			
		||||
        value = strdup(Value);
 | 
			
		||||
        return true;
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetupLine::Save(FILE *f)
 | 
			
		||||
{
 | 
			
		||||
  return fprintf(f, "%s%s%s = %s\n", plugin ? plugin : "", plugin ? "." : "", name, value) > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -- cSetup -----------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cSetup Setup;
 | 
			
		||||
 | 
			
		||||
char *cSetup::fileName = NULL;
 | 
			
		||||
 | 
			
		||||
cSetup::cSetup(void)
 | 
			
		||||
{
 | 
			
		||||
  OSDLanguage = 0;
 | 
			
		||||
@@ -930,6 +997,7 @@ cSetup::cSetup(void)
 | 
			
		||||
  MenuScrollPage = 1;
 | 
			
		||||
  MarkInstantRecord = 1;
 | 
			
		||||
  strcpy(NameInstantRecord, "TITLE EPISODE");
 | 
			
		||||
  InstantRecordTime = 180;
 | 
			
		||||
  LnbSLOF    = 11700;
 | 
			
		||||
  LnbFrequLo =  9750;
 | 
			
		||||
  LnbFrequHi = 10600;
 | 
			
		||||
@@ -964,19 +1032,77 @@ cSetup::cSetup(void)
 | 
			
		||||
  CurrentVolume = MAXVOLUME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cSetup::PrintCaCaps(FILE *f, const char *Name)
 | 
			
		||||
cSetup& cSetup::operator= (const cSetup &s)
 | 
			
		||||
{
 | 
			
		||||
  memcpy(&__BeginData__, &s.__BeginData__, (char *)&s.__EndData__ - (char *)&s.__BeginData__);
 | 
			
		||||
  return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cSetupLine *cSetup::Get(const char *Name, const char *Plugin)
 | 
			
		||||
{
 | 
			
		||||
  for (cSetupLine *l = First(); l; l = Next(l)) {
 | 
			
		||||
      if ((l->Plugin() == NULL) == (Plugin == NULL)) {
 | 
			
		||||
         if ((!Plugin || strcasecmp(l->Plugin(), Plugin) == 0) && strcasecmp(l->Name(), Name) == 0)
 | 
			
		||||
            return l;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cSetup::Store(const char *Name, const char *Value, const char *Plugin)
 | 
			
		||||
{
 | 
			
		||||
  if (Name && *Name) {
 | 
			
		||||
     cSetupLine *l = Get(Name, Plugin);
 | 
			
		||||
     if (l)
 | 
			
		||||
        Del(l);
 | 
			
		||||
     if (Value)
 | 
			
		||||
        Add(new cSetupLine(Name, Value, Plugin));
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cSetup::Store(const char *Name, int Value, const char *Plugin)
 | 
			
		||||
{
 | 
			
		||||
  char *buffer = NULL;
 | 
			
		||||
  asprintf(&buffer, "%d", Value);
 | 
			
		||||
  Store(Name, buffer, Plugin);
 | 
			
		||||
  delete buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetup::Load(const char *FileName)
 | 
			
		||||
{
 | 
			
		||||
  if (cConfig<cSetupLine>::Load(FileName, true)) {
 | 
			
		||||
     bool result = true;
 | 
			
		||||
     for (cSetupLine *l = First(); l; l = Next(l)) {
 | 
			
		||||
         if (l->Plugin()) {
 | 
			
		||||
            cPlugin *p = cPluginManager::GetPlugin(l->Plugin());
 | 
			
		||||
            if (p && !p->SetupParse(l->Name(), l->Value()))
 | 
			
		||||
               result = false;
 | 
			
		||||
            }
 | 
			
		||||
         else {
 | 
			
		||||
            if (!Parse(l->Name(), l->Value()))
 | 
			
		||||
               result = false;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
     return result;
 | 
			
		||||
     }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cSetup::StoreCaCaps(const char *Name)
 | 
			
		||||
{
 | 
			
		||||
  for (int d = 0; d < MAXDVBAPI; d++) {
 | 
			
		||||
      int written = 0;
 | 
			
		||||
      char buffer[MAXPARSEBUFFER];
 | 
			
		||||
      char *q = buffer;
 | 
			
		||||
      *buffer = 0;
 | 
			
		||||
      for (int i = 0; i < MAXCACAPS; i++) {
 | 
			
		||||
          if (CaCaps[d][i]) {
 | 
			
		||||
             if (!written++)
 | 
			
		||||
                fprintf(f, "CaCaps             = %d", d + 1);
 | 
			
		||||
             fprintf(f, " %d", CaCaps[d][i]);
 | 
			
		||||
             if (!*buffer)
 | 
			
		||||
                q += snprintf(buffer, sizeof(buffer), "%d", d + 1);
 | 
			
		||||
             q += snprintf(q, sizeof(buffer) - (q - buffer), " %d", CaCaps[d][i]);
 | 
			
		||||
             }
 | 
			
		||||
          }
 | 
			
		||||
      if (written)
 | 
			
		||||
         fprintf(f, "\n");
 | 
			
		||||
      if (*buffer)
 | 
			
		||||
         Store(Name, buffer);
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1003,142 +1129,99 @@ bool cSetup::ParseCaCaps(const char *Value)
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetup::Parse(char *s)
 | 
			
		||||
bool cSetup::Parse(const char *Name, const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  char *p = strchr(s, '=');
 | 
			
		||||
  if (p) {
 | 
			
		||||
     *p = 0;
 | 
			
		||||
     char *Name  = compactspace(s);
 | 
			
		||||
     char *Value = compactspace(p + 1);
 | 
			
		||||
     if (*Name && *Value) {
 | 
			
		||||
        if      (!strcasecmp(Name, "OSDLanguage"))         OSDLanguage        = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "PrimaryDVB"))          PrimaryDVB         = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "ShowInfoOnChSwitch"))  ShowInfoOnChSwitch = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MenuScrollPage"))      MenuScrollPage     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MarkInstantRecord"))   MarkInstantRecord  = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "NameInstantRecord"))   strn0cpy(NameInstantRecord, Value, MaxFileName);
 | 
			
		||||
        else if (!strcasecmp(Name, "LnbSLOF"))             LnbSLOF            = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "LnbFrequLo"))          LnbFrequLo         = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "LnbFrequHi"))          LnbFrequHi         = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "DiSEqC"))              DiSEqC             = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "SetSystemTime"))       SetSystemTime      = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "TimeTransponder"))     TimeTransponder    = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MarginStart"))         MarginStart        = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MarginStop"))          MarginStop         = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "EPGScanTimeout"))      EPGScanTimeout     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "EPGBugfixLevel"))      EPGBugfixLevel     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "SVDRPTimeout"))        SVDRPTimeout       = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "SortTimers"))          SortTimers         = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "PrimaryLimit"))        PrimaryLimit       = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "DefaultPriority"))     DefaultPriority    = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "DefaultLifetime"))     DefaultLifetime    = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "UseSubtitle"))         UseSubtitle        = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "RecordingDirs"))       RecordingDirs      = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "VideoFormat"))         VideoFormat        = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "RecordDolbyDigital"))  RecordDolbyDigital = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "ChannelInfoPos"))      ChannelInfoPos     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "OSDwidth"))            OSDwidth           = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "OSDheight"))           OSDheight          = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "OSDMessageTime"))      OSDMessageTime     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MaxVideoFileSize"))    MaxVideoFileSize   = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "SplitEditedFiles"))    SplitEditedFiles   = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MinEventTimeout"))     MinEventTimeout    = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MinUserInactivity"))   MinUserInactivity  = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "MultiSpeedMode"))      MultiSpeedMode     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "ShowReplayMode"))      ShowReplayMode     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "CaCaps"))              return ParseCaCaps(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "CurrentChannel"))      CurrentChannel     = atoi(Value);
 | 
			
		||||
        else if (!strcasecmp(Name, "CurrentVolume"))       CurrentVolume      = atoi(Value);
 | 
			
		||||
        else
 | 
			
		||||
           return false;
 | 
			
		||||
        return true;
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetup::Load(const char *FileName)
 | 
			
		||||
{
 | 
			
		||||
  isyslog(LOG_INFO, "loading %s", FileName);
 | 
			
		||||
  delete fileName;
 | 
			
		||||
  fileName = strdup(FileName);
 | 
			
		||||
  FILE *f = fopen(fileName, "r");
 | 
			
		||||
  if (f) {
 | 
			
		||||
     int line = 0;
 | 
			
		||||
     char buffer[MAXPARSEBUFFER];
 | 
			
		||||
     bool result = true;
 | 
			
		||||
     while (fgets(buffer, sizeof(buffer), f) > 0) {
 | 
			
		||||
           line++;
 | 
			
		||||
           stripspace(buffer);
 | 
			
		||||
           if (!isempty(buffer)) {
 | 
			
		||||
              if (*buffer != '#' && !Parse(buffer)) {
 | 
			
		||||
                 esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
 | 
			
		||||
                 result = false;
 | 
			
		||||
                 }
 | 
			
		||||
              }
 | 
			
		||||
           }
 | 
			
		||||
     fclose(f);
 | 
			
		||||
     return result;
 | 
			
		||||
     }
 | 
			
		||||
  if      (!strcasecmp(Name, "OSDLanguage"))         OSDLanguage        = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "PrimaryDVB"))          PrimaryDVB         = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "ShowInfoOnChSwitch"))  ShowInfoOnChSwitch = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MenuScrollPage"))      MenuScrollPage     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MarkInstantRecord"))   MarkInstantRecord  = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "NameInstantRecord"))   strn0cpy(NameInstantRecord, Value, MaxFileName);
 | 
			
		||||
  else if (!strcasecmp(Name, "InstantRecordTime"))   InstantRecordTime  = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "LnbSLOF"))             LnbSLOF            = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "LnbFrequLo"))          LnbFrequLo         = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "LnbFrequHi"))          LnbFrequHi         = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "DiSEqC"))              DiSEqC             = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "SetSystemTime"))       SetSystemTime      = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "TimeTransponder"))     TimeTransponder    = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MarginStart"))         MarginStart        = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MarginStop"))          MarginStop         = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "EPGScanTimeout"))      EPGScanTimeout     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "EPGBugfixLevel"))      EPGBugfixLevel     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "SVDRPTimeout"))        SVDRPTimeout       = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "SortTimers"))          SortTimers         = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "PrimaryLimit"))        PrimaryLimit       = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "DefaultPriority"))     DefaultPriority    = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "DefaultLifetime"))     DefaultLifetime    = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "UseSubtitle"))         UseSubtitle        = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "RecordingDirs"))       RecordingDirs      = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "VideoFormat"))         VideoFormat        = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "RecordDolbyDigital"))  RecordDolbyDigital = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "ChannelInfoPos"))      ChannelInfoPos     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "OSDwidth"))            OSDwidth           = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "OSDheight"))           OSDheight          = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "OSDMessageTime"))      OSDMessageTime     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MaxVideoFileSize"))    MaxVideoFileSize   = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "SplitEditedFiles"))    SplitEditedFiles   = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MinEventTimeout"))     MinEventTimeout    = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MinUserInactivity"))   MinUserInactivity  = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "MultiSpeedMode"))      MultiSpeedMode     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "ShowReplayMode"))      ShowReplayMode     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "CaCaps"))              return ParseCaCaps(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "CurrentChannel"))      CurrentChannel     = atoi(Value);
 | 
			
		||||
  else if (!strcasecmp(Name, "CurrentVolume"))       CurrentVolume      = atoi(Value);
 | 
			
		||||
  else
 | 
			
		||||
     LOG_ERROR_STR(FileName);
 | 
			
		||||
  return false;
 | 
			
		||||
     return false;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSetup::Save(const char *FileName)
 | 
			
		||||
bool cSetup::Save(void)
 | 
			
		||||
{
 | 
			
		||||
  if (!FileName)
 | 
			
		||||
     FileName = fileName;
 | 
			
		||||
  if (FileName) {
 | 
			
		||||
     cSafeFile f(FileName);
 | 
			
		||||
     if (f.Open()) {
 | 
			
		||||
        fprintf(f, "# VDR Setup\n");
 | 
			
		||||
        fprintf(f, "OSDLanguage        = %d\n", OSDLanguage);
 | 
			
		||||
        fprintf(f, "PrimaryDVB         = %d\n", PrimaryDVB);
 | 
			
		||||
        fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
 | 
			
		||||
        fprintf(f, "MenuScrollPage     = %d\n", MenuScrollPage);
 | 
			
		||||
        fprintf(f, "MarkInstantRecord  = %d\n", MarkInstantRecord);
 | 
			
		||||
        fprintf(f, "NameInstantRecord  = %s\n", NameInstantRecord);
 | 
			
		||||
        fprintf(f, "LnbSLOF            = %d\n", LnbSLOF);
 | 
			
		||||
        fprintf(f, "LnbFrequLo         = %d\n", LnbFrequLo);
 | 
			
		||||
        fprintf(f, "LnbFrequHi         = %d\n", LnbFrequHi);
 | 
			
		||||
        fprintf(f, "DiSEqC             = %d\n", DiSEqC);
 | 
			
		||||
        fprintf(f, "SetSystemTime      = %d\n", SetSystemTime);
 | 
			
		||||
        fprintf(f, "TimeTransponder    = %d\n", TimeTransponder);
 | 
			
		||||
        fprintf(f, "MarginStart        = %d\n", MarginStart);
 | 
			
		||||
        fprintf(f, "MarginStop         = %d\n", MarginStop);
 | 
			
		||||
        fprintf(f, "EPGScanTimeout     = %d\n", EPGScanTimeout);
 | 
			
		||||
        fprintf(f, "EPGBugfixLevel     = %d\n", EPGBugfixLevel);
 | 
			
		||||
        fprintf(f, "SVDRPTimeout       = %d\n", SVDRPTimeout);
 | 
			
		||||
        fprintf(f, "SortTimers         = %d\n", SortTimers);
 | 
			
		||||
        fprintf(f, "PrimaryLimit       = %d\n", PrimaryLimit);
 | 
			
		||||
        fprintf(f, "DefaultPriority    = %d\n", DefaultPriority);
 | 
			
		||||
        fprintf(f, "DefaultLifetime    = %d\n", DefaultLifetime);
 | 
			
		||||
        fprintf(f, "UseSubtitle        = %d\n", UseSubtitle);
 | 
			
		||||
        fprintf(f, "RecordingDirs      = %d\n", RecordingDirs);
 | 
			
		||||
        fprintf(f, "VideoFormat        = %d\n", VideoFormat);
 | 
			
		||||
        fprintf(f, "RecordDolbyDigital = %d\n", RecordDolbyDigital);
 | 
			
		||||
        fprintf(f, "ChannelInfoPos     = %d\n", ChannelInfoPos);
 | 
			
		||||
        fprintf(f, "OSDwidth           = %d\n", OSDwidth);
 | 
			
		||||
        fprintf(f, "OSDheight          = %d\n", OSDheight);
 | 
			
		||||
        fprintf(f, "OSDMessageTime     = %d\n", OSDMessageTime);
 | 
			
		||||
        fprintf(f, "MaxVideoFileSize   = %d\n", MaxVideoFileSize);
 | 
			
		||||
        fprintf(f, "SplitEditedFiles   = %d\n", SplitEditedFiles);
 | 
			
		||||
        fprintf(f, "MinEventTimeout    = %d\n", MinEventTimeout);
 | 
			
		||||
        fprintf(f, "MinUserInactivity  = %d\n", MinUserInactivity);
 | 
			
		||||
        fprintf(f, "MultiSpeedMode     = %d\n", MultiSpeedMode);
 | 
			
		||||
        fprintf(f, "ShowReplayMode     = %d\n", ShowReplayMode);
 | 
			
		||||
        PrintCaCaps(f, "CaCaps");
 | 
			
		||||
        fprintf(f, "CurrentChannel     = %d\n", CurrentChannel);
 | 
			
		||||
        fprintf(f, "CurrentVolume      = %d\n", CurrentVolume);
 | 
			
		||||
        if (f.Close()) {
 | 
			
		||||
           isyslog(LOG_INFO, "saved setup to %s", FileName);
 | 
			
		||||
           return true;
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
  Store("OSDLanguage",        OSDLanguage);
 | 
			
		||||
  Store("PrimaryDVB",         PrimaryDVB);
 | 
			
		||||
  Store("ShowInfoOnChSwitch", ShowInfoOnChSwitch);
 | 
			
		||||
  Store("MenuScrollPage",     MenuScrollPage);
 | 
			
		||||
  Store("MarkInstantRecord",  MarkInstantRecord);
 | 
			
		||||
  Store("NameInstantRecord",  NameInstantRecord);
 | 
			
		||||
  Store("InstantRecordTime",  InstantRecordTime);
 | 
			
		||||
  Store("LnbSLOF",            LnbSLOF);
 | 
			
		||||
  Store("LnbFrequLo",         LnbFrequLo);
 | 
			
		||||
  Store("LnbFrequHi",         LnbFrequHi);
 | 
			
		||||
  Store("DiSEqC",             DiSEqC);
 | 
			
		||||
  Store("SetSystemTime",      SetSystemTime);
 | 
			
		||||
  Store("TimeTransponder",    TimeTransponder);
 | 
			
		||||
  Store("MarginStart",        MarginStart);
 | 
			
		||||
  Store("MarginStop",         MarginStop);
 | 
			
		||||
  Store("EPGScanTimeout",     EPGScanTimeout);
 | 
			
		||||
  Store("EPGBugfixLevel",     EPGBugfixLevel);
 | 
			
		||||
  Store("SVDRPTimeout",       SVDRPTimeout);
 | 
			
		||||
  Store("SortTimers",         SortTimers);
 | 
			
		||||
  Store("PrimaryLimit",       PrimaryLimit);
 | 
			
		||||
  Store("DefaultPriority",    DefaultPriority);
 | 
			
		||||
  Store("DefaultLifetime",    DefaultLifetime);
 | 
			
		||||
  Store("UseSubtitle",        UseSubtitle);
 | 
			
		||||
  Store("RecordingDirs",      RecordingDirs);
 | 
			
		||||
  Store("VideoFormat",        VideoFormat);
 | 
			
		||||
  Store("RecordDolbyDigital", RecordDolbyDigital);
 | 
			
		||||
  Store("ChannelInfoPos",     ChannelInfoPos);
 | 
			
		||||
  Store("OSDwidth",           OSDwidth);
 | 
			
		||||
  Store("OSDheight",          OSDheight);
 | 
			
		||||
  Store("OSDMessageTime",     OSDMessageTime);
 | 
			
		||||
  Store("MaxVideoFileSize",   MaxVideoFileSize);
 | 
			
		||||
  Store("SplitEditedFiles",   SplitEditedFiles);
 | 
			
		||||
  Store("MinEventTimeout",    MinEventTimeout);
 | 
			
		||||
  Store("MinUserInactivity",  MinUserInactivity);
 | 
			
		||||
  Store("MultiSpeedMode",     MultiSpeedMode);
 | 
			
		||||
  Store("ShowReplayMode",     ShowReplayMode);
 | 
			
		||||
  StoreCaCaps("CaCaps");
 | 
			
		||||
  Store("CurrentChannel",     CurrentChannel);
 | 
			
		||||
  Store("CurrentVolume",      CurrentVolume);
 | 
			
		||||
 | 
			
		||||
  Sort();
 | 
			
		||||
 | 
			
		||||
  if (cConfig<cSetupLine>::Save()) {
 | 
			
		||||
     isyslog(LOG_INFO, "saved setup to %s", FileName());
 | 
			
		||||
     return true;
 | 
			
		||||
     }
 | 
			
		||||
  else
 | 
			
		||||
     esyslog(LOG_ERR, "attempt to save setup without file name");
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								config.h
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								config.h
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: config.h 1.109 2002/04/07 13:08:12 kls Exp $
 | 
			
		||||
 * $Id: config.h 1.113 2002/05/04 14:29:29 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __CONFIG_H
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
#include "eit.h"
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
 | 
			
		||||
#define VDRVERSION "1.0.0"
 | 
			
		||||
#define VDRVERSION "1.1.0"
 | 
			
		||||
 | 
			
		||||
#define MAXPRIORITY 99
 | 
			
		||||
#define MAXLIFETIME 99
 | 
			
		||||
@@ -149,7 +149,7 @@ public:
 | 
			
		||||
  cTimer(const cEventInfo *EventInfo);
 | 
			
		||||
  virtual ~cTimer();
 | 
			
		||||
  cTimer& operator= (const cTimer &Timer);
 | 
			
		||||
  bool operator< (const cTimer &Timer);
 | 
			
		||||
  virtual bool operator< (const cListObject &ListObject);
 | 
			
		||||
  const char *ToText(void);
 | 
			
		||||
  bool Parse(const char *s);
 | 
			
		||||
  bool Save(FILE *f);
 | 
			
		||||
@@ -220,7 +220,8 @@ private:
 | 
			
		||||
public:
 | 
			
		||||
  cConfig(void) { fileName = NULL; }
 | 
			
		||||
  virtual ~cConfig() { delete fileName; }
 | 
			
		||||
  virtual bool Load(const char *FileName, bool AllowComments = false)
 | 
			
		||||
  const char *FileName(void) { return fileName; }
 | 
			
		||||
  bool Load(const char *FileName, bool AllowComments = false)
 | 
			
		||||
  {
 | 
			
		||||
    Clear();
 | 
			
		||||
    fileName = strdup(FileName);
 | 
			
		||||
@@ -323,20 +324,42 @@ extern cCommands Commands;
 | 
			
		||||
extern cSVDRPhosts SVDRPhosts;
 | 
			
		||||
extern cCaDefinitions CaDefinitions;
 | 
			
		||||
 | 
			
		||||
class cSetup {
 | 
			
		||||
class cSetupLine : public cListObject {
 | 
			
		||||
private:
 | 
			
		||||
  static char *fileName;
 | 
			
		||||
  void PrintCaCaps(FILE *f, const char *Name);
 | 
			
		||||
  bool ParseCaCaps(const char *Value);
 | 
			
		||||
  char *plugin;
 | 
			
		||||
  char *name;
 | 
			
		||||
  char *value;
 | 
			
		||||
public:
 | 
			
		||||
  cSetupLine(void);
 | 
			
		||||
  cSetupLine(const char *Name, const char *Value, const char *Plugin = NULL);
 | 
			
		||||
  virtual ~cSetupLine();
 | 
			
		||||
  virtual bool operator< (const cListObject &ListObject);
 | 
			
		||||
  const char *Plugin(void) { return plugin; }
 | 
			
		||||
  const char *Name(void) { return name; }
 | 
			
		||||
  const char *Value(void) { return value; }
 | 
			
		||||
  bool Parse(char *s);
 | 
			
		||||
  bool Save(FILE *f);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cSetup : public cConfig<cSetupLine> {
 | 
			
		||||
  friend class cPlugin; // needs to be able to call Store()
 | 
			
		||||
private:
 | 
			
		||||
  void StoreCaCaps(const char *Name);
 | 
			
		||||
  bool ParseCaCaps(const char *Value);
 | 
			
		||||
  bool Parse(const char *Name, const char *Value);
 | 
			
		||||
  cSetupLine *Get(const char *Name, const char *Plugin = NULL);
 | 
			
		||||
  void Store(const char *Name, const char *Value, const char *Plugin = NULL);
 | 
			
		||||
  void Store(const char *Name, int Value, const char *Plugin = NULL);
 | 
			
		||||
public:
 | 
			
		||||
  // Also adjust cMenuSetup (menu.c) when adding parameters here!
 | 
			
		||||
  int __BeginData__;
 | 
			
		||||
  int OSDLanguage;
 | 
			
		||||
  int PrimaryDVB;
 | 
			
		||||
  int ShowInfoOnChSwitch;
 | 
			
		||||
  int MenuScrollPage;
 | 
			
		||||
  int MarkInstantRecord;
 | 
			
		||||
  char NameInstantRecord[MaxFileName];
 | 
			
		||||
  int InstantRecordTime;
 | 
			
		||||
  int LnbSLOF;
 | 
			
		||||
  int LnbFrequLo;
 | 
			
		||||
  int LnbFrequHi;
 | 
			
		||||
@@ -365,9 +388,11 @@ public:
 | 
			
		||||
  int CaCaps[MAXDVBAPI][MAXCACAPS];
 | 
			
		||||
  int CurrentChannel;
 | 
			
		||||
  int CurrentVolume;
 | 
			
		||||
  int __EndData__;
 | 
			
		||||
  cSetup(void);
 | 
			
		||||
  cSetup& operator= (const cSetup &s);
 | 
			
		||||
  bool Load(const char *FileName);
 | 
			
		||||
  bool Save(const char *FileName = NULL);
 | 
			
		||||
  bool Save(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
extern cSetup Setup;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								dvbapi.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								dvbapi.c
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: dvbapi.c 1.170 2002/04/07 09:35:51 kls Exp $
 | 
			
		||||
 * $Id: dvbapi.c 1.174 2002/05/03 15:59:32 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "dvbapi.h"
 | 
			
		||||
@@ -279,8 +279,7 @@ bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *Pictu
 | 
			
		||||
int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *FileOffset, int *Length, bool StayOffEnd)
 | 
			
		||||
{
 | 
			
		||||
  if (index) {
 | 
			
		||||
     if (Forward)
 | 
			
		||||
        CatchUp();
 | 
			
		||||
     CatchUp();
 | 
			
		||||
     int d = Forward ? 1 : -1;
 | 
			
		||||
     for (;;) {
 | 
			
		||||
         Index += d;
 | 
			
		||||
@@ -533,6 +532,8 @@ void cRecordBuffer::Input(void)
 | 
			
		||||
                  int w = Put(p, r);
 | 
			
		||||
                  p += w;
 | 
			
		||||
                  r -= w;
 | 
			
		||||
                  if (r > 0)
 | 
			
		||||
                     usleep(1); // this keeps the CPU load low
 | 
			
		||||
                  }
 | 
			
		||||
            t = time(NULL);
 | 
			
		||||
            }
 | 
			
		||||
@@ -1810,21 +1811,24 @@ bool cDvbApi::SetPrimaryDvbApi(int n)
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cDvbApi::CanShift(int Ca, int Priority)
 | 
			
		||||
int cDvbApi::CanShift(int Ca, int Priority, int UsedCards)
 | 
			
		||||
{
 | 
			
		||||
  // Test whether a recording on this DVB device can be shifted to another one
 | 
			
		||||
  // in order to perform a new recording with the given Ca and Priority on this device:
 | 
			
		||||
  int ShiftLevel = -1; // default means this device can't be shifted
 | 
			
		||||
  if (UsedCards & (1 << CardIndex()) != 0)
 | 
			
		||||
     return ShiftLevel; // otherwise we would get into a loop
 | 
			
		||||
  if (Recording()) {
 | 
			
		||||
     if (ProvidesCa(Ca) // this device provides the requested Ca
 | 
			
		||||
        && (Ca != this->Ca() // the requested Ca is different from the one currently used...
 | 
			
		||||
           || Priority > this->Priority())) { // ...or the request comes from a higher priority
 | 
			
		||||
        cDvbApi *d = NULL;
 | 
			
		||||
        int Provides[MAXDVBAPI];
 | 
			
		||||
        UsedCards |= (1 << CardIndex());
 | 
			
		||||
        for (int i = 0; i < NumDvbApis; i++) {
 | 
			
		||||
            if ((Provides[i] = dvbApi[i]->ProvidesCa(this->Ca())) != 0) { // this device is basicly able to do the job
 | 
			
		||||
               if (dvbApi[i] != this) { // it is not _this_ device
 | 
			
		||||
                  int sl = dvbApi[i]->CanShift(this->Ca(), Priority); // this is the original Priority!
 | 
			
		||||
                  int sl = dvbApi[i]->CanShift(this->Ca(), Priority, UsedCards); // this is the original Priority!
 | 
			
		||||
                  if (sl >= 0 && (ShiftLevel < 0 || sl < ShiftLevel)) {
 | 
			
		||||
                     d = dvbApi[i];
 | 
			
		||||
                     ShiftLevel = sl;
 | 
			
		||||
@@ -2301,16 +2305,17 @@ bool cDvbApi::SetPid(int fd, dmxPesType_t PesType, int Pid, dmxOutput_t Output)
 | 
			
		||||
{
 | 
			
		||||
  if (Pid) {
 | 
			
		||||
     CHECK(ioctl(fd, DMX_STOP));
 | 
			
		||||
     dmxPesFilterParams pesFilterParams;
 | 
			
		||||
     pesFilterParams.pid     = Pid;
 | 
			
		||||
     pesFilterParams.input   = DMX_IN_FRONTEND;
 | 
			
		||||
     pesFilterParams.output  = Output;
 | 
			
		||||
     pesFilterParams.pesType = PesType;
 | 
			
		||||
     pesFilterParams.flags   = DMX_IMMEDIATE_START;
 | 
			
		||||
     if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
 | 
			
		||||
        if (Pid != 0x1FFF)
 | 
			
		||||
     if (Pid != 0x1FFF) {
 | 
			
		||||
        dmxPesFilterParams pesFilterParams;
 | 
			
		||||
        pesFilterParams.pid     = Pid;
 | 
			
		||||
        pesFilterParams.input   = DMX_IN_FRONTEND;
 | 
			
		||||
        pesFilterParams.output  = Output;
 | 
			
		||||
        pesFilterParams.pesType = PesType;
 | 
			
		||||
        pesFilterParams.flags   = DMX_IMMEDIATE_START;
 | 
			
		||||
        if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
 | 
			
		||||
           LOG_ERROR;
 | 
			
		||||
        return false;
 | 
			
		||||
           return false;
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  return true;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								dvbapi.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								dvbapi.h
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: dvbapi.h 1.68 2002/03/10 10:50:00 kls Exp $
 | 
			
		||||
 * $Id: dvbapi.h 1.69 2002/04/21 09:49:22 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DVBAPI_H
 | 
			
		||||
@@ -104,7 +104,7 @@ private:
 | 
			
		||||
  static int useDvbApi;
 | 
			
		||||
  int cardIndex;
 | 
			
		||||
  int caCaps[MAXCACAPS];
 | 
			
		||||
  int CanShift(int Ca, int Priority);
 | 
			
		||||
  int CanShift(int Ca, int Priority, int UsedCards = 0);
 | 
			
		||||
public:
 | 
			
		||||
  static cDvbApi *PrimaryDvbApi;
 | 
			
		||||
  static void SetUseDvbApi(int n);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								dvbosd.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								dvbosd.c
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: dvbosd.c 1.12 2002/01/13 16:25:18 kls Exp $
 | 
			
		||||
 * $Id: dvbosd.c 1.13 2002/04/13 11:34:48 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "dvbosd.h"
 | 
			
		||||
@@ -25,6 +25,9 @@ cPalette::cPalette(int Bpp)
 | 
			
		||||
 | 
			
		||||
int cPalette::Index(eDvbColor Color)
 | 
			
		||||
{
 | 
			
		||||
#if __BYTE_ORDER == __BIG_ENDIAN
 | 
			
		||||
  Color = eDvbColor(((Color & 0xFF) << 24) | ((Color & 0xFF00) << 8) | ((Color & 0xFF0000) >> 8) | ((Color & 0xFF000000) >> 24));
 | 
			
		||||
#endif
 | 
			
		||||
  for (int i = 0; i < numColors; i++) {
 | 
			
		||||
      if (color[i] == Color) {
 | 
			
		||||
         used[i] = true;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								i18n.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								i18n.h
									
									
									
									
									
								
							@@ -4,16 +4,28 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: i18n.h 1.1 2000/11/11 09:27:25 kls Exp $
 | 
			
		||||
 * $Id: i18n.h 1.2 2002/05/05 13:42:31 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __I18N_H
 | 
			
		||||
#define __I18N_H
 | 
			
		||||
 | 
			
		||||
extern const int NumLanguages;
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
const char *tr(const char *s);
 | 
			
		||||
const int I18nNumLanguages = 12;
 | 
			
		||||
 | 
			
		||||
const char * const * Languages(void);
 | 
			
		||||
typedef const char *tI18nPhrase[I18nNumLanguages];
 | 
			
		||||
 | 
			
		||||
void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin);
 | 
			
		||||
 | 
			
		||||
const char *I18nTranslate(const char *s, const char *Plugin = NULL);
 | 
			
		||||
 | 
			
		||||
const char * const * I18nLanguages(void);
 | 
			
		||||
 | 
			
		||||
#ifdef PLUGIN_NAME_I18N
 | 
			
		||||
#define tr(s)  I18nTranslate(s, PLUGIN_NAME_I18N)
 | 
			
		||||
#else
 | 
			
		||||
#define tr(s)  I18nTranslate(s)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif //__I18N_H
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: interface.h 1.24 2001/09/01 15:14:50 kls Exp $
 | 
			
		||||
 * $Id: interface.h 1.25 2002/04/19 13:17:15 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __INTERFACE_H
 | 
			
		||||
@@ -46,6 +46,7 @@ public:
 | 
			
		||||
  void SetBitmap(int x, int y, const cBitmap &Bitmap);
 | 
			
		||||
  void Flush(void);
 | 
			
		||||
  void SetCols(int *c);
 | 
			
		||||
  const int *GetCols(void) { return cols; }
 | 
			
		||||
  eDvbFont SetFont(eDvbFont Font);
 | 
			
		||||
  char *WrapText(const char *Text, int Width, int *Height);
 | 
			
		||||
  void Write(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										611
									
								
								menu.c
									
									
									
									
									
								
							
							
						
						
									
										611
									
								
								menu.c
									
									
									
									
									
								
							@@ -4,10 +4,11 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: menu.c 1.182 2002/04/06 09:41:59 kls Exp $
 | 
			
		||||
 * $Id: menu.c 1.190 2002/05/09 10:13:47 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "menu.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@@ -15,134 +16,19 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "eit.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
#include "menuitems.h"
 | 
			
		||||
#include "plugin.h"
 | 
			
		||||
#include "videodir.h"
 | 
			
		||||
 | 
			
		||||
#define MENUTIMEOUT     120 // seconds
 | 
			
		||||
#define MAXWAIT4EPGINFO  10 // seconds
 | 
			
		||||
#define MODETIMEOUT       3 // seconds
 | 
			
		||||
 | 
			
		||||
#define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
 | 
			
		||||
 | 
			
		||||
#define CHNUMWIDTH  (Channels.Count() > 999 ? 5 : 4) // there are people with more than 999 channels...
 | 
			
		||||
 | 
			
		||||
const char *FileNameChars = " aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-.#~^";
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditItem ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditItem : public cOsdItem {
 | 
			
		||||
private:
 | 
			
		||||
  const char *name;
 | 
			
		||||
  const char *value;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditItem(const char *Name);
 | 
			
		||||
  ~cMenuEditItem();
 | 
			
		||||
  void SetValue(const char *Value);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuEditItem::cMenuEditItem(const char *Name)
 | 
			
		||||
{
 | 
			
		||||
  name = strdup(Name);
 | 
			
		||||
  value = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuEditItem::~cMenuEditItem()
 | 
			
		||||
{
 | 
			
		||||
  delete name;
 | 
			
		||||
  delete value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditItem::SetValue(const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  delete value;
 | 
			
		||||
  value = strdup(Value);
 | 
			
		||||
  char *buffer = NULL;
 | 
			
		||||
  asprintf(&buffer, "%s:\t%s", name, value);
 | 
			
		||||
  SetText(buffer, false);
 | 
			
		||||
  Display();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditIntItem ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditIntItem : public cMenuEditItem {
 | 
			
		||||
protected:
 | 
			
		||||
  int *value;
 | 
			
		||||
  int min, max;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
 | 
			
		||||
:cMenuEditItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  value = Value;
 | 
			
		||||
  min = Min;
 | 
			
		||||
  max = Max;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditIntItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[16];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "%d", *value);
 | 
			
		||||
  SetValue(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     int newValue;
 | 
			
		||||
     if (k0 <= Key && Key <= k9) {
 | 
			
		||||
        if (fresh) {
 | 
			
		||||
           *value = 0;
 | 
			
		||||
           fresh = false;
 | 
			
		||||
           }
 | 
			
		||||
        newValue = *value  * 10 + (Key - k0);
 | 
			
		||||
        }
 | 
			
		||||
     else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
 | 
			
		||||
        newValue = *value - 1;
 | 
			
		||||
        fresh = true;
 | 
			
		||||
        }
 | 
			
		||||
     else if (NORMALKEY(Key) == kRight) {
 | 
			
		||||
        newValue = *value + 1;
 | 
			
		||||
        fresh = true;
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        return state;
 | 
			
		||||
     if ((!fresh || min <= newValue) && newValue <= max) {
 | 
			
		||||
        *value = newValue;
 | 
			
		||||
        Set();
 | 
			
		||||
        }
 | 
			
		||||
     state = osContinue;
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditBoolItem -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditBoolItem : public cMenuEditIntItem {
 | 
			
		||||
protected:
 | 
			
		||||
  const char *falseString, *trueString;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString = NULL, const char *TrueString = NULL);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString, const char *TrueString)
 | 
			
		||||
:cMenuEditIntItem(Name, Value, 0, 1)
 | 
			
		||||
{
 | 
			
		||||
  falseString = FalseString ? FalseString : tr("no");
 | 
			
		||||
  trueString = TrueString ? TrueString : tr("yes");
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditBoolItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[16];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "%s", *value ? trueString : falseString);
 | 
			
		||||
  SetValue(buf);
 | 
			
		||||
}
 | 
			
		||||
const char *FileNameChars = " abcdefghijklmnopqrstuvwxyz0123456789-.#~";
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditChanItem -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@@ -448,186 +334,6 @@ eOSState cMenuEditTimeItem::ProcessKey(eKeys Key)
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditChrItem ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditChrItem : public cMenuEditItem {
 | 
			
		||||
private:
 | 
			
		||||
  char *value;
 | 
			
		||||
  const char *allowed;
 | 
			
		||||
  const char *current;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditChrItem(const char *Name, char *Value, const char *Allowed);
 | 
			
		||||
  ~cMenuEditChrItem();
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
 | 
			
		||||
:cMenuEditItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  value = Value;
 | 
			
		||||
  allowed = strdup(Allowed);
 | 
			
		||||
  current = strchr(allowed, *Value);
 | 
			
		||||
  if (!current)
 | 
			
		||||
     current = allowed;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuEditChrItem::~cMenuEditChrItem()
 | 
			
		||||
{
 | 
			
		||||
  delete allowed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditChrItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[2];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "%c", *value);
 | 
			
		||||
  SetValue(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     if (NORMALKEY(Key) == kLeft) {
 | 
			
		||||
        if (current > allowed)
 | 
			
		||||
           current--;
 | 
			
		||||
        }
 | 
			
		||||
     else if (NORMALKEY(Key) == kRight) {
 | 
			
		||||
        if (*(current + 1))
 | 
			
		||||
           current++;
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        return state;
 | 
			
		||||
     *value = *current;
 | 
			
		||||
     Set();
 | 
			
		||||
     state = osContinue;
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditStrItem ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditStrItem : public cMenuEditItem {
 | 
			
		||||
private:
 | 
			
		||||
  char *value;
 | 
			
		||||
  int length;
 | 
			
		||||
  const char *allowed;
 | 
			
		||||
  int pos;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
  char Inc(char c, bool Up);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
 | 
			
		||||
  ~cMenuEditStrItem();
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
 | 
			
		||||
:cMenuEditItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  value = Value;
 | 
			
		||||
  length = Length;
 | 
			
		||||
  allowed = strdup(Allowed);
 | 
			
		||||
  pos = -1;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuEditStrItem::~cMenuEditStrItem()
 | 
			
		||||
{
 | 
			
		||||
  delete allowed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditStrItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[1000];
 | 
			
		||||
  if (pos >= 0) {
 | 
			
		||||
     strncpy(buf, value, pos);
 | 
			
		||||
     const char *s = value[pos] != '^' ? value + pos + 1 : "";
 | 
			
		||||
     snprintf(buf + pos, sizeof(buf) - pos - 2, "[%c]%s", *(value + pos), s);
 | 
			
		||||
     SetValue(buf);
 | 
			
		||||
     }
 | 
			
		||||
  else
 | 
			
		||||
     SetValue(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char cMenuEditStrItem::Inc(char c, bool Up)
 | 
			
		||||
{
 | 
			
		||||
  const char *p = strchr(allowed, c);
 | 
			
		||||
  if (!p)
 | 
			
		||||
     p = allowed;
 | 
			
		||||
  if (Up) {
 | 
			
		||||
     if (!*++p)
 | 
			
		||||
        p = allowed;
 | 
			
		||||
     }
 | 
			
		||||
  else if (--p < allowed)
 | 
			
		||||
     p = allowed + strlen(allowed) - 1;
 | 
			
		||||
  return *p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  switch (Key) {
 | 
			
		||||
    case kLeft|k_Repeat:
 | 
			
		||||
    case kLeft:  if (pos > 0) {
 | 
			
		||||
                    if (value[pos] == '^')
 | 
			
		||||
                       value[pos] = 0;
 | 
			
		||||
                    pos--;
 | 
			
		||||
                    }
 | 
			
		||||
                 break;
 | 
			
		||||
    case kRight|k_Repeat:
 | 
			
		||||
    case kRight: if (pos < length && value[pos] != '^' && (pos < int(strlen(value) - 1) || value[pos] != ' ')) {
 | 
			
		||||
                    if (++pos >= int(strlen(value))) {
 | 
			
		||||
                       value[pos] = ' ';
 | 
			
		||||
                       value[pos + 1] = 0;
 | 
			
		||||
                       }
 | 
			
		||||
                    }
 | 
			
		||||
                 break;
 | 
			
		||||
    case kUp|k_Repeat:
 | 
			
		||||
    case kUp:
 | 
			
		||||
    case kDown|k_Repeat:
 | 
			
		||||
    case kDown:  if (pos >= 0)
 | 
			
		||||
                    value[pos] = Inc(value[pos], NORMALKEY(Key) == kUp);
 | 
			
		||||
                 else
 | 
			
		||||
                    return cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
                 break;
 | 
			
		||||
    case kOk:    if (pos >= 0) {
 | 
			
		||||
                    if (value[pos] == '^')
 | 
			
		||||
                       value[pos] = 0;
 | 
			
		||||
                    pos = -1;
 | 
			
		||||
                    stripspace(value);
 | 
			
		||||
                    break;
 | 
			
		||||
                    }
 | 
			
		||||
                 // run into default
 | 
			
		||||
    default:     return cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
    }
 | 
			
		||||
  Set();
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditStraItem -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditStraItem : public cMenuEditIntItem {
 | 
			
		||||
private:
 | 
			
		||||
  const char * const *strings;
 | 
			
		||||
protected:
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuEditStraItem::cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings)
 | 
			
		||||
:cMenuEditIntItem(Name, Value, 0, NumStrings - 1)
 | 
			
		||||
{
 | 
			
		||||
  strings = Strings;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditStraItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  SetValue(strings[*value]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditCaItem -------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuEditCaItem : public cMenuEditIntItem {
 | 
			
		||||
@@ -699,7 +405,7 @@ cMenuEditChannel::cMenuEditChannel(int Index)
 | 
			
		||||
  channel = Channels.Get(Index);
 | 
			
		||||
  if (channel) {
 | 
			
		||||
     data = *channel;
 | 
			
		||||
     Add(new cMenuEditStrItem( tr("Name"),          data.name, sizeof(data.name), FileNameChars));
 | 
			
		||||
     Add(new cMenuEditStrItem( tr("Name"),          data.name, sizeof(data.name), tr(FileNameChars)));
 | 
			
		||||
     Add(new cMenuEditIntItem( tr("Frequency"),    &data.frequency));
 | 
			
		||||
     Add(new cMenuEditChrItem( tr("Polarization"), &data.polarization, "hv"));
 | 
			
		||||
     Add(new cMenuEditIntItem( tr("DiSEqC"),       &data.diseqc, 0, 10)); //TODO exact limits???
 | 
			
		||||
@@ -919,116 +625,6 @@ eOSState cMenuChannels::ProcessKey(eKeys Key)
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuTextItem ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuTextItem : public cOsdItem {
 | 
			
		||||
private:
 | 
			
		||||
  char *text;
 | 
			
		||||
  int x, y, w, h, lines, offset;
 | 
			
		||||
  eDvbColor fgColor, bgColor;
 | 
			
		||||
  eDvbFont font;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuTextItem(const char *Text, int X, int Y, int W, int H = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground, eDvbFont Font = fontOsd);
 | 
			
		||||
  ~cMenuTextItem();
 | 
			
		||||
  int Height(void) { return h; }
 | 
			
		||||
  void Clear(void);
 | 
			
		||||
  virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
 | 
			
		||||
  bool CanScrollUp(void) { return offset > 0; }
 | 
			
		||||
  bool CanScrollDown(void) { return h + offset < lines; }
 | 
			
		||||
  void ScrollUp(bool Page);
 | 
			
		||||
  void ScrollDown(bool Page);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuTextItem::cMenuTextItem(const char *Text, int X, int Y, int W, int H, eDvbColor FgColor, eDvbColor BgColor, eDvbFont Font)
 | 
			
		||||
{
 | 
			
		||||
  x = X;
 | 
			
		||||
  y = Y;
 | 
			
		||||
  w = W;
 | 
			
		||||
  h = H;
 | 
			
		||||
  fgColor = FgColor;
 | 
			
		||||
  bgColor = BgColor;
 | 
			
		||||
  font = Font;
 | 
			
		||||
  offset = 0;
 | 
			
		||||
  eDvbFont oldFont = Interface->SetFont(font);
 | 
			
		||||
  text = Interface->WrapText(Text, w - 1, &lines);
 | 
			
		||||
  Interface->SetFont(oldFont);
 | 
			
		||||
  if (h < 0)
 | 
			
		||||
     h = lines;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuTextItem::~cMenuTextItem()
 | 
			
		||||
{
 | 
			
		||||
  delete text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::Clear(void)
 | 
			
		||||
{
 | 
			
		||||
  Interface->Fill(x, y, w, h, bgColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
 | 
			
		||||
{
 | 
			
		||||
  int l = 0;
 | 
			
		||||
  char *t = text;
 | 
			
		||||
  eDvbFont oldFont = Interface->SetFont(font);
 | 
			
		||||
  while (*t) {
 | 
			
		||||
        char *n = strchr(t, '\n');
 | 
			
		||||
        if (l >= offset) {
 | 
			
		||||
           if (n)
 | 
			
		||||
              *n = 0;
 | 
			
		||||
           Interface->Write(x, y + l - offset, t, fgColor, bgColor);
 | 
			
		||||
           if (n)
 | 
			
		||||
              *n = '\n';
 | 
			
		||||
           else
 | 
			
		||||
              break;
 | 
			
		||||
           }
 | 
			
		||||
        if (!n)
 | 
			
		||||
           break;
 | 
			
		||||
        t = n + 1;
 | 
			
		||||
        if (++l >= h + offset)
 | 
			
		||||
           break;
 | 
			
		||||
        }
 | 
			
		||||
  Interface->SetFont(oldFont);
 | 
			
		||||
  // scroll indicators use inverted color scheme!
 | 
			
		||||
  if (CanScrollUp())   Interface->Write(x + w - 1, y,         "^", bgColor, fgColor);
 | 
			
		||||
  if (CanScrollDown()) Interface->Write(x + w - 1, y + h - 1, "v", bgColor, fgColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::ScrollUp(bool Page)
 | 
			
		||||
{
 | 
			
		||||
  if (CanScrollUp()) {
 | 
			
		||||
     Clear();
 | 
			
		||||
     offset = max(offset - (Page ? h : 1), 0);
 | 
			
		||||
     Display();
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::ScrollDown(bool Page)
 | 
			
		||||
{
 | 
			
		||||
  if (CanScrollDown()) {
 | 
			
		||||
     Clear();
 | 
			
		||||
     offset = min(offset + (Page ? h : 1), lines - h);
 | 
			
		||||
     Display();
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuTextItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  switch (Key) {
 | 
			
		||||
    case kLeft|k_Repeat:
 | 
			
		||||
    case kLeft:
 | 
			
		||||
    case kUp|k_Repeat:
 | 
			
		||||
    case kUp:            ScrollUp(NORMALKEY(Key) == kLeft);    break;
 | 
			
		||||
    case kRight|k_Repeat:
 | 
			
		||||
    case kRight:
 | 
			
		||||
    case kDown|k_Repeat:
 | 
			
		||||
    case kDown:          ScrollDown(NORMALKEY(Key) == kRight); break;
 | 
			
		||||
    default:             return osUnknown;
 | 
			
		||||
    }
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuText -------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuText : public cOsdMenu {
 | 
			
		||||
@@ -1086,7 +682,7 @@ cMenuEditTimer::cMenuEditTimer(int Index, bool New)
 | 
			
		||||
//TODO VPS???
 | 
			
		||||
     Add(new cMenuEditIntItem( tr("Priority"),     &data.priority, 0, MAXPRIORITY));
 | 
			
		||||
     Add(new cMenuEditIntItem( tr("Lifetime"),     &data.lifetime, 0, MAXLIFETIME));
 | 
			
		||||
     Add(new cMenuEditStrItem( tr("File"),          data.file, sizeof(data.file), FileNameChars));
 | 
			
		||||
     Add(new cMenuEditStrItem( tr("File"),          data.file, sizeof(data.file), tr(FileNameChars)));
 | 
			
		||||
     SetFirstDayItem();
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
@@ -1929,60 +1525,6 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuSetupPage --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuSetupPage : public cOsdMenu {
 | 
			
		||||
protected:
 | 
			
		||||
  cSetup data;
 | 
			
		||||
  int osdLanguage;
 | 
			
		||||
  void SetupTitle(const char *s);
 | 
			
		||||
  virtual void Set(void) = 0;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuSetupPage(void);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuSetupPage::cMenuSetupPage(void)
 | 
			
		||||
:cOsdMenu("", 33)
 | 
			
		||||
{
 | 
			
		||||
  data = Setup;
 | 
			
		||||
  osdLanguage = Setup.OSDLanguage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuSetupPage::SetupTitle(const char *s)
 | 
			
		||||
{
 | 
			
		||||
  char buf[40]; // can't call tr() for more than one string at a time!
 | 
			
		||||
  char *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
 | 
			
		||||
  snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
 | 
			
		||||
  SetTitle(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetupPage::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cOsdMenu::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     switch (Key) {
 | 
			
		||||
       case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
 | 
			
		||||
                 cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
 | 
			
		||||
                 Setup = data;
 | 
			
		||||
                 Setup.Save();
 | 
			
		||||
                 cDvbApi::SetCaCaps();
 | 
			
		||||
                 break;
 | 
			
		||||
       default: break;
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
  if (data.OSDLanguage != osdLanguage) {
 | 
			
		||||
     int OriginalOSDLanguage = Setup.OSDLanguage;
 | 
			
		||||
     Setup.OSDLanguage = data.OSDLanguage;
 | 
			
		||||
     Set();
 | 
			
		||||
     Display();
 | 
			
		||||
     osdLanguage = data.OSDLanguage;
 | 
			
		||||
     Setup.OSDLanguage = OriginalOSDLanguage;
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuSetupOSD ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuSetupOSD : public cMenuSetupPage {
 | 
			
		||||
@@ -1996,7 +1538,7 @@ void cMenuSetupOSD::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  Clear();
 | 
			
		||||
  SetupTitle("OSD");
 | 
			
		||||
  Add(new cMenuEditStraItem(tr("Setup.OSD$Language"),               &data.OSDLanguage, NumLanguages, Languages()));
 | 
			
		||||
  Add(new cMenuEditStraItem(tr("Setup.OSD$Language"),               &data.OSDLanguage, I18nNumLanguages, I18nLanguages()));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.OSD$Width"),                  &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.OSD$Height"),                 &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.OSD$Message time (s)"),       &data.OSDMessageTime, 1, 60));
 | 
			
		||||
@@ -2104,7 +1646,8 @@ void cMenuSetupRecord::Set(void)
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Recording$Default lifetime (d)"),      &data.DefaultLifetime, 0, MAXLIFETIME));
 | 
			
		||||
  Add(new cMenuEditBoolItem(tr("Setup.Recording$Use episode name"),          &data.UseSubtitle));
 | 
			
		||||
  Add(new cMenuEditBoolItem(tr("Setup.Recording$Mark instant recording"),    &data.MarkInstantRecord));
 | 
			
		||||
  Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"),     data.NameInstantRecord, sizeof(data.NameInstantRecord), FileNameChars));
 | 
			
		||||
  Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"),     data.NameInstantRecord, sizeof(data.NameInstantRecord), tr(FileNameChars)));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Recording$Instant rec. time (min)"),   &data.InstantRecordTime, 1, MAXINSTANTRECTIME));
 | 
			
		||||
  Add(new cMenuEditBoolItem(tr("Setup.Recording$Record Dolby Digital"),      &data.RecordDolbyDigital));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZE));
 | 
			
		||||
  Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"),        &data.SplitEditedFiles));
 | 
			
		||||
@@ -2142,7 +1685,76 @@ void cMenuSetupMisc::Set(void)
 | 
			
		||||
  SetupTitle("Miscellaneous");
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. event timeout (min)"),   &data.MinEventTimeout));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. user inactivity (min)"), &data.MinUserInactivity));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (min)"),        &data.SVDRPTimeout));
 | 
			
		||||
  Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"),          &data.SVDRPTimeout));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuSetupPluginItem --------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuSetupPluginItem : public cOsdItem {
 | 
			
		||||
private:
 | 
			
		||||
  int pluginIndex;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuSetupPluginItem(const char *Name, int Index);
 | 
			
		||||
  int PluginIndex(void) { return pluginIndex; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuSetupPluginItem::cMenuSetupPluginItem(const char *Name, int Index)
 | 
			
		||||
:cOsdItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  pluginIndex = Index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuSetupPlugins -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuSetupPlugins : public cMenuSetupPage {
 | 
			
		||||
private:
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuSetupPlugins(void) { Set(); }
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
void cMenuSetupPlugins::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  Clear();
 | 
			
		||||
  SetupTitle("Plugins");
 | 
			
		||||
  SetHasHotkeys();
 | 
			
		||||
  for (int i = 0; ; i++) {
 | 
			
		||||
      cPlugin *p = cPluginManager::GetPlugin(i);
 | 
			
		||||
      if (p) {
 | 
			
		||||
         char *buffer = NULL;
 | 
			
		||||
         asprintf(&buffer, "%s (%s) - %s", p->Name(), p->Version(), p->Description());
 | 
			
		||||
         Add(new cMenuSetupPluginItem(hk(buffer), i));
 | 
			
		||||
         delete buffer;
 | 
			
		||||
         }
 | 
			
		||||
      else
 | 
			
		||||
         break;
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cOsdMenu::ProcessKey(Key); // not cMenuSetupPage::ProcessKey()!
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     switch (Key) {
 | 
			
		||||
       case kOk: {
 | 
			
		||||
                   cMenuSetupPluginItem *item = (cMenuSetupPluginItem *)Get(Current());
 | 
			
		||||
                   if (item) {
 | 
			
		||||
                      cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
 | 
			
		||||
                      if (p) {
 | 
			
		||||
                         cOsdMenu *menu = p->SetupMenu();
 | 
			
		||||
                         if (menu)
 | 
			
		||||
                            return AddSubMenu(menu);
 | 
			
		||||
                         Interface->Info(tr("This plugin has no setup parameters!"));
 | 
			
		||||
                         }
 | 
			
		||||
                      }
 | 
			
		||||
                  }
 | 
			
		||||
                  break;
 | 
			
		||||
       default:   break;
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuSetup ------------------------------------------------------------
 | 
			
		||||
@@ -2165,7 +1777,9 @@ cMenuSetup::cMenuSetup(void)
 | 
			
		||||
void cMenuSetup::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  Clear();
 | 
			
		||||
  SetTitle(tr("Setup"));
 | 
			
		||||
  char buffer[64];
 | 
			
		||||
  snprintf(buffer, sizeof(buffer), "%s - VDR %s", tr("Setup"), VDRVERSION);
 | 
			
		||||
  SetTitle(buffer);
 | 
			
		||||
  SetHasHotkeys();
 | 
			
		||||
  Add(new cOsdItem(hk(tr("OSD")),           osUser1));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("EPG")),           osUser2));
 | 
			
		||||
@@ -2175,7 +1789,9 @@ void cMenuSetup::Set(void)
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Recording")),     osUser6));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Replay")),        osUser7));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Miscellaneous")), osUser8));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Restart")),       osUser9));
 | 
			
		||||
  if (cPluginManager::HasPlugins())
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Plugins")),       osUser9));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Restart")),       osUser10));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetup::Restart(void)
 | 
			
		||||
@@ -2201,7 +1817,8 @@ eOSState cMenuSetup::ProcessKey(eKeys Key)
 | 
			
		||||
    case osUser6: return AddSubMenu(new cMenuSetupRecord);
 | 
			
		||||
    case osUser7: return AddSubMenu(new cMenuSetupReplay);
 | 
			
		||||
    case osUser8: return AddSubMenu(new cMenuSetupMisc);
 | 
			
		||||
    case osUser9: return Restart();
 | 
			
		||||
    case osUser9: return AddSubMenu(new cMenuSetupPlugins);
 | 
			
		||||
    case osUser10: return Restart();
 | 
			
		||||
    default: ;
 | 
			
		||||
    }
 | 
			
		||||
  if (Setup.OSDLanguage != osdLanguage) {
 | 
			
		||||
@@ -2264,6 +1881,22 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuPluginItem -------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuPluginItem : public cOsdItem {
 | 
			
		||||
private:
 | 
			
		||||
  int pluginIndex;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuPluginItem(const char *Name, int Index);
 | 
			
		||||
  int PluginIndex(void) { return pluginIndex; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cMenuPluginItem::cMenuPluginItem(const char *Name, int Index)
 | 
			
		||||
:cOsdItem(Name, osPlugin)
 | 
			
		||||
{
 | 
			
		||||
  pluginIndex = Index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuMain -------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#define STOP_RECORDING tr(" Stop recording ")
 | 
			
		||||
@@ -2308,6 +1941,22 @@ void cMenuMain::Set(void)
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Channels")),   osChannels));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Timers")),     osTimers));
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Recordings")), osRecordings));
 | 
			
		||||
 | 
			
		||||
  // Plugins:
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; ; i++) {
 | 
			
		||||
      cPlugin *p = cPluginManager::GetPlugin(i);
 | 
			
		||||
      if (p) {
 | 
			
		||||
         const char *item = p->MainMenuEntry();
 | 
			
		||||
         if (item)
 | 
			
		||||
            Add(new cMenuPluginItem(hk(item), i));
 | 
			
		||||
         }
 | 
			
		||||
      else
 | 
			
		||||
         break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  // More basic menu items:
 | 
			
		||||
 | 
			
		||||
  Add(new cOsdItem(hk(tr("Setup")),      osSetup));
 | 
			
		||||
  if (Commands.Count())
 | 
			
		||||
     Add(new cOsdItem(hk(tr("Commands")),  osCommands));
 | 
			
		||||
@@ -2375,6 +2024,19 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
 | 
			
		||||
                          return osEnd;
 | 
			
		||||
                          }
 | 
			
		||||
                       break;
 | 
			
		||||
    case osPlugin:     {
 | 
			
		||||
                         cMenuPluginItem *item = (cMenuPluginItem *)Get(Current());
 | 
			
		||||
                         if (item) {
 | 
			
		||||
                            cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
 | 
			
		||||
                            if (p) {
 | 
			
		||||
                               cOsdMenu *menu = p->MainMenuAction();
 | 
			
		||||
                               if (menu)
 | 
			
		||||
                                  return AddSubMenu(menu);
 | 
			
		||||
                               }
 | 
			
		||||
                            }
 | 
			
		||||
                         state = osEnd;
 | 
			
		||||
                       }
 | 
			
		||||
                       break;
 | 
			
		||||
    default: switch (Key) {
 | 
			
		||||
               case kMenu:   state = osEnd;    break;
 | 
			
		||||
               case kRed:    if (!HasSubMenu())
 | 
			
		||||
@@ -3185,6 +2847,7 @@ void cReplayControl::TimeSearch(void)
 | 
			
		||||
     else
 | 
			
		||||
        return;
 | 
			
		||||
     }
 | 
			
		||||
  timeoutShow = 0;
 | 
			
		||||
  TimeSearchDisplay();
 | 
			
		||||
  timeSearchActive = true;
 | 
			
		||||
}
 | 
			
		||||
@@ -3287,7 +2950,7 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
 | 
			
		||||
        }
 | 
			
		||||
     else if (modeOnly)
 | 
			
		||||
        ShowMode();
 | 
			
		||||
     else 
 | 
			
		||||
     else
 | 
			
		||||
        shown = ShowProgress(!shown) || shown;
 | 
			
		||||
     }
 | 
			
		||||
  bool DisplayedFrames = displayFrames;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								menu.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								menu.h
									
									
									
									
									
								
							@@ -4,11 +4,11 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: menu.h 1.41 2002/03/31 13:53:23 kls Exp $
 | 
			
		||||
 * $Id: menu.h 1.42 2002/04/13 15:31:41 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _MENU_H
 | 
			
		||||
#define _MENU_H
 | 
			
		||||
#ifndef __MENU_H
 | 
			
		||||
#define __MENU_H
 | 
			
		||||
 | 
			
		||||
#include "dvbapi.h"
 | 
			
		||||
#include "osd.h"
 | 
			
		||||
@@ -142,4 +142,4 @@ public:
 | 
			
		||||
  static void ClearLastReplayed(const char *FileName);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //_MENU_H
 | 
			
		||||
#endif //__MENU_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										476
									
								
								menuitems.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										476
									
								
								menuitems.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,476 @@
 | 
			
		||||
/*
 | 
			
		||||
 * menuitems.c: General purpose menu items
 | 
			
		||||
 *
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: menuitems.c 1.1 2002/05/09 10:10:12 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "menuitems.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditItem ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuEditItem::cMenuEditItem(const char *Name)
 | 
			
		||||
{
 | 
			
		||||
  name = strdup(Name);
 | 
			
		||||
  value = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuEditItem::~cMenuEditItem()
 | 
			
		||||
{
 | 
			
		||||
  delete name;
 | 
			
		||||
  delete value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditItem::SetValue(const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  delete value;
 | 
			
		||||
  value = strdup(Value);
 | 
			
		||||
  char *buffer = NULL;
 | 
			
		||||
  asprintf(&buffer, "%s:\t%s", name, value);
 | 
			
		||||
  SetText(buffer, false);
 | 
			
		||||
  Display();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditIntItem ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
 | 
			
		||||
:cMenuEditItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  value = Value;
 | 
			
		||||
  min = Min;
 | 
			
		||||
  max = Max;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditIntItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[16];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "%d", *value);
 | 
			
		||||
  SetValue(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     int newValue;
 | 
			
		||||
     if (k0 <= Key && Key <= k9) {
 | 
			
		||||
        if (fresh) {
 | 
			
		||||
           *value = 0;
 | 
			
		||||
           fresh = false;
 | 
			
		||||
           }
 | 
			
		||||
        newValue = *value  * 10 + (Key - k0);
 | 
			
		||||
        }
 | 
			
		||||
     else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
 | 
			
		||||
        newValue = *value - 1;
 | 
			
		||||
        fresh = true;
 | 
			
		||||
        }
 | 
			
		||||
     else if (NORMALKEY(Key) == kRight) {
 | 
			
		||||
        newValue = *value + 1;
 | 
			
		||||
        fresh = true;
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        return state;
 | 
			
		||||
     if ((!fresh || min <= newValue) && newValue <= max) {
 | 
			
		||||
        *value = newValue;
 | 
			
		||||
        Set();
 | 
			
		||||
        }
 | 
			
		||||
     state = osContinue;
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditBoolItem -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString, const char *TrueString)
 | 
			
		||||
:cMenuEditIntItem(Name, Value, 0, 1)
 | 
			
		||||
{
 | 
			
		||||
  falseString = FalseString ? FalseString : tr("no");
 | 
			
		||||
  trueString = TrueString ? TrueString : tr("yes");
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditBoolItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[16];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "%s", *value ? trueString : falseString);
 | 
			
		||||
  SetValue(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditChrItem ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
 | 
			
		||||
:cMenuEditItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  value = Value;
 | 
			
		||||
  allowed = strdup(Allowed);
 | 
			
		||||
  current = strchr(allowed, *Value);
 | 
			
		||||
  if (!current)
 | 
			
		||||
     current = allowed;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuEditChrItem::~cMenuEditChrItem()
 | 
			
		||||
{
 | 
			
		||||
  delete allowed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditChrItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[2];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "%c", *value);
 | 
			
		||||
  SetValue(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     if (NORMALKEY(Key) == kLeft) {
 | 
			
		||||
        if (current > allowed)
 | 
			
		||||
           current--;
 | 
			
		||||
        }
 | 
			
		||||
     else if (NORMALKEY(Key) == kRight) {
 | 
			
		||||
        if (*(current + 1))
 | 
			
		||||
           current++;
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        return state;
 | 
			
		||||
     *value = *current;
 | 
			
		||||
     Set();
 | 
			
		||||
     state = osContinue;
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditStrItem ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
 | 
			
		||||
:cMenuEditItem(Name)
 | 
			
		||||
{
 | 
			
		||||
  value = Value;
 | 
			
		||||
  length = Length;
 | 
			
		||||
  allowed = strdup(Allowed);
 | 
			
		||||
  pos = -1;
 | 
			
		||||
  insert = uppercase = false;
 | 
			
		||||
  newchar = true;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuEditStrItem::~cMenuEditStrItem()
 | 
			
		||||
{
 | 
			
		||||
  delete allowed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditStrItem::SetHelpKeys(void)
 | 
			
		||||
{
 | 
			
		||||
  if (pos >= 0)
 | 
			
		||||
     Interface->Help(tr("ABC/abc"), tr(insert ? "Overwrite" : "Insert"), tr("Delete"));
 | 
			
		||||
  else
 | 
			
		||||
     Interface->Help(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditStrItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  char buf[1000];
 | 
			
		||||
  const char *fmt = insert && newchar ? "[]%c%s" : "[%c]%s";
 | 
			
		||||
 | 
			
		||||
  if (pos >= 0) {
 | 
			
		||||
     strncpy(buf, value, pos);
 | 
			
		||||
     snprintf(buf + pos, sizeof(buf) - pos - 2, fmt, *(value + pos), value + pos + 1);
 | 
			
		||||
     int width = Interface->Width() - Interface->GetCols()[0];
 | 
			
		||||
     if (cDvbApi::PrimaryDvbApi->WidthInCells(buf) <= width) {
 | 
			
		||||
        // the whole buffer fits on the screen
 | 
			
		||||
        SetValue(buf);
 | 
			
		||||
        return;
 | 
			
		||||
        }
 | 
			
		||||
     width *= cDvbApi::PrimaryDvbApi->CellWidth();
 | 
			
		||||
     width -= cDvbApi::PrimaryDvbApi->Width('>'); // assuming '<' and '>' have the same with
 | 
			
		||||
     int w = 0;
 | 
			
		||||
     int i = 0;
 | 
			
		||||
     int l = strlen(buf);
 | 
			
		||||
     while (i < l && w <= width)
 | 
			
		||||
           w += cDvbApi::PrimaryDvbApi->Width(buf[i++]);
 | 
			
		||||
     if (i >= pos + 4) {
 | 
			
		||||
        // the cursor fits on the screen
 | 
			
		||||
        buf[i - 1] = '>';
 | 
			
		||||
        buf[i] = 0;
 | 
			
		||||
        SetValue(buf);
 | 
			
		||||
        return;
 | 
			
		||||
        }
 | 
			
		||||
     // the cursor doesn't fit on the screen
 | 
			
		||||
     w = 0;
 | 
			
		||||
     if (buf[i = pos + 3]) {
 | 
			
		||||
        buf[i] = '>';
 | 
			
		||||
        buf[i + 1] = 0;
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        i--;
 | 
			
		||||
     while (i >= 0 && w <= width)
 | 
			
		||||
           w += cDvbApi::PrimaryDvbApi->Width(buf[i--]);
 | 
			
		||||
     buf[++i] = '<';
 | 
			
		||||
     SetValue(buf + i);
 | 
			
		||||
     }
 | 
			
		||||
  else
 | 
			
		||||
     SetValue(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char cMenuEditStrItem::Inc(char c, bool Up)
 | 
			
		||||
{
 | 
			
		||||
  const char *p = strchr(allowed, c);
 | 
			
		||||
  if (!p)
 | 
			
		||||
     p = allowed;
 | 
			
		||||
  if (Up) {
 | 
			
		||||
     if (!*++p)
 | 
			
		||||
        p = allowed;
 | 
			
		||||
     }
 | 
			
		||||
  else if (--p < allowed)
 | 
			
		||||
     p = allowed + strlen(allowed) - 1;
 | 
			
		||||
  return *p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  switch (Key) {
 | 
			
		||||
    case kRed:   // Switch between upper- and lowercase characters
 | 
			
		||||
                 if (pos >= 0 && (!insert || !newchar)) {
 | 
			
		||||
                    uppercase = !uppercase;
 | 
			
		||||
                    value[pos] = uppercase ? toupper(value[pos]) : tolower(value[pos]);
 | 
			
		||||
                    }
 | 
			
		||||
                 break;
 | 
			
		||||
    case kGreen: // Toggle insert/overwrite modes
 | 
			
		||||
                 if (pos >= 0) {
 | 
			
		||||
                    insert = !insert;
 | 
			
		||||
                    newchar = true;
 | 
			
		||||
                    }
 | 
			
		||||
                 SetHelpKeys();
 | 
			
		||||
                 break;
 | 
			
		||||
    case kYellow|k_Repeat:
 | 
			
		||||
    case kYellow: // Remove the character at current position; in insert mode it is the character to the right of cursor
 | 
			
		||||
                 if (pos >= 0) {
 | 
			
		||||
                    if (strlen(value) > 1) {
 | 
			
		||||
                       memmove(value + pos, value + pos + 1, strlen(value) - pos);
 | 
			
		||||
                       // reduce position, if we removed the last character
 | 
			
		||||
                       if (pos == int(strlen(value)))
 | 
			
		||||
                          pos--;
 | 
			
		||||
                       }
 | 
			
		||||
                    else if (strlen(value) == 1)
 | 
			
		||||
                       value[0] = ' '; // This is the last character in the string, replace it with a blank
 | 
			
		||||
                    if (isalpha(value[pos]))
 | 
			
		||||
                       uppercase = isupper(value[pos]);
 | 
			
		||||
                    newchar = true;
 | 
			
		||||
                    }
 | 
			
		||||
                 break;
 | 
			
		||||
    case kLeft|k_Repeat:
 | 
			
		||||
    case kLeft:  if (pos > 0) {
 | 
			
		||||
                    if (!insert || newchar)
 | 
			
		||||
                       pos--;
 | 
			
		||||
                    newchar = true;
 | 
			
		||||
                    }
 | 
			
		||||
                 if (!insert && isalpha(value[pos]))
 | 
			
		||||
                    uppercase = isupper(value[pos]);
 | 
			
		||||
                 break;
 | 
			
		||||
    case kRight|k_Repeat:
 | 
			
		||||
    case kRight: if (pos < length && pos < int(strlen(value)) ) {
 | 
			
		||||
                    if (++pos >= int(strlen(value))) {
 | 
			
		||||
                       if (pos >= 2 && value[pos - 1] == ' ' && value[pos - 2] == ' ')
 | 
			
		||||
                          pos--; // allow only two blanks at the end
 | 
			
		||||
                       else {
 | 
			
		||||
                          value[pos] = ' ';
 | 
			
		||||
                          value[pos + 1] = 0;
 | 
			
		||||
                          }
 | 
			
		||||
                       }
 | 
			
		||||
                    }
 | 
			
		||||
                 newchar = true;
 | 
			
		||||
                 if (!insert && isalpha(value[pos]))
 | 
			
		||||
                    uppercase = isupper(value[pos]);
 | 
			
		||||
                 if (pos == 0)
 | 
			
		||||
                    SetHelpKeys();
 | 
			
		||||
                 break;
 | 
			
		||||
    case kUp|k_Repeat:
 | 
			
		||||
    case kUp:
 | 
			
		||||
    case kDown|k_Repeat:
 | 
			
		||||
    case kDown:  if (pos >= 0) {
 | 
			
		||||
                    if (insert && newchar) {
 | 
			
		||||
                       // create a new character in insert mode
 | 
			
		||||
                       if (int(strlen(value)) < length) {
 | 
			
		||||
                          memmove(value + pos + 1, value + pos, strlen(value) - pos + 1);
 | 
			
		||||
                          value[pos] = ' ';
 | 
			
		||||
                          }
 | 
			
		||||
                       }
 | 
			
		||||
                    if (uppercase)
 | 
			
		||||
                       value[pos] = toupper(Inc(tolower(value[pos]), NORMALKEY(Key) == kUp));
 | 
			
		||||
                    else
 | 
			
		||||
                       value[pos] =         Inc(        value[pos],  NORMALKEY(Key) == kUp);
 | 
			
		||||
                    newchar = false;
 | 
			
		||||
                    }
 | 
			
		||||
                 else
 | 
			
		||||
                    return cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
                 break;
 | 
			
		||||
    case kOk:    if (pos >= 0) {
 | 
			
		||||
                    pos = -1;
 | 
			
		||||
                    newchar = true;
 | 
			
		||||
                    stripspace(value);
 | 
			
		||||
                    SetHelpKeys();
 | 
			
		||||
                    break;
 | 
			
		||||
                    }
 | 
			
		||||
                 // run into default
 | 
			
		||||
    default:     return cMenuEditItem::ProcessKey(Key);
 | 
			
		||||
    }
 | 
			
		||||
  Set();
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuEditStraItem -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuEditStraItem::cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings)
 | 
			
		||||
:cMenuEditIntItem(Name, Value, 0, NumStrings - 1)
 | 
			
		||||
{
 | 
			
		||||
  strings = Strings;
 | 
			
		||||
  Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuEditStraItem::Set(void)
 | 
			
		||||
{
 | 
			
		||||
  SetValue(strings[*value]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuTextItem ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuTextItem::cMenuTextItem(const char *Text, int X, int Y, int W, int H, eDvbColor FgColor, eDvbColor BgColor, eDvbFont Font)
 | 
			
		||||
{
 | 
			
		||||
  x = X;
 | 
			
		||||
  y = Y;
 | 
			
		||||
  w = W;
 | 
			
		||||
  h = H;
 | 
			
		||||
  fgColor = FgColor;
 | 
			
		||||
  bgColor = BgColor;
 | 
			
		||||
  font = Font;
 | 
			
		||||
  offset = 0;
 | 
			
		||||
  eDvbFont oldFont = Interface->SetFont(font);
 | 
			
		||||
  text = Interface->WrapText(Text, w - 1, &lines);
 | 
			
		||||
  Interface->SetFont(oldFont);
 | 
			
		||||
  if (h < 0)
 | 
			
		||||
     h = lines;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuTextItem::~cMenuTextItem()
 | 
			
		||||
{
 | 
			
		||||
  delete text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::Clear(void)
 | 
			
		||||
{
 | 
			
		||||
  Interface->Fill(x, y, w, h, bgColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
 | 
			
		||||
{
 | 
			
		||||
  int l = 0;
 | 
			
		||||
  char *t = text;
 | 
			
		||||
  eDvbFont oldFont = Interface->SetFont(font);
 | 
			
		||||
  while (*t) {
 | 
			
		||||
        char *n = strchr(t, '\n');
 | 
			
		||||
        if (l >= offset) {
 | 
			
		||||
           if (n)
 | 
			
		||||
              *n = 0;
 | 
			
		||||
           Interface->Write(x, y + l - offset, t, fgColor, bgColor);
 | 
			
		||||
           if (n)
 | 
			
		||||
              *n = '\n';
 | 
			
		||||
           else
 | 
			
		||||
              break;
 | 
			
		||||
           }
 | 
			
		||||
        if (!n)
 | 
			
		||||
           break;
 | 
			
		||||
        t = n + 1;
 | 
			
		||||
        if (++l >= h + offset)
 | 
			
		||||
           break;
 | 
			
		||||
        }
 | 
			
		||||
  Interface->SetFont(oldFont);
 | 
			
		||||
  // scroll indicators use inverted color scheme!
 | 
			
		||||
  if (CanScrollUp())   Interface->Write(x + w - 1, y,         "^", bgColor, fgColor);
 | 
			
		||||
  if (CanScrollDown()) Interface->Write(x + w - 1, y + h - 1, "v", bgColor, fgColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::ScrollUp(bool Page)
 | 
			
		||||
{
 | 
			
		||||
  if (CanScrollUp()) {
 | 
			
		||||
     Clear();
 | 
			
		||||
     offset = max(offset - (Page ? h : 1), 0);
 | 
			
		||||
     Display();
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuTextItem::ScrollDown(bool Page)
 | 
			
		||||
{
 | 
			
		||||
  if (CanScrollDown()) {
 | 
			
		||||
     Clear();
 | 
			
		||||
     offset = min(offset + (Page ? h : 1), lines - h);
 | 
			
		||||
     Display();
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuTextItem::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  switch (Key) {
 | 
			
		||||
    case kLeft|k_Repeat:
 | 
			
		||||
    case kLeft:
 | 
			
		||||
    case kUp|k_Repeat:
 | 
			
		||||
    case kUp:            ScrollUp(NORMALKEY(Key) == kLeft);    break;
 | 
			
		||||
    case kRight|k_Repeat:
 | 
			
		||||
    case kRight:
 | 
			
		||||
    case kDown|k_Repeat:
 | 
			
		||||
    case kDown:          ScrollDown(NORMALKEY(Key) == kRight); break;
 | 
			
		||||
    default:             return osUnknown;
 | 
			
		||||
    }
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuSetupPage --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuSetupPage::cMenuSetupPage(void)
 | 
			
		||||
:cOsdMenu("", 33)
 | 
			
		||||
{
 | 
			
		||||
  data = Setup;
 | 
			
		||||
  osdLanguage = Setup.OSDLanguage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuSetupPage::SetupTitle(const char *s)
 | 
			
		||||
{
 | 
			
		||||
  char buf[40]; // can't call tr() for more than one string at a time!
 | 
			
		||||
  char *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
 | 
			
		||||
  snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
 | 
			
		||||
  SetTitle(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetupPage::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cOsdMenu::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     switch (Key) {
 | 
			
		||||
       case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
 | 
			
		||||
                 cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
 | 
			
		||||
                 Setup = data;
 | 
			
		||||
                 Setup.Save();
 | 
			
		||||
                 cDvbApi::SetCaCaps();
 | 
			
		||||
                 break;
 | 
			
		||||
       default: break;
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
  if (data.OSDLanguage != osdLanguage) {
 | 
			
		||||
     int OriginalOSDLanguage = Setup.OSDLanguage;
 | 
			
		||||
     Setup.OSDLanguage = data.OSDLanguage;
 | 
			
		||||
     Set();
 | 
			
		||||
     Display();
 | 
			
		||||
     osdLanguage = data.OSDLanguage;
 | 
			
		||||
     Setup.OSDLanguage = OriginalOSDLanguage;
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										110
									
								
								menuitems.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								menuitems.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
/*
 | 
			
		||||
 * menuitems.h: General purpose menu items
 | 
			
		||||
 *
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: menuitems.h 1.1 2002/05/09 09:41:06 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MENUITEMS_H
 | 
			
		||||
#define __MENUITEMS_H
 | 
			
		||||
 | 
			
		||||
#include "osd.h"
 | 
			
		||||
 | 
			
		||||
class cMenuEditItem : public cOsdItem {
 | 
			
		||||
private:
 | 
			
		||||
  const char *name;
 | 
			
		||||
  const char *value;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditItem(const char *Name);
 | 
			
		||||
  ~cMenuEditItem();
 | 
			
		||||
  void SetValue(const char *Value);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuEditIntItem : public cMenuEditItem {
 | 
			
		||||
protected:
 | 
			
		||||
  int *value;
 | 
			
		||||
  int min, max;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuEditBoolItem : public cMenuEditIntItem {
 | 
			
		||||
protected:
 | 
			
		||||
  const char *falseString, *trueString;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString = NULL, const char *TrueString = NULL);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuEditChrItem : public cMenuEditItem {
 | 
			
		||||
private:
 | 
			
		||||
  char *value;
 | 
			
		||||
  const char *allowed;
 | 
			
		||||
  const char *current;
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditChrItem(const char *Name, char *Value, const char *Allowed);
 | 
			
		||||
  ~cMenuEditChrItem();
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuEditStrItem : public cMenuEditItem {
 | 
			
		||||
private:
 | 
			
		||||
  char *value;
 | 
			
		||||
  int length;
 | 
			
		||||
  const char *allowed;
 | 
			
		||||
  int pos;
 | 
			
		||||
  bool insert, newchar, uppercase;
 | 
			
		||||
  void SetHelpKeys(void);
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
  char Inc(char c, bool Up);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
 | 
			
		||||
  ~cMenuEditStrItem();
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuEditStraItem : public cMenuEditIntItem {
 | 
			
		||||
private:
 | 
			
		||||
  const char * const *strings;
 | 
			
		||||
protected:
 | 
			
		||||
  virtual void Set(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuTextItem : public cOsdItem {
 | 
			
		||||
private:
 | 
			
		||||
  char *text;
 | 
			
		||||
  int x, y, w, h, lines, offset;
 | 
			
		||||
  eDvbColor fgColor, bgColor;
 | 
			
		||||
  eDvbFont font;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuTextItem(const char *Text, int X, int Y, int W, int H = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground, eDvbFont Font = fontOsd);
 | 
			
		||||
  ~cMenuTextItem();
 | 
			
		||||
  int Height(void) { return h; }
 | 
			
		||||
  void Clear(void);
 | 
			
		||||
  virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
 | 
			
		||||
  bool CanScrollUp(void) { return offset > 0; }
 | 
			
		||||
  bool CanScrollDown(void) { return h + offset < lines; }
 | 
			
		||||
  void ScrollUp(bool Page);
 | 
			
		||||
  void ScrollDown(bool Page);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuSetupPage : public cOsdMenu {
 | 
			
		||||
protected:
 | 
			
		||||
  cSetup data;
 | 
			
		||||
  int osdLanguage;
 | 
			
		||||
  void SetupTitle(const char *s);
 | 
			
		||||
  virtual void Set(void) = 0;
 | 
			
		||||
public:
 | 
			
		||||
  cMenuSetupPage(void);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__MENUITEMS_H
 | 
			
		||||
							
								
								
									
										250
									
								
								newplugin
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										250
									
								
								newplugin
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,250 @@
 | 
			
		||||
#!/usr/bin/perl -w
 | 
			
		||||
 | 
			
		||||
# newplugin: Initializing a new plugin source directory
 | 
			
		||||
#
 | 
			
		||||
# Creates a new plugin source directory from which to start implementing
 | 
			
		||||
# a plugin for VDR.
 | 
			
		||||
# See the file PLUGINS.html for detailed instructions on how to
 | 
			
		||||
# write a plugin.
 | 
			
		||||
#
 | 
			
		||||
# Usage: newplugin <name>
 | 
			
		||||
#
 | 
			
		||||
# See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
# how to reach the author.
 | 
			
		||||
#
 | 
			
		||||
# $Id: newplugin 1.1 2002/05/09 15:12:26 kls Exp $
 | 
			
		||||
 | 
			
		||||
$PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
 | 
			
		||||
 | 
			
		||||
die "Please use only lowercase letters and digits in the plugin name\n" if ($PLUGIN_NAME =~ tr/a-z0-9//c);
 | 
			
		||||
 | 
			
		||||
$PLUGIN_CLASS   = ucfirst($PLUGIN_NAME);
 | 
			
		||||
 | 
			
		||||
$PLUGIN_VERSION = "0.0.1";
 | 
			
		||||
$PLUGIN_DESCRIPTION = "Enter description for '$PLUGIN_NAME' plugin";
 | 
			
		||||
$PLUGIN_MAINENTRY = $PLUGIN_CLASS;
 | 
			
		||||
 | 
			
		||||
$PLUGINS_SRC = "PLUGINS/SRC";
 | 
			
		||||
 | 
			
		||||
$README = qq
 | 
			
		||||
{This is a "plugin" for the Video Disk Recorder (VDR).
 | 
			
		||||
 | 
			
		||||
Written by:                  Your Name <email\@host.dom>
 | 
			
		||||
 | 
			
		||||
Project's homepage:          URL
 | 
			
		||||
 | 
			
		||||
Latest version available at: URL
 | 
			
		||||
 | 
			
		||||
See the file COPYING for license information.
 | 
			
		||||
 | 
			
		||||
Description:
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
$HISTORY_TITLE = "VDR Plugin '$PLUGIN_NAME' Revision History";
 | 
			
		||||
$HISTORY_LINE = '-' x length($HISTORY_TITLE);
 | 
			
		||||
$HISTORY_DATE = sprintf("%4d-%02d-%02d", (localtime)[5] + 1900, (localtime)[4] + 1, (localtime)[3]);
 | 
			
		||||
$HISTORY = qq
 | 
			
		||||
{$HISTORY_TITLE
 | 
			
		||||
$HISTORY_LINE
 | 
			
		||||
 | 
			
		||||
$HISTORY_DATE: Version $PLUGIN_VERSION
 | 
			
		||||
 | 
			
		||||
- Initial revision.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
$MAKEFILE = qq
 | 
			
		||||
{#
 | 
			
		||||
# 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 = $PLUGIN_NAME
 | 
			
		||||
 | 
			
		||||
### The version number of this plugin (taken from the main source file):
 | 
			
		||||
 | 
			
		||||
VERSION = `grep 'static const char \\*VERSION *=' \$(PLUGIN).c | awk '{ print \$\$6 }' | sed -e 's/[";]//g'`
 | 
			
		||||
 | 
			
		||||
### The directory environment:
 | 
			
		||||
 | 
			
		||||
DVBDIR = ../../../../DVB/ost/include
 | 
			
		||||
VDRDIR = ../../..
 | 
			
		||||
VDRINC = \$(VDRDIR)/include
 | 
			
		||||
LIBDIR = ../../lib
 | 
			
		||||
TMPDIR = /tmp
 | 
			
		||||
 | 
			
		||||
### The version number of VDR (taken from VDR's "config.h"):
 | 
			
		||||
 | 
			
		||||
VDRVERSION = `grep 'define VDRVERSION ' \$(VDRDIR)/config.h | awk '{ print \$\$3 }' | sed -e 's/"//g'`
 | 
			
		||||
 | 
			
		||||
### The name of the distribution archive:
 | 
			
		||||
 | 
			
		||||
ARCHIVE = vdr-\$(PLUGIN)-\$(VERSION)
 | 
			
		||||
 | 
			
		||||
### Includes and Defines (add further entries here):
 | 
			
		||||
 | 
			
		||||
INCLUDES = -I\$(VDRINC) -I\$(DVBDIR)
 | 
			
		||||
 | 
			
		||||
DEFINES = -DPLUGIN_NAME_I18N='"\$(PLUGIN)"'
 | 
			
		||||
 | 
			
		||||
### The object files (add further files here):
 | 
			
		||||
 | 
			
		||||
OBJS = \$(PLUGIN).o
 | 
			
		||||
 | 
			
		||||
### The C++ compiler and options:
 | 
			
		||||
 | 
			
		||||
CXX      = g++
 | 
			
		||||
CXXFLAGS = -O2 -Wall -Woverloaded-virtual -m486
 | 
			
		||||
 | 
			
		||||
### Implicit rules:
 | 
			
		||||
 | 
			
		||||
%.o: %.c
 | 
			
		||||
	\$(CXX) \$(CXXFLAGS) -c \$(DEFINES) \$(INCLUDES) \$<
 | 
			
		||||
 | 
			
		||||
# Dependencies:
 | 
			
		||||
 | 
			
		||||
MAKEDEP = g++ -MM -MG
 | 
			
		||||
DEPFILE = .dependencies
 | 
			
		||||
\$(DEPFILE): Makefile
 | 
			
		||||
	\@\$(MAKEDEP) \$(DEFINES) \$(INCLUDES) \$(OBJS:%.o=%.c) > \$\@
 | 
			
		||||
 | 
			
		||||
include \$(DEPFILE)
 | 
			
		||||
 | 
			
		||||
### Targets:
 | 
			
		||||
 | 
			
		||||
all: libvdr-\$(PLUGIN).so
 | 
			
		||||
 | 
			
		||||
libvdr-\$(PLUGIN).so: \$(OBJS)
 | 
			
		||||
	\$(CXX) \$(CXXFLAGS) -shared \$(OBJS) -o \$\@
 | 
			
		||||
	\@cp \$\@ \$(LIBDIR)/\$\@.\$(VDRVERSION)
 | 
			
		||||
 | 
			
		||||
package: clean
 | 
			
		||||
	\@-rm -rf \$(TMPDIR)/\$(ARCHIVE)
 | 
			
		||||
	\@mkdir \$(TMPDIR)/\$(ARCHIVE)
 | 
			
		||||
	\@cp -a * \$(TMPDIR)/\$(ARCHIVE)
 | 
			
		||||
	\@tar czf \$(ARCHIVE).tgz -C \$(TMPDIR) \$(ARCHIVE)
 | 
			
		||||
	\@-rm -rf \$(TMPDIR)/\$(ARCHIVE)
 | 
			
		||||
	\@echo Distribution archive created as \$(ARCHIVE).tgz
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	\@-rm -f \$(OBJS) \$(DEPFILE) *.so *.tgz core* *~
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
$MAIN = qq
 | 
			
		||||
{/*
 | 
			
		||||
 * $PLUGIN_NAME.c: A plugin for the Video Disk Recorder
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * \$Id\$
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <vdr/plugin.h>
 | 
			
		||||
 | 
			
		||||
static const char *VERSION        = "$PLUGIN_VERSION";
 | 
			
		||||
static const char *DESCRIPTION    = "$PLUGIN_DESCRIPTION";
 | 
			
		||||
static const char *MAINMENUENTRY  = "$PLUGIN_MAINENTRY";
 | 
			
		||||
 | 
			
		||||
class cPlugin$PLUGIN_CLASS : public cPlugin {
 | 
			
		||||
private:
 | 
			
		||||
  // Add any member variables or functions you may need here.
 | 
			
		||||
public:
 | 
			
		||||
  cPlugin$PLUGIN_CLASS(void);
 | 
			
		||||
  virtual ~cPlugin$PLUGIN_CLASS();
 | 
			
		||||
  virtual const char *Version(void) { return VERSION; }
 | 
			
		||||
  virtual const char *Description(void) { return DESCRIPTION; }
 | 
			
		||||
  virtual const char *CommandLineHelp(void);
 | 
			
		||||
  virtual bool ProcessArgs(int argc, char *argv[]);
 | 
			
		||||
  virtual void Start(void);
 | 
			
		||||
  virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
 | 
			
		||||
  virtual cOsdMenu *MainMenuAction(void);
 | 
			
		||||
  virtual cMenuSetupPage *SetupMenu(void);
 | 
			
		||||
  virtual bool SetupParse(const char *Name, const char *Value);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cPlugin${PLUGIN_CLASS}::cPlugin$PLUGIN_CLASS(void)
 | 
			
		||||
{
 | 
			
		||||
  // Initialize any member varaiables here.
 | 
			
		||||
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
 | 
			
		||||
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cPlugin${PLUGIN_CLASS}::~cPlugin$PLUGIN_CLASS()
 | 
			
		||||
{
 | 
			
		||||
  // Clean up after yourself!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cPlugin${PLUGIN_CLASS}::CommandLineHelp(void)
 | 
			
		||||
{
 | 
			
		||||
  // Return a string that describes all known command line options.
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPlugin${PLUGIN_CLASS}::ProcessArgs(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  // Implement command line argument processing here if applicable.
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPlugin${PLUGIN_CLASS}::Start(void)
 | 
			
		||||
{
 | 
			
		||||
  // Start any background activities the plugin shall perform.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cOsdMenu *cPlugin${PLUGIN_CLASS}::MainMenuAction(void)
 | 
			
		||||
{
 | 
			
		||||
  // Perform the action when selected from the main VDR menu.
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuSetupPage *cPlugin${PLUGIN_CLASS}::SetupMenu(void)
 | 
			
		||||
{
 | 
			
		||||
  // Return a setup menu in case the plugin supports one.
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPlugin${PLUGIN_CLASS}::SetupParse(const char *Name, const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  // Parse your own setup parameters and store their values.
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VDRPLUGINCREATOR(cPlugin$PLUGIN_CLASS); // Don't touch this!
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
$PLUGINDIR = "$PLUGINS_SRC/$PLUGIN_NAME";
 | 
			
		||||
 | 
			
		||||
die "The directory $PLUGINS_SRC doesn't exist!\n" unless (-d "$PLUGINS_SRC");
 | 
			
		||||
die "A plugin named '$PLUGIN_NAME' already exists in $PLUGINS_SRC!\n" if (-e "$PLUGINDIR");
 | 
			
		||||
mkdir("$PLUGINDIR") || die "$!";
 | 
			
		||||
 | 
			
		||||
CreateFile("README", $README);
 | 
			
		||||
CreateFile("HISTORY", $HISTORY);
 | 
			
		||||
CreateFile("Makefile", $MAKEFILE);
 | 
			
		||||
CreateFile("$PLUGIN_NAME.c", $MAIN);
 | 
			
		||||
`cp COPYING "$PLUGINDIR"` if (-e "COPYING");
 | 
			
		||||
 | 
			
		||||
print qq{
 | 
			
		||||
The new plugin source directory has been created in "$PLUGINDIR".
 | 
			
		||||
 | 
			
		||||
The next steps you should perform now are:
 | 
			
		||||
 | 
			
		||||
* edit the file "README" to adjust it to your specific implementation
 | 
			
		||||
* fill in the code skeleton in "$PLUGIN_NAME.c" to implement your plugin function
 | 
			
		||||
* add further source files if necessary
 | 
			
		||||
* adapt the "Makefile" if necessary
 | 
			
		||||
* do "make plugins" from the VDR source directory to build your plugin
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
sub CreateFile
 | 
			
		||||
{
 | 
			
		||||
  my ($Name, $Content) = @_;
 | 
			
		||||
  open(FILE, ">$PLUGINDIR/$Name") || die "$Name:  $!\n";
 | 
			
		||||
  print FILE $Content;
 | 
			
		||||
  close(FILE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								osd.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								osd.c
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: osd.c 1.23 2002/03/29 16:34:03 kls Exp $
 | 
			
		||||
 * $Id: osd.c 1.24 2002/05/01 11:53:24 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "osd.h"
 | 
			
		||||
@@ -105,12 +105,13 @@ cOsdMenu::~cOsdMenu()
 | 
			
		||||
 | 
			
		||||
const char *cOsdMenu::hk(const char *s)
 | 
			
		||||
{
 | 
			
		||||
  static char buffer[32];
 | 
			
		||||
  static char buffer[64];
 | 
			
		||||
  if (s && hasHotkeys) {
 | 
			
		||||
     if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ')
 | 
			
		||||
        digit = 10; // prevents automatic hotkeys - input already has them
 | 
			
		||||
     if (digit < 9) {
 | 
			
		||||
        snprintf(buffer, sizeof(buffer), " %d %s", ++digit, s);
 | 
			
		||||
        digit = -1; // prevents automatic hotkeys - input already has them
 | 
			
		||||
     if (digit >= 0) {
 | 
			
		||||
        digit++;
 | 
			
		||||
        snprintf(buffer, sizeof(buffer), " %c %s", (digit < 10) ? '0' + digit : ' ' , s);
 | 
			
		||||
        s = buffer;
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								osd.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								osd.h
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: osd.h 1.27 2002/03/10 16:18:11 kls Exp $
 | 
			
		||||
 * $Id: osd.h 1.28 2002/05/01 11:17:42 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __OSD_H
 | 
			
		||||
@@ -23,6 +23,7 @@ enum eOSState { osUnknown,
 | 
			
		||||
                osChannels,
 | 
			
		||||
                osTimers,
 | 
			
		||||
                osRecordings,
 | 
			
		||||
                osPlugin,
 | 
			
		||||
                osSetup,
 | 
			
		||||
                osCommands,
 | 
			
		||||
                osRecord,
 | 
			
		||||
@@ -43,6 +44,7 @@ enum eOSState { osUnknown,
 | 
			
		||||
                osUser7,
 | 
			
		||||
                osUser8,
 | 
			
		||||
                osUser9,
 | 
			
		||||
                osUser10,
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
class cOsdItem : public cListObject {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										319
									
								
								plugin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								plugin.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,319 @@
 | 
			
		||||
/*
 | 
			
		||||
 * plugin.c: The VDR plugin interface
 | 
			
		||||
 *
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: plugin.c 1.1 2002/05/09 16:26:56 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "plugin.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#define LIBVDR_PREFIX  "libvdr-"
 | 
			
		||||
#define SO_INDICATOR   ".so."
 | 
			
		||||
 | 
			
		||||
#define MAXPLUGINARGS  1024
 | 
			
		||||
 | 
			
		||||
// --- cPlugin ---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cPlugin::cPlugin(void) 
 | 
			
		||||
{
 | 
			
		||||
  name = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cPlugin::~cPlugin()
 | 
			
		||||
{
 | 
			
		||||
  I18nRegister(NULL, Name());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPlugin::SetName(const char *s)
 | 
			
		||||
{
 | 
			
		||||
  name = s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cPlugin::CommandLineHelp(void)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPlugin::ProcessArgs(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPlugin::Start(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cPlugin::MainMenuEntry(void)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cOsdMenu *cPlugin::MainMenuAction(void)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuSetupPage *cPlugin::SetupMenu(void)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPlugin::SetupParse(const char *Name, const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPlugin::SetupStore(const char *Name, const char *Value)
 | 
			
		||||
{
 | 
			
		||||
  Setup.Store(Name, Value, this->Name());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPlugin::SetupStore(const char *Name, int Value)
 | 
			
		||||
{
 | 
			
		||||
  Setup.Store(Name, Value, this->Name());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPlugin::RegisterI18n(const tI18nPhrase * const Phrases)
 | 
			
		||||
{
 | 
			
		||||
  I18nRegister(Phrases, Name());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cDll ------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cDll::cDll(const char *FileName, const char *Args)
 | 
			
		||||
{
 | 
			
		||||
  fileName = strdup(FileName);
 | 
			
		||||
  args = Args ? strdup(Args) : NULL;
 | 
			
		||||
  handle = NULL;
 | 
			
		||||
  plugin = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cDll::~cDll()
 | 
			
		||||
{
 | 
			
		||||
  delete plugin;
 | 
			
		||||
  if (handle)
 | 
			
		||||
     dlclose(handle);
 | 
			
		||||
  delete args;
 | 
			
		||||
  delete fileName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *SkipQuote(char *s)
 | 
			
		||||
{
 | 
			
		||||
  char c = *s;
 | 
			
		||||
  strcpy(s, s + 1);
 | 
			
		||||
  while (*s && *s != c) {
 | 
			
		||||
        if (*s == '\\')
 | 
			
		||||
           strcpy(s, s + 1);
 | 
			
		||||
        if (*s)
 | 
			
		||||
           s++;
 | 
			
		||||
        }
 | 
			
		||||
  if (*s) {
 | 
			
		||||
     strcpy(s, s + 1);
 | 
			
		||||
     return s;
 | 
			
		||||
     }
 | 
			
		||||
  esyslog(LOG_ERR, "ERROR: missing closing %c", c);
 | 
			
		||||
  fprintf(stderr, "vdr: missing closing %c\n", c);
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cDll::Load(bool Log)
 | 
			
		||||
{
 | 
			
		||||
  if (Log)
 | 
			
		||||
     isyslog(LOG_INFO, "loading plugin: %s", fileName);
 | 
			
		||||
  if (handle) {
 | 
			
		||||
     esyslog(LOG_ERR, "attempt to load plugin '%s' twice!", fileName);
 | 
			
		||||
     return false;
 | 
			
		||||
     }
 | 
			
		||||
  handle = dlopen(fileName, RTLD_NOW);
 | 
			
		||||
  const char *error = dlerror();
 | 
			
		||||
  if (!error) {
 | 
			
		||||
     void *(*creator)(void);
 | 
			
		||||
     (void *)creator = dlsym(handle, "VDRPluginCreator");
 | 
			
		||||
     if (!(error = dlerror()))
 | 
			
		||||
        plugin = (cPlugin *)creator();
 | 
			
		||||
     }
 | 
			
		||||
  if (!error) {
 | 
			
		||||
     if (plugin && args) {
 | 
			
		||||
        int argc = 0;
 | 
			
		||||
        char *argv[MAXPLUGINARGS];
 | 
			
		||||
        char *p = args;
 | 
			
		||||
        char *q = NULL;
 | 
			
		||||
        bool done = false;
 | 
			
		||||
        while (!done) {
 | 
			
		||||
              if (!q)
 | 
			
		||||
                 q = p;
 | 
			
		||||
              switch (*p) {
 | 
			
		||||
                case '\\': strcpy(p, p + 1);
 | 
			
		||||
                           if (*p)
 | 
			
		||||
                              p++;
 | 
			
		||||
                           else {
 | 
			
		||||
                              esyslog(LOG_ERR, "ERROR: missing character after \\");
 | 
			
		||||
                              fprintf(stderr, "vdr: missing character after \\\n");
 | 
			
		||||
                              return false;
 | 
			
		||||
                              }
 | 
			
		||||
                           break;
 | 
			
		||||
                case '"':
 | 
			
		||||
                case '\'': if ((p = SkipQuote(p)) == NULL)
 | 
			
		||||
                              return false;
 | 
			
		||||
                           break;
 | 
			
		||||
                default: if (!*p || isspace(*p)) {
 | 
			
		||||
                            done = !*p;
 | 
			
		||||
                            *p = 0;
 | 
			
		||||
                            if (q) {
 | 
			
		||||
                               if (argc < MAXPLUGINARGS - 1)
 | 
			
		||||
                                  argv[argc++] = q;
 | 
			
		||||
                               else {
 | 
			
		||||
                                  esyslog(LOG_ERR, "ERROR: plugin argument list too long");
 | 
			
		||||
                                  fprintf(stderr, "vdr: plugin argument list too long\n");
 | 
			
		||||
                                  return false;
 | 
			
		||||
                                  }
 | 
			
		||||
                               q = NULL;
 | 
			
		||||
                               }
 | 
			
		||||
                            }
 | 
			
		||||
                         if (!done)
 | 
			
		||||
                            p++;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
        argv[argc] = NULL;
 | 
			
		||||
        if (argc)
 | 
			
		||||
           plugin->SetName(argv[0]);
 | 
			
		||||
        optind = 0; // to reset the getopt() data
 | 
			
		||||
        return !argc || plugin->ProcessArgs(argc, argv);
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  else {
 | 
			
		||||
     esyslog(LOG_ERR, "ERROR: %s", error);
 | 
			
		||||
     fprintf(stderr, "vdr: %s\n", error);
 | 
			
		||||
     }
 | 
			
		||||
  return !error && plugin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cPluginManager --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cPluginManager *cPluginManager::pluginManager = NULL;
 | 
			
		||||
 | 
			
		||||
cPluginManager::cPluginManager(const char *Directory)
 | 
			
		||||
{
 | 
			
		||||
  directory = NULL;
 | 
			
		||||
  if (pluginManager) {
 | 
			
		||||
     fprintf(stderr, "vdr: attempt to create more than one plugin manager - exiting!\n");
 | 
			
		||||
     exit(2);
 | 
			
		||||
     }
 | 
			
		||||
  SetDirectory(Directory);
 | 
			
		||||
  pluginManager = this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cPluginManager::~cPluginManager()
 | 
			
		||||
{
 | 
			
		||||
  Shutdown();
 | 
			
		||||
  delete directory;
 | 
			
		||||
  if (pluginManager == this)
 | 
			
		||||
     pluginManager = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPluginManager::SetDirectory(const char *Directory)
 | 
			
		||||
{
 | 
			
		||||
  delete directory;
 | 
			
		||||
  directory = Directory ? strdup(Directory) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPluginManager::AddPlugin(const char *Args)
 | 
			
		||||
{
 | 
			
		||||
  if (strcmp(Args, "*") == 0) {
 | 
			
		||||
     DIR *d = opendir(directory);
 | 
			
		||||
     if (d) {
 | 
			
		||||
        struct dirent *e;
 | 
			
		||||
        while ((e = readdir(d)) != NULL) {
 | 
			
		||||
              if (strstr(e->d_name, LIBVDR_PREFIX) == e->d_name) {
 | 
			
		||||
                 char *p = strstr(e->d_name, SO_INDICATOR);
 | 
			
		||||
                 if (p) {
 | 
			
		||||
                    *p = 0;
 | 
			
		||||
                    p += strlen(SO_INDICATOR);
 | 
			
		||||
                    if (strcmp(p, VDRVERSION) == 0) {
 | 
			
		||||
                       char *name = e->d_name + strlen(LIBVDR_PREFIX);
 | 
			
		||||
                       if (strcmp(name, "*") != 0) { // let's not get into a loop!
 | 
			
		||||
                          AddPlugin(e->d_name + strlen(LIBVDR_PREFIX));
 | 
			
		||||
                          }
 | 
			
		||||
                       }
 | 
			
		||||
                    }
 | 
			
		||||
                 }
 | 
			
		||||
              }
 | 
			
		||||
        closedir(d);
 | 
			
		||||
        }
 | 
			
		||||
     return;
 | 
			
		||||
     }
 | 
			
		||||
  char *s = strdup(Args);
 | 
			
		||||
  char *p = strchr(s, ' ');
 | 
			
		||||
  if (p)
 | 
			
		||||
     *p = 0;
 | 
			
		||||
  char *buffer = NULL;
 | 
			
		||||
  asprintf(&buffer, "%s/%s%s%s%s", directory, LIBVDR_PREFIX, s, SO_INDICATOR, VDRVERSION);
 | 
			
		||||
  dlls.Add(new cDll(buffer, Args));
 | 
			
		||||
  delete buffer;
 | 
			
		||||
  delete s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPluginManager::LoadPlugins(bool Log)
 | 
			
		||||
{
 | 
			
		||||
  for (cDll *dll = dlls.First(); dll; dll = dlls.Next(dll)) {
 | 
			
		||||
      if (!dll->Load(Log))
 | 
			
		||||
         return false;
 | 
			
		||||
      }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPluginManager::StartPlugins(void)
 | 
			
		||||
{
 | 
			
		||||
  for (cDll *dll = dlls.First(); dll; dll = dlls.Next(dll)) {
 | 
			
		||||
      cPlugin *p = dll->Plugin();
 | 
			
		||||
      if (p) {
 | 
			
		||||
         int Language = Setup.OSDLanguage;
 | 
			
		||||
         Setup.OSDLanguage = 0; // the i18n texts are only available _after_ Start()
 | 
			
		||||
         isyslog(LOG_INFO, "starting plugin: %s (%s): %s", p->Name(), p->Version(), p->Description());
 | 
			
		||||
         Setup.OSDLanguage = Language;
 | 
			
		||||
         dll->Plugin()->Start();
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPluginManager::HasPlugins(void)
 | 
			
		||||
{
 | 
			
		||||
  return pluginManager && pluginManager->dlls.Count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cPlugin *cPluginManager::GetPlugin(int Index)
 | 
			
		||||
{
 | 
			
		||||
  cDll *dll = pluginManager ? pluginManager->dlls.Get(Index) : NULL;
 | 
			
		||||
  return dll ? dll->Plugin() : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cPlugin *cPluginManager::GetPlugin(const char *Name)
 | 
			
		||||
{
 | 
			
		||||
  if (pluginManager) {
 | 
			
		||||
     for (cDll *dll = pluginManager->dlls.First(); dll; dll = pluginManager->dlls.Next(dll)) {
 | 
			
		||||
         cPlugin *p = dll->Plugin();
 | 
			
		||||
         if (p && strcmp(p->Name(), Name) == 0)
 | 
			
		||||
            return p;
 | 
			
		||||
         }
 | 
			
		||||
     }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPluginManager::Shutdown(bool Log)
 | 
			
		||||
{
 | 
			
		||||
  cDll *dll;
 | 
			
		||||
  while ((dll = dlls.Last()) != NULL) {
 | 
			
		||||
        if (Log) {
 | 
			
		||||
           cPlugin *p = dll->Plugin();
 | 
			
		||||
           if (p)
 | 
			
		||||
              isyslog(LOG_INFO, "stopping plugin: %s", p->Name());
 | 
			
		||||
           }
 | 
			
		||||
        dlls.Del(dll);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								plugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								plugin.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
 * plugin.h: The VDR plugin interface
 | 
			
		||||
 *
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: plugin.h 1.1 2002/05/09 10:16:09 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __PLUGIN_H
 | 
			
		||||
#define __PLUGIN_H
 | 
			
		||||
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
#include "menuitems.h"
 | 
			
		||||
#include "osd.h"
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
 | 
			
		||||
#define VDRPLUGINCREATOR(PluginClass) extern "C" void *VDRPluginCreator(void) { return new PluginClass; }
 | 
			
		||||
 | 
			
		||||
class cPlugin {
 | 
			
		||||
  friend class cDll;
 | 
			
		||||
private:
 | 
			
		||||
  const char *name;
 | 
			
		||||
  void SetName(const char *s);
 | 
			
		||||
public:
 | 
			
		||||
  cPlugin(void);
 | 
			
		||||
  virtual ~cPlugin();
 | 
			
		||||
 | 
			
		||||
  const char *Name(void) { return name; }
 | 
			
		||||
  virtual const char *Version(void) = 0;
 | 
			
		||||
  virtual const char *Description(void) = 0;
 | 
			
		||||
  virtual const char *CommandLineHelp(void);
 | 
			
		||||
 | 
			
		||||
  virtual bool ProcessArgs(int argc, char *argv[]);
 | 
			
		||||
  virtual void Start(void);
 | 
			
		||||
 | 
			
		||||
  virtual const char *MainMenuEntry(void);
 | 
			
		||||
  virtual cOsdMenu *MainMenuAction(void);
 | 
			
		||||
 | 
			
		||||
  virtual cMenuSetupPage *SetupMenu(void);
 | 
			
		||||
  virtual bool SetupParse(const char *Name, const char *Value);
 | 
			
		||||
  void SetupStore(const char *Name, const char *Value = NULL);
 | 
			
		||||
  void SetupStore(const char *Name, int Value);
 | 
			
		||||
 | 
			
		||||
  void RegisterI18n(const tI18nPhrase * const Phrases);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cDll : public cListObject {
 | 
			
		||||
private:
 | 
			
		||||
  char *fileName;
 | 
			
		||||
  char *args;
 | 
			
		||||
  void *handle;
 | 
			
		||||
  cPlugin *plugin;
 | 
			
		||||
public:
 | 
			
		||||
  cDll(const char *FileName, const char *Args);
 | 
			
		||||
  virtual ~cDll();
 | 
			
		||||
  bool Load(bool Log = false);
 | 
			
		||||
  cPlugin *Plugin(void) { return plugin; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cDlls : public cList<cDll> {};
 | 
			
		||||
 | 
			
		||||
class cPluginManager {
 | 
			
		||||
private:
 | 
			
		||||
  static cPluginManager *pluginManager;
 | 
			
		||||
  char *directory;
 | 
			
		||||
  cDlls dlls;
 | 
			
		||||
public:
 | 
			
		||||
  cPluginManager(const char *Directory);
 | 
			
		||||
  virtual ~cPluginManager();
 | 
			
		||||
  void SetDirectory(const char *Directory);
 | 
			
		||||
  void AddPlugin(const char *Args);
 | 
			
		||||
  bool LoadPlugins(bool Log = false);
 | 
			
		||||
  void StartPlugins(void);
 | 
			
		||||
  static bool HasPlugins(void);
 | 
			
		||||
  static cPlugin *GetPlugin(int Index);
 | 
			
		||||
  static cPlugin *GetPlugin(const char *Name);
 | 
			
		||||
  void Shutdown(bool Log = false);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__PLUGIN_H
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: recording.c 1.60 2002/04/01 10:51:23 kls Exp $
 | 
			
		||||
 * $Id: recording.c 1.61 2002/04/21 14:02:55 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "recording.h"
 | 
			
		||||
@@ -222,7 +222,6 @@ static char *ExchangeChars(char *s, bool ToFileSystem)
 | 
			
		||||
                  case '+':
 | 
			
		||||
                  case ',':
 | 
			
		||||
                  case '-':
 | 
			
		||||
                  case '.':
 | 
			
		||||
                  case ';':
 | 
			
		||||
                  case '=':
 | 
			
		||||
                  case '0' ... '9':
 | 
			
		||||
@@ -237,7 +236,8 @@ static char *ExchangeChars(char *s, bool ToFileSystem)
 | 
			
		||||
                  case ' ': *p = '_'; break;
 | 
			
		||||
                  case '~': *p = '/'; break;
 | 
			
		||||
                  // characters that have to be encoded:
 | 
			
		||||
                  default: {
 | 
			
		||||
                  default:
 | 
			
		||||
                    if (*p != '.' || !*(p + 1) || *(p + 1) == '~') { // Windows can't handle '.' at the end of directory names
 | 
			
		||||
                       int l = p - s;
 | 
			
		||||
                       s = (char *)realloc(s, strlen(s) + 10);
 | 
			
		||||
                       p = s + l;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								remote.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								remote.h
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: remote.h 1.15 2001/07/22 14:42:59 kls Exp $
 | 
			
		||||
 * $Id: remote.h 1.16 2002/05/09 11:43:04 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __REMOTE_H
 | 
			
		||||
@@ -95,7 +95,7 @@ public:
 | 
			
		||||
 | 
			
		||||
#elif !defined REMOTE_NONE
 | 
			
		||||
 | 
			
		||||
#error Please define a remote control mode!
 | 
			
		||||
// #error Please define a remote control mode!
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								ringbuffer.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								ringbuffer.c
									
									
									
									
									
								
							@@ -7,7 +7,7 @@
 | 
			
		||||
 * Parts of this file were inspired by the 'ringbuffy.c' from the
 | 
			
		||||
 * LinuxDVB driver (see linuxtv.org).
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: ringbuffer.c 1.5 2001/11/03 09:50:46 kls Exp $
 | 
			
		||||
 * $Id: ringbuffer.c 1.6 2002/04/18 15:46:36 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ringbuffer.h"
 | 
			
		||||
@@ -154,7 +154,6 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
 | 
			
		||||
     Lock();
 | 
			
		||||
     int rest = Size() - head;
 | 
			
		||||
     int diff = tail - head;
 | 
			
		||||
     Unlock();
 | 
			
		||||
     int free = (diff > 0) ? diff - 1 : Size() + diff - 1;
 | 
			
		||||
     if (statistics) {
 | 
			
		||||
        int fill = Size() - free - 1 + Count;
 | 
			
		||||
@@ -167,22 +166,25 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
 | 
			
		||||
              dsyslog(LOG_INFO, "buffer usage: %d%%", percent);
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     if (free <= 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
     if (free < Count)
 | 
			
		||||
        Count = free;
 | 
			
		||||
     if (Count > maxFill)
 | 
			
		||||
        maxFill = Count;
 | 
			
		||||
     if (Count >= rest) {
 | 
			
		||||
        memcpy(buffer + head, Data, rest);
 | 
			
		||||
        if (Count - rest)
 | 
			
		||||
           memcpy(buffer, Data + rest, Count - rest);
 | 
			
		||||
        head = Count - rest;
 | 
			
		||||
        }
 | 
			
		||||
     else {
 | 
			
		||||
        memcpy(buffer + head, Data, Count);
 | 
			
		||||
        head += Count;
 | 
			
		||||
     if (free > 0) {
 | 
			
		||||
        if (free < Count)
 | 
			
		||||
           Count = free;
 | 
			
		||||
        if (Count > maxFill)
 | 
			
		||||
           maxFill = Count;
 | 
			
		||||
        if (Count >= rest) {
 | 
			
		||||
           memcpy(buffer + head, Data, rest);
 | 
			
		||||
           if (Count - rest)
 | 
			
		||||
              memcpy(buffer, Data + rest, Count - rest);
 | 
			
		||||
           head = Count - rest;
 | 
			
		||||
           }
 | 
			
		||||
        else {
 | 
			
		||||
           memcpy(buffer + head, Data, Count);
 | 
			
		||||
           head += Count;
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        Count = 0;
 | 
			
		||||
     Unlock();
 | 
			
		||||
     }
 | 
			
		||||
  return Count;
 | 
			
		||||
}
 | 
			
		||||
@@ -193,22 +195,24 @@ int cRingBufferLinear::Get(uchar *Data, int Count)
 | 
			
		||||
     Lock();
 | 
			
		||||
     int rest = Size() - tail;
 | 
			
		||||
     int diff = head - tail;
 | 
			
		||||
     Unlock();
 | 
			
		||||
     int cont = (diff >= 0) ? diff : Size() + diff;
 | 
			
		||||
     if (rest <= 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
     if (cont < Count)
 | 
			
		||||
        Count = cont;
 | 
			
		||||
     if (Count >= rest) {
 | 
			
		||||
        memcpy(Data, buffer + tail, rest);
 | 
			
		||||
        if (Count - rest)
 | 
			
		||||
           memcpy(Data + rest, buffer, Count - rest);
 | 
			
		||||
        tail = Count - rest;
 | 
			
		||||
        }
 | 
			
		||||
     else {
 | 
			
		||||
        memcpy(Data, buffer + tail, Count);
 | 
			
		||||
        tail += Count;
 | 
			
		||||
     if (rest > 0) {
 | 
			
		||||
        if (cont < Count)
 | 
			
		||||
           Count = cont;
 | 
			
		||||
        if (Count >= rest) {
 | 
			
		||||
           memcpy(Data, buffer + tail, rest);
 | 
			
		||||
           if (Count - rest)
 | 
			
		||||
              memcpy(Data + rest, buffer, Count - rest);
 | 
			
		||||
           tail = Count - rest;
 | 
			
		||||
           }
 | 
			
		||||
        else {
 | 
			
		||||
           memcpy(Data, buffer + tail, Count);
 | 
			
		||||
           tail += Count;
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        Count = 0;
 | 
			
		||||
     Unlock();
 | 
			
		||||
     }
 | 
			
		||||
  return Count;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								tools.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tools.c
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: tools.c 1.62 2002/03/31 20:51:06 kls Exp $
 | 
			
		||||
 * $Id: tools.c 1.63 2002/05/01 16:20:30 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
@@ -251,10 +251,10 @@ int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
 | 
			
		||||
  int Free = 0;
 | 
			
		||||
  struct statfs statFs;
 | 
			
		||||
  if (statfs(Directory, &statFs) == 0) {
 | 
			
		||||
     int blocksPerMeg = 1024 * 1024 / statFs.f_bsize;
 | 
			
		||||
     double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize;
 | 
			
		||||
     if (UsedMB)
 | 
			
		||||
        *UsedMB = (statFs.f_blocks - statFs.f_bfree) / blocksPerMeg;
 | 
			
		||||
     Free = statFs.f_bavail / blocksPerMeg;
 | 
			
		||||
        *UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg);
 | 
			
		||||
     Free = int(statFs.f_bavail / blocksPerMeg);
 | 
			
		||||
     }
 | 
			
		||||
  else
 | 
			
		||||
     LOG_ERROR_STR(Directory);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								vdr.1
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								vdr.1
									
									
									
									
									
								
							@@ -8,9 +8,9 @@
 | 
			
		||||
.\" License as specified in the file COPYING that comes with the
 | 
			
		||||
.\" vdr distribution.
 | 
			
		||||
.\"
 | 
			
		||||
.\" $Id: vdr.1 1.3 2002/04/07 13:11:43 kls Exp $
 | 
			
		||||
.\" $Id: vdr.1 1.4 2002/05/09 16:04:17 kls Exp $
 | 
			
		||||
.\"
 | 
			
		||||
.TH vdr 1 "7 Apr 2002" "1.0.0" "Video Disk Recorder"
 | 
			
		||||
.TH vdr 1 "9 May 2002" "1.1.0" "Video Disk Recorder"
 | 
			
		||||
.SH NAME
 | 
			
		||||
vdr - the Video Disk Recorder
 | 
			
		||||
.SH SYNOPSIS
 | 
			
		||||
@@ -68,6 +68,11 @@ Set logging to \fIlevel\fR.
 | 
			
		||||
\fB2\fR\ =\ errors and info, \fB3\fR\ =\ errors, info and debug.
 | 
			
		||||
The default logging level is \fB3\fR.
 | 
			
		||||
.TP
 | 
			
		||||
.BI -L\  dir ,\ --lib= dir
 | 
			
		||||
Search for plugins in directory \fIdir\fR (default is ./PLUGINS/lib).
 | 
			
		||||
There can be several \fB-L\fR options with different \fIdir\fR values.
 | 
			
		||||
Each of them will apply to the \fB-P\fR options following it.
 | 
			
		||||
.TP
 | 
			
		||||
.B -m, --mute
 | 
			
		||||
Mute audio of the primary DVB device at startup.
 | 
			
		||||
.TP
 | 
			
		||||
@@ -77,6 +82,18 @@ The default SVDRP port is \fB2001\fR.
 | 
			
		||||
You need to edit the file \fIsvdrphosts.conf\fR in order to enable
 | 
			
		||||
access to the SVDRP port.
 | 
			
		||||
.TP
 | 
			
		||||
.BI -P\  options ,\ --plugin= options
 | 
			
		||||
Load a plugin, defined by the given \fIoptions\fR.
 | 
			
		||||
The first word in \fIoptions\fR must be the name of an existing \fBvdr\fR
 | 
			
		||||
plugin, optionally followed by a blank separated list of command line options
 | 
			
		||||
for that plugin. If \fIoptions\fR contains any blanks, you need to enclose it
 | 
			
		||||
in quotes, like for example
 | 
			
		||||
 | 
			
		||||
\fBvdr -P "abc -a -b xyz"\fR
 | 
			
		||||
 | 
			
		||||
which would load a plugin named \fBabc\fR, giving it the command line options
 | 
			
		||||
\fB-a\ -b\ xyz\fR.
 | 
			
		||||
.TP
 | 
			
		||||
.BI -r\  cmd ,\ --record= cmd
 | 
			
		||||
Call \fIcmd\fR before and after a recording.
 | 
			
		||||
.TP
 | 
			
		||||
@@ -104,6 +121,9 @@ Successful program execution.
 | 
			
		||||
.B 1
 | 
			
		||||
An error has been detected which requires the DVB driver and \fBvdr\fR
 | 
			
		||||
to be re-loaded.
 | 
			
		||||
.TP
 | 
			
		||||
.B 2
 | 
			
		||||
An non-recoverable error has been detected, \fBvdr\fR has given up.
 | 
			
		||||
.SH FILES
 | 
			
		||||
.TP
 | 
			
		||||
.I channels.conf
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								vdr.c
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								vdr.c
									
									
									
									
									
								
							@@ -22,7 +22,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * The project's page is at http://www.cadsoft.de/people/kls/vdr
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: vdr.c 1.102 2002/03/29 10:09:20 kls Exp $
 | 
			
		||||
 * $Id: vdr.c 1.104 2002/05/05 10:34:31 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
#include "interface.h"
 | 
			
		||||
#include "menu.h"
 | 
			
		||||
#include "plugin.h"
 | 
			
		||||
#include "recording.h"
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
#include "videodir.h"
 | 
			
		||||
@@ -79,14 +80,18 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
#define DEFAULTSVDRPPORT 2001
 | 
			
		||||
#define DEFAULTWATCHDOG     0 // seconds
 | 
			
		||||
#define DEFAULTPLUGINDIR "./PLUGINS/lib"
 | 
			
		||||
 | 
			
		||||
  int SVDRPport = DEFAULTSVDRPPORT;
 | 
			
		||||
  const char *ConfigDirectory = NULL;
 | 
			
		||||
  bool DisplayHelp = false;
 | 
			
		||||
  bool DisplayVersion = false;
 | 
			
		||||
  bool DaemonMode = false;
 | 
			
		||||
  bool MuteAudio = false;
 | 
			
		||||
  int WatchdogTimeout = DEFAULTWATCHDOG;
 | 
			
		||||
  const char *Terminal = NULL;
 | 
			
		||||
  const char *Shutdown = NULL;
 | 
			
		||||
  cPluginManager PluginManager(DEFAULTPLUGINDIR);
 | 
			
		||||
 | 
			
		||||
  static struct option long_options[] = {
 | 
			
		||||
      { "audio",    required_argument, NULL, 'a' },
 | 
			
		||||
@@ -95,8 +100,10 @@ int main(int argc, char *argv[])
 | 
			
		||||
      { "device",   required_argument, NULL, 'D' },
 | 
			
		||||
      { "epgfile",  required_argument, NULL, 'E' },
 | 
			
		||||
      { "help",     no_argument,       NULL, 'h' },
 | 
			
		||||
      { "lib",      required_argument, NULL, 'L' },
 | 
			
		||||
      { "log",      required_argument, NULL, 'l' },
 | 
			
		||||
      { "mute",     no_argument,       NULL, 'm' },
 | 
			
		||||
      { "plugin",   required_argument, NULL, 'P' },
 | 
			
		||||
      { "port",     required_argument, NULL, 'p' },
 | 
			
		||||
      { "record",   required_argument, NULL, 'r' },
 | 
			
		||||
      { "shutdown", required_argument, NULL, 's' },
 | 
			
		||||
@@ -108,8 +115,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  int c;
 | 
			
		||||
  int option_index = 0;
 | 
			
		||||
  while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:mp:r:s:t:v:Vw:", long_options, &option_index)) != -1) {
 | 
			
		||||
  while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:L:mp:P:r:s:t:v:Vw:", long_options, NULL)) != -1) {
 | 
			
		||||
        switch (c) {
 | 
			
		||||
          case 'a': cDvbApi::SetAudioCommand(optarg);
 | 
			
		||||
                    break;
 | 
			
		||||
@@ -128,40 +134,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'E': cSIProcessor::SetEpgDataFileName(*optarg != '-' ? optarg : NULL);
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'h': printf("Usage: vdr [OPTION]\n\n"           // for easier orientation, this is column 80|
 | 
			
		||||
                           "  -a CMD,   --audio=CMD    send Dolby Digital audio to stdin of command CMD\n"
 | 
			
		||||
                           "  -c DIR,   --config=DIR   read config files from DIR (default is to read them\n"
 | 
			
		||||
                           "                           from the video directory)\n"
 | 
			
		||||
                           "  -d,       --daemon       run in daemon mode\n"
 | 
			
		||||
                           "  -D NUM,   --device=NUM   use only the given DVB device (NUM = 0, 1, 2...)\n"
 | 
			
		||||
                           "                           there may be several -D options (default: all DVB\n"
 | 
			
		||||
                           "                           devices will be used)\n"
 | 
			
		||||
                           "  -E FILE   --epgfile=FILE write the EPG data into the given FILE (default is\n"
 | 
			
		||||
                           "                           %s); use '-E-' to disable this\n"
 | 
			
		||||
                           "                           if FILE is a directory, the default EPG file will be\n"
 | 
			
		||||
                           "                           created in that directory\n"
 | 
			
		||||
                           "  -h,       --help         print this help and exit\n"
 | 
			
		||||
                           "  -l LEVEL, --log=LEVEL    set log level (default: 3)\n"
 | 
			
		||||
                           "                           0 = no logging, 1 = errors only,\n"
 | 
			
		||||
                           "                           2 = errors and info, 3 = errors, info and debug\n"
 | 
			
		||||
                           "  -m,       --mute         mute audio of the primary DVB device at startup\n"
 | 
			
		||||
                           "  -p PORT,  --port=PORT    use PORT for SVDRP (default: %d)\n"
 | 
			
		||||
                           "                           0 turns off SVDRP\n"
 | 
			
		||||
                           "  -r CMD,   --record=CMD   call CMD before and after a recording\n"
 | 
			
		||||
                           "  -s CMD,   --shutdown=CMD call CMD to shutdown the computer\n"
 | 
			
		||||
                           "  -t TTY,   --terminal=TTY controlling tty\n"
 | 
			
		||||
                           "  -V,       --version      print version information and exit\n"
 | 
			
		||||
                           "  -v DIR,   --video=DIR    use DIR as video directory (default: %s)\n"
 | 
			
		||||
                           "  -w SEC,   --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
 | 
			
		||||
                           "                           seconds (default: %d); '0' disables the watchdog\n"
 | 
			
		||||
                           "\n"
 | 
			
		||||
                           "Report bugs to <vdr-bugs@cadsoft.de>\n",
 | 
			
		||||
                           cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'",
 | 
			
		||||
                           DEFAULTSVDRPPORT,
 | 
			
		||||
                           VideoDirectory,
 | 
			
		||||
                           DEFAULTWATCHDOG
 | 
			
		||||
                           );
 | 
			
		||||
                    return 0;
 | 
			
		||||
          case 'h': DisplayHelp = true;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'l': if (isnumber(optarg)) {
 | 
			
		||||
                       int l = atoi(optarg);
 | 
			
		||||
@@ -173,6 +146,8 @@ int main(int argc, char *argv[])
 | 
			
		||||
                    fprintf(stderr, "vdr: invalid log level: %s\n", optarg);
 | 
			
		||||
                    return 2;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'L': PluginManager.SetDirectory(optarg);
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'm': MuteAudio = true;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'p': if (isnumber(optarg))
 | 
			
		||||
@@ -182,14 +157,15 @@ int main(int argc, char *argv[])
 | 
			
		||||
                       return 2;
 | 
			
		||||
                       }
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'P': PluginManager.AddPlugin(optarg);
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'r': cRecordingUserCommand::SetCommand(optarg);
 | 
			
		||||
                    break;
 | 
			
		||||
          case 's': Shutdown = optarg;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 't': Terminal = optarg;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'V': printf("vdr, version %s\n", VDRVERSION);
 | 
			
		||||
                    return 0;
 | 
			
		||||
          case 'V': DisplayVersion = true;
 | 
			
		||||
                    break;
 | 
			
		||||
          case 'v': VideoDirectory = optarg;
 | 
			
		||||
                    while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
 | 
			
		||||
@@ -209,6 +185,71 @@ int main(int argc, char *argv[])
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  // Help and version info:
 | 
			
		||||
 | 
			
		||||
  if (DisplayHelp || DisplayVersion) {
 | 
			
		||||
     if (!PluginManager.HasPlugins())
 | 
			
		||||
        PluginManager.AddPlugin("*"); // adds all available plugins
 | 
			
		||||
     PluginManager.LoadPlugins();
 | 
			
		||||
     if (DisplayHelp) {
 | 
			
		||||
        printf("Usage: vdr [OPTIONS]\n\n"          // for easier orientation, this is column 80|
 | 
			
		||||
               "  -a CMD,   --audio=CMD    send Dolby Digital audio to stdin of command CMD\n"
 | 
			
		||||
               "  -c DIR,   --config=DIR   read config files from DIR (default is to read them\n"
 | 
			
		||||
               "                           from the video directory)\n"
 | 
			
		||||
               "  -d,       --daemon       run in daemon mode\n"
 | 
			
		||||
               "  -D NUM,   --device=NUM   use only the given DVB device (NUM = 0, 1, 2...)\n"
 | 
			
		||||
               "                           there may be several -D options (default: all DVB\n"
 | 
			
		||||
               "                           devices will be used)\n"
 | 
			
		||||
               "  -E FILE   --epgfile=FILE write the EPG data into the given FILE (default is\n"
 | 
			
		||||
               "                           %s); use '-E-' to disable this\n"
 | 
			
		||||
               "                           if FILE is a directory, the default EPG file will be\n"
 | 
			
		||||
               "                           created in that directory\n"
 | 
			
		||||
               "  -h,       --help         print this help and exit\n"
 | 
			
		||||
               "  -l LEVEL, --log=LEVEL    set log level (default: 3)\n"
 | 
			
		||||
               "                           0 = no logging, 1 = errors only,\n"
 | 
			
		||||
               "                           2 = errors and info, 3 = errors, info and debug\n"
 | 
			
		||||
               "  -L DIR,   --lib=DIR      search for plugins in DIR (default is %s)\n"
 | 
			
		||||
               "  -m,       --mute         mute audio of the primary DVB device at startup\n"
 | 
			
		||||
               "  -p PORT,  --port=PORT    use PORT for SVDRP (default: %d)\n"
 | 
			
		||||
               "                           0 turns off SVDRP\n"
 | 
			
		||||
               "  -P OPT,   --plugin=OPT   load a plugin defined by the given options\n"
 | 
			
		||||
               "  -r CMD,   --record=CMD   call CMD before and after a recording\n"
 | 
			
		||||
               "  -s CMD,   --shutdown=CMD call CMD to shutdown the computer\n"
 | 
			
		||||
               "  -t TTY,   --terminal=TTY controlling tty\n"
 | 
			
		||||
               "  -v DIR,   --video=DIR    use DIR as video directory (default: %s)\n"
 | 
			
		||||
               "  -V,       --version      print version information and exit\n"
 | 
			
		||||
               "  -w SEC,   --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
 | 
			
		||||
               "                           seconds (default: %d); '0' disables the watchdog\n"
 | 
			
		||||
               "\n",
 | 
			
		||||
               cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'",
 | 
			
		||||
               DEFAULTPLUGINDIR,
 | 
			
		||||
               DEFAULTSVDRPPORT,
 | 
			
		||||
               VideoDirectory,
 | 
			
		||||
               DEFAULTWATCHDOG
 | 
			
		||||
               );
 | 
			
		||||
        }
 | 
			
		||||
     if (DisplayVersion)
 | 
			
		||||
        printf("vdr (%s) - The Video Disk Recorder\n", VDRVERSION);
 | 
			
		||||
     if (PluginManager.HasPlugins()) {
 | 
			
		||||
        if (DisplayHelp)
 | 
			
		||||
           printf("Plugins: vdr -P\"name [OPTIONS]\"\n\n");
 | 
			
		||||
        for (int i = 0; ; i++) {
 | 
			
		||||
            cPlugin *p = PluginManager.GetPlugin(i);
 | 
			
		||||
            if (p) {
 | 
			
		||||
               const char *help = p->CommandLineHelp();
 | 
			
		||||
               printf("%s (%s) - %s\n", p->Name(), p->Version(), p->Description());
 | 
			
		||||
               if (DisplayHelp && help) {
 | 
			
		||||
                  printf("\n");
 | 
			
		||||
                  puts(help);
 | 
			
		||||
                  }
 | 
			
		||||
               }
 | 
			
		||||
            else
 | 
			
		||||
               break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
     return 0;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
  // Log file:
 | 
			
		||||
 | 
			
		||||
  if (SysLogLevel > 0)
 | 
			
		||||
@@ -250,6 +291,11 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
  isyslog(LOG_INFO, "VDR version %s started", VDRVERSION);
 | 
			
		||||
 | 
			
		||||
  // Load plugins:
 | 
			
		||||
 | 
			
		||||
  if (!PluginManager.LoadPlugins(true))
 | 
			
		||||
     return 2;
 | 
			
		||||
 | 
			
		||||
  // Configuration data:
 | 
			
		||||
 | 
			
		||||
  if (!ConfigDirectory)
 | 
			
		||||
@@ -276,6 +322,12 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
  cSIProcessor::Read();
 | 
			
		||||
 | 
			
		||||
  // Start plugins:
 | 
			
		||||
 | 
			
		||||
  PluginManager.StartPlugins();
 | 
			
		||||
 | 
			
		||||
  // Channel:
 | 
			
		||||
 | 
			
		||||
  Channels.SwitchTo(Setup.CurrentChannel);
 | 
			
		||||
  if (MuteAudio)
 | 
			
		||||
     cDvbApi::PrimaryDvbApi->ToggleMute();
 | 
			
		||||
@@ -469,7 +521,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
                 Interface->Info(tr("Editing process finished"));
 | 
			
		||||
              }
 | 
			
		||||
           }
 | 
			
		||||
        if (!*Interact && (!cRecordControls::Active() || ForceShutdown)) {
 | 
			
		||||
        if (!*Interact && ((!cRecordControls::Active() && !cVideoCutter::Active()) || ForceShutdown)) {
 | 
			
		||||
           time_t Now = time(NULL);
 | 
			
		||||
           if (Now - LastActivity > ACTIVITYTIMEOUT) {
 | 
			
		||||
              // Shutdown:
 | 
			
		||||
@@ -529,6 +581,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
  Setup.CurrentChannel = cDvbApi::CurrentChannel();
 | 
			
		||||
  Setup.CurrentVolume  = cDvbApi::CurrentVolume();
 | 
			
		||||
  Setup.Save();
 | 
			
		||||
  PluginManager.Shutdown(true);
 | 
			
		||||
  cVideoCutter::Stop();
 | 
			
		||||
  delete Menu;
 | 
			
		||||
  delete ReplayControl;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user