mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented 'skins' and 'themes'
This commit is contained in:
parent
7aab06d8b1
commit
5d99df7b77
@ -962,3 +962,7 @@ Marcus M
|
||||
|
||||
Pekka Virtanen <pekka.virtanen@sci.fi>
|
||||
for adding language code handling to the subtitling descriptor in 'libsi'
|
||||
|
||||
John Kennedy <rkennedy@ix.netcom.com>
|
||||
for publishing "A Fast Bresenham Algorithm For Drawing Ellipses" (found at
|
||||
http://homepage.smc.edu/kennedy_john/BELIPSE.PDF)
|
||||
|
34
HISTORY
34
HISTORY
@ -2746,7 +2746,7 @@ Video Disk Recorder Revision History
|
||||
- Now explicitly turning on the LNB power at startup, because newer drivers don't
|
||||
do this any more (thanks to Oliver Endriss for pointing this out).
|
||||
|
||||
2004-03-28: Version 1.3.7
|
||||
2004-05-16: Version 1.3.7
|
||||
|
||||
- Fixed a memory leak in thread handling when using NPTL (thanks to Jon Burgess).
|
||||
- Fixed handling Setup.RecordDolbyDigital, which was broken since version 1.1.6.
|
||||
@ -2759,3 +2759,35 @@ Video Disk Recorder Revision History
|
||||
- Moved several menu item classes from menu.c to menuitems.[hc] to make them
|
||||
available for plugins.
|
||||
- The epg2html.pl script now handles '|' in description texts.
|
||||
- The new setup option "OSD/Use small font" can be used to control the use of
|
||||
the small font (see MANUAL for details).
|
||||
- Swapped osd.[hc] and osdbase.[hc] to have the virtual OSD base class named cOsd.
|
||||
Plugins may need to adjust their #include statements.
|
||||
- Colors are now given as AARRGGBB instead of AABBGGRR. The values are mapped to
|
||||
the driver's (wrong) sequence in dvbosd.c (this should really be fixed in the
|
||||
driver, together with the endian problem).
|
||||
- The new OSD setup parameters "Left" and "Top" can be used to define the top left
|
||||
corner of the OSD.
|
||||
- The OSD size prameters are now in pixel (as opposed to formerly characters).
|
||||
When reading a 'setup.conf' file from an older version of VDR, the OSDwidth
|
||||
and OSDheight values will be converted to pixel automatically.
|
||||
- The OSD is now fully device independent. See the comments in VDR/osd.h and the
|
||||
description in PLUGINS.html for information on how a plugin can implement an OSD
|
||||
display on arbitrary hardware.
|
||||
- The OSD (actually its cBitmap class) can now handle XPM files. There are several
|
||||
XPM files in the VDR/symbols directory which can be used by skins (some of these
|
||||
have been taken from the "elchi" patch). See VDR/skinsttng.c for examples on how
|
||||
to use these.
|
||||
- Due to the changes in the OSD handling the DEBUG_OSD option for a textual OSD
|
||||
has been dropped. There will be a plugin that implements a skin with this
|
||||
functionality later.
|
||||
- The entire OSD display can now be implemented via "skins". See VDR/skins.[hc],
|
||||
VDR/skinclassic.[hc], VDR/skinsttng.[hc] and PLUGINS.html for information on how
|
||||
a plugin can implement its own skin. By default VDR comes with a "Classic" skin
|
||||
that implements the OSD display known from previous versions, and the new skin
|
||||
named "ST:TNG Panels", which is also the default skin now. The actual skin can
|
||||
be selected through "Setup/OSD/Skin".
|
||||
- The colors used in a skin can now be configured using "themes". See PLUGINS.html
|
||||
for information on how a skin can make use of themes, and man vdr(5) for the
|
||||
structure of a theme file. The actual theme to use can be selected through
|
||||
"Setup/OSD/Theme".
|
||||
|
5
INSTALL
5
INSTALL
@ -40,11 +40,6 @@ following values in the 'make' call to activate the respective control mode:
|
||||
|
||||
If you want to disable control via the PC keyboard, you can add NO_KBD=1
|
||||
to the 'make' call.
|
||||
Adding "DEBUG_OSD=1" will use the PC screen (or current window)
|
||||
to display texts instead of the DVB card's on-screen display
|
||||
interface. These modes are useful when testing new menus if you
|
||||
only have a remote connection to the VDR (which, in my case, is
|
||||
located in the living room and has neither a monitor nor a keyboard).
|
||||
|
||||
If your video directory will be on a VFAT partition, add the compile
|
||||
time switch
|
||||
|
17
MANUAL
17
MANUAL
@ -425,13 +425,26 @@ Version 1.2
|
||||
|
||||
Language = English Defines the language used to display the OSD texts.
|
||||
|
||||
Width = 52 The width and height of the OSD .
|
||||
Height = 18 The valid ranges are width=40...56, height=12...21.
|
||||
Skin = ST:TNG Panels Defines the "skin" used to display the OSD menus.
|
||||
|
||||
Theme = Default Defines the "theme" to use with the current skin.
|
||||
|
||||
Left = 54 The top and left offset of the OSD.
|
||||
Top = 45 The valid ranges are left=0...672, top=0...567.
|
||||
|
||||
Width = 624 The width and height of the OSD.
|
||||
Height = 486 The valid ranges are width=480...672, height=324...567.
|
||||
The Width must be a multiple of 8.
|
||||
|
||||
Message time = 1 The time (in seconds) how long an informational
|
||||
message shall be displayed on the OSD. The valid range
|
||||
is 1...60.
|
||||
|
||||
Use small font = 1 Defines whether the small font shall be used. 0 means never
|
||||
use the small font, 1 means use the small font wherever the
|
||||
current skin wants to, and 2 means always use the small
|
||||
font.
|
||||
|
||||
Channel info position = bottom
|
||||
The position of the channel info window in the OSD
|
||||
(either 'bottom' or 'top').
|
||||
|
12
Makefile
12
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 1.65 2004/01/18 14:16:53 kls Exp $
|
||||
# $Id: Makefile 1.66 2004/05/08 09:15:00 kls Exp $
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
@ -36,8 +36,9 @@ SILIB = $(LSIDIR)/libsi.a
|
||||
OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd.o\
|
||||
dvbplayer.o dvbspu.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
|
||||
lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o rcu.o\
|
||||
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o sources.o\
|
||||
spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o
|
||||
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o\
|
||||
skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\
|
||||
timers.o tools.o transfer.o vdr.o videodir.o
|
||||
|
||||
FIXFONT_ISO8859_1 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
|
||||
OSDFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||
@ -60,11 +61,6 @@ DEFINES += -D_GNU_SOURCE
|
||||
DEFINES += -DVIDEODIR=\"$(VIDEODIR)\"
|
||||
DEFINES += -DPLUGINDIR=\"$(PLUGINLIBDIR)\"
|
||||
|
||||
ifdef DEBUG_OSD
|
||||
DEFINES += -DDEBUG_OSD
|
||||
NCURSESLIB = -lncurses
|
||||
endif
|
||||
|
||||
ifdef VFAT
|
||||
# for people who want their video directory on a VFAT partition
|
||||
DEFINES += -DVFAT
|
||||
|
215
PLUGINS.html
215
PLUGINS.html
@ -9,17 +9,20 @@
|
||||
<center><b>Version 1.3</b></center>
|
||||
<p>
|
||||
<center>
|
||||
Copyright © 2003 Klaus Schmidinger<br>
|
||||
Copyright © 2004 Klaus Schmidinger<br>
|
||||
<a href="mailto:kls@cadsoft.de">kls@cadsoft.de</a><br>
|
||||
<a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a>
|
||||
</center>
|
||||
<p>
|
||||
<!--X1.2.6--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
<!--X1.2.6--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
Important modifications introduced in version 1.2.6 are marked like this.
|
||||
<!--X1.2.6--></td></tr></table>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
Important modifications introduced in version 1.3.0 are marked like this.
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
<!--X1.3.7--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
Important modifications introduced in version 1.3.7 are marked like this.
|
||||
<!--X1.3.7--></td></tr></table>
|
||||
<p>
|
||||
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.
|
||||
@ -67,10 +70,14 @@ structures and allows it to hook itself into specific areas to perform special a
|
||||
<li><a href="#Status monitor">Status monitor</a>
|
||||
<li><a href="#Players">Players</a>
|
||||
<li><a href="#Receivers">Receivers</a>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
<li><a href="#Filters">Filters</a>
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
<li><a href="#The On Screen Display">The On Screen Display</a>
|
||||
<!--X1.3.7--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<li><a href="#Skins">Skins</a>
|
||||
<li><a href="#Themes">Themes</a>
|
||||
<!--X1.3.7--></td></tr></table>
|
||||
<li><a href="#Devices">Devices</a>
|
||||
<li><a href="#Dolby Digital">Dolby Digital</a>
|
||||
<li><a href="#Remote Control">Remote Control</a>
|
||||
@ -1207,7 +1214,7 @@ Mode</i>).
|
||||
If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i>
|
||||
and will automatically detach itself from the <tt>cDevice</tt>.
|
||||
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
<a name="Filters"><hr><h2>Filters</h2>
|
||||
|
||||
<center><i><b>A Fistful of Datas</b></i></center><p>
|
||||
@ -1253,35 +1260,166 @@ and will automatically detach itself from the <tt>cDevice</tt>.
|
||||
See VDR/eit.c or VDR/pat.c to learn how to process filter data.
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
|
||||
<!--X1.3.7--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<a name="The On Screen Display"><hr><h2>The On Screen Display</h2>
|
||||
|
||||
<center><i><b>Express yourself</b></i></center><p>
|
||||
<center><i><b>Window to the world</b></i></center><p>
|
||||
|
||||
Most of the time a plugin should be able to access the OSD through the
|
||||
standard mechanisms also used by VDR itself. However, these set up the OSD in
|
||||
a manner of textual rows and columns, and automatically set the various
|
||||
windows and color depths.
|
||||
<p>
|
||||
If a plugin needs to have total control over the OSD, it can call the
|
||||
static function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/osd.h>
|
||||
|
||||
cOsdBase *MyOsd = cOsd::OpenRaw(x, y);
|
||||
cOsd *MyOsd = cOsdProvider::NewOsd(x, y);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
where <tt>x</tt> and <tt>y</tt> are the coordinates of the upper left corner
|
||||
of the OSD area on the screen. Such a "raw" OSD doesn't display anything
|
||||
of the OSD area on the screen. Such an OSD doesn't display anything
|
||||
yet, so you need to at least call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
MyOsd->Create(...);
|
||||
tArea Area = { 0, 0, 100, 100, 4 };
|
||||
MyOsd->SetAreas(Area, 1);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
to define an actual OSD drawing area (see VDR/osdbase.h for the declarations
|
||||
of these functions, and VDR/osd.c to see how VDR opens the OSD and sets up
|
||||
to define an actual OSD drawing area (see VDR/osd.h for the declarations
|
||||
of these functions, and VDR/skinsttng.c to see how VDR opens the OSD and sets up
|
||||
its windows and color depths).
|
||||
<p>
|
||||
Theoretically the OSD supports a full screen drawing area, with 32 bit color
|
||||
depth. However, the actual OSD device in use may not be able to provide the
|
||||
full area or color depth, maybe because of lack of OSD memory or other restrictions.
|
||||
A plugin that uses the OSD should therefore test whether the OSD is able to
|
||||
provide the requested functionality, and should offer alternate color depths
|
||||
to allow a less powerfull OSD implementation to still work reasonably.
|
||||
Since it is often not really necessary to have hundreds or thousands of colors
|
||||
all over the OSD area, a plugin can divide the total drawing area into several
|
||||
sub-areas with different color depths and separate color palettes, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
tArea Area = { 0, 0, 99, 99, 4 };
|
||||
if (osd->CanHandleAreas(Area, 1) == oeOk)
|
||||
osd->SetAreas(Area, 1);
|
||||
else {
|
||||
tArea Areas[] = { { 0, 0, 99, 19, 2 },
|
||||
{ 0, 20, 99, 79, 2 },
|
||||
{ 0, 80, 99, 99, 4 }
|
||||
};
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
In this example an OSD with 100 by 100 pixel and 4 bit color depth shall
|
||||
be opened, so at first a single area with the full required resolution
|
||||
is set up and <tt>CanHandleAreas()</tt> is called with it. If the result indicates
|
||||
that the OSD will be able to handle this drawing area, a call to <tt>SetAreas()</tt>
|
||||
actually sets it. If a single area with that resolution can't be handled,
|
||||
a second attempt is made in which the total drawing area is divided into
|
||||
three horizontal stripes, two of which use only 2 bit color depth (because
|
||||
the objects drawn in there can be displayed with 4 colors) while the third
|
||||
one still requests 4 bit color depth.
|
||||
<p>
|
||||
Note that a plugin should always at first request a single drawing area
|
||||
with the full required resolution. Only if this fails shall it use alternate
|
||||
areas. Drawing areas are always rectangular and may not overlap (but do not need
|
||||
to be adjacent).
|
||||
|
||||
<a name="Skins"><hr><h2>Skins</h2>
|
||||
|
||||
<center><i><b>The emperor's new clothes</b></i></center><p>
|
||||
|
||||
The way VDR displays its menus to the user is implemented through <i>skins</i>.
|
||||
A particular skin provides several functions that return objects to be used
|
||||
for displaying a specific part of the OSD, like a menu, the channel display
|
||||
or the volume bar.
|
||||
<p>
|
||||
By default VDR offers the <i>Classic</i> and the <i>ST:TNG Panels</i> skins,
|
||||
which can be selected through Setup/OSD/Skin. A plugin can implement an
|
||||
arbitrary skin of its own by doing something similar to what's done in
|
||||
<tt>VDR/skinclassic.c</tt>.
|
||||
<p>
|
||||
The first step in implementing a new skin is to derive a class from <tt>cSkin</tt>
|
||||
that provides the handling objects necessary to do the actual work:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include "skins.h"
|
||||
|
||||
class cMySkin : public cSkin {
|
||||
public:
|
||||
cMySkin(void);
|
||||
virtual const char *Description(void);
|
||||
virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
|
||||
virtual cSkinDisplayMenu *DisplayMenu(void);
|
||||
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
|
||||
virtual cSkinDisplayVolume *DisplayVolume(void);
|
||||
virtual cSkinDisplayMessage *DisplayMessage(void);
|
||||
};
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
See the comments in <tt>VDR/skins.h</tt> for details. <tt>VDR/skinclassic.[hc]</tt>
|
||||
can be used as an example for how to implement all the necessary classes and
|
||||
functions to compose a complete skin. See also the chapter about <a href="#Themes">themes</a>
|
||||
if you want to make the colors used by your skin configurable.
|
||||
<p>
|
||||
To add your new skin to the list of skins available to the user in Setup/OSD/Skin,
|
||||
all you need to do is create a new object of your skin class, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
new cMySkin;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
in the <a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||
Do not delete this object, it will be automatically deleted when the program ends.
|
||||
|
||||
<a name="Themes"><hr><h2>Themes</h2>
|
||||
|
||||
<center><i><b>Eye of the beholder...</b></i></center><p>
|
||||
|
||||
A <i>theme</i> is a collection of colors that can be used by a <a href="#Skins">skin</a>.
|
||||
Since every skin most likely has its own idea about what parts of it can be
|
||||
<i>themed</i>, and different skins may have completely different numbers of
|
||||
"themeable" parts, a particular theme can only be used with the skin it was designed
|
||||
for. A particular skin, however, can have any number of themes. Which theme
|
||||
will be actually used can be defined in Setup/OSD/Theme.
|
||||
<p>
|
||||
In order to make a skin "themeable" is shall create an object of type cTheme, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
static cTheme Theme;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The next step is to define the colors that shall be provided by this theme, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
THEME_CLR(Theme, clrTitle, 0xFFBC8024);
|
||||
THEME_CLR(Theme, clrButtonRedFg, clrWhite);
|
||||
THEME_CLR(Theme, clrButtonRedBg, clrRed);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
<tt>THEME_CLR()</tt> is a helper macro that adds the given color name
|
||||
and its default color value to the theme.
|
||||
<p>
|
||||
Any color names can be used, but they should always start with <tt>clr...</tt> and
|
||||
if a given color has a foreground and a background value, the two names shall be
|
||||
distinguished by appending <tt>...Fg</tt> and <tt>...Bg</tt>, respectively.
|
||||
<p>
|
||||
Color values can be either 32 bit hexadecimal numbers in the form 0xAARRGGBB
|
||||
(where the individual bytes represent Alpha (transparency), Red, Green
|
||||
and Blue component, respectively), or one of the predefined color names from
|
||||
<tt>VDR/osd.h</tt>.
|
||||
<p>
|
||||
In the actual drawing code of a skin, the color names defined with the <tt>THEME_CLR()</tt>
|
||||
macros can be used to fetch the actual color values from the theme, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
osd->DrawText(x, y, s, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedBg), font);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
By default this will use the colors that have been defined in the respective
|
||||
<tt>THEME_CLR()</tt> line, but may be overwritten through user supplied theme
|
||||
files (see <tt>man vdr(5)</tt> for information about the format of a theme file).
|
||||
<!--X1.3.7--></td></tr></table>
|
||||
|
||||
<a name="Devices"><hr><h2>Devices</h2>
|
||||
|
||||
@ -1297,7 +1435,7 @@ into a VDR system; or an analog TV receiver card, which does the MPEG encoding
|
||||
"on the fly" - assuming your machine is fast enough), or just a software program that takes an MPEG data
|
||||
stream and displays it, for instance, on an existing graphics adapter.
|
||||
<p>
|
||||
To implement an additional device, a plugin must derive a class from cDevice:
|
||||
To implement an additional device, a plugin must derive a class from <tt>cDevice</tt>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/device.h>
|
||||
@ -1374,7 +1512,7 @@ The functions to implement replaying capabilites are
|
||||
virtual bool HasDecoder(void) const;
|
||||
virtual bool CanReplay(void) const;
|
||||
virtual bool SetPlayMode(ePlayMode PlayMode);
|
||||
<!--X1.2.6--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
<!--X1.2.6--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
virtual int64_t GetSTC(void);
|
||||
<!--X1.2.6--></td></tr></table>
|
||||
virtual void TrickSpeed(int Speed);
|
||||
@ -1396,7 +1534,7 @@ virtual void SetVideoFormat(bool VideoFormat16_9);
|
||||
virtual void SetVolumeDevice(int Volume);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
<p>
|
||||
<b>Section Filtering</b>
|
||||
<p>
|
||||
@ -1426,23 +1564,46 @@ handle section data.
|
||||
<p>
|
||||
<b>On Screen Display</b>
|
||||
<p>
|
||||
<!--X1.3.7--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
If your device provides On Screen Display (OSD) capabilities (which every device
|
||||
that is supposed to be used as a primary device should do), it can implement
|
||||
the function
|
||||
that is supposed to be used as a primary device should do), it shall implement
|
||||
an "OSD provider" class, derived from <tt>cOsdProvider</tt>, which, when its <tt>CreateOsd()</tt>
|
||||
function is called, returns an object derived from <tt>cOsd</tt>, which can be used to
|
||||
access the device's OSD:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual cOsdBase *NewOsd(int x, int y);
|
||||
class cMyOsdProvider : public cOsdProvider {
|
||||
public:
|
||||
cMyOsdProvider(void);
|
||||
virtual cOsd *CreateOsd(int Left, int Top);
|
||||
};
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which must return a newly created object of a derived cOsdBase class that
|
||||
implements the functions necessary to display OSD information on your device.
|
||||
The caller of this function will delete the object as soon as it is no longer
|
||||
needed.
|
||||
In its <tt>MakePrimaryDevice()</tt> function the device shall create an object
|
||||
of this class, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
void cMyDevice::MakePrimaryDevice(bool On)
|
||||
{
|
||||
new cMyOsdProvider;
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The OSD provider object is allocated on the heap and shall not be deleted
|
||||
(it will be deleted automatically in case a different device sets up an OSD
|
||||
provider, or when the program ends).
|
||||
|
||||
Note that an OSD implementation need not be physically linked to the device
|
||||
in any way. All it needs to make sure is that the OSD will be visible to the
|
||||
user - whether this goes through OSD facilities of the physical device (like
|
||||
a "full featured" DVB card) or through a graphics adapter that overlays its
|
||||
output with the video signal, doesn't matter.
|
||||
<!--X1.3.7--></td></tr></table>
|
||||
|
||||
<p>
|
||||
<b>Initializing new devices</b>
|
||||
<p>
|
||||
A derived cDevice class shall implement a static function
|
||||
A derived <tt>cDevice</tt> class shall implement a static function
|
||||
in which it determines whether the necessary hardware to run this sort of
|
||||
device is actually present in this machine (or whatever other prerequisites
|
||||
might be important), and then creates as many device objects as necessary.
|
||||
|
@ -8,3 +8,7 @@ VDR Plugin 'osddemo' Revision History
|
||||
2002-12-13: Version 0.1.0
|
||||
|
||||
- Changed setting of CXX and CXXFLAGS variables in Makefile.
|
||||
|
||||
2004-04-30: Version 0.1.1
|
||||
|
||||
- New OSD handling.
|
||||
|
@ -3,12 +3,12 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: osddemo.c 1.2 2002/12/13 15:02:01 kls Exp $
|
||||
* $Id: osddemo.c 1.3 2004/05/16 09:28:51 kls Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/plugin.h>
|
||||
|
||||
static const char *VERSION = "0.1.0";
|
||||
static const char *VERSION = "0.1.1";
|
||||
static const char *DESCRIPTION = "Demo of arbitrary OSD setup";
|
||||
static const char *MAINMENUENTRY = "Osd Demo";
|
||||
|
||||
@ -16,10 +16,10 @@ static const char *MAINMENUENTRY = "Osd Demo";
|
||||
|
||||
class cLineGame : public cOsdObject {
|
||||
private:
|
||||
cOsdBase *osd;
|
||||
cOsd *osd;
|
||||
int x;
|
||||
int y;
|
||||
eDvbColor color;
|
||||
tColor color;
|
||||
public:
|
||||
cLineGame(void);
|
||||
~cLineGame();
|
||||
@ -41,15 +41,11 @@ cLineGame::~cLineGame()
|
||||
|
||||
void cLineGame::Show(void)
|
||||
{
|
||||
osd = cOsd::OpenRaw(100, 50);
|
||||
osd = cOsdProvider::NewOsd(100, 50);
|
||||
if (osd) {
|
||||
osd->Create(0, 0, 100, 200, 4);
|
||||
osd->AddColor(clrBackground);
|
||||
osd->AddColor(clrRed);
|
||||
osd->AddColor(clrGreen);
|
||||
osd->AddColor(clrYellow);
|
||||
osd->AddColor(clrBlue);
|
||||
osd->Clear();
|
||||
tArea Area = { 0, 0, 99, 199, 4 };
|
||||
osd->SetAreas(&Area, 1);
|
||||
osd->DrawRectangle(0, 0, 99, 199, clrGray50);
|
||||
osd->Flush();
|
||||
}
|
||||
}
|
||||
@ -70,7 +66,7 @@ eOSState cLineGame::ProcessKey(eKeys Key)
|
||||
case kOk: return osEnd;
|
||||
default: return state;
|
||||
}
|
||||
osd->Fill(x, y, x + 3, y + 3, color);
|
||||
osd->DrawRectangle(x, y, x + 3, y + 3, color);
|
||||
osd->Flush();
|
||||
state = osContinue;
|
||||
}
|
||||
|
18
channels.c
18
channels.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.c 1.24 2004/02/13 15:37:42 kls Exp $
|
||||
* $Id: channels.c 1.25 2004/04/03 13:42:06 kls Exp $
|
||||
*/
|
||||
|
||||
#include "channels.h"
|
||||
@ -888,3 +888,19 @@ cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, i
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *ChannelString(const cChannel *Channel, int Number)
|
||||
{
|
||||
static char buffer[256];
|
||||
if (Channel) {
|
||||
if (Channel->GroupSep())
|
||||
snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
|
||||
else
|
||||
snprintf(buffer, sizeof(buffer), "%d%s %s", Channel->Number(), Number ? "-" : "", Channel->Name());
|
||||
}
|
||||
else if (Number)
|
||||
snprintf(buffer, sizeof(buffer), "%d-", Number);
|
||||
else
|
||||
snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
|
||||
return buffer;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.h 1.16 2004/02/13 15:16:36 kls Exp $
|
||||
* $Id: channels.h 1.17 2004/04/03 13:40:47 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CHANNELS_H
|
||||
@ -203,4 +203,6 @@ public:
|
||||
|
||||
extern cChannels Channels;
|
||||
|
||||
const char *ChannelString(const cChannel *Channel, int Number);
|
||||
|
||||
#endif //__CHANNELS_H
|
||||
|
29
config.c
29
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.125 2004/02/28 11:12:20 kls Exp $
|
||||
* $Id: config.c 1.126 2004/05/16 10:08:09 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -245,6 +245,8 @@ cSetup Setup;
|
||||
cSetup::cSetup(void)
|
||||
{
|
||||
OSDLanguage = 0;
|
||||
strcpy(OSDSkin, "sttng");
|
||||
strcpy(OSDTheme, "default");
|
||||
PrimaryDVB = 1;
|
||||
ShowInfoOnChSwitch = 1;
|
||||
MenuScrollPage = 1;
|
||||
@ -279,9 +281,12 @@ cSetup::cSetup(void)
|
||||
UpdateChannels = 4;
|
||||
RecordDolbyDigital = 1;
|
||||
ChannelInfoPos = 0;
|
||||
OSDwidth = 52;
|
||||
OSDheight = 18;
|
||||
OSDLeft = 54;
|
||||
OSDTop = 45;
|
||||
OSDWidth = 624;
|
||||
OSDHeight = 486;
|
||||
OSDMessageTime = 1;
|
||||
UseSmallFont = 1;
|
||||
MaxVideoFileSize = MAXVIDEOFILESIZE;
|
||||
SplitEditedFiles = 0;
|
||||
MinEventTimeout = 30;
|
||||
@ -392,6 +397,8 @@ bool cSetup::ParseLanguages(const char *Value, int *Values)
|
||||
bool cSetup::Parse(const char *Name, const char *Value)
|
||||
{
|
||||
if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDSkin")) strn0cpy(OSDSkin, Value, MaxSkinName);
|
||||
else if (!strcasecmp(Name, "OSDTheme")) strn0cpy(OSDTheme, Value, MaxThemeName);
|
||||
else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
|
||||
@ -426,9 +433,12 @@ bool cSetup::Parse(const char *Name, const char *Value)
|
||||
else if (!strcasecmp(Name, "UpdateChannels")) UpdateChannels = 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, "OSDLeft")) OSDLeft = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDTop")) OSDTop = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDWidth")) { OSDWidth = atoi(Value); if (OSDWidth < 100) OSDWidth *= 12; OSDWidth &= ~0x07; } // OSD width must be a multiple of 8
|
||||
else if (!strcasecmp(Name, "OSDHeight")) { OSDHeight = atoi(Value); if (OSDHeight < 100) OSDHeight *= 27; }
|
||||
else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "UseSmallFont")) UseSmallFont = 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);
|
||||
@ -446,6 +456,8 @@ bool cSetup::Parse(const char *Name, const char *Value)
|
||||
bool cSetup::Save(void)
|
||||
{
|
||||
Store("OSDLanguage", OSDLanguage);
|
||||
Store("OSDSkin", OSDSkin);
|
||||
Store("OSDTheme", OSDTheme);
|
||||
Store("PrimaryDVB", PrimaryDVB);
|
||||
Store("ShowInfoOnChSwitch", ShowInfoOnChSwitch);
|
||||
Store("MenuScrollPage", MenuScrollPage);
|
||||
@ -480,9 +492,12 @@ bool cSetup::Save(void)
|
||||
Store("UpdateChannels", UpdateChannels);
|
||||
Store("RecordDolbyDigital", RecordDolbyDigital);
|
||||
Store("ChannelInfoPos", ChannelInfoPos);
|
||||
Store("OSDwidth", OSDwidth);
|
||||
Store("OSDheight", OSDheight);
|
||||
Store("OSDLeft", OSDLeft);
|
||||
Store("OSDTop", OSDTop);
|
||||
Store("OSDWidth", OSDWidth);
|
||||
Store("OSDHeight", OSDHeight);
|
||||
Store("OSDMessageTime", OSDMessageTime);
|
||||
Store("UseSmallFont", UseSmallFont);
|
||||
Store("MaxVideoFileSize", MaxVideoFileSize);
|
||||
Store("SplitEditedFiles", SplitEditedFiles);
|
||||
Store("MinEventTimeout", MinEventTimeout);
|
||||
|
17
config.h
17
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.191 2004/03/14 16:51:13 kls Exp $
|
||||
* $Id: config.h 1.192 2004/05/08 09:18:36 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -26,12 +26,14 @@
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
|
||||
#define MINOSDWIDTH 40
|
||||
#define MAXOSDWIDTH 56
|
||||
#define MINOSDHEIGHT 12
|
||||
#define MAXOSDHEIGHT 21
|
||||
#define MINOSDWIDTH 480
|
||||
#define MAXOSDWIDTH 672
|
||||
#define MINOSDHEIGHT 324
|
||||
#define MAXOSDHEIGHT 567
|
||||
|
||||
#define MaxFileName 256
|
||||
#define MaxSkinName 16
|
||||
#define MaxThemeName 16
|
||||
|
||||
class cCommand : public cListObject {
|
||||
private:
|
||||
@ -204,6 +206,8 @@ public:
|
||||
// Also adjust cMenuSetup (menu.c) when adding parameters here!
|
||||
int __BeginData__;
|
||||
int OSDLanguage;
|
||||
char OSDSkin[MaxSkinName];
|
||||
char OSDTheme[MaxThemeName];
|
||||
int PrimaryDVB;
|
||||
int ShowInfoOnChSwitch;
|
||||
int MenuScrollPage;
|
||||
@ -235,8 +239,9 @@ public:
|
||||
int UpdateChannels;
|
||||
int RecordDolbyDigital;
|
||||
int ChannelInfoPos;
|
||||
int OSDwidth, OSDheight;
|
||||
int OSDLeft, OSDTop, OSDWidth, OSDHeight;
|
||||
int OSDMessageTime;
|
||||
int UseSmallFont;
|
||||
int MaxVideoFileSize;
|
||||
int SplitEditedFiles;
|
||||
int MinEventTimeout, MinUserInactivity;
|
||||
|
17
device.c
17
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 1.53 2004/02/08 15:05:11 kls Exp $
|
||||
* $Id: device.c 1.54 2004/04/17 10:07:10 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -126,11 +126,6 @@ bool cDevice::HasDecoder(void) const
|
||||
return false;
|
||||
}
|
||||
|
||||
cOsdBase *cDevice::NewOsd(int x, int y)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cSpuDecoder *cDevice::GetSpuDecoder(void)
|
||||
{
|
||||
return NULL;
|
||||
@ -360,11 +355,9 @@ bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
|
||||
for (int i = 3; i--;) {
|
||||
switch (SetChannel(Channel, LiveView)) {
|
||||
case scrOk: return true;
|
||||
case scrNotAvailable: if (Interface)
|
||||
Interface->Error(tr("Channel not available!"));
|
||||
case scrNotAvailable: Skins.Message(mtError, tr("Channel not available!"));
|
||||
return false;
|
||||
case scrNoTransfer: if (Interface)
|
||||
Interface->Error(tr("Can't start Transfer Mode!"));
|
||||
case scrNoTransfer: Skins.Message(mtError, tr("Can't start Transfer Mode!"));
|
||||
return false;
|
||||
case scrFailed: break; // loop will retry
|
||||
}
|
||||
@ -396,8 +389,8 @@ bool cDevice::SwitchChannel(int Direction)
|
||||
if (PrimaryDevice()->SwitchChannel(channel, true))
|
||||
result = true;
|
||||
}
|
||||
else if (n != first && Interface)
|
||||
Interface->Error(tr("Channel not available!"));
|
||||
else if (n != first)
|
||||
Skins.Message(mtError, tr("Channel not available!"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
11
device.h
11
device.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.h 1.41 2004/03/14 10:47:01 kls Exp $
|
||||
* $Id: device.h 1.42 2004/04/17 10:15:25 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -54,7 +54,6 @@ enum eVideoSystem { vsPAL,
|
||||
vsNTSC
|
||||
};
|
||||
|
||||
class cOsdBase;
|
||||
class cChannel;
|
||||
class cPlayer;
|
||||
class cReceiver;
|
||||
@ -139,15 +138,9 @@ public:
|
||||
virtual bool HasDecoder(void) const;
|
||||
///< Tells whether this device has an MPEG decoder.
|
||||
|
||||
// OSD facilities
|
||||
// SPU facilities
|
||||
|
||||
public:
|
||||
virtual cOsdBase *NewOsd(int x, int y);
|
||||
///< Creates a new cOsdBase object that can be used by the cOsd class
|
||||
///< to display information on the screen, with the upper left corner
|
||||
///< of the OSD at the given coordinates. If a derived cDevice doesn't
|
||||
///< implement this function, NULL will be returned by default (which
|
||||
///< means the device has no OSD capabilities).
|
||||
virtual cSpuDecoder *GetSpuDecoder(void);
|
||||
///< Returns a pointer to the device's SPU decoder (or NULL, if this
|
||||
///< device doesn't have an SPU decoder).
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 1.83 2004/03/14 14:47:46 kls Exp $
|
||||
* $Id: dvbdevice.c 1.84 2004/05/01 13:15:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -427,7 +427,7 @@ bool cDvbDevice::Initialize(void)
|
||||
void cDvbDevice::MakePrimaryDevice(bool On)
|
||||
{
|
||||
if (HasDecoder())
|
||||
cDvbOsd::SetDvbDevice(On ? this : NULL);
|
||||
new cDvbOsdProvider(fd_osd);
|
||||
}
|
||||
|
||||
bool cDvbDevice::HasDecoder(void) const
|
||||
@ -446,11 +446,6 @@ int cDvbDevice::ProvidesCa(const cChannel *Channel) const
|
||||
return cDevice::ProvidesCa(Channel);
|
||||
}
|
||||
|
||||
cOsdBase *cDvbDevice::NewOsd(int x, int y)
|
||||
{
|
||||
return new cDvbOsd(x, y);
|
||||
}
|
||||
|
||||
cSpuDecoder *cDvbDevice::GetSpuDecoder(void)
|
||||
{
|
||||
if (!spuDecoder && IsPrimaryDevice())
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.h 1.26 2004/01/03 10:21:50 kls Exp $
|
||||
* $Id: dvbdevice.h 1.27 2004/04/17 11:56:22 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBDEVICE_H
|
||||
@ -26,7 +26,6 @@ class cDvbTuner;
|
||||
/// The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API.
|
||||
|
||||
class cDvbDevice : public cDevice {
|
||||
friend class cDvbOsd;
|
||||
private:
|
||||
static bool Probe(const char *FileName);
|
||||
///< Probes for existing DVB devices.
|
||||
@ -38,7 +37,6 @@ public:
|
||||
private:
|
||||
fe_type_t frontendType;
|
||||
int fd_osd, fd_audio, fd_video, fd_dvr, fd_stc;
|
||||
int OsdDeviceHandle(void) const { return fd_osd; }
|
||||
protected:
|
||||
virtual void MakePrimaryDevice(bool On);
|
||||
public:
|
||||
@ -47,12 +45,11 @@ public:
|
||||
virtual int ProvidesCa(const cChannel *Channel) const;
|
||||
virtual bool HasDecoder(void) const;
|
||||
|
||||
// OSD facilities
|
||||
// SPU facilities
|
||||
|
||||
private:
|
||||
cDvbSpuDecoder *spuDecoder;
|
||||
public:
|
||||
cOsdBase *NewOsd(int x, int y);
|
||||
virtual cSpuDecoder *GetSpuDecoder(void);
|
||||
|
||||
// Channel facilities
|
||||
|
152
dvbosd.c
152
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.21 2003/04/12 12:10:12 kls Exp $
|
||||
* $Id: dvbosd.c 1.22 2004/05/01 15:10:44 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbosd.h"
|
||||
@ -13,40 +13,49 @@
|
||||
#include <sys/unistd.h>
|
||||
#include "tools.h"
|
||||
|
||||
const cDvbDevice *cDvbOsd::dvbDevice = NULL;
|
||||
// --- cDvbOsd ---------------------------------------------------------------
|
||||
|
||||
cDvbOsd::cDvbOsd(int x, int y)
|
||||
:cOsdBase(x, y)
|
||||
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
|
||||
#define MAXOSDMEMORY 92000 // number of bytes available to the OSD (depends on firmware version, but there is no way of determining the actual value)
|
||||
|
||||
cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev)
|
||||
:cOsd(Left, Top)
|
||||
{
|
||||
osdDev = dvbDevice ? dvbDevice->OsdDeviceHandle() : -1;
|
||||
if (dvbDevice && osdDev < 0)
|
||||
osdDev = OsdDev;
|
||||
shown = false;
|
||||
if (osdDev < 0)
|
||||
esyslog("ERROR: illegal OSD device handle (%d)!", osdDev);
|
||||
}
|
||||
|
||||
cDvbOsd::~cDvbOsd()
|
||||
{
|
||||
for (int i = 0; i < NumWindows(); i++)
|
||||
CloseWindow(GetWindowNr(i));
|
||||
if (shown) {
|
||||
cBitmap *Bitmap;
|
||||
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
|
||||
Cmd(OSD_SetWindow, 0, i + 1);
|
||||
Cmd(OSD_Close);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbOsd::SetDvbDevice(const cDvbDevice *DvbDevice)
|
||||
eOsdError cDvbOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
|
||||
{
|
||||
dvbDevice = DvbDevice;
|
||||
eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
|
||||
if (Result == oeOk) {
|
||||
if (NumAreas > MAXNUMWINDOWS)
|
||||
return oeTooManyAreas;
|
||||
int TotalMemory = 0;
|
||||
for (int i = 0; i < NumAreas; i++) {
|
||||
if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8)
|
||||
return oeBppNotSupported;
|
||||
if ((Areas[i].Width() & (8 / Areas[i].bpp - 1)) != 0)
|
||||
return oeWrongAlignment;
|
||||
TotalMemory += Areas[i].Width() * Areas[i].Height() / (8 / Areas[i].bpp);
|
||||
}
|
||||
|
||||
bool cDvbOsd::SetWindow(cWindow *Window)
|
||||
{
|
||||
if (Window) {
|
||||
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
||||
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
||||
int Handle = Window->Handle();
|
||||
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
||||
Cmd(OSD_SetWindow, 0, Handle + 1);
|
||||
return true;
|
||||
if (TotalMemory > MAXOSDMEMORY)
|
||||
return oeOutOfMemory;
|
||||
}
|
||||
esyslog("ERROR: illegal window handle: %d", Handle);
|
||||
}
|
||||
return false;
|
||||
return Result;
|
||||
}
|
||||
|
||||
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
|
||||
@ -64,51 +73,78 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
|
||||
}
|
||||
}
|
||||
|
||||
bool cDvbOsd::OpenWindow(cWindow *Window)
|
||||
void cDvbOsd::Flush(void)
|
||||
{
|
||||
if (SetWindow(Window)) {
|
||||
Cmd(OSD_Open, Window->Bpp(), X0() + Window->X0(), Y0() + Window->Y0(), X0() + Window->X0() + Window->Width() - 1, Y0() + Window->Y0() + Window->Height() - 1, (void *)1); // initially hidden!
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDvbOsd::CommitWindow(cWindow *Window)
|
||||
{
|
||||
if (SetWindow(Window)) {
|
||||
cBitmap *Bitmap;
|
||||
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
|
||||
Cmd(OSD_SetWindow, 0, i + 1);
|
||||
if (!shown)
|
||||
Cmd(OSD_Open, Bitmap->Bpp(), Left() + Bitmap->X0(), Top() + Bitmap->Y0(), Left() + Bitmap->X0() + Bitmap->Width() - 1, Top() + Bitmap->Y0() + Bitmap->Height() - 1, (void *)1); // initially hidden!
|
||||
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||
if (Window->Dirty(x1, y1, x2, y2)) {
|
||||
if (Bitmap->Dirty(x1, y1, x2, y2)) {
|
||||
//TODO Workaround: apparently the bitmap sent to the driver always has to be a multiple
|
||||
//TODO of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
|
||||
//TODO Fix driver (should be able to handle any size bitmaps!)
|
||||
while ((x1 > 0 || x2 < Bitmap->Width() - 1) && ((x2 - x1) & 7) != 7) {
|
||||
if (x2 < Bitmap->Width() - 1)
|
||||
x2++;
|
||||
else if (x1 > 0)
|
||||
x1--;
|
||||
}
|
||||
//TODO "... / 2" <==> Bpp???
|
||||
while ((y1 > 0 || y2 < Bitmap->Height() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) {
|
||||
if (y2 < Bitmap->Height() - 1)
|
||||
y2++;
|
||||
else if (y1 > 0)
|
||||
y1--;
|
||||
}
|
||||
while ((x1 > 0 || x2 < Bitmap->Width() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) {
|
||||
if (x2 < Bitmap->Width() - 1)
|
||||
x2++;
|
||||
else if (x1 > 0)
|
||||
x1--;
|
||||
}
|
||||
// commit colors:
|
||||
int FirstColor = 0, LastColor = 0;
|
||||
const eDvbColor *pal;
|
||||
while ((pal = Window->NewColors(FirstColor, LastColor)) != NULL)
|
||||
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
|
||||
int NumColors;
|
||||
const tColor *Colors = Bitmap->Colors(NumColors);
|
||||
if (Colors) {
|
||||
//TODO this should be fixed in the driver!
|
||||
tColor colors[NumColors];
|
||||
for (int i = 0; i < NumColors; i++) {
|
||||
// convert AARRGGBB to AABBGGRR (the driver expects the colors the wrong way):
|
||||
colors[i] = (Colors[i] & 0xFF000000) | ((Colors[i] & 0x0000FF) << 16) | (Colors[i] & 0x00FF00) | ((Colors[i] & 0xFF0000) >> 16);
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
// actually the driver itself should access the bytes according to the current endianness!
|
||||
colors[i] = ((colors[i] & 0xFF) << 24) | ((colors[i] & 0xFF00) << 8) | ((colors[i] & 0xFF0000) >> 8) | ((colors[i] & 0xFF000000) >> 24);
|
||||
#endif
|
||||
}
|
||||
Colors = colors;
|
||||
//TODO end of stuff that should be fixed in the driver
|
||||
Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors);
|
||||
}
|
||||
// commit modified data:
|
||||
Cmd(OSD_SetBlock, Window->Width(), x1, y1, x2, y2, Window->Data(x1, y1));
|
||||
Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
|
||||
}
|
||||
Bitmap->Clean();
|
||||
}
|
||||
if (!shown) {
|
||||
// Showing the windows in a separate loop to avoid seeing them come up one after another
|
||||
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
|
||||
Cmd(OSD_SetWindow, 0, i + 1);
|
||||
Cmd(OSD_MoveWindow, 0, Left() + Bitmap->X0(), Top() + Bitmap->Y0());
|
||||
}
|
||||
shown = true;
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbOsd::ShowWindow(cWindow *Window)
|
||||
// --- cDvbOsdProvider -------------------------------------------------------
|
||||
|
||||
cDvbOsdProvider::cDvbOsdProvider(int OsdDev)
|
||||
{
|
||||
if (SetWindow(Window))
|
||||
Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0());
|
||||
osdDev = OsdDev;
|
||||
}
|
||||
|
||||
void cDvbOsd::HideWindow(cWindow *Window, bool Hide)
|
||||
cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top)
|
||||
{
|
||||
if (SetWindow(Window))
|
||||
Cmd(Hide ? OSD_Hide : OSD_Show, 0);
|
||||
}
|
||||
|
||||
void cDvbOsd::MoveWindow(cWindow *Window, int x, int y)
|
||||
{
|
||||
if (SetWindow(Window))
|
||||
Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y);
|
||||
}
|
||||
|
||||
void cDvbOsd::CloseWindow(cWindow *Window)
|
||||
{
|
||||
if (SetWindow(Window))
|
||||
Cmd(OSD_Close);
|
||||
return new cDvbOsd(Left, Top, osdDev);
|
||||
}
|
||||
|
29
dvbosd.h
29
dvbosd.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbosd.h 1.16 2002/11/01 10:05:47 kls Exp $
|
||||
* $Id: dvbosd.h 1.17 2004/04/30 13:44:16 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBOSD_H
|
||||
@ -12,25 +12,26 @@
|
||||
|
||||
#include <linux/dvb/osd.h>
|
||||
#include "dvbdevice.h"
|
||||
#include "osdbase.h"
|
||||
#include "osd.h"
|
||||
|
||||
class cDvbOsd : public cOsdBase {
|
||||
class cDvbOsd : public cOsd {
|
||||
private:
|
||||
static const cDvbDevice *dvbDevice;
|
||||
int osdDev;
|
||||
bool SetWindow(cWindow *Window);
|
||||
bool shown;
|
||||
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
|
||||
protected:
|
||||
virtual bool OpenWindow(cWindow *Window);
|
||||
virtual void CommitWindow(cWindow *Window);
|
||||
virtual void ShowWindow(cWindow *Window);
|
||||
virtual void HideWindow(cWindow *Window, bool Hide);
|
||||
virtual void MoveWindow(cWindow *Window, int x, int y);
|
||||
virtual void CloseWindow(cWindow *Window);
|
||||
public:
|
||||
cDvbOsd(int x, int y);
|
||||
cDvbOsd(int Left, int Top, int OsdDev);
|
||||
virtual ~cDvbOsd();
|
||||
static void SetDvbDevice(const cDvbDevice *DvbDevice);
|
||||
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
class cDvbOsdProvider : public cOsdProvider {
|
||||
private:
|
||||
int osdDev;
|
||||
public:
|
||||
cDvbOsdProvider(int OsdDev);
|
||||
virtual cOsd *CreateOsd(int Left, int Top);
|
||||
};
|
||||
|
||||
#endif //__DVBOSD_H
|
||||
|
17
dvbspu.c
17
dvbspu.c
@ -8,7 +8,7 @@
|
||||
*
|
||||
* parts of this file are derived from the OMS program.
|
||||
*
|
||||
* $Id: dvbspu.c 1.5 2003/10/12 09:43:18 kls Exp $
|
||||
* $Id: dvbspu.c 1.6 2004/04/30 13:45:02 kls Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -16,8 +16,6 @@
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "osd.h"
|
||||
#include "osdbase.h"
|
||||
#include "device.h"
|
||||
#include "dvbspu.h"
|
||||
|
||||
@ -105,13 +103,13 @@ cBitmap *cDvbSpuBitmap::getBitmap(const aDvbSpuPalDescr paldescr,
|
||||
if (w & 0x03)
|
||||
w += 4 - (w & 0x03);
|
||||
|
||||
cBitmap *ret = new cBitmap(w, h, 2, true);
|
||||
cBitmap *ret = new cBitmap(w, h, 2);
|
||||
|
||||
// set the palette
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint32_t color =
|
||||
pal.getColor(paldescr[i].index, paldescr[i].trans);
|
||||
ret->SetColor(i, (eDvbColor) color);
|
||||
ret->SetColor(i, (tColor) color);
|
||||
}
|
||||
|
||||
// set the content
|
||||
@ -323,8 +321,9 @@ int cDvbSpuDecoder::ScaleYres(int value)
|
||||
|
||||
void cDvbSpuDecoder::DrawBmp(sDvbSpuRect & size, cBitmap * bmp)
|
||||
{
|
||||
osd->Create(size.x1, size.y1, size.width(), size.height(), 2, false);
|
||||
osd->SetBitmap(size.x1, size.y1, *bmp);
|
||||
tArea Area = { size.x1, size.y1, size.x2, size.y2, 2 };
|
||||
osd->SetAreas(&Area, 1);
|
||||
osd->DrawBitmap(size.x1, size.y1, *bmp);
|
||||
delete bmp;
|
||||
}
|
||||
|
||||
@ -360,8 +359,8 @@ void cDvbSpuDecoder::Draw(void)
|
||||
|
||||
if (bg || fg) {
|
||||
if (osd == NULL)
|
||||
if ((osd = cOsd::OpenRaw(0, 0)) == NULL) {
|
||||
dsyslog("OpenRaw failed\n");
|
||||
if ((osd = cOsdProvider::NewOsd(0, 0)) == NULL) {
|
||||
dsyslog("NewOsd failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
6
dvbspu.h
6
dvbspu.h
@ -8,7 +8,7 @@
|
||||
*
|
||||
* parts of this file are derived from the OMS program.
|
||||
*
|
||||
* $Id: dvbspu.h 1.2 2002/09/29 13:49:01 kls Exp $
|
||||
* $Id: dvbspu.h 1.3 2004/04/30 13:44:41 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBSPU_H
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "osdbase.h"
|
||||
#include "osd.h"
|
||||
#include "spu.h"
|
||||
|
||||
typedef struct sDvbSpuPalDescr {
|
||||
@ -91,7 +91,7 @@ class cDvbSpuBitmap {
|
||||
|
||||
class cDvbSpuDecoder:public cSpuDecoder {
|
||||
private:
|
||||
cOsdBase * osd;
|
||||
cOsd * osd;
|
||||
|
||||
// processing state
|
||||
uint8_t *spu;
|
||||
|
@ -4,14 +4,14 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eitscan.c 1.21 2004/02/14 13:44:31 kls Exp $
|
||||
* $Id: eitscan.c 1.22 2004/04/16 13:33:34 kls Exp $
|
||||
*/
|
||||
|
||||
#include "eitscan.h"
|
||||
#include <stdlib.h>
|
||||
#include "channels.h"
|
||||
#include "dvbdevice.h"
|
||||
#include "interface.h"
|
||||
#include "skins.h"
|
||||
|
||||
// --- cScanData -------------------------------------------------------------
|
||||
|
||||
@ -149,7 +149,7 @@ void cEITScanner::Process(void)
|
||||
if ((!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) && Device->ProvidesTransponder(Channel)) {
|
||||
if (Device == cDevice::PrimaryDevice() && !currentChannel) {
|
||||
currentChannel = Device->CurrentChannel();
|
||||
Interface->Info("Starting EPG scan");
|
||||
Skins.Message(mtInfo, "Starting EPG scan");
|
||||
}
|
||||
currentDevice = Device;//XXX see also dvbdevice.c!!!
|
||||
Device->SwitchChannel(Channel, false);
|
||||
|
136
font.c
136
font.c
@ -4,9 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: font.c 1.5 2004/01/16 13:17:57 kls Exp $
|
||||
* $Id: font.c 1.6 2004/04/24 15:25:48 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "font.h"
|
||||
#include "tools.h"
|
||||
|
||||
@ -22,6 +24,8 @@
|
||||
#include "fontosd-iso8859-7.c"
|
||||
#include "fontsml-iso8859-7.c"
|
||||
|
||||
// --- cFont -----------------------------------------------------------------
|
||||
|
||||
static void *FontData[eDvbCodeSize][eDvbFontSize] = {
|
||||
{ FontOsd_iso8859_1, FontFix_iso8859_1, FontSml_iso8859_1 },
|
||||
{ FontOsd_iso8859_5, FontFix_iso8859_5, FontSml_iso8859_5 },
|
||||
@ -44,9 +48,9 @@ cFont::cFont(void *Data)
|
||||
|
||||
void cFont::SetData(void *Data)
|
||||
{
|
||||
int h = ((tCharData *)Data)->height;
|
||||
height = ((tCharData *)Data)->height;
|
||||
for (int i = 0; i < NUMCHARS; i++)
|
||||
data[i] = (tCharData *)&((tPixelData *)Data)[(i < 32 ? 0 : i - 32) * (h + 2)];
|
||||
data[i] = (tCharData *)&((tPixelData *)Data)[(i < 32 ? 0 : i - 32) * (height + 2)];
|
||||
}
|
||||
|
||||
int cFont::Width(const char *s) const
|
||||
@ -61,7 +65,7 @@ int cFont::Height(const char *s) const
|
||||
{
|
||||
int h = 0;
|
||||
if (s && *s)
|
||||
h = Height(*s); // all characters have the same height!
|
||||
h = height; // all characters have the same height!
|
||||
return h;
|
||||
}
|
||||
|
||||
@ -95,7 +99,131 @@ void cFont::SetFont(eDvbFont Font, void *Data)
|
||||
|
||||
const cFont *cFont::GetFont(eDvbFont Font)
|
||||
{
|
||||
if (Setup.UseSmallFont == 0 && Font == fontSml)
|
||||
Font = fontOsd;
|
||||
else if (Setup.UseSmallFont == 2 && Font == fontOsd)
|
||||
Font = fontSml;
|
||||
if (!fonts[Font])
|
||||
SetFont(Font);
|
||||
return fonts[Font];
|
||||
}
|
||||
|
||||
// --- cTextWrapper ----------------------------------------------------------
|
||||
|
||||
cTextWrapper::cTextWrapper(void)
|
||||
{
|
||||
text = eol = NULL;
|
||||
lines = 0;
|
||||
lastLine = -1;
|
||||
}
|
||||
|
||||
cTextWrapper::cTextWrapper(const char *Text, const cFont *Font, int Width)
|
||||
{
|
||||
text = NULL;
|
||||
Set(Text, Font, Width);
|
||||
}
|
||||
|
||||
cTextWrapper::~cTextWrapper()
|
||||
{
|
||||
free(text);
|
||||
}
|
||||
|
||||
void cTextWrapper::Set(const char *Text, const cFont *Font, int Width)
|
||||
{
|
||||
free(text);
|
||||
text = Text ? strdup(Text) : NULL;
|
||||
eol = NULL;
|
||||
lines = 0;
|
||||
lastLine = -1;
|
||||
if (!text)
|
||||
return;
|
||||
lines = 1;
|
||||
if (Width <= 0)
|
||||
return;
|
||||
|
||||
char *Blank = NULL;
|
||||
char *Delim = NULL;
|
||||
int w = 0;
|
||||
|
||||
stripspace(text); // strips trailing newlines
|
||||
|
||||
for (char *p = text; *p; ) {
|
||||
if (*p == '\n') {
|
||||
lines++;
|
||||
w = 0;
|
||||
Blank = Delim = NULL;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
else if (isspace(*p))
|
||||
Blank = p;
|
||||
int cw = Font->Width(*p);
|
||||
if (w + cw > Width) {
|
||||
if (Blank) {
|
||||
*Blank = '\n';
|
||||
p = Blank;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// Here's the ugly part, where we don't have any whitespace to
|
||||
// punch in a newline, so we need to make room for it:
|
||||
if (Delim)
|
||||
p = Delim + 1; // let's fall back to the most recent delimiter
|
||||
char *s = MALLOC(char, strlen(text) + 2); // The additional '\n' plus the terminating '\0'
|
||||
int l = p - text;
|
||||
strncpy(s, text, l);
|
||||
s[l] = '\n';
|
||||
strcpy(s + l + 1, p);
|
||||
free(text);
|
||||
text = s;
|
||||
p = text + l;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
w += cw;
|
||||
if (strchr("-.,:;!?_", *p)) {
|
||||
Delim = p;
|
||||
Blank = NULL;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
const char *cTextWrapper::Text(void)
|
||||
{
|
||||
if (eol) {
|
||||
*eol = '\n';
|
||||
eol = NULL;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
const char *cTextWrapper::GetLine(int Line)
|
||||
{
|
||||
char *s = NULL;
|
||||
if (Line < lines) {
|
||||
if (eol) {
|
||||
*eol = '\n';
|
||||
if (Line == lastLine + 1)
|
||||
s = eol + 1;
|
||||
eol = NULL;
|
||||
}
|
||||
if (!s) {
|
||||
s = text;
|
||||
for (int i = 0; i < Line; i++) {
|
||||
s = strchr(s, '\n');
|
||||
if (s)
|
||||
s++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s) {
|
||||
if ((eol = strchr(s, '\n')) != NULL)
|
||||
*eol = 0;
|
||||
}
|
||||
lastLine = Line;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
32
font.h
32
font.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: font.h 1.5 2004/01/16 13:18:28 kls Exp $
|
||||
* $Id: font.h 1.6 2004/04/12 10:21:03 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __FONT_H
|
||||
@ -38,13 +38,20 @@ private:
|
||||
static eDvbCode code;
|
||||
static cFont *fonts[];
|
||||
const tCharData *data[NUMCHARS];
|
||||
int height;
|
||||
public:
|
||||
cFont(void *Data);
|
||||
void SetData(void *Data);
|
||||
int Width(unsigned char c) const { return data[c]->width; }
|
||||
///< Returns the width of the given character.
|
||||
int Width(const char *s) const;
|
||||
///< Returns the width of the given string.
|
||||
int Height(unsigned char c) const { return data[c]->height; }
|
||||
///< Returns the height of the given character.
|
||||
int Height(const char *s) const;
|
||||
///< Returns the height of the given string.
|
||||
int Height(void) const { return height; }
|
||||
///< Returns the height of this font (all characters have the same height).
|
||||
const tCharData *CharData(unsigned char c) const { return data[c]; }
|
||||
static bool SetCode(const char *Code);
|
||||
static void SetCode(eDvbCode Code);
|
||||
@ -52,4 +59,27 @@ public:
|
||||
static const cFont *GetFont(eDvbFont Font);
|
||||
};
|
||||
|
||||
class cTextWrapper {
|
||||
private:
|
||||
char *text;
|
||||
char *eol;
|
||||
int lines;
|
||||
int lastLine;
|
||||
public:
|
||||
cTextWrapper(void);
|
||||
cTextWrapper(const char *Text, const cFont *Font, int Width);
|
||||
~cTextWrapper();
|
||||
void Set(const char *Text, const cFont *Font, int Width);
|
||||
///< Wraps the Text to make it fit into the area defined by the given Width
|
||||
///< when displayed with the given Font.
|
||||
///< Wrapping is done by inserting the necessary number of newline
|
||||
///< characters into the string.
|
||||
const char *Text(void);
|
||||
///< Returns the full wrapped text.
|
||||
int Lines(void) { return lines; }
|
||||
///< Returns the actual number of lines needed to display the full wrapped text.
|
||||
const char *GetLine(int Line);
|
||||
///< Returns the given Line. The first line is numbered 0.
|
||||
};
|
||||
|
||||
#endif //__FONT_H
|
||||
|
182
i18n.c
182
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.153 2004/03/26 15:02:59 kls Exp $
|
||||
* $Id: i18n.c 1.154 2004/05/08 09:25:02 kls Exp $
|
||||
*
|
||||
* Translations provided by:
|
||||
*
|
||||
@ -2193,6 +2193,78 @@ const tI18nPhrase Phrases[] = {
|
||||
"Idioma",
|
||||
"Ï×ëÚ",
|
||||
},
|
||||
{ "Setup.OSD$Skin",
|
||||
"Oberfläche",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Setup.OSD$Theme",
|
||||
"Thema",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Setup.OSD$Left",
|
||||
"Links",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Setup.OSD$Top",
|
||||
"Oben",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Setup.OSD$Width",
|
||||
"Breite",
|
||||
"Sirina",
|
||||
@ -2247,6 +2319,78 @@ const tI18nPhrase Phrases[] = {
|
||||
"Durada dels missatges (s)",
|
||||
"´ÛØâÕÛìÝÞáâì ßÞÚÐ×Ð áÞÞÑéÕÝØÙ (áÕÚ)",
|
||||
},
|
||||
{ "Setup.OSD$Use small font",
|
||||
"Kleine Schrift benutzen",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "never",
|
||||
"nie",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "skin dependent",
|
||||
"je nach Oberfläche",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "always",
|
||||
"immer",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Setup.OSD$Channel info position",
|
||||
"Kanal-Info Position",
|
||||
"Pozicija informacije o kanalu",
|
||||
@ -4214,6 +4358,42 @@ const tI18nPhrase Phrases[] = {
|
||||
"Aquest plugin no admet configuració!",
|
||||
"¼ÞÔãÛì ÝÕ ØÜÕÕâ ßÐàÐÜÕâàÞÒ ÝÐáâàÞÙÚØ!",
|
||||
},
|
||||
{ "Classic VDR",
|
||||
"Klassischer VDR",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "ST:TNG Panels",
|
||||
"ST:TNG Konsolen",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
341
interface.c
341
interface.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.c 1.66 2003/10/24 15:48:00 kls Exp $
|
||||
* $Id: interface.c 1.67 2004/05/02 10:57:06 kls Exp $
|
||||
*/
|
||||
|
||||
#include "interface.h"
|
||||
@ -12,16 +12,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "i18n.h"
|
||||
#include "osd.h"
|
||||
#include "status.h"
|
||||
|
||||
cInterface *Interface = NULL;
|
||||
|
||||
cInterface::cInterface(int SVDRPport)
|
||||
{
|
||||
open = 0;
|
||||
cols[0] = 0;
|
||||
width = height = 0;
|
||||
interrupted = false;
|
||||
SVDRP = NULL;
|
||||
if (SVDRPport)
|
||||
@ -33,38 +29,17 @@ cInterface::~cInterface()
|
||||
delete SVDRP;
|
||||
}
|
||||
|
||||
void cInterface::Open(int NumCols, int NumLines)
|
||||
{
|
||||
if (!open++) {
|
||||
if (NumCols == 0)
|
||||
NumCols = Setup.OSDwidth;
|
||||
if (NumLines == 0)
|
||||
NumLines = Setup.OSDheight;
|
||||
cOsd::Open(width = NumCols, height = NumLines);
|
||||
}
|
||||
}
|
||||
|
||||
void cInterface::Close(void)
|
||||
{
|
||||
if (open == 1)
|
||||
Clear();
|
||||
if (!--open) {
|
||||
cOsd::Close();
|
||||
width = height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
eKeys cInterface::GetKey(bool Wait)
|
||||
{
|
||||
if (!cRemote::HasKeys())
|
||||
Flush();
|
||||
Skins.Flush();
|
||||
if (SVDRP) {
|
||||
if (SVDRP->Process())
|
||||
Wait = false;
|
||||
if (!open) {
|
||||
if (!Skins.IsOpen()) {
|
||||
char *message = SVDRP->GetMessage();
|
||||
if (message) {
|
||||
Info(message);
|
||||
Skins.Message(mtInfo, message);
|
||||
free(message);
|
||||
}
|
||||
}
|
||||
@ -76,7 +51,7 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||
{
|
||||
if (Seconds == 0)
|
||||
Seconds = Setup.OSDMessageTime;
|
||||
Flush();
|
||||
Skins.Flush();
|
||||
eKeys Key = kNone;
|
||||
time_t timeout = time(NULL) + Seconds;
|
||||
for (;;) {
|
||||
@ -90,267 +65,37 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||
return Key;
|
||||
}
|
||||
|
||||
void cInterface::Clear(void)
|
||||
{
|
||||
if (open)
|
||||
cOsd::Clear();
|
||||
cStatus::MsgOsdClear();
|
||||
}
|
||||
|
||||
void cInterface::ClearEol(int x, int y, eDvbColor Color)
|
||||
{
|
||||
if (open)
|
||||
cOsd::ClrEol(x, y, Color);
|
||||
}
|
||||
|
||||
void cInterface::Fill(int x, int y, int w, int h, eDvbColor Color)
|
||||
{
|
||||
if (open)
|
||||
cOsd::Fill(x, y, w, h, Color);
|
||||
}
|
||||
|
||||
void cInterface::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
{
|
||||
if (open)
|
||||
cOsd::SetBitmap(x, y, Bitmap);
|
||||
}
|
||||
|
||||
void cInterface::Flush(void)
|
||||
{
|
||||
if (open)
|
||||
cOsd::Flush();
|
||||
}
|
||||
|
||||
void cInterface::SetCols(int *c)
|
||||
{
|
||||
for (int i = 0; i < MaxCols; i++) {
|
||||
cols[i] = *c++;
|
||||
if (cols[i] == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eDvbFont cInterface::SetFont(eDvbFont Font)
|
||||
{
|
||||
return cOsd::SetFont(Font);
|
||||
}
|
||||
|
||||
char *cInterface::WrapText(const char *Text, int Width, int *Height)
|
||||
{
|
||||
// Wraps the Text to make it fit into the area defined by the given Width
|
||||
// (which is given in character cells).
|
||||
// The actual number of lines resulting from this operation is returned in
|
||||
// Height.
|
||||
// The returned string is newly created on the heap and the caller
|
||||
// is responsible for deleting it once it is no longer used.
|
||||
// Wrapping is done by inserting the necessary number of newline
|
||||
// characters into the string.
|
||||
|
||||
int Lines = 1;
|
||||
char *t = strdup(Text);
|
||||
char *Blank = NULL;
|
||||
char *Delim = NULL;
|
||||
int w = 0;
|
||||
|
||||
Width *= cOsd::CellWidth();
|
||||
|
||||
while (*t && t[strlen(t) - 1] == '\n')
|
||||
t[strlen(t) - 1] = 0; // skips trailing newlines
|
||||
|
||||
for (char *p = t; *p; ) {
|
||||
if (*p == '|')
|
||||
*p = '\n';
|
||||
if (*p == '\n') {
|
||||
Lines++;
|
||||
w = 0;
|
||||
Blank = Delim = NULL;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
else if (isspace(*p))
|
||||
Blank = p;
|
||||
int cw = cOsd::Width(*p);
|
||||
if (w + cw > Width) {
|
||||
if (Blank) {
|
||||
*Blank = '\n';
|
||||
p = Blank;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// Here's the ugly part, where we don't have any whitespace to
|
||||
// punch in a newline, so we need to make room for it:
|
||||
if (Delim)
|
||||
p = Delim + 1; // let's fall back to the most recent delimiter
|
||||
char *s = MALLOC(char, strlen(t) + 2); // The additional '\n' plus the terminating '\0'
|
||||
int l = p - t;
|
||||
strncpy(s, t, l);
|
||||
s[l] = '\n';
|
||||
strcpy(s + l + 1, p);
|
||||
free(t);
|
||||
t = s;
|
||||
p = t + l;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
w += cw;
|
||||
if (strchr("-.,:;!?_", *p)) {
|
||||
Delim = p;
|
||||
Blank = NULL;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
*Height = Lines;
|
||||
return t;
|
||||
}
|
||||
|
||||
void cInterface::Write(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
if (open)
|
||||
cOsd::Text(x, y, s, FgColor, BgColor);
|
||||
}
|
||||
|
||||
void cInterface::WriteText(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
if (open) {
|
||||
ClearEol(x, y, BgColor);
|
||||
int col = 0;
|
||||
for (;;) {
|
||||
const char *t = strchr(s, '\t');
|
||||
const char *p = s;
|
||||
char buf[1000];
|
||||
if (t && col < MaxCols && cols[col] > 0) {
|
||||
unsigned int n = t - s;
|
||||
if (n >= sizeof(buf))
|
||||
n = sizeof(buf) - 1;
|
||||
strncpy(buf, s, n);
|
||||
buf[n] = 0;
|
||||
p = buf;
|
||||
s = t + 1;
|
||||
}
|
||||
Write(x, y, p, FgColor, BgColor);
|
||||
if (p == s)
|
||||
break;
|
||||
x += cols[col++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cInterface::Title(const char *s)
|
||||
{
|
||||
ClearEol(0, 0, clrCyan);
|
||||
const char *t = strchr(s, '\t');
|
||||
if (t) {
|
||||
char buffer[Width() + 1];
|
||||
unsigned int n = t - s;
|
||||
if (n >= sizeof(buffer))
|
||||
n = sizeof(buffer) - 1;
|
||||
strn0cpy(buffer, s, n + 1);
|
||||
Write(1, 0, buffer, clrBlack, clrCyan);
|
||||
t++;
|
||||
Write(-(cOsd::WidthInCells(t) + 1), 0, t, clrBlack, clrCyan);
|
||||
}
|
||||
else {
|
||||
int x = (Width() - strlen(s)) / 2;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
Write(x, 0, s, clrBlack, clrCyan);
|
||||
}
|
||||
cStatus::MsgOsdTitle(s);
|
||||
}
|
||||
|
||||
void cInterface::Status(const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
int Line = (abs(height) == 1) ? 0 : -2;
|
||||
ClearEol(0, Line, s ? BgColor : clrBackground);
|
||||
if (s) {
|
||||
int x = (Width() - int(strlen(s))) / 2;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
Write(x, Line, s, FgColor, BgColor);
|
||||
}
|
||||
cStatus::MsgOsdStatusMessage(s);
|
||||
}
|
||||
|
||||
void cInterface::Info(const char *s)
|
||||
{
|
||||
Open(Setup.OSDwidth, -1);
|
||||
isyslog("info: %s", s);
|
||||
Status(s, clrBlack, clrGreen);
|
||||
Wait();
|
||||
Status(NULL);
|
||||
Close();
|
||||
}
|
||||
|
||||
void cInterface::Error(const char *s)
|
||||
{
|
||||
Open(Setup.OSDwidth, -1);
|
||||
esyslog("ERROR: %s", s);
|
||||
Status(s, clrWhite, clrRed);
|
||||
Wait();
|
||||
Status(NULL);
|
||||
Close();
|
||||
}
|
||||
|
||||
bool cInterface::Confirm(const char *s, int Seconds, bool WaitForTimeout)
|
||||
{
|
||||
Open(Setup.OSDwidth, -1);
|
||||
isyslog("confirm: %s", s);
|
||||
Status(s, clrBlack, clrYellow);
|
||||
eKeys k = Wait(Seconds);
|
||||
eKeys k = Skins.Message(mtWarning, s, Seconds);
|
||||
bool result = WaitForTimeout ? k == kNone : k == kOk;
|
||||
Status(NULL);
|
||||
Close();
|
||||
isyslog("%sconfirmed", result ? "" : "not ");
|
||||
return result;
|
||||
}
|
||||
|
||||
void cInterface::HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor)
|
||||
bool cInterface::QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu)
|
||||
{
|
||||
if (open) {
|
||||
const int w = Width() / 4;
|
||||
cOsd::Fill(Index * w, -1, w, 1, Text ? BgColor : clrBackground);
|
||||
if (Text) {
|
||||
int l = (w - int(strlen(Text))) / 2;
|
||||
if (l < 0)
|
||||
l = 0;
|
||||
cOsd::Text(Index * w + l, -1, Text, FgColor, BgColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cInterface::Help(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||
{
|
||||
HelpButton(0, Red, clrBlack, clrRed);
|
||||
HelpButton(1, Green, clrBlack, clrGreen);
|
||||
HelpButton(2, Yellow, clrBlack, clrYellow);
|
||||
HelpButton(3, Blue, clrWhite, clrBlue);
|
||||
cStatus::MsgOsdHelpKeys(Red, Green, Yellow, Blue);
|
||||
}
|
||||
|
||||
bool cInterface::QueryKeys(cRemote *Remote)
|
||||
{
|
||||
WriteText(1, 3, tr("Phase 1: Detecting RC code type"));
|
||||
WriteText(1, 5, tr("Press any key on the RC unit"));
|
||||
Flush();
|
||||
DisplayMenu->SetItem(tr("Phase 1: Detecting RC code type"), 1, false, false);
|
||||
DisplayMenu->SetItem(tr("Press any key on the RC unit"), 3, false, false);
|
||||
DisplayMenu->Flush();
|
||||
if (Remote->Initialize()) {
|
||||
WriteText(1, 5, tr("RC code detected!"));
|
||||
WriteText(1, 6, tr("Do not press any key..."));
|
||||
Flush();
|
||||
DisplayMenu->SetItem(tr("RC code detected!"), 3, false, false);
|
||||
DisplayMenu->SetItem(tr("Do not press any key..."), 4, false, false);
|
||||
DisplayMenu->Flush();
|
||||
sleep(3);
|
||||
ClearEol(0, 5);
|
||||
ClearEol(0, 6);
|
||||
DisplayMenu->SetItem("", 3, false, false);
|
||||
DisplayMenu->SetItem("", 4, false, false);
|
||||
|
||||
WriteText(1, 3, tr("Phase 2: Learning specific key codes"));
|
||||
DisplayMenu->SetItem(tr("Phase 2: Learning specific key codes"), 1, false, false);
|
||||
eKeys NewKey = kUp;
|
||||
while (NewKey != kNone) {
|
||||
char *Prompt;
|
||||
asprintf(&Prompt, tr("Press key for '%s'"), tr(cKey::ToString(NewKey)));
|
||||
WriteText(1, 5, Prompt);
|
||||
DisplayMenu->SetItem(Prompt, 3, false, false);
|
||||
free(Prompt);
|
||||
cRemote::Clear();
|
||||
Flush();
|
||||
DisplayMenu->Flush();
|
||||
for (eKeys k = NewKey; k == NewKey; ) {
|
||||
char *NewCode = NULL;
|
||||
eKeys Key = cRemote::Get(100, &NewCode);
|
||||
@ -362,20 +107,20 @@ bool cInterface::QueryKeys(cRemote *Remote)
|
||||
Keys.Del(last);
|
||||
}
|
||||
break;
|
||||
case kDown: WriteText(1, 5, tr("Press 'Up' to confirm"));
|
||||
WriteText(1, 6, tr("Press 'Down' to continue"));
|
||||
ClearEol(0, 7);
|
||||
ClearEol(0, 8);
|
||||
ClearEol(0, 9);
|
||||
Flush();
|
||||
case kDown: DisplayMenu->SetItem(tr("Press 'Up' to confirm"), 3, false, false);
|
||||
DisplayMenu->SetItem(tr("Press 'Down' to continue"), 4, false, false);
|
||||
DisplayMenu->SetItem("", 5, false, false);
|
||||
DisplayMenu->SetItem("", 6, false, false);
|
||||
DisplayMenu->SetItem("", 7, false, false);
|
||||
DisplayMenu->Flush();
|
||||
for (;;) {
|
||||
Key = cRemote::Get(100);
|
||||
if (Key == kUp) {
|
||||
Clear();
|
||||
DisplayMenu->Clear();
|
||||
return true;
|
||||
}
|
||||
else if (Key == kDown) {
|
||||
ClearEol(0, 6);
|
||||
DisplayMenu->SetItem("", 4, false, false);
|
||||
k = kNone; // breaks the outer for() loop
|
||||
break;
|
||||
}
|
||||
@ -394,17 +139,17 @@ bool cInterface::QueryKeys(cRemote *Remote)
|
||||
}
|
||||
}
|
||||
if (NewKey > kUp)
|
||||
WriteText(1, 7, tr("(press 'Up' to go back)"));
|
||||
DisplayMenu->SetItem(tr("(press 'Up' to go back)"), 5, false, false);
|
||||
else
|
||||
ClearEol(0, 7);
|
||||
DisplayMenu->SetItem("", 5, false, false);
|
||||
if (NewKey > kDown)
|
||||
WriteText(1, 8, tr("(press 'Down' to end key definition)"));
|
||||
DisplayMenu->SetItem(tr("(press 'Down' to end key definition)"), 6, false, false);
|
||||
else
|
||||
ClearEol(0, 8);
|
||||
DisplayMenu->SetItem("", 6, false, false);
|
||||
if (NewKey > kMenu)
|
||||
WriteText(1, 9, tr("(press 'Menu' to skip this key)"));
|
||||
DisplayMenu->SetItem(tr("(press 'Menu' to skip this key)"), 7, false, false);
|
||||
else
|
||||
ClearEol(0, 9);
|
||||
DisplayMenu->SetItem("", 7, false, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -421,33 +166,31 @@ void cInterface::LearnKeys(void)
|
||||
bool known = Keys.KnowsRemote(Remote->Name());
|
||||
dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
|
||||
if (!known) {
|
||||
Open();
|
||||
char Headline[Width()];
|
||||
cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu();
|
||||
char Headline[256];
|
||||
snprintf(Headline, sizeof(Headline), tr("Learning Remote Control Keys (%s)"), Remote->Name());
|
||||
Clear();
|
||||
cRemote::Clear();
|
||||
WriteText(1, 1, Headline);
|
||||
DisplayMenu->SetTitle(Headline);
|
||||
cRemote::SetLearning(Remote);
|
||||
bool rc = QueryKeys(Remote);
|
||||
bool rc = QueryKeys(Remote, DisplayMenu);
|
||||
cRemote::SetLearning(NULL);
|
||||
Clear();
|
||||
DisplayMenu->Clear();
|
||||
if (!rc) {
|
||||
Close();
|
||||
delete DisplayMenu;
|
||||
continue;
|
||||
}
|
||||
WriteText(1, 1, Headline);
|
||||
WriteText(1, 3, tr("Phase 3: Saving key codes"));
|
||||
WriteText(1, 5, tr("Press 'Up' to save, 'Down' to cancel"));
|
||||
DisplayMenu->SetItem(tr("Phase 3: Saving key codes"), 1, false, false);
|
||||
DisplayMenu->SetItem(tr("Press 'Up' to save, 'Down' to cancel"), 3, false, false);
|
||||
for (;;) {
|
||||
eKeys key = GetKey();
|
||||
if (key == kUp) {
|
||||
Keys.Save();
|
||||
Close();
|
||||
delete DisplayMenu;
|
||||
break;
|
||||
}
|
||||
else if (key == kDown) {
|
||||
Keys.Load();
|
||||
Close();
|
||||
delete DisplayMenu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
35
interface.h
35
interface.h
@ -4,57 +4,30 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.h 1.30 2003/10/05 09:42:53 kls Exp $
|
||||
* $Id: interface.h 1.31 2004/05/01 11:11:13 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __INTERFACE_H
|
||||
#define __INTERFACE_H
|
||||
|
||||
#include "config.h"
|
||||
#include "osdbase.h"
|
||||
#include "remote.h"
|
||||
#include "skins.h"
|
||||
#include "svdrp.h"
|
||||
|
||||
class cInterface {
|
||||
public:
|
||||
enum { MaxCols = 5 };
|
||||
private:
|
||||
int width, height;
|
||||
int open;
|
||||
int cols[MaxCols];
|
||||
bool interrupted;
|
||||
cSVDRP *SVDRP;
|
||||
bool QueryKeys(cRemote *Remote);
|
||||
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
|
||||
eKeys Wait(int Seconds = 0, bool KeepChar = false);
|
||||
bool QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu);
|
||||
public:
|
||||
cInterface(int SVDRPport = 0);
|
||||
~cInterface();
|
||||
bool IsOpen(void) { return open > 0; }
|
||||
void Open(int NumCols = 0, int NumLines = 0);
|
||||
void Close(void);
|
||||
bool HasSVDRPConnection(void) { return SVDRP && SVDRP->HasConnection(); }
|
||||
void Interrupt(void) { interrupted = true; }
|
||||
int Width(void) { return width; }
|
||||
int Height(void) { return height; }
|
||||
eKeys GetKey(bool Wait = true);
|
||||
void Clear(void);
|
||||
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
||||
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
|
||||
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);
|
||||
void WriteText(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
void Title(const char *s);
|
||||
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
|
||||
void Info(const char *s);
|
||||
void Error(const char *s);
|
||||
eKeys Wait(int Seconds = 0, bool KeepChar = false);
|
||||
bool Confirm(const char *s, int Seconds = 10, bool WaitForTimeout = false);
|
||||
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
void LearnKeys(void);
|
||||
};
|
||||
|
||||
|
487
menu.c
487
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.298 2004/03/28 09:17:15 kls Exp $
|
||||
* $Id: menu.c 1.299 2004/05/15 14:15:33 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -18,12 +18,14 @@
|
||||
#include "cutter.h"
|
||||
#include "eitscan.h"
|
||||
#include "i18n.h"
|
||||
#include "interface.h"
|
||||
#include "menuitems.h"
|
||||
#include "plugin.h"
|
||||
#include "recording.h"
|
||||
#include "remote.h"
|
||||
#include "sources.h"
|
||||
#include "status.h"
|
||||
#include "themes.h"
|
||||
#include "timers.h"
|
||||
#include "transfer.h"
|
||||
#include "videodir.h"
|
||||
@ -309,7 +311,7 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
|
||||
Channels.SetModified();
|
||||
}
|
||||
else {
|
||||
Interface->Error(tr("Channel settings are not unique!"));
|
||||
Skins.Message(mtError, tr("Channel settings are not unique!"));
|
||||
state = osContinue;
|
||||
}
|
||||
}
|
||||
@ -334,7 +336,7 @@ cMenuChannelItem::cMenuChannelItem(cChannel *Channel)
|
||||
{
|
||||
channel = Channel;
|
||||
if (channel->GroupSep())
|
||||
SetColor(clrCyan, clrBackground);
|
||||
SetSelectable(false);
|
||||
Set();
|
||||
}
|
||||
|
||||
@ -433,7 +435,7 @@ eOSState cMenuChannels::Delete(void)
|
||||
// Check if there is a timer using this channel:
|
||||
for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) {
|
||||
if (ti->Channel() == channel) {
|
||||
Interface->Error(tr("Channel is being used by a timer!"));
|
||||
Skins.Message(mtError, tr("Channel is being used by a timer!"));
|
||||
return osContinue;
|
||||
}
|
||||
}
|
||||
@ -498,19 +500,42 @@ eOSState cMenuChannels::ProcessKey(eKeys Key)
|
||||
// --- cMenuText -------------------------------------------------------------
|
||||
|
||||
class cMenuText : public cOsdMenu {
|
||||
private:
|
||||
const char *text;
|
||||
public:
|
||||
cMenuText(const char *Title, const char *Text, eDvbFont Font = fontOsd);
|
||||
virtual void Display(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuText::cMenuText(const char *Title, const char *Text, eDvbFont Font)
|
||||
:cOsdMenu(Title)
|
||||
{
|
||||
Add(new cMenuTextItem(Text, 1, 2, Setup.OSDwidth - 2, MAXOSDITEMS, clrWhite, clrBackground, Font));
|
||||
text = Text;
|
||||
}
|
||||
|
||||
void cMenuText::Display(void)
|
||||
{
|
||||
cOsdMenu::Display();
|
||||
DisplayMenu()->SetText(text, true);//XXX define control character in text to choose the font???
|
||||
}
|
||||
|
||||
eOSState cMenuText::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kUp|k_Repeat:
|
||||
case kUp:
|
||||
case kDown|k_Repeat:
|
||||
case kDown:
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft:
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight);
|
||||
return osContinue;
|
||||
default: break;
|
||||
}
|
||||
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
@ -595,7 +620,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||
if (ch)
|
||||
data.channel = ch;
|
||||
else {
|
||||
Interface->Error(tr("*** Invalid Channel ***"));
|
||||
Skins.Message(mtError, tr("*** Invalid Channel ***"));
|
||||
break;
|
||||
}
|
||||
if (!*data.file)
|
||||
@ -775,6 +800,7 @@ eOSState cMenuTimers::Summary(void)
|
||||
cTimer *ti = CurrentTimer();
|
||||
if (ti && !isempty(ti->Summary()))
|
||||
return AddSubMenu(new cMenuText(tr("Summary"), ti->Summary()));
|
||||
//XXX cSkin::SetRecording()???
|
||||
return Edit(); // convenience for people not using the Summary feature ;-)
|
||||
}
|
||||
|
||||
@ -812,7 +838,7 @@ private:
|
||||
const cEvent *event;
|
||||
public:
|
||||
cMenuEvent(const cEvent *Event, bool CanSwitch = false);
|
||||
cMenuEvent(bool Now);
|
||||
virtual void Display(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
@ -823,39 +849,34 @@ cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch)
|
||||
if (event) {
|
||||
cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true);
|
||||
if (channel) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->Name(), 5, event->GetDateString(), event->GetTimeString(), event->GetEndTimeString());
|
||||
SetTitle(buffer, false);
|
||||
free(buffer);
|
||||
int Line = 2;
|
||||
cMenuTextItem *item;
|
||||
const char *Title = event->Title();
|
||||
const char *Subtitle = event->ShortText();
|
||||
const char *ExtendedDescription = event->Description();
|
||||
if (!isempty(Title)) {
|
||||
Add(item = new cMenuTextItem(Title, 1, Line, Setup.OSDwidth - 2, -1, clrCyan));
|
||||
Line += item->Height() + 1;
|
||||
}
|
||||
if (!isempty(Subtitle)) {
|
||||
Add(item = new cMenuTextItem(Subtitle, 1, Line, Setup.OSDwidth - 2, -1, clrYellow));
|
||||
Line += item->Height() + 1;
|
||||
}
|
||||
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, "VPS: %s", Event->GetVpsString());
|
||||
Add(item = new cMenuTextItem(buffer, 1, Line, Setup.OSDwidth - 2, -1, clrYellow));
|
||||
free(buffer);
|
||||
Line += item->Height() + 1;
|
||||
}
|
||||
if (!isempty(ExtendedDescription))
|
||||
Add(new cMenuTextItem(ExtendedDescription, 1, Line, Setup.OSDwidth - 2, Height() - Line - 2, clrCyan), true);
|
||||
SetTitle(channel->Name());
|
||||
SetHelp(tr("Record"), NULL, NULL, CanSwitch ? tr("Switch") : NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cMenuEvent::Display(void)
|
||||
{
|
||||
cOsdMenu::Display();
|
||||
DisplayMenu()->SetEvent(event);
|
||||
}
|
||||
|
||||
eOSState cMenuEvent::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kUp|k_Repeat:
|
||||
case kUp:
|
||||
case kDown|k_Repeat:
|
||||
case kDown:
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft:
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight);
|
||||
return osContinue;
|
||||
default: break;
|
||||
}
|
||||
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
@ -942,7 +963,7 @@ eOSState cMenuWhatsOn::Switch(void)
|
||||
if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
|
||||
return osEnd;
|
||||
}
|
||||
Interface->Error(tr("Can't switch channel!"));
|
||||
Skins.Message(mtError, tr("Can't switch channel!"));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
@ -1086,7 +1107,7 @@ eOSState cMenuSchedule::Switch(void)
|
||||
if (Channels.SwitchTo(otherChannel))
|
||||
return osEnd;
|
||||
}
|
||||
Interface->Error(tr("Can't switch channel!"));
|
||||
Skins.Message(mtError, tr("Can't switch channel!"));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
@ -1184,10 +1205,10 @@ eOSState cMenuCommands::Execute(void)
|
||||
}
|
||||
if (confirmed) {
|
||||
asprintf(&buffer, "%s...", command->Title());
|
||||
Interface->Status(buffer);
|
||||
Interface->Flush();
|
||||
Skins.Message(mtStatus, buffer);
|
||||
free(buffer);
|
||||
const char *Result = command->Execute(parameters);
|
||||
Skins.Message(mtStatus, NULL);
|
||||
if (Result)
|
||||
return AddSubMenu(new cMenuText(command->Title(), Result, fontFix));
|
||||
return osEnd;
|
||||
@ -1388,11 +1409,11 @@ cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
|
||||
base = Base ? strdup(Base) : NULL;
|
||||
level = Setup.RecordingDirs ? Level : -1;
|
||||
Display(); // this keeps the higher level menus from showing up briefly when pressing 'Back' during replay
|
||||
if (!Base) {
|
||||
Interface->Status(tr("scanning recordings..."));
|
||||
Interface->Flush();
|
||||
}
|
||||
if (!Base)
|
||||
Skins.Message(mtStatus, tr("scanning recordings..."));
|
||||
if (Base || Recordings.Load()) {
|
||||
if (!Base)
|
||||
Skins.Message(mtStatus, NULL);
|
||||
const char *LastReplayed = cReplayControl::LastReplayed();
|
||||
cMenuRecordingItem *LastItem = NULL;
|
||||
char *LastItemText = NULL;
|
||||
@ -1459,7 +1480,7 @@ cRecording *cMenuRecordings::GetRecording(cMenuRecordingItem *Item)
|
||||
{
|
||||
cRecording *recording = Recordings.GetByName(Item->FileName());
|
||||
if (!recording)
|
||||
Interface->Error(tr("Error while accessing recording!"));
|
||||
Skins.Message(mtError, tr("Error while accessing recording!"));
|
||||
return recording;
|
||||
}
|
||||
|
||||
@ -1547,7 +1568,7 @@ eOSState cMenuRecordings::Delete(void)
|
||||
return osBack;
|
||||
}
|
||||
else
|
||||
Interface->Error(tr("Error while deleting recording!"));
|
||||
Skins.Message(mtError, tr("Error while deleting recording!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1641,39 +1662,101 @@ void cMenuSetupBase::Store(void)
|
||||
|
||||
class cMenuSetupOSD : public cMenuSetupBase {
|
||||
private:
|
||||
const char *useSmallFontTexts[3];
|
||||
int numSkins;
|
||||
int originalSkinIndex;
|
||||
int skinIndex;
|
||||
const char **skinDescriptions;
|
||||
cThemes themes;
|
||||
int themeIndex;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuSetupOSD(void) { Set(); }
|
||||
virtual ~cMenuSetupOSD() { cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]); }
|
||||
cMenuSetupOSD(void);
|
||||
virtual ~cMenuSetupOSD();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuSetupOSD::cMenuSetupOSD(void)
|
||||
{
|
||||
numSkins = Skins.Count();
|
||||
skinIndex = originalSkinIndex = Skins.Current()->Index();
|
||||
skinDescriptions = new const char*[numSkins];
|
||||
themes.Load(Skins.Current()->Name());
|
||||
themeIndex = Skins.Current()->Theme() ? themes.GetThemeIndex(Skins.Current()->Theme()->Description()) : 0;
|
||||
Set();
|
||||
}
|
||||
|
||||
cMenuSetupOSD::~cMenuSetupOSD()
|
||||
{
|
||||
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
|
||||
delete skinDescriptions;
|
||||
}
|
||||
|
||||
void cMenuSetupOSD::Set(void)
|
||||
{
|
||||
int current = Current();
|
||||
for (cSkin *Skin = Skins.First(); Skin; Skin = Skins.Next(Skin))
|
||||
skinDescriptions[Skin->Index()] = Skin->Description();
|
||||
useSmallFontTexts[0] = tr("never");
|
||||
useSmallFontTexts[1] = tr("skin dependent");
|
||||
useSmallFontTexts[2] = tr("always");
|
||||
Clear();
|
||||
SetSection(tr("OSD"));
|
||||
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 cMenuEditStraItem(tr("Setup.OSD$Skin"), &skinIndex, numSkins, skinDescriptions));
|
||||
if (themes.NumThemes())
|
||||
Add(new cMenuEditStraItem(tr("Setup.OSD$Theme"), &themeIndex, themes.NumThemes(), themes.Descriptions()));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Left"), &data.OSDLeft, 0, MAXOSDWIDTH));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Top"), &data.OSDTop, 0, MAXOSDHEIGHT));
|
||||
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));
|
||||
Add(new cMenuEditStraItem(tr("Setup.OSD$Use small font"), &data.UseSmallFont, 3, useSmallFontTexts));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.OSD$Channel info position"), &data.ChannelInfoPos, tr("bottom"), tr("top")));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.OSD$Info on channel switch"), &data.ShowInfoOnChSwitch));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll pages"), &data.MenuScrollPage));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.OSD$Sort timers"), &data.SortTimers));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.OSD$Recording directories"), &data.RecordingDirs));
|
||||
SetCurrent(Get(current));
|
||||
Display();
|
||||
}
|
||||
|
||||
eOSState cMenuSetupOSD::ProcessKey(eKeys Key)
|
||||
{
|
||||
if (Key == kOk) {
|
||||
if (skinIndex != originalSkinIndex) {
|
||||
cSkin *Skin = Skins.Get(skinIndex);
|
||||
if (Skin) {
|
||||
strn0cpy(data.OSDSkin, Skin->Name(), sizeof(data.OSDSkin));
|
||||
Skins.SetCurrent(Skin->Name());
|
||||
}
|
||||
}
|
||||
if (themes.NumThemes() && Skins.Current()->Theme()) {
|
||||
Skins.Current()->Theme()->Load(themes.FileName(themeIndex));
|
||||
strn0cpy(data.OSDTheme, themes.Name(themeIndex), sizeof(data.OSDTheme));
|
||||
}
|
||||
data.OSDWidth &= ~0x07; // OSD width must be a multiple of 8
|
||||
}
|
||||
|
||||
int osdLanguage = data.OSDLanguage;
|
||||
int oldSkinIndex = skinIndex;
|
||||
eOSState state = cMenuSetupBase::ProcessKey(Key);
|
||||
|
||||
if (data.OSDLanguage != osdLanguage) {
|
||||
if (data.OSDLanguage != osdLanguage || skinIndex != oldSkinIndex) {
|
||||
int OriginalOSDLanguage = Setup.OSDLanguage;
|
||||
Setup.OSDLanguage = data.OSDLanguage;
|
||||
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
|
||||
|
||||
cSkin *Skin = Skins.Get(skinIndex);
|
||||
if (Skin) {
|
||||
char *d = themes.NumThemes() ? strdup(themes.Descriptions()[themeIndex]) : NULL;
|
||||
themes.Load(Skin->Name());
|
||||
if (skinIndex != oldSkinIndex)
|
||||
themeIndex = d ? themes.GetThemeIndex(d) : 0;
|
||||
free(d);
|
||||
}
|
||||
|
||||
Set();
|
||||
Display();
|
||||
Setup.OSDLanguage = OriginalOSDLanguage;
|
||||
}
|
||||
return state;
|
||||
@ -1912,7 +1995,7 @@ eOSState cMenuSetupCICAM::Menu(void)
|
||||
if (CiHandler && CiHandler->EnterMenu(Slot))
|
||||
return osEnd; // the CAM menu will be executed explicitly from the main loop
|
||||
else
|
||||
Interface->Error(tr("Can't open CAM menu!"));
|
||||
Skins.Message(mtError, tr("Can't open CAM menu!"));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
@ -1921,11 +2004,11 @@ eOSState cMenuSetupCICAM::Reset(void)
|
||||
int Slot = 0;
|
||||
cCiHandler *CiHandler = GetCurrentCiHandler(&Slot);
|
||||
if (CiHandler && CiHandler->Reset(Slot)) {
|
||||
Interface->Info(tr("CAM has been reset"));
|
||||
Skins.Message(mtInfo, tr("CAM has been reset"));
|
||||
return osEnd;
|
||||
}
|
||||
else
|
||||
Interface->Error(tr("Can't reset CAM!"));
|
||||
Skins.Message(mtError, tr("Can't reset CAM!"));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
@ -2064,7 +2147,7 @@ eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
|
||||
menu->SetPlugin(p);
|
||||
return AddSubMenu(menu);
|
||||
}
|
||||
Interface->Info(tr("This plugin has no setup parameters!"));
|
||||
Skins.Message(mtInfo, tr("This plugin has no setup parameters!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2199,7 +2282,7 @@ cOsdObject *cMenuMain::PluginOsdObject(void)
|
||||
void cMenuMain::Set(const char *Plugin)
|
||||
{
|
||||
Clear();
|
||||
//SetTitle("VDR"); // this is done below, including disk usage
|
||||
//XXX //SetTitle("VDR"); // this is done below, including disk usage
|
||||
SetHasHotkeys();
|
||||
|
||||
// Title with disk usage:
|
||||
@ -2213,6 +2296,7 @@ void cMenuMain::Set(const char *Plugin)
|
||||
int Hours = Minutes / 60;
|
||||
Minutes %= 60;
|
||||
snprintf(buffer, sizeof(buffer), "%s - %s %d%% - %2d:%02d %s", tr("VDR"), tr("Disk"), Percent, Hours, Minutes, tr("free"));
|
||||
//XXX -> skin function!!!
|
||||
SetTitle(buffer);
|
||||
|
||||
// Basic menu items:
|
||||
@ -2337,9 +2421,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
const char **at = &AudioTracks[CurrentAudioTrack];
|
||||
if (!*++at)
|
||||
at = AudioTracks;
|
||||
Interface->Clear();
|
||||
cDevice::PrimaryDevice()->SetAudioTrack(at - AudioTracks);
|
||||
//XXX Interface->Info(*at);
|
||||
state = osEnd;
|
||||
}
|
||||
}
|
||||
@ -2376,14 +2458,14 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
|
||||
{
|
||||
group = -1;
|
||||
withInfo = !Switched || Setup.ShowInfoOnChSwitch;
|
||||
int EpgLines = withInfo ? 5 : 1;
|
||||
lines = 0;
|
||||
displayChannel = Skins.Current()->DisplayChannel(withInfo);
|
||||
number = 0;
|
||||
channel = Channels.GetByNumber(Number);
|
||||
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
|
||||
lastPresent = lastFollowing = NULL;
|
||||
if (channel) {
|
||||
DisplayChannel();
|
||||
DisplayInfo();
|
||||
displayChannel->Flush();
|
||||
}
|
||||
lastTime = time_ms();
|
||||
}
|
||||
@ -2392,94 +2474,41 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
|
||||
:cOsdObject(true)
|
||||
{
|
||||
group = -1;
|
||||
lines = 0;
|
||||
number = 0;
|
||||
lastPresent = lastFollowing = NULL;
|
||||
lastTime = time_ms();
|
||||
withInfo = Setup.ShowInfoOnChSwitch;
|
||||
int EpgLines = withInfo ? 5 : 1;
|
||||
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
|
||||
displayChannel = Skins.Current()->DisplayChannel(withInfo);
|
||||
ProcessKey(FirstKey);
|
||||
}
|
||||
|
||||
cDisplayChannel::~cDisplayChannel()
|
||||
{
|
||||
Interface->Close();
|
||||
delete displayChannel;
|
||||
}
|
||||
|
||||
void cDisplayChannel::DisplayChannel(void)
|
||||
{
|
||||
int BufSize = Width() + 1;
|
||||
char buffer[BufSize];
|
||||
*buffer = 0;
|
||||
if (channel) {
|
||||
if (channel->GroupSep())
|
||||
snprintf(buffer, BufSize, "%s", channel->Name());
|
||||
else
|
||||
snprintf(buffer, BufSize, "%d%s %s", channel->Number(), number ? "-" : "", channel->Name());
|
||||
}
|
||||
else if (number)
|
||||
snprintf(buffer, BufSize, "%d-", number);
|
||||
else
|
||||
snprintf(buffer, BufSize, "%s", tr("*** Invalid Channel ***"));
|
||||
Interface->Fill(0, 0, Setup.OSDwidth, 1, clrBackground);
|
||||
Interface->Write(0, 0, buffer);
|
||||
const char *date = DayDateTime();
|
||||
Interface->Write(-strlen(date), 0, date);
|
||||
cStatus::MsgOsdChannel(buffer);
|
||||
displayChannel->SetChannel(channel, number);
|
||||
cStatus::MsgOsdChannel(ChannelString(channel, number));
|
||||
lastPresent = lastFollowing = NULL;
|
||||
}
|
||||
|
||||
void cDisplayChannel::DisplayInfo(void)
|
||||
{
|
||||
if (withInfo && channel) {
|
||||
const cEvent *Present = NULL, *Following = NULL;
|
||||
cSchedulesLock SchedulesLock;
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
const char *PresentTitle = NULL, *PresentSubtitle = NULL, *FollowingTitle = NULL, *FollowingSubtitle = NULL;
|
||||
int Lines = 0;
|
||||
if ((Present = Schedule->GetPresentEvent(true)) != NULL) {
|
||||
PresentTitle = Present->Title();
|
||||
if (!isempty(PresentTitle))
|
||||
Lines++;
|
||||
PresentSubtitle = Present->ShortText();
|
||||
if (!isempty(PresentSubtitle))
|
||||
Lines++;
|
||||
}
|
||||
if ((Following = Schedule->GetFollowingEvent(true)) != NULL) {
|
||||
FollowingTitle = Following->Title();
|
||||
if (!isempty(FollowingTitle))
|
||||
Lines++;
|
||||
FollowingSubtitle = Following->ShortText();
|
||||
if (!isempty(FollowingSubtitle))
|
||||
Lines++;
|
||||
}
|
||||
if (Lines > lines) {
|
||||
const int t = 6;
|
||||
int l = 1;
|
||||
Interface->Fill(0, 1, Setup.OSDwidth, Lines, clrBackground);
|
||||
if (!isempty(PresentTitle)) {
|
||||
Interface->Write(0, l, Present->GetTimeString(), clrYellow, clrBackground);
|
||||
Interface->Write(t, l, PresentTitle, clrCyan, clrBackground);
|
||||
l++;
|
||||
}
|
||||
if (!isempty(PresentSubtitle)) {
|
||||
Interface->Write(t, l, PresentSubtitle, clrCyan, clrBackground);
|
||||
l++;
|
||||
}
|
||||
if (!isempty(FollowingTitle)) {
|
||||
Interface->Write(0, l, Following->GetTimeString(), clrYellow, clrBackground);
|
||||
Interface->Write(t, l, FollowingTitle, clrCyan, clrBackground);
|
||||
l++;
|
||||
}
|
||||
if (!isempty(FollowingSubtitle)) {
|
||||
Interface->Write(t, l, FollowingSubtitle, clrCyan, clrBackground);
|
||||
}
|
||||
Interface->Flush();
|
||||
lines = Lines;
|
||||
lastTime = time_ms();
|
||||
cStatus::MsgOsdProgramme(Present ? Present->StartTime() : 0, PresentTitle, PresentSubtitle, Following ? Following->StartTime() : 0, FollowingTitle, FollowingSubtitle);
|
||||
const cEvent *Present = Schedule->GetPresentEvent(true);
|
||||
const cEvent *Following = Schedule->GetFollowingEvent(true);
|
||||
if (Present != lastPresent || Following != lastFollowing) {
|
||||
displayChannel->SetEvents(Present, Following);
|
||||
cStatus::MsgOsdProgramme(Present ? Present->StartTime() : 0, Present ? Present->Title() : NULL, Present ? Present->ShortText() : NULL, Following ? Following->StartTime() : 0, Following ? Following->Title() : NULL, Following ? Following->ShortText() : NULL);
|
||||
lastPresent = Present;
|
||||
lastFollowing = Following;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2488,11 +2517,10 @@ void cDisplayChannel::DisplayInfo(void)
|
||||
|
||||
void cDisplayChannel::Refresh(void)
|
||||
{
|
||||
Interface->Clear();
|
||||
channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
DisplayChannel();
|
||||
displayChannel->SetEvents(NULL, NULL);
|
||||
lastTime = time_ms();
|
||||
lines = 0;
|
||||
}
|
||||
|
||||
eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
@ -2509,7 +2537,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
number = number * 10 + Key - k0;
|
||||
if (number > 0) {
|
||||
channel = Channels.GetByNumber(number);
|
||||
Interface->Clear();
|
||||
displayChannel->SetEvents(NULL, NULL);
|
||||
withInfo = false;
|
||||
DisplayChannel();
|
||||
lastTime = time_ms();
|
||||
@ -2528,7 +2556,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
}
|
||||
if (n > 0) {
|
||||
// This channel is the only one that fits the input, so let's take it right away:
|
||||
Interface->Flush(); // makes sure the user sees his last input
|
||||
displayChannel->Flush(); // makes sure the user sees his last input
|
||||
Channels.SwitchTo(number);
|
||||
return osEnd;
|
||||
}
|
||||
@ -2555,7 +2583,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
group = SaveGroup;
|
||||
channel = Channels.Get(group);
|
||||
if (channel) {
|
||||
Interface->Clear();
|
||||
displayChannel->SetEvents(NULL, NULL);
|
||||
DisplayChannel();
|
||||
if (!channel->GroupSep())
|
||||
group = -1;
|
||||
@ -2604,85 +2632,50 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
};
|
||||
if (time_ms() - lastTime < INFOTIMEOUT) {
|
||||
DisplayInfo();
|
||||
displayChannel->Flush();
|
||||
return osContinue;
|
||||
}
|
||||
return osEnd;
|
||||
}
|
||||
|
||||
// --- cVolumeBar ------------------------------------------------------------
|
||||
|
||||
class cVolumeBar : public cBitmap {
|
||||
public:
|
||||
cVolumeBar(int Width, int Height, int Current, int Total, const char *Prompt = NULL);
|
||||
};
|
||||
|
||||
cVolumeBar::cVolumeBar(int Width, int Height, int Current, int Total, const char *Prompt)
|
||||
:cBitmap(Width, Height, 2)
|
||||
{
|
||||
int l = Prompt ? cBitmap::Width(Prompt) : 0;
|
||||
int p = (Width - l) * Current / Total;
|
||||
Text(0, 0, Prompt, clrGreen);
|
||||
Fill(l, 0, p, Height - 1, clrGreen);
|
||||
Fill(l + p, 0, Width - 1, Height - 1, clrWhite);
|
||||
}
|
||||
|
||||
// --- cDisplayVolume --------------------------------------------------------
|
||||
|
||||
#define VOLUMETIMEOUT 1000 //ms
|
||||
#define MUTETIMEOUT 5000 //ms
|
||||
|
||||
cDisplayVolume *cDisplayVolume::displayVolume = NULL;
|
||||
cDisplayVolume *cDisplayVolume::currentDisplayVolume = NULL;
|
||||
|
||||
cDisplayVolume::cDisplayVolume(void)
|
||||
:cOsdObject(true)
|
||||
{
|
||||
displayVolume = this;
|
||||
currentDisplayVolume = this;
|
||||
timeout = time_ms() + (cDevice::PrimaryDevice()->IsMute() ? MUTETIMEOUT : VOLUMETIMEOUT);
|
||||
Interface->Open(Setup.OSDwidth, -1);
|
||||
displayVolume = Skins.Current()->DisplayVolume();
|
||||
Show();
|
||||
}
|
||||
|
||||
cDisplayVolume::~cDisplayVolume()
|
||||
{
|
||||
Interface->Close();
|
||||
displayVolume = NULL;
|
||||
delete displayVolume;
|
||||
currentDisplayVolume = NULL;
|
||||
}
|
||||
|
||||
void cDisplayVolume::Show(void)
|
||||
{
|
||||
cDevice *device = cDevice::PrimaryDevice();
|
||||
if (device->IsMute()) {
|
||||
Interface->Fill(0, 0, Width(), 1, clrTransparent);
|
||||
Interface->Write(0, 0, tr("Mute"), clrGreen);
|
||||
}
|
||||
else {
|
||||
int Current = cDevice::CurrentVolume();
|
||||
int Total = MAXVOLUME;
|
||||
const char *Prompt = tr("Volume ");
|
||||
#ifdef DEBUG_OSD
|
||||
int l = strlen(Prompt);
|
||||
int p = int(double(Width() - l) * Current / Total + 0.5);
|
||||
Interface->Write(0, 0, Prompt, clrGreen);
|
||||
Interface->Fill(l, 0, p, 1, clrGreen);
|
||||
Interface->Fill(l + p, 0, Width() - l - p, 1, clrWhite);
|
||||
#else
|
||||
cVolumeBar VolumeBar(Width() * cOsd::CellWidth(), cOsd::LineHeight(), Current, Total, Prompt);
|
||||
Interface->SetBitmap(0, 0, VolumeBar);
|
||||
#endif
|
||||
}
|
||||
displayVolume->SetVolume(cDevice::CurrentVolume(), MAXVOLUME, cDevice::PrimaryDevice()->IsMute());
|
||||
}
|
||||
|
||||
cDisplayVolume *cDisplayVolume::Create(void)
|
||||
{
|
||||
if (!displayVolume)
|
||||
if (!currentDisplayVolume)
|
||||
new cDisplayVolume;
|
||||
return displayVolume;
|
||||
return currentDisplayVolume;
|
||||
}
|
||||
|
||||
void cDisplayVolume::Process(eKeys Key)
|
||||
{
|
||||
if (displayVolume)
|
||||
displayVolume->ProcessKey(Key);
|
||||
if (currentDisplayVolume)
|
||||
currentDisplayVolume->ProcessKey(Key);
|
||||
}
|
||||
|
||||
eOSState cDisplayVolume::ProcessKey(eKeys Key)
|
||||
@ -2920,9 +2913,7 @@ bool cRecordControls::StopPrimary(bool DoIt)
|
||||
|
||||
bool cRecordControls::PauseLiveVideo(void)
|
||||
{
|
||||
Interface->Open(Setup.OSDwidth, -1);
|
||||
Interface->Status(tr("Pausing live video..."));
|
||||
Interface->Flush();
|
||||
Skins.Message(mtStatus, tr("Pausing live video..."));
|
||||
cReplayControl::SetRecording(NULL, NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed()
|
||||
if (Start(NULL, true)) {
|
||||
sleep(2); // allow recorded file to fill up enough to start replaying
|
||||
@ -2930,11 +2921,11 @@ bool cRecordControls::PauseLiveVideo(void)
|
||||
cControl::Launch(rc);
|
||||
cControl::Attach();
|
||||
sleep(1); // allow device to replay some frames, so we have a picture
|
||||
Interface->Close();
|
||||
Skins.Message(mtStatus, NULL);
|
||||
rc->ProcessKey(kPause); // pause, allowing replay mode display
|
||||
return true;
|
||||
}
|
||||
Interface->Close();
|
||||
Skins.Message(mtStatus, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3001,50 +2992,6 @@ void cRecordControls::Shutdown(void)
|
||||
DELETENULL(RecordControls[i]);
|
||||
}
|
||||
|
||||
// --- cProgressBar ----------------------------------------------------------
|
||||
|
||||
class cProgressBar : public cBitmap {
|
||||
protected:
|
||||
int total;
|
||||
int Pos(int p) { return p * width / total; }
|
||||
void Mark(int x, bool Start, bool Current);
|
||||
public:
|
||||
cProgressBar(int Width, int Height, int Current, int Total, const cMarks &Marks);
|
||||
};
|
||||
|
||||
cProgressBar::cProgressBar(int Width, int Height, int Current, int Total, const cMarks &Marks)
|
||||
:cBitmap(Width, Height, 2)
|
||||
{
|
||||
total = Total;
|
||||
if (total > 0) {
|
||||
int p = Pos(Current);
|
||||
Fill(0, 0, p, Height - 1, clrGreen);
|
||||
Fill(p + 1, 0, Width - 1, Height - 1, clrWhite);
|
||||
bool Start = true;
|
||||
for (const cMark *m = Marks.First(); m; m = Marks.Next(m)) {
|
||||
int p1 = Pos(m->position);
|
||||
if (Start) {
|
||||
const cMark *m2 = Marks.Next(m);
|
||||
int p2 = Pos(m2 ? m2->position : total);
|
||||
int h = Height / 3;
|
||||
Fill(p1, h, p2, Height - h, clrRed);
|
||||
}
|
||||
Mark(p1, Start, m->position == Current);
|
||||
Start = !Start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cProgressBar::Mark(int x, bool Start, bool Current)
|
||||
{
|
||||
Fill(x, 0, x, height - 1, clrBlack);
|
||||
const int d = height / (Current ? 3 : 9);
|
||||
for (int i = 0; i < d; i++) {
|
||||
int h = Start ? i : height - 1 - i;
|
||||
Fill(x - d + i, h, x + d - i, h, Current ? clrRed : clrBlack);
|
||||
}
|
||||
}
|
||||
|
||||
// --- cReplayControl --------------------------------------------------------
|
||||
|
||||
char *cReplayControl::fileName = NULL;
|
||||
@ -3053,8 +3000,11 @@ char *cReplayControl::title = NULL;
|
||||
cReplayControl::cReplayControl(void)
|
||||
:cDvbPlayerControl(fileName)
|
||||
{
|
||||
displayReplay = NULL;
|
||||
visible = modeOnly = shown = displayFrames = false;
|
||||
lastCurrent = lastTotal = -1;
|
||||
lastPlay = lastForward = false;
|
||||
lastSpeed = -1;
|
||||
timeoutShow = 0;
|
||||
timeSearchActive = false;
|
||||
marks.Load(fileName);
|
||||
@ -3108,61 +3058,36 @@ void cReplayControl::Show(void)
|
||||
void cReplayControl::Hide(void)
|
||||
{
|
||||
if (visible) {
|
||||
Interface->Close();
|
||||
delete displayReplay;
|
||||
displayReplay = NULL;
|
||||
needsFastResponse = visible = false;
|
||||
modeOnly = false;
|
||||
lastPlay = lastForward = false;
|
||||
lastSpeed = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void cReplayControl::DisplayAtBottom(const char *s)
|
||||
{
|
||||
if (s) {
|
||||
int w = cOsd::WidthInCells(s);
|
||||
int d = max(Width() - w, 0) / 2;
|
||||
if (modeOnly) //XXX remove when displaying replay mode differently
|
||||
Interface->Fill(0, -1, Interface->Width(), 1, clrTransparent); //XXX remove when displaying replay mode differently
|
||||
Interface->Write(d, -1, s);
|
||||
Interface->Flush();
|
||||
}
|
||||
else
|
||||
Interface->Fill(12, 2, Width() - 22, 1, clrBackground);
|
||||
}
|
||||
|
||||
void cReplayControl::ShowMode(void)
|
||||
{
|
||||
if (Setup.ShowReplayMode && !timeSearchActive) {
|
||||
if (visible || Setup.ShowReplayMode) {
|
||||
bool Play, Forward;
|
||||
int Speed;
|
||||
if (GetReplayMode(Play, Forward, Speed)) {
|
||||
if (GetReplayMode(Play, Forward, Speed) && (!visible || Play != lastPlay || Forward != lastForward || Speed != lastSpeed)) {
|
||||
bool NormalPlay = (Play && Speed == -1);
|
||||
|
||||
if (!visible) {
|
||||
if (NormalPlay)
|
||||
return; // no need to do indicate ">" unless there was a different mode displayed before
|
||||
// open small display
|
||||
/*XXX change when displaying replay mode differently
|
||||
Interface->Open(9, -1);
|
||||
Interface->Clear();
|
||||
XXX*/
|
||||
Interface->Open(0, -1); //XXX remove when displaying replay mode differently
|
||||
visible = modeOnly = true;
|
||||
displayReplay = Skins.Current()->DisplayReplay(modeOnly);
|
||||
}
|
||||
|
||||
if (modeOnly && !timeoutShow && NormalPlay)
|
||||
timeoutShow = time(NULL) + MODETIMEOUT;
|
||||
const char *Mode;
|
||||
if (Speed == -1) Mode = Play ? " > " : " || ";
|
||||
else if (Play) Mode = Forward ? " X>> " : " <<X ";
|
||||
else Mode = Forward ? " X|> " : " <|X ";
|
||||
char buf[16];
|
||||
strn0cpy(buf, Mode, sizeof(buf));
|
||||
char *p = strchr(buf, 'X');
|
||||
if (p)
|
||||
*p = Speed > 0 ? '1' + Speed - 1 : ' ';
|
||||
|
||||
eDvbFont OldFont = Interface->SetFont(fontFix);
|
||||
DisplayAtBottom(buf);
|
||||
Interface->SetFont(OldFont);
|
||||
displayReplay->SetMode(Play, Forward, Speed);
|
||||
lastPlay = Play;
|
||||
lastForward = Forward;
|
||||
lastSpeed = Speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3173,33 +3098,26 @@ bool cReplayControl::ShowProgress(bool Initial)
|
||||
|
||||
if (GetIndex(Current, Total) && Total > 0) {
|
||||
if (!visible) {
|
||||
Interface->Open(Setup.OSDwidth, -3);
|
||||
displayReplay = Skins.Current()->DisplayReplay(modeOnly);
|
||||
displayReplay->SetMarks(&marks);
|
||||
needsFastResponse = visible = true;
|
||||
}
|
||||
if (Initial) {
|
||||
Interface->Clear();
|
||||
if (title)
|
||||
Interface->Write(0, 0, title);
|
||||
displayReplay->SetTitle(title);
|
||||
lastCurrent = lastTotal = -1;
|
||||
}
|
||||
if (Total != lastTotal) {
|
||||
Interface->Write(-7, 2, IndexToHMSF(Total));
|
||||
displayReplay->SetTotal(IndexToHMSF(Total));
|
||||
if (!Initial)
|
||||
Interface->Flush();
|
||||
displayReplay->Flush();
|
||||
}
|
||||
if (Current != lastCurrent || Total != lastTotal) {
|
||||
#ifdef DEBUG_OSD
|
||||
int p = Width() * Current / Total;
|
||||
Interface->Fill(0, 1, p, 1, clrGreen);
|
||||
Interface->Fill(p, 1, Width() - p, 1, clrWhite);
|
||||
#else
|
||||
cProgressBar ProgressBar(Width() * cOsd::CellWidth(), cOsd::LineHeight(), Current, Total, marks);
|
||||
Interface->SetBitmap(0, cOsd::LineHeight(), ProgressBar);
|
||||
displayReplay->SetProgress(Current, Total);
|
||||
if (!Initial)
|
||||
Interface->Flush();
|
||||
#endif
|
||||
Interface->Write(0, 2, IndexToHMSF(Current, displayFrames));
|
||||
Interface->Flush();
|
||||
displayReplay->Flush();
|
||||
displayReplay->SetCurrent(IndexToHMSF(Current, displayFrames));
|
||||
displayReplay->Flush();
|
||||
lastCurrent = Current;
|
||||
}
|
||||
lastTotal = Total;
|
||||
@ -3223,7 +3141,7 @@ void cReplayControl::TimeSearchDisplay(void)
|
||||
char cm10 = timeSearchPos > 1 ? m10 : '-';
|
||||
char cm1 = timeSearchPos > 0 ? m1 : '-';
|
||||
sprintf(buf + len, "%c%c:%c%c", ch10, ch1, cm10, cm1);
|
||||
DisplayAtBottom(buf);
|
||||
displayReplay->SetJump(buf);
|
||||
}
|
||||
|
||||
void cReplayControl::TimeSearchProcess(eKeys Key)
|
||||
@ -3269,7 +3187,7 @@ void cReplayControl::TimeSearchProcess(eKeys Key)
|
||||
if (timeSearchHide)
|
||||
Hide();
|
||||
else
|
||||
DisplayAtBottom();
|
||||
displayReplay->SetJump(NULL);
|
||||
ShowMode();
|
||||
}
|
||||
}
|
||||
@ -3354,14 +3272,14 @@ void cReplayControl::EditCut(void)
|
||||
Hide();
|
||||
if (!cCutter::Active()) {
|
||||
if (!marks.Count())
|
||||
Interface->Error(tr("No editing marks defined!"));
|
||||
Skins.Message(mtError, tr("No editing marks defined!"));
|
||||
else if (!cCutter::Start(fileName))
|
||||
Interface->Error(tr("Can't start editing process!"));
|
||||
Skins.Message(mtError, tr("Can't start editing process!"));
|
||||
else
|
||||
Interface->Info(tr("Editing process started"));
|
||||
Skins.Message(mtInfo, tr("Editing process started"));
|
||||
}
|
||||
else
|
||||
Interface->Error(tr("Editing process already active!"));
|
||||
Skins.Message(mtError, tr("Editing process already active!"));
|
||||
ShowMode();
|
||||
}
|
||||
}
|
||||
@ -3466,8 +3384,5 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
|
||||
}
|
||||
if (DoShowMode)
|
||||
ShowMode();
|
||||
if (DisplayedFrames && !displayFrames)
|
||||
Interface->Fill(0, 2, 11, 1, clrBackground);
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
|
16
menu.h
16
menu.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.h 1.60 2004/02/15 14:11:28 kls Exp $
|
||||
* $Id: menu.h 1.61 2004/04/30 13:45:19 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENU_H
|
||||
@ -13,10 +13,11 @@
|
||||
#include "ci.h"
|
||||
#include "device.h"
|
||||
#include "epg.h"
|
||||
#include "osd.h"
|
||||
#include "osdbase.h"
|
||||
#include "dvbplayer.h"
|
||||
#include "recorder.h"
|
||||
#include "recording.h"
|
||||
#include "skins.h"
|
||||
|
||||
class cMenuMain : public cOsdMenu {
|
||||
private:
|
||||
@ -32,12 +33,14 @@ public:
|
||||
|
||||
class cDisplayChannel : public cOsdObject {
|
||||
private:
|
||||
cSkinDisplayChannel *displayChannel;
|
||||
int group;
|
||||
bool withInfo;
|
||||
int lines;
|
||||
int lastTime;
|
||||
int number;
|
||||
cChannel *channel;
|
||||
const cEvent *lastPresent;
|
||||
const cEvent *lastFollowing;
|
||||
void DisplayChannel(void);
|
||||
void DisplayInfo(void);
|
||||
void Refresh(void);
|
||||
@ -50,8 +53,9 @@ public:
|
||||
|
||||
class cDisplayVolume : public cOsdObject {
|
||||
private:
|
||||
cSkinDisplayVolume *displayVolume;
|
||||
int timeout;
|
||||
static cDisplayVolume *displayVolume;
|
||||
static cDisplayVolume *currentDisplayVolume;
|
||||
virtual void Show(void);
|
||||
cDisplayVolume(void);
|
||||
public:
|
||||
@ -150,9 +154,12 @@ public:
|
||||
|
||||
class cReplayControl : public cDvbPlayerControl {
|
||||
private:
|
||||
cSkinDisplayReplay *displayReplay;
|
||||
cMarks marks;
|
||||
bool visible, modeOnly, shown, displayFrames;
|
||||
int lastCurrent, lastTotal;
|
||||
bool lastPlay, lastForward;
|
||||
int lastSpeed;
|
||||
time_t timeoutShow;
|
||||
bool timeSearchActive, timeSearchHide;
|
||||
int timeSearchTime, timeSearchPos;
|
||||
@ -162,7 +169,6 @@ private:
|
||||
void ShowTimed(int Seconds = 0);
|
||||
static char *fileName;
|
||||
static char *title;
|
||||
void DisplayAtBottom(const char *s = NULL);
|
||||
void ShowMode(void);
|
||||
bool ShowProgress(bool Initial);
|
||||
void MarkToggle(void);
|
||||
|
115
menuitems.c
115
menuitems.c
@ -4,13 +4,15 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.c 1.16 2004/03/28 09:17:51 kls Exp $
|
||||
* $Id: menuitems.c 1.17 2004/05/02 10:37:34 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menuitems.h"
|
||||
#include <ctype.h>
|
||||
#include "i18n.h"
|
||||
#include "plugin.h"
|
||||
#include "remote.h"
|
||||
#include "skins.h"
|
||||
#include "status.h"
|
||||
|
||||
const char *FileNameChars = " abcdefghijklmnopqrstuvwxyz0123456789-.#~";
|
||||
@ -36,7 +38,6 @@ void cMenuEditItem::SetValue(const char *Value)
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%s:\t%s", name, value);
|
||||
SetText(buffer, false);
|
||||
Display();
|
||||
cStatus::MsgOsdCurrentItem(buffer);
|
||||
}
|
||||
|
||||
@ -253,9 +254,9 @@ cMenuEditStrItem::~cMenuEditStrItem()
|
||||
void cMenuEditStrItem::SetHelpKeys(void)
|
||||
{
|
||||
if (pos >= 0)
|
||||
Interface->Help(tr("ABC/abc"), tr(insert ? "Overwrite" : "Insert"), tr("Delete"));
|
||||
cSkinDisplay::Current()->SetButtons(tr("ABC/abc"), tr(insert ? "Overwrite" : "Insert"), tr("Delete"));
|
||||
else
|
||||
Interface->Help(NULL);
|
||||
cSkinDisplay::Current()->SetButtons(NULL);
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::Set(void)
|
||||
@ -264,21 +265,21 @@ void cMenuEditStrItem::Set(void)
|
||||
const char *fmt = insert && newchar ? "[]%c%s" : "[%c]%s";
|
||||
|
||||
if (pos >= 0) {
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
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 (cOsd::WidthInCells(buf) <= width) {
|
||||
int width = cSkinDisplay::Current()->EditableWidth();
|
||||
if (font->Width(buf) <= width) {
|
||||
// the whole buffer fits on the screen
|
||||
SetValue(buf);
|
||||
return;
|
||||
}
|
||||
width *= cOsd::CellWidth();
|
||||
width -= cOsd::Width('>'); // assuming '<' and '>' have the same with
|
||||
width -= font->Width('>'); // assuming '<' and '>' have the same with
|
||||
int w = 0;
|
||||
int i = 0;
|
||||
int l = strlen(buf);
|
||||
while (i < l && w <= width)
|
||||
w += cOsd::Width(buf[i++]);
|
||||
w += font->Width(buf[i++]);
|
||||
if (i >= pos + 4) {
|
||||
// the cursor fits on the screen
|
||||
buf[i - 1] = '>';
|
||||
@ -295,7 +296,7 @@ void cMenuEditStrItem::Set(void)
|
||||
else
|
||||
i--;
|
||||
while (i >= 0 && w <= width)
|
||||
w += cOsd::Width(buf[i--]);
|
||||
w += font->Width(buf[i--]);
|
||||
buf[++i] = '<';
|
||||
SetValue(buf + i);
|
||||
}
|
||||
@ -461,100 +462,6 @@ 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()
|
||||
{
|
||||
free(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);
|
||||
cStatus::MsgOsdTextItem(text);
|
||||
}
|
||||
|
||||
void cMenuTextItem::ScrollUp(bool Page)
|
||||
{
|
||||
if (CanScrollUp()) {
|
||||
Clear();
|
||||
offset = max(offset - (Page ? h : 1), 0);
|
||||
Display();
|
||||
}
|
||||
cStatus::MsgOsdTextItem(NULL, true);
|
||||
}
|
||||
|
||||
void cMenuTextItem::ScrollDown(bool Page)
|
||||
{
|
||||
if (CanScrollDown()) {
|
||||
Clear();
|
||||
offset = min(offset + (Page ? h : 1), lines - h);
|
||||
Display();
|
||||
}
|
||||
cStatus::MsgOsdTextItem(NULL, false);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// --- cMenuEditChanItem -----------------------------------------------------
|
||||
|
||||
cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
|
||||
|
23
menuitems.h
23
menuitems.h
@ -4,13 +4,13 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.h 1.7 2004/03/28 09:16:24 kls Exp $
|
||||
* $Id: menuitems.h 1.8 2004/04/30 13:45:28 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENUITEMS_H
|
||||
#define __MENUITEMS_H
|
||||
|
||||
#include "osd.h"
|
||||
#include "osdbase.h"
|
||||
|
||||
extern const char *FileNameChars;
|
||||
|
||||
@ -100,25 +100,6 @@ 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 cMenuEditChanItem : public cMenuEditIntItem {
|
||||
protected:
|
||||
virtual void Set(void);
|
||||
|
472
osd.h
472
osd.h
@ -4,169 +4,349 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osd.h 1.40 2003/09/14 10:59:22 kls Exp $
|
||||
* $Id: osd.h 1.41 2004/05/15 14:54:37 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSD_H
|
||||
#define __OSD_H
|
||||
|
||||
#if defined(DEBUG_OSD)
|
||||
#include <ncurses.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "osdbase.h"
|
||||
#include "interface.h"
|
||||
#include "osdbase.h"
|
||||
#include "tools.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "font.h"
|
||||
|
||||
#define MAXOSDITEMS (Setup.OSDheight - 4)
|
||||
#define MAXNUMCOLORS 256
|
||||
|
||||
enum eOSState { osUnknown,
|
||||
osContinue,
|
||||
osSchedule,
|
||||
osChannels,
|
||||
osTimers,
|
||||
osRecordings,
|
||||
osPlugin,
|
||||
osSetup,
|
||||
osCommands,
|
||||
osPause,
|
||||
osRecord,
|
||||
osReplay,
|
||||
osStopRecord,
|
||||
osStopReplay,
|
||||
osCancelEdit,
|
||||
osSwitchDvb,
|
||||
osBack,
|
||||
osEnd,
|
||||
os_User, // the following values can be used locally
|
||||
osUser1,
|
||||
osUser2,
|
||||
osUser3,
|
||||
osUser4,
|
||||
osUser5,
|
||||
osUser6,
|
||||
osUser7,
|
||||
osUser8,
|
||||
osUser9,
|
||||
osUser10,
|
||||
enum {
|
||||
//AARRGGBB
|
||||
clrTransparent = 0x00000000,
|
||||
clrGray50 = 0x7F000000, // 50% gray
|
||||
clrBlack = 0xFF000000,
|
||||
clrRed = 0xFFFC1414,
|
||||
clrGreen = 0xFF24FC24,
|
||||
clrYellow = 0xFFFCC024,
|
||||
clrMagenta = 0xFFB000FC,
|
||||
clrBlue = 0xFF0000FC,
|
||||
clrCyan = 0xFF00FCFC,
|
||||
clrWhite = 0xFFFCFCFC,
|
||||
};
|
||||
|
||||
enum eOsdError { oeOk,
|
||||
oeTooManyAreas,
|
||||
oeTooManyColors,
|
||||
oeBppNotSupported,
|
||||
oeAreasOverlap,
|
||||
oeWrongAlignment,
|
||||
oeOutOfMemory,
|
||||
oeUnknown,
|
||||
};
|
||||
|
||||
typedef uint32_t tColor;
|
||||
typedef uint8_t tIndex;
|
||||
|
||||
class cPalette {
|
||||
private:
|
||||
tColor color[MAXNUMCOLORS];
|
||||
int bpp;
|
||||
int maxColors, numColors;
|
||||
bool modified;
|
||||
protected:
|
||||
typedef tIndex tIndexes[MAXNUMCOLORS];
|
||||
public:
|
||||
cPalette(int Bpp = 8);
|
||||
///< Initializes the palette with the given color depth.
|
||||
int Bpp(void) { return bpp; }
|
||||
void Reset(void);
|
||||
///< Resets the palette, making it contain no colors.
|
||||
int Index(tColor Color);
|
||||
///< Returns the index of the given Color (the first color has index 0).
|
||||
///< If Color is not yet contained in this palette, it will be added if
|
||||
///< there is a free slot. If the color can't be added to this palette,
|
||||
///< 0 will be returned.
|
||||
tColor Color(int Index) { return Index < maxColors ? color[Index] : 0; }
|
||||
///< Returns the color at the given Index. If Index is outside the valid
|
||||
///< range, 0 will be returned.
|
||||
void SetBpp(int Bpp);
|
||||
///< Sets the color depth of this palette to the given value.
|
||||
///< The palette contents will be reset, so that it contains no colors.
|
||||
void SetColor(int Index, tColor Color);
|
||||
///< Sets the palette entry at Index to Color. If Index is larger than
|
||||
///< the number of currently used entries in this palette, the entries
|
||||
///< in between will have undefined values.
|
||||
const tColor *Colors(int &NumColors);
|
||||
///< Returns a pointer to the complete color table and stores the
|
||||
///< number of valid entries in NumColors. If no colors have been
|
||||
///< stored yet, NumColors will be set to 0 and the function will
|
||||
///< return NULL.
|
||||
void Take(const cPalette &Palette, tIndexes *Indexes = NULL, tColor ColorFg = 0, tColor ColorBg = 0);
|
||||
///< Takes the colors from the given Palette and adds them to this palette,
|
||||
///< using existing entries if possible. If Indexes is given, it will be
|
||||
///< filled with the index values that each color of Palette has in this
|
||||
///< palette. If either of ColorFg or ColorBg is not zero, the first color
|
||||
///< in Palette will be taken as ColorBg, and the second color will become
|
||||
///< ColorFg.
|
||||
};
|
||||
|
||||
enum eTextAlignment { taCenter = 0x00,
|
||||
taLeft = 0x01,
|
||||
taRight = 0x02,
|
||||
taTop = 0x04,
|
||||
taBottom = 0x08,
|
||||
taDefault = taTop | taLeft
|
||||
};
|
||||
|
||||
class cBitmap : public cPalette {
|
||||
private:
|
||||
tIndex *bitmap;
|
||||
int x0, y0;
|
||||
int width, height;
|
||||
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
||||
public:
|
||||
cBitmap(int Width, int Height, int Bpp, int X0 = 0, int Y0 = 0);
|
||||
///< Creates a bitmap with the given Width, Height and color depth (Bpp).
|
||||
///< X0 and Y0 define the offset at which this bitmap will be located on the OSD.
|
||||
///< All coordinates given in the other functions will be relative to
|
||||
///< this offset (unless specified otherwise).
|
||||
cBitmap(const char *FileName);
|
||||
///< Creates a bitmap and loads an XPM image from the given file.
|
||||
cBitmap(char *Xpm[]);
|
||||
///< Creates a bitmap from the given XPM data.
|
||||
virtual ~cBitmap();
|
||||
int X0(void) const { return x0; }
|
||||
int Y0(void) const { return y0; }
|
||||
int Width(void) const { return width; }
|
||||
int Height(void) const { return height; }
|
||||
void SetSize(int Width, int Height);
|
||||
///< Sets the size of this bitmap to the given values. Any previous
|
||||
///< contents of the bitmap will be lost. If Width and Height are the same
|
||||
///< as the current values, nothing will happen and the bitmap remains
|
||||
///< unchanged.
|
||||
bool Contains(int x, int y) const;
|
||||
///< Returns true if this bitmap contains the point (x, y).
|
||||
bool Intersects(int x1, int y1, int x2, int y2) const;
|
||||
///< Returns true if this bitmap intersects with the rectangle
|
||||
///< defined by the given coordinates.
|
||||
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
||||
///< Tells whether there is a dirty area and returns the bounding
|
||||
///< rectangle of that area (relative to the bitmaps origin).
|
||||
void Clean(void);
|
||||
///< Marks the dirty area as clean.
|
||||
bool LoadXpm(const char *FileName);
|
||||
///< Calls SetXpm() with the data from the file FileName.
|
||||
///< Returns true if the operation was successful.
|
||||
bool SetXpm(char *Xpm[]);
|
||||
///< Sets this bitmap to the given XPM data. Any previous bitmap or
|
||||
///< palette data will be overwritten with the new data.
|
||||
///< Returns true if the operation was successful.
|
||||
void SetIndex(int x, int y, tIndex Index);
|
||||
///< Sets the index at the given coordinates to Index.
|
||||
///< Coordinates are relative to the bitmap's origin.
|
||||
void DrawPixel(int x, int y, tColor Color);
|
||||
///< Sets the pixel at the given coordinates to the given Color, which is
|
||||
///< a full 32 bit ARGB value.
|
||||
///< If the coordinates are outside the bitmap area, no pixel will be set.
|
||||
void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0);
|
||||
///< Sets the pixels in this bitmap with the data from the given
|
||||
///< Bitmap, putting the upper left corner of the Bitmap at (x, y).
|
||||
///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap
|
||||
///< will be mapped to ColorBg and the second palette entry will be mapped to
|
||||
///< ColorFg (palette indexes are defined so that 0 is the background and
|
||||
///< 1 is the foreground color).
|
||||
void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
|
||||
///< Draws the given string at coordinates (x, y) with the given foreground
|
||||
///< and background color and font. If Width and Height are given, the text
|
||||
///< will be drawn into a rectangle with the given size and the given
|
||||
///< Alignment (default is top-left).
|
||||
void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
|
||||
///< Draws a filled rectangle defined by the upper left (x1, y1) and lower right
|
||||
///< (x2, y2) corners with the given Color. If the rectangle covers the entire
|
||||
///< bitmap area, the color palette will be reset, so that new colors can be
|
||||
///< used for drawing.
|
||||
void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0);
|
||||
///< Draws a filled ellipse defined by the upper left (x1, y1) and lower right
|
||||
///< (x2, y2) corners with the given Color. Quadrants controls which parts of
|
||||
///< the ellipse are actually drawn:
|
||||
///< 0 draws the entire ellipse
|
||||
///< 1..4 draws only the first, second, third or fourth quadrant, respectively
|
||||
///< 5..8 draws the right, top, left or bottom half, respectively
|
||||
///< -1..-8 draws the inverted part of the given quadrant(s)
|
||||
///< If Quadrants is not 0, the coordinates are those of the actual area, not
|
||||
///< the full circle!
|
||||
void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type);
|
||||
///< Draws a "slope" into the rectangle defined by the upper left (x1, y1) and
|
||||
///< lower right (x2, y2) corners with the given Color. Type controls the
|
||||
///< direction of the slope and which side of it will be drawn:
|
||||
///< 0: horizontal, rising, lower
|
||||
///< 1: horizontal, rising, upper
|
||||
///< 2: horizontal, falling, lower
|
||||
///< 3: horizontal, falling, upper
|
||||
///< 4: vertical, rising, lower
|
||||
///< 5: vertical, rising, upper
|
||||
///< 6: vertical, falling, lower
|
||||
///< 7: vertical, falling, upper
|
||||
const tIndex *Data(int x, int y);
|
||||
///< Returns the address of the index byte at the given coordinates.
|
||||
};
|
||||
|
||||
struct tArea {
|
||||
int x1, y1, x2, y2;
|
||||
int bpp;
|
||||
int Width(void) const { return x2 - x1 + 1; }
|
||||
int Height(void) const { return y2 - y1 + 1; }
|
||||
bool Intersects(const tArea &Area) const { return !(x2 < Area.x1 || x1 > Area.x2 || y2 < Area.y1 || y1 > Area.y2); }
|
||||
};
|
||||
|
||||
#define MAXOSDAREAS 16
|
||||
|
||||
class cOsd {
|
||||
private:
|
||||
enum { charWidth = 12, // average character width
|
||||
lineHeight = 27 // smallest text height
|
||||
};
|
||||
#ifdef DEBUG_OSD
|
||||
static WINDOW *window;
|
||||
enum { MaxColorPairs = 16 };
|
||||
static int colorPairs[MaxColorPairs];
|
||||
static void SetColor(eDvbColor colorFg, eDvbColor colorBg = clrBackground);
|
||||
#else
|
||||
static cOsdBase *osd;
|
||||
#endif
|
||||
static int cols, rows;
|
||||
static bool isOpen;
|
||||
cBitmap *savedRegion;
|
||||
cBitmap *bitmaps[MAXOSDAREAS];
|
||||
int numBitmaps;
|
||||
int left, top, width, height;
|
||||
public:
|
||||
static void Initialize(void);
|
||||
cOsd(int Left, int Top);
|
||||
///< Initializes the OSD with the given coordinates.
|
||||
///< By default it is assumed that the full area will be able to display
|
||||
///< full 32 bit graphics (ARGB with eight bit for each color and the alpha
|
||||
///< value, repectively). However, the actual hardware in use may not be
|
||||
///< able to display such a high resolution OSD, so there is an option to
|
||||
///< divide the full OSD area into several sub-areas with lower color depths
|
||||
///< and individual palettes. The sub-areas need not necessarily cover the
|
||||
///< entire OSD area, but only the OSD area actually covered by sub-areas
|
||||
///< will be available for drawing.
|
||||
///< At least one area must be defined in order to set the actual width and
|
||||
///< height of the OSD. Also, the caller must first try to use an area that
|
||||
///< consists of only one sub-area that covers the entire drawing space,
|
||||
///< and should require only the minimum necessary color depth. This is
|
||||
///< because a derived cOsd class may or may not be able to handle more
|
||||
///< than one area.
|
||||
virtual ~cOsd();
|
||||
///< Shuts down the OSD.
|
||||
static bool IsOpen(void) { return isOpen; }
|
||||
int Left(void) { return left; }
|
||||
int Top(void) { return top; }
|
||||
int Width(void) { return width; }
|
||||
int Height(void) { return height; }
|
||||
cBitmap *GetBitmap(int Area);
|
||||
///< Returns a pointer to the bitmap for the given Area, or NULL if no
|
||||
///< such bitmap exists.
|
||||
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
|
||||
///< Checks whether the OSD can display the given set of sub-areas.
|
||||
///< The return value indicates whether a call to SetAreas() with this
|
||||
///< set of areas will succeed. CanHandleAreas() may be called with an
|
||||
///< OSD that is already in use with other areas and will not interfere
|
||||
///< with the current operation of the OSD.
|
||||
///< A derived class must first call the base class CanHandleAreas()
|
||||
///< to check the basic conditions, like not overlapping etc.
|
||||
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
|
||||
///< Sets the sub-areas to the given areas.
|
||||
///< The return value indicates whether the operation was successful.
|
||||
///< If an error is reported, nothing will have changed and the previous
|
||||
///< OSD (if any) will still be displayed as before.
|
||||
///< If the OSD has been divided into several sub-areas, all areas that
|
||||
///< are part of the rectangle that surrounds a given drawing operation
|
||||
///< will be drawn into, with the proper offsets.
|
||||
virtual void SaveRegion(int x1, int y1, int x2, int y2);
|
||||
///< Saves the region defined by the given coordinates for later restoration
|
||||
///< through RestoreRegion(). Only one saved region can be active at any
|
||||
///< given time.
|
||||
virtual void RestoreRegion(void);
|
||||
///< Restores the region previously saved by a call to SaveRegion().
|
||||
///< If SaveRegion() has not been called before, nothing will happen.
|
||||
virtual eOsdError SetPalette(const cPalette &Palette, int Area);
|
||||
///< Sets the Palette for the given Area (the first area is numbered 0).
|
||||
virtual void DrawPixel(int x, int y, tColor Color);
|
||||
///< Sets the pixel at the given coordinates to the given Color, which is
|
||||
///< a full 32 bit ARGB value.
|
||||
///< If the OSD area has been divided into separate sub-areas, and the
|
||||
///< given coordinates don't fall into any of these sub-areas, no pixel will
|
||||
///< be set.
|
||||
virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0);
|
||||
///< Sets the pixels in the OSD with the data from the given
|
||||
///< Bitmap, putting the upper left corner of the Bitmap at (x, y).
|
||||
///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap
|
||||
///< will be mapped to ColorBg and the second palette entry will be mapped to
|
||||
///< ColorFg (palette indexes are defined so that 0 is the background and
|
||||
///< 1 is the foreground color).
|
||||
virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
|
||||
///< Draws the given string at coordinates (x, y) with the given foreground
|
||||
///< and background color and font. If Width and Height are given, the text
|
||||
///< will be drawn into a rectangle with the given size and the given
|
||||
///< Alignment (default is top-left).
|
||||
virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
|
||||
///< Draws a filled rectangle defined by the upper left (x1, y1) and lower right
|
||||
///< (x2, y2) corners with the given Color.
|
||||
virtual void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0);
|
||||
///< Draws a filled ellipse defined by the upper left (x1, y1) and lower right
|
||||
///< (x2, y2) corners with the given Color. Quadrants controls which parts of
|
||||
///< the ellipse are actually drawn:
|
||||
///< 0 draws the entire ellipse
|
||||
///< 1..4 draws only the first, second, third or fourth quadrant, respectively
|
||||
///< 5..8 draws the right, top, left or bottom half, respectively
|
||||
///< -1..-8 draws the inverted part of the given quadrant(s)
|
||||
///< If Quadrants is not 0, the coordinates are those of the actual area, not
|
||||
///< the full circle!
|
||||
void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type);
|
||||
///< Draws a "slope" into the rectangle defined by the upper left (x1, y1) and
|
||||
///< lower right (x2, y2) corners with the given Color. Type controls the
|
||||
///< direction of the slope and which side of it will be drawn:
|
||||
///< 0: horizontal, rising, lower
|
||||
///< 1: horizontal, rising, upper
|
||||
///< 2: horizontal, falling, lower
|
||||
///< 3: horizontal, falling, upper
|
||||
///< 4: vertical, rising, lower
|
||||
///< 5: vertical, rising, upper
|
||||
///< 6: vertical, falling, lower
|
||||
///< 7: vertical, falling, upper
|
||||
virtual void Flush(void);
|
||||
///< Actually commits all data to the OSD hardware.
|
||||
};
|
||||
|
||||
class cOsdProvider {
|
||||
private:
|
||||
static cOsdProvider *osdProvider;
|
||||
protected:
|
||||
virtual cOsd *CreateOsd(int Left, int Top) = 0;
|
||||
///< Returns a pointer to a newly created cOsd object, which will be located
|
||||
///< at the given coordinates.
|
||||
public:
|
||||
cOsdProvider(void);
|
||||
//XXX maybe parameter to make this one "sticky"??? (frame-buffer etc.)
|
||||
virtual ~cOsdProvider();
|
||||
static cOsd *NewOsd(int Left, int Top);
|
||||
///< Returns a pointer to a newly created cOsd object, which will be located
|
||||
///< at the given coordinates. When the cOsd object is no longer needed, the
|
||||
///< caller must delete it.
|
||||
static void Shutdown(void);
|
||||
static cOsdBase *OpenRaw(int x, int y);
|
||||
// Returns a raw OSD without any predefined windows or colors.
|
||||
// If the "normal" OSD is currently in use, NULL will be returned.
|
||||
// The caller must delete this object before the "normal" OSD is used again!
|
||||
static void Open(int w, int h);
|
||||
static void Close(void);
|
||||
static void Clear(void);
|
||||
static void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
|
||||
static void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
static void ClrEol(int x, int y, eDvbColor color = clrBackground);
|
||||
static int CellWidth(void);
|
||||
static int LineHeight(void);
|
||||
static int Width(unsigned char c);
|
||||
static int WidthInCells(const char *s);
|
||||
static eDvbFont SetFont(eDvbFont Font);
|
||||
static void Text(int x, int y, const char *s, eDvbColor colorFg = clrWhite, eDvbColor colorBg = clrBackground);
|
||||
static void Flush(void);
|
||||
///< Shuts down the OSD provider facility by deleting the current OSD provider.
|
||||
};
|
||||
|
||||
class cOsdItem : public cListObject {
|
||||
class cTextScroller {
|
||||
private:
|
||||
char *text;
|
||||
int offset;
|
||||
eOSState state;
|
||||
protected:
|
||||
bool fresh;
|
||||
bool userColor;
|
||||
eDvbColor fgColor, bgColor;
|
||||
cOsd *osd;
|
||||
int left, top, width, height;
|
||||
const cFont *font;
|
||||
tColor colorFg, colorBg;
|
||||
int offset, shown;
|
||||
cTextWrapper textWrapper;
|
||||
void DrawText(void);
|
||||
public:
|
||||
cOsdItem(eOSState State = osUnknown);
|
||||
cOsdItem(const char *Text, eOSState State = osUnknown);
|
||||
virtual ~cOsdItem();
|
||||
bool HasUserColor(void) { return userColor; }
|
||||
void SetText(const char *Text, bool Copy = true);
|
||||
void SetColor(eDvbColor FgColor, eDvbColor BgColor = clrBackground);
|
||||
const char *Text(void) { return text; }
|
||||
virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
virtual void Set(void) {}
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cOsdObject {
|
||||
friend class cOsdMenu;
|
||||
private:
|
||||
bool isMenu;
|
||||
protected:
|
||||
bool needsFastResponse;
|
||||
public:
|
||||
cOsdObject(bool FastResponse = false) { isMenu = false; needsFastResponse = FastResponse; }
|
||||
virtual ~cOsdObject() {}
|
||||
int Width(void) { return Interface->Width(); }
|
||||
int Height(void) { return Interface->Height(); }
|
||||
bool NeedsFastResponse(void) { return needsFastResponse; }
|
||||
bool IsMenu(void) { return isMenu; }
|
||||
virtual void Show(void) {}
|
||||
virtual eOSState ProcessKey(eKeys Key) { return osUnknown; }
|
||||
};
|
||||
|
||||
class cOsdMenu : public cOsdObject, public cList<cOsdItem> {
|
||||
private:
|
||||
char *title;
|
||||
int cols[cInterface::MaxCols];
|
||||
int first, current, marked;
|
||||
cOsdMenu *subMenu;
|
||||
const char *helpRed, *helpGreen, *helpYellow, *helpBlue;
|
||||
char *status;
|
||||
int digit;
|
||||
bool hasHotkeys;
|
||||
protected:
|
||||
bool visible;
|
||||
const char *hk(const char *s);
|
||||
void SetHasHotkeys(void);
|
||||
virtual void Clear(void);
|
||||
bool SpecialItem(int idx);
|
||||
void SetCurrent(cOsdItem *Item);
|
||||
void RefreshCurrent(void);
|
||||
void DisplayCurrent(bool Current);
|
||||
void CursorUp(void);
|
||||
void CursorDown(void);
|
||||
void PageUp(void);
|
||||
void PageDown(void);
|
||||
void Mark(void);
|
||||
eOSState HotKey(eKeys Key);
|
||||
eOSState AddSubMenu(cOsdMenu *SubMenu);
|
||||
eOSState CloseSubMenu();
|
||||
bool HasSubMenu(void) { return subMenu; }
|
||||
void SetStatus(const char *s);
|
||||
void SetTitle(const char *Title, bool ShowDate = true);
|
||||
void SetHelp(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
virtual void Del(int Index);
|
||||
public:
|
||||
cOsdMenu(const char *Title, int c0 = 0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0);
|
||||
virtual ~cOsdMenu();
|
||||
int Current(void) { return current; }
|
||||
void Add(cOsdItem *Item, bool Current = false, cOsdItem *After = NULL);
|
||||
void Ins(cOsdItem *Item, bool Current = false, cOsdItem *Before = NULL);
|
||||
virtual void Display(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
cTextScroller(void);
|
||||
cTextScroller(cOsd *Osd, int Left, int Top, int Width, int Height, const char *Text, const cFont *Font, tColor ColorFg, tColor ColorBg);
|
||||
void Set(cOsd *Osd, int Left, int Top, int Width, int Height, const char *Text, const cFont *Font, tColor ColorFg, tColor ColorBg);
|
||||
void Reset(void);
|
||||
int Left(void) { return left; }
|
||||
int Top(void) { return top; }
|
||||
int Width(void) { return width; }
|
||||
int Height(void) { return height; }
|
||||
int Total(void) { return textWrapper.Lines(); }
|
||||
int Offset(void) { return offset; }
|
||||
int Shown(void) { return shown; }
|
||||
bool CanScroll(void) { return CanScrollUp() || CanScrollDown(); }
|
||||
bool CanScrollUp(void) { return offset > 0; }
|
||||
bool CanScrollDown(void) { return offset + shown < Total(); }
|
||||
void Scroll(bool Up, bool Page);
|
||||
};
|
||||
|
||||
#endif //__OSD_H
|
||||
|
697
osdbase.c
697
osdbase.c
@ -4,495 +4,410 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osdbase.c 1.12 2004/01/31 10:31:13 kls Exp $
|
||||
* $Id: osdbase.c 1.13 2004/05/01 10:51:43 kls Exp $
|
||||
*/
|
||||
|
||||
#include "osdbase.h"
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
#include "tools.h"
|
||||
#include <string.h>
|
||||
#include "device.h"
|
||||
#include "i18n.h"
|
||||
#include "remote.h"
|
||||
#include "status.h"
|
||||
|
||||
// --- cPalette --------------------------------------------------------------
|
||||
// --- cOsdItem --------------------------------------------------------------
|
||||
|
||||
cPalette::cPalette(int Bpp)
|
||||
cOsdItem::cOsdItem(eOSState State)
|
||||
{
|
||||
maxColors = 1 << Bpp;
|
||||
numColors = 0;
|
||||
full = false;
|
||||
text = NULL;
|
||||
offset = -1;
|
||||
state = State;
|
||||
selectable = true;
|
||||
fresh = true;
|
||||
}
|
||||
|
||||
void cPalette::SetColor(int Index, eDvbColor Color)
|
||||
cOsdItem::cOsdItem(const char *Text, eOSState State)
|
||||
{
|
||||
if (Index < maxColors) {
|
||||
if (numColors < Index)
|
||||
numColors = Index + 1;
|
||||
used[Index] = true;
|
||||
color[Index] = Color;
|
||||
fetched[Index] = false;
|
||||
}
|
||||
text = NULL;
|
||||
offset = -1;
|
||||
state = State;
|
||||
selectable = true;
|
||||
fresh = true;
|
||||
SetText(Text);
|
||||
}
|
||||
|
||||
int cPalette::Index(eDvbColor Color)
|
||||
cOsdItem::~cOsdItem()
|
||||
{
|
||||
#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;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (!full) {
|
||||
if (numColors < maxColors) {
|
||||
color[numColors++] = Color;
|
||||
used[numColors - 1] = true;
|
||||
fetched[numColors - 1] = false;
|
||||
return numColors - 1;
|
||||
}
|
||||
for (int i = maxColors; --i >= 0; ) {
|
||||
if (!used[i]) {
|
||||
color[i] = Color;
|
||||
used[i] = true;
|
||||
fetched[i] = false;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
esyslog("ERROR: too many different colors used in palette");
|
||||
full = true;
|
||||
}
|
||||
return 0;
|
||||
free(text);
|
||||
}
|
||||
|
||||
void cPalette::Reset(void)
|
||||
void cOsdItem::SetText(const char *Text, bool Copy)
|
||||
{
|
||||
for (int i = 0; i < numColors; i++)
|
||||
used[i] = fetched[i] = false;
|
||||
full = false;
|
||||
free(text);
|
||||
text = Copy ? strdup(Text) : (char *)Text; // text assumes ownership!
|
||||
}
|
||||
|
||||
const eDvbColor *cPalette::NewColors(int &FirstColor, int &LastColor)
|
||||
void cOsdItem::SetSelectable(bool Selectable)
|
||||
{
|
||||
for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
|
||||
if (!fetched[FirstColor]) {
|
||||
for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
|
||||
fetched[LastColor] = true;
|
||||
LastColor--; // the loop ended one past the last one!
|
||||
return &color[FirstColor];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
selectable = Selectable;
|
||||
}
|
||||
|
||||
const eDvbColor *cPalette::AllColors(int &NumColors)
|
||||
void cOsdItem::SetFresh(bool Fresh)
|
||||
{
|
||||
NumColors = numColors;
|
||||
return numColors ? color : NULL;
|
||||
fresh = Fresh;
|
||||
}
|
||||
|
||||
void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
|
||||
eOSState cOsdItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
for (int i = 0; i < Palette.numColors; i++) {
|
||||
if (Palette.used[i]) {
|
||||
int n = Index(Palette.color[i]);
|
||||
if (Indexes)
|
||||
(*Indexes)[i] = n;
|
||||
}
|
||||
}
|
||||
return Key == kOk ? state : osUnknown;
|
||||
}
|
||||
|
||||
// --- cBitmap ---------------------------------------------------------------
|
||||
// --- cOsdMenu --------------------------------------------------------------
|
||||
|
||||
cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
|
||||
:cPalette(Bpp)
|
||||
cSkinDisplayMenu *cOsdMenu::displayMenu = NULL;
|
||||
int cOsdMenu::displayMenuCount = 0;
|
||||
int cOsdMenu::displayMenuItems = 0;//XXX dynamic???
|
||||
|
||||
cOsdMenu::cOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4)
|
||||
{
|
||||
width = Width;
|
||||
height = Height;
|
||||
clearWithBackground = ClearWithBackground;
|
||||
bitmap = NULL;
|
||||
fontType = fontOsd;
|
||||
font = NULL;
|
||||
if (width > 0 && height > 0) {
|
||||
bitmap = MALLOC(u_char, width * height);
|
||||
if (bitmap) {
|
||||
Clean();
|
||||
memset(bitmap, 0x00, width * height);
|
||||
SetFont(fontOsd);
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: can't allocate bitmap!");
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: illegal bitmap parameters (%d, %d)!", width, height);
|
||||
}
|
||||
|
||||
cBitmap::~cBitmap()
|
||||
{
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
eDvbFont cBitmap::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = fontType;
|
||||
if (fontType != Font || !font) {
|
||||
font = cFont::GetFont(Font);
|
||||
fontType = Font;
|
||||
}
|
||||
return oldFont;
|
||||
}
|
||||
|
||||
bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
|
||||
{
|
||||
if (dirtyX2 >= 0) {
|
||||
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
|
||||
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
|
||||
//TODO Fix driver (should be able to handle any size bitmaps!)
|
||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
|
||||
if (dirtyX2 < width - 1)
|
||||
dirtyX2++;
|
||||
else if (dirtyX1 > 0)
|
||||
dirtyX1--;
|
||||
}
|
||||
//XXX "... / 2" <==> Bpp???
|
||||
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||
if (dirtyY2 < height - 1)
|
||||
dirtyY2++;
|
||||
else if (dirtyY1 > 0)
|
||||
dirtyY1--;
|
||||
}
|
||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||
if (dirtyX2 < width - 1)
|
||||
dirtyX2++;
|
||||
else if (dirtyX1 > 0)
|
||||
dirtyX1--;
|
||||
}
|
||||
x1 = dirtyX1;
|
||||
y1 = dirtyY1;
|
||||
x2 = dirtyX2;
|
||||
y2 = dirtyY2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cBitmap::Clean(void)
|
||||
{
|
||||
dirtyX1 = width;
|
||||
dirtyY1 = height;
|
||||
dirtyX2 = -1;
|
||||
dirtyY2 = -1;
|
||||
}
|
||||
|
||||
void cBitmap::SetIndex(int x, int y, u_char Index)
|
||||
{
|
||||
if (bitmap) {
|
||||
if (0 <= x && x < width && 0 <= y && y < height) {
|
||||
if (bitmap[width * y + x] != Index) {
|
||||
bitmap[width * y + x] = Index;
|
||||
if (dirtyX1 > x) dirtyX1 = x;
|
||||
if (dirtyY1 > y) dirtyY1 = y;
|
||||
if (dirtyX2 < x) dirtyX2 = x;
|
||||
if (dirtyY2 < y) dirtyY2 = y;
|
||||
}
|
||||
}
|
||||
isMenu = true;
|
||||
digit = 0;
|
||||
hasHotkeys = false;
|
||||
title = NULL;
|
||||
SetTitle(Title);
|
||||
cols[0] = c0;
|
||||
cols[1] = c1;
|
||||
cols[2] = c2;
|
||||
cols[3] = c3;
|
||||
cols[4] = c4;
|
||||
first = 0;
|
||||
current = marked = -1;
|
||||
subMenu = NULL;
|
||||
helpRed = helpGreen = helpYellow = helpBlue = NULL;
|
||||
status = NULL;
|
||||
if (!displayMenuCount++) {
|
||||
displayMenu = Skins.Current()->DisplayMenu();
|
||||
displayMenuItems = displayMenu->MaxItems();
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
|
||||
cOsdMenu::~cOsdMenu()
|
||||
{
|
||||
SetIndex(x, y, Index(Color));
|
||||
free(title);
|
||||
delete subMenu;
|
||||
free(status);
|
||||
displayMenu->Clear();
|
||||
cStatus::MsgOsdClear();
|
||||
if (!--displayMenuCount)
|
||||
DELETENULL(displayMenu);
|
||||
}
|
||||
|
||||
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
const char *cOsdMenu::hk(const char *s)
|
||||
{
|
||||
if (bitmap && Bitmap.bitmap) {
|
||||
tIndexes Indexes;
|
||||
Take(Bitmap, &Indexes);
|
||||
for (int ix = 0; ix < Bitmap.width; ix++) {
|
||||
for (int iy = 0; iy < Bitmap.height; iy++)
|
||||
SetIndex(x + ix, y + iy, Indexes[int(Bitmap.bitmap[Bitmap.width * iy + ix])]);
|
||||
static char buffer[64];
|
||||
if (s && hasHotkeys) {
|
||||
if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ')
|
||||
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;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int cBitmap::Width(unsigned char c)
|
||||
void cOsdMenu::SetHasHotkeys(void)
|
||||
{
|
||||
return font ? font->Width(c) : -1;
|
||||
hasHotkeys = true;
|
||||
digit = 0;
|
||||
}
|
||||
|
||||
int cBitmap::Width(const char *s)
|
||||
void cOsdMenu::SetStatus(const char *s)
|
||||
{
|
||||
return font ? font->Width(s) : -1;
|
||||
free(status);
|
||||
status = s ? strdup(s) : NULL;
|
||||
displayMenu->SetMessage(mtStatus, s);
|
||||
}
|
||||
|
||||
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||
void cOsdMenu::SetTitle(const char *Title)
|
||||
{
|
||||
if (bitmap) {
|
||||
u_char fg = Index(ColorFg);
|
||||
u_char bg = Index(ColorBg);
|
||||
int h = font->Height(s);
|
||||
while (s && *s) {
|
||||
const cFont::tCharData *CharData = font->CharData(*s++);
|
||||
if (int(x + CharData->width) > width)
|
||||
free(title);
|
||||
title = strdup(Title);
|
||||
}
|
||||
|
||||
void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||
{
|
||||
// strings are NOT copied - must be constants!!!
|
||||
helpRed = Red;
|
||||
helpGreen = Green;
|
||||
helpYellow = Yellow;
|
||||
helpBlue = Blue;
|
||||
displayMenu->SetButtons(helpRed, helpGreen, helpYellow, helpBlue);
|
||||
cStatus::MsgOsdHelpKeys(helpRed, helpGreen, helpYellow, helpBlue);
|
||||
}
|
||||
|
||||
void cOsdMenu::Del(int Index)
|
||||
{
|
||||
cList<cOsdItem>::Del(Get(Index));
|
||||
if (current == Count())
|
||||
current--;
|
||||
if (Index == first && first > 0)
|
||||
first--;
|
||||
}
|
||||
|
||||
void cOsdMenu::Add(cOsdItem *Item, bool Current, cOsdItem *After)
|
||||
{
|
||||
cList<cOsdItem>::Add(Item, After);
|
||||
if (Current)
|
||||
current = Item->Index();
|
||||
}
|
||||
|
||||
void cOsdMenu::Ins(cOsdItem *Item, bool Current, cOsdItem *Before)
|
||||
{
|
||||
cList<cOsdItem>::Ins(Item, Before);
|
||||
if (Current)
|
||||
current = Item->Index();
|
||||
}
|
||||
|
||||
void cOsdMenu::Display(void)
|
||||
{
|
||||
if (subMenu) {
|
||||
subMenu->Display();
|
||||
return;
|
||||
}
|
||||
displayMenu->Clear();
|
||||
cStatus::MsgOsdClear();
|
||||
displayMenu->SetTabs(cols[0], cols[1], cols[2], cols[3], cols[4]);//XXX
|
||||
displayMenu->SetTitle(title);
|
||||
cStatus::MsgOsdTitle(title);
|
||||
displayMenu->SetButtons(helpRed, helpGreen, helpYellow, helpBlue);
|
||||
cStatus::MsgOsdHelpKeys(helpRed, helpGreen, helpYellow, helpBlue);
|
||||
int count = Count();
|
||||
if (count > 0) {
|
||||
int ni = 0;
|
||||
for (cOsdItem *item = First(); item; item = Next(item))
|
||||
cStatus::MsgOsdItem(item->Text(), ni++);
|
||||
if (current < 0)
|
||||
current = 0; // just for safety - there HAS to be a current item!
|
||||
if (current - first >= displayMenuItems || current < first) {
|
||||
first = current - displayMenuItems / 2;
|
||||
if (first + displayMenuItems > count)
|
||||
first = count - displayMenuItems;
|
||||
if (first < 0)
|
||||
first = 0;
|
||||
}
|
||||
int i = first;
|
||||
int n = 0;
|
||||
for (cOsdItem *item = Get(first); item; item = Next(item)) {
|
||||
displayMenu->SetItem(item->Text(), i - first, i == current, item->Selectable());
|
||||
if (i == current)
|
||||
cStatus::MsgOsdCurrentItem(item->Text());
|
||||
if (++n == displayMenuItems)
|
||||
break;
|
||||
for (int row = 0; row < h; row++) {
|
||||
cFont::tPixelData PixelData = CharData->lines[row];
|
||||
for (int col = CharData->width; col-- > 0; ) {
|
||||
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
|
||||
PixelData >>= 1;
|
||||
}
|
||||
}
|
||||
x += CharData->width;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!isempty(status))
|
||||
displayMenu->SetMessage(mtStatus, status);
|
||||
}
|
||||
|
||||
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||
void cOsdMenu::SetCurrent(cOsdItem *Item)
|
||||
{
|
||||
if (bitmap) {
|
||||
u_char c = Index(Color);
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
SetIndex(x, y, c);
|
||||
}
|
||||
current = Item ? Item->Index() : -1;
|
||||
}
|
||||
|
||||
void cBitmap::Clear(void)
|
||||
void cOsdMenu::RefreshCurrent(void)
|
||||
{
|
||||
Reset();
|
||||
if (clearWithBackground)
|
||||
Fill(0, 0, width - 1, height - 1, clrBackground);
|
||||
cOsdItem *item = Get(current);
|
||||
if (item)
|
||||
item->Set();
|
||||
}
|
||||
|
||||
const u_char *cBitmap::Data(int x, int y)
|
||||
void cOsdMenu::DisplayCurrent(bool Current)
|
||||
{
|
||||
return &bitmap[y * width + x];
|
||||
cOsdItem *item = Get(current);
|
||||
if (item) {
|
||||
displayMenu->SetItem(item->Text(), current - first, Current, item->Selectable());
|
||||
if (Current)
|
||||
cStatus::MsgOsdCurrentItem(item->Text());
|
||||
if (!Current)
|
||||
item->SetFresh(true); // leaving the current item resets 'fresh'
|
||||
}
|
||||
}
|
||||
|
||||
// --- cWindow ---------------------------------------------------------------
|
||||
|
||||
cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||
:cBitmap(w, h, Bpp, ClearWithBackground)
|
||||
void cOsdMenu::Clear(void)
|
||||
{
|
||||
handle = Handle;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
bpp = Bpp;
|
||||
tiled = Tiled;
|
||||
shown = false;
|
||||
first = 0;
|
||||
current = marked = -1;
|
||||
cList<cOsdItem>::Clear();
|
||||
}
|
||||
|
||||
bool cWindow::Contains(int x, int y)
|
||||
bool cOsdMenu::SelectableItem(int idx)
|
||||
{
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
return x >= 0 && y >= 0 && x < width && y < height;
|
||||
cOsdItem *item = Get(idx);
|
||||
return item && item->Selectable();
|
||||
}
|
||||
|
||||
void cWindow::Relocate(int x, int y)
|
||||
void cOsdMenu::CursorUp(void)
|
||||
{
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
|
||||
void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||
{
|
||||
if (tiled) {
|
||||
x1 -= x0;
|
||||
y1 -= y0;
|
||||
x2 -= x0;
|
||||
y2 -= y0;
|
||||
}
|
||||
cBitmap::Fill(x1, y1, x2, y2, Color);
|
||||
}
|
||||
|
||||
void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
{
|
||||
if (tiled) {
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
}
|
||||
cBitmap::SetBitmap(x, y, Bitmap);
|
||||
}
|
||||
|
||||
void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||
{
|
||||
if (tiled) {
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
}
|
||||
cBitmap::Text(x, y, s, ColorFg, ColorBg);
|
||||
}
|
||||
|
||||
const u_char *cWindow::Data(int x, int y)
|
||||
{
|
||||
return cBitmap::Data(x, y);
|
||||
}
|
||||
|
||||
// --- cOsdBase --------------------------------------------------------------
|
||||
|
||||
cOsdBase::cOsdBase(int x, int y)
|
||||
{
|
||||
numWindows = 0;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
|
||||
cOsdBase::~cOsdBase()
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
delete window[i];
|
||||
}
|
||||
|
||||
tWindowHandle cOsdBase::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||
{
|
||||
if (numWindows < MAXNUMWINDOWS) {
|
||||
if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
|
||||
if ((w & 0x03) != 0) {
|
||||
w += 4 - (w & 0x03);
|
||||
dsyslog("OSD window width must be a multiple of 4 - increasing to %d", w);
|
||||
}
|
||||
cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled);
|
||||
if (OpenWindow(win)) {
|
||||
window[win->Handle()] = win;
|
||||
numWindows++;
|
||||
return win->Handle();
|
||||
if (current > 0) {
|
||||
int tmpCurrent = current;
|
||||
while (--tmpCurrent >= 0 && !SelectableItem(tmpCurrent));
|
||||
if (tmpCurrent < 0)
|
||||
return;
|
||||
if (tmpCurrent >= first)
|
||||
DisplayCurrent(false);
|
||||
current = tmpCurrent;
|
||||
if (current < first) {
|
||||
first = first > displayMenuItems - 1 ? first - (displayMenuItems - 1) : 0;
|
||||
if (Setup.MenuScrollPage)
|
||||
current = !SelectableItem(first) ? first + 1 : first;
|
||||
Display();
|
||||
}
|
||||
else
|
||||
delete win;
|
||||
DisplayCurrent(true);
|
||||
}
|
||||
}
|
||||
|
||||
void cOsdMenu::CursorDown(void)
|
||||
{
|
||||
int last = Count() - 1;
|
||||
int lastOnScreen = first + displayMenuItems - 1;
|
||||
|
||||
if (current < last) {
|
||||
int tmpCurrent = current;
|
||||
while (++tmpCurrent <= last && !SelectableItem(tmpCurrent));
|
||||
if (tmpCurrent > last)
|
||||
return;
|
||||
if (tmpCurrent <= lastOnScreen)
|
||||
DisplayCurrent(false);
|
||||
current = tmpCurrent;
|
||||
if (current > lastOnScreen) {
|
||||
first += displayMenuItems - 1;
|
||||
lastOnScreen = first + displayMenuItems - 1;
|
||||
if (lastOnScreen > last) {
|
||||
first = last - (displayMenuItems - 1);
|
||||
lastOnScreen = last;
|
||||
}
|
||||
if (Setup.MenuScrollPage)
|
||||
current = !SelectableItem(lastOnScreen) ? lastOnScreen - 1 : lastOnScreen;
|
||||
Display();
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: illegal OSD parameters");
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: too many OSD windows");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cOsdBase::AddColor(eDvbColor Color, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
w->Index(Color);
|
||||
w->Reset();
|
||||
DisplayCurrent(true);
|
||||
}
|
||||
}
|
||||
|
||||
cWindow *cOsdBase::GetWindow(int x, int y)
|
||||
void cOsdMenu::PageUp(void)
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
if (window[i]->Tiled() && window[i]->Contains(x, y))
|
||||
return window[i];
|
||||
current -= displayMenuItems;
|
||||
first -= displayMenuItems;
|
||||
if (first < 0)
|
||||
first = current = 0;
|
||||
if (!SelectableItem(current)) {
|
||||
current -= (current > 0) ? 1 : -1;
|
||||
first = min(first, current - 1);
|
||||
}
|
||||
return NULL;
|
||||
Display();
|
||||
DisplayCurrent(true);
|
||||
}
|
||||
|
||||
cWindow *cOsdBase::GetWindow(tWindowHandle Window)
|
||||
void cOsdMenu::PageDown(void)
|
||||
{
|
||||
if (0 <= Window && Window < numWindows)
|
||||
return window[Window];
|
||||
if (Window == LAST_CREATED_WINDOW && numWindows > 0)
|
||||
return window[numWindows - 1];
|
||||
return NULL;
|
||||
current += displayMenuItems;
|
||||
first += displayMenuItems;
|
||||
int count = Count();
|
||||
if (current > count - 1) {
|
||||
current = count - 1;
|
||||
first = max(0, count - displayMenuItems);
|
||||
}
|
||||
if (!SelectableItem(current)) {
|
||||
current += (current < count - 1) ? 1 : -1;
|
||||
first = max(first, current - displayMenuItems);
|
||||
}
|
||||
Display();
|
||||
DisplayCurrent(true);
|
||||
}
|
||||
|
||||
void cOsdBase::Flush(void)
|
||||
void cOsdMenu::Mark(void)
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
CommitWindow(window[i]);
|
||||
window[i]->Clean();
|
||||
}
|
||||
// Showing the windows in a separate loop to avoid seeing them come up one after another
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
if (!window[i]->Shown())
|
||||
ShowWindow(window[i]);
|
||||
if (Count() && marked < 0) {
|
||||
marked = current;
|
||||
SetStatus(tr("Up/Dn for new location - OK to move"));
|
||||
}
|
||||
}
|
||||
|
||||
void cOsdBase::Clear(tWindowHandle Window)
|
||||
eOSState cOsdMenu::HotKey(eKeys Key)
|
||||
{
|
||||
if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) {
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
if (Window == ALL_WINDOWS || window[i]->Tiled())
|
||||
window[i]->Clear();
|
||||
for (cOsdItem *item = First(); item; item = Next(item)) {
|
||||
const char *s = item->Text();
|
||||
if (s && (s = skipspace(s)) != NULL) {
|
||||
if (*s == Key - k1 + '1') {
|
||||
current = item->Index();
|
||||
cRemote::Put(kOk, true);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w)
|
||||
w->Clear();
|
||||
}
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
void cOsdBase::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window)
|
||||
eOSState cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window);
|
||||
if (w)
|
||||
w->Fill(x1, y1, x2, y2, Color);
|
||||
delete subMenu;
|
||||
subMenu = SubMenu;
|
||||
subMenu->Display();
|
||||
return osContinue; // convenience return value
|
||||
}
|
||||
|
||||
void cOsdBase::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window)
|
||||
eOSState cOsdMenu::CloseSubMenu()
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||
if (w)
|
||||
w->SetBitmap(x, y, Bitmap);
|
||||
delete subMenu;
|
||||
subMenu = NULL;
|
||||
RefreshCurrent();
|
||||
Display();
|
||||
return osContinue; // convenience return value
|
||||
}
|
||||
|
||||
int cOsdBase::Width(unsigned char c)
|
||||
eOSState cOsdMenu::ProcessKey(eKeys Key)
|
||||
{
|
||||
return numWindows ? window[0]->Width(c) : 0;
|
||||
if (subMenu) {
|
||||
eOSState state = subMenu->ProcessKey(Key);
|
||||
if (state == osBack)
|
||||
return CloseSubMenu();
|
||||
return state;
|
||||
}
|
||||
|
||||
int cOsdBase::Width(const char *s)
|
||||
{
|
||||
return numWindows ? window[0]->Width(s) : 0;
|
||||
cOsdItem *item = Get(current);
|
||||
if (marked < 0 && item) {
|
||||
eOSState state = item->ProcessKey(Key);
|
||||
if (state != osUnknown) {
|
||||
DisplayCurrent(true);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
switch (Key) {
|
||||
case k1...k9: return hasHotkeys ? HotKey(Key) : osUnknown;
|
||||
case kUp|k_Repeat:
|
||||
case kUp: CursorUp(); break;
|
||||
case kDown|k_Repeat:
|
||||
case kDown: CursorDown(); break;
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft: PageUp(); break;
|
||||
case kRight|k_Repeat:
|
||||
case kRight: PageDown(); break;
|
||||
case kBack: return osBack;
|
||||
case kOk: if (marked >= 0) {
|
||||
SetStatus(NULL);
|
||||
if (marked != current)
|
||||
Move(marked, current);
|
||||
marked = -1;
|
||||
break;
|
||||
}
|
||||
// else run into default
|
||||
default: if (marked < 0)
|
||||
return osUnknown;
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eDvbFont cOsdBase::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = Font;
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
oldFont = window[i]->SetFont(Font);
|
||||
return oldFont;
|
||||
}
|
||||
|
||||
void cOsdBase::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||
if (w)
|
||||
w->Text(x, y, s, ColorFg, ColorBg);
|
||||
}
|
||||
|
||||
void cOsdBase::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
if (NewWidth > 0 && NewHeight > 0) {
|
||||
if ((NewWidth & 0x03) != 0) {
|
||||
NewWidth += 4 - (NewWidth & 0x03);
|
||||
dsyslog("OSD window width must be a multiple of 4 - increasing to %d", NewWidth);
|
||||
}
|
||||
CloseWindow(w);
|
||||
cWindow *NewWindow = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled());
|
||||
window[w->Handle()] = NewWindow;
|
||||
delete w;
|
||||
OpenWindow(NewWindow);
|
||||
}
|
||||
else {
|
||||
MoveWindow(w, x, y);
|
||||
w->Relocate(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cOsdBase::Hide(tWindowHandle Window)
|
||||
{
|
||||
HideWindow(GetWindow(Window), true);
|
||||
}
|
||||
|
||||
void cOsdBase::Show(tWindowHandle Window)
|
||||
{
|
||||
HideWindow(GetWindow(Window), false);
|
||||
}
|
||||
|
294
osdbase.h
294
osdbase.h
@ -4,221 +4,127 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osdbase.h 1.9 2004/01/31 10:28:49 kls Exp $
|
||||
* $Id: osdbase.h 1.10 2004/04/30 13:40:11 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSDBASE_H
|
||||
#define __OSDBASE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "font.h"
|
||||
#include "config.h"
|
||||
#include "osd.h"
|
||||
#include "skins.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define MAXNUMCOLORS 256
|
||||
|
||||
enum eDvbColor {
|
||||
#ifdef DEBUG_OSD
|
||||
clrBackground,
|
||||
clrTransparent = clrBackground,
|
||||
clrBlack = clrBackground,
|
||||
clrRed,
|
||||
clrGreen,
|
||||
clrYellow,
|
||||
clrBlue,
|
||||
clrMagenta,
|
||||
clrCyan,
|
||||
clrWhite,
|
||||
#else
|
||||
clrTransparent = 0x00000000,
|
||||
clrBackground = 0x7F000000, // 50% gray
|
||||
clrBlack = 0xFF000000,
|
||||
clrRed = 0xFF1414FC,
|
||||
clrGreen = 0xFF24FC24,
|
||||
clrYellow = 0xFF24C0FC,
|
||||
clrMagenta = 0xFFFC00B0,
|
||||
clrBlue = 0xFFFC0000,
|
||||
clrCyan = 0xFFFCFC00,
|
||||
clrWhite = 0xFFFCFCFC,
|
||||
#endif
|
||||
enum eOSState { osUnknown,
|
||||
osContinue,
|
||||
osSchedule,
|
||||
osChannels,
|
||||
osTimers,
|
||||
osRecordings,
|
||||
osPlugin,
|
||||
osSetup,
|
||||
osCommands,
|
||||
osPause,
|
||||
osRecord,
|
||||
osReplay,
|
||||
osStopRecord,
|
||||
osStopReplay,
|
||||
osCancelEdit,
|
||||
osSwitchDvb,
|
||||
osBack,
|
||||
osEnd,
|
||||
os_User, // the following values can be used locally
|
||||
osUser1,
|
||||
osUser2,
|
||||
osUser3,
|
||||
osUser4,
|
||||
osUser5,
|
||||
osUser6,
|
||||
osUser7,
|
||||
osUser8,
|
||||
osUser9,
|
||||
osUser10,
|
||||
};
|
||||
|
||||
class cPalette {
|
||||
class cOsdItem : public cListObject {
|
||||
private:
|
||||
eDvbColor color[MAXNUMCOLORS];
|
||||
int maxColors, numColors;
|
||||
bool used[MAXNUMCOLORS];
|
||||
bool fetched[MAXNUMCOLORS];
|
||||
bool full;
|
||||
char *text;
|
||||
int offset;
|
||||
eOSState state;
|
||||
bool selectable;
|
||||
protected:
|
||||
typedef u_char tIndexes[MAXNUMCOLORS];
|
||||
bool fresh;
|
||||
public:
|
||||
cPalette(int Bpp);
|
||||
int Index(eDvbColor Color);
|
||||
void Reset(void);
|
||||
void SetColor(int Index, eDvbColor Color);
|
||||
eDvbColor GetColor(int Index) { return Index < maxColors ? color[Index] : clrBlack; }
|
||||
const eDvbColor *NewColors(int &FirstColor, int &LastColor);
|
||||
// With every call this function returns a consecutive range of
|
||||
// color entries that have been added since the last call. The
|
||||
// return value is the address of the first new color, and the
|
||||
// index of the first and last new color are returned in the given
|
||||
// int parameters. If there are no new color entries, NULL will
|
||||
// be returned.
|
||||
const eDvbColor *AllColors(int &NumColors);
|
||||
// Returns a pointer to the complete color table and stores the
|
||||
// number of valid entries in NumColors. If no colors have been
|
||||
// stored yet, NumColors will be set to 0 and the function will
|
||||
// return NULL.
|
||||
void Take(const cPalette &Palette, tIndexes *Indexes = NULL);
|
||||
cOsdItem(eOSState State = osUnknown);
|
||||
cOsdItem(const char *Text, eOSState State = osUnknown);
|
||||
virtual ~cOsdItem();
|
||||
bool Selectable(void) { return selectable; }
|
||||
void SetText(const char *Text, bool Copy = true);
|
||||
void SetSelectable(bool Selectable);
|
||||
void SetFresh(bool Fresh);
|
||||
const char *Text(void) { return text; }
|
||||
virtual void Set(void) {}
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cBitmap : public cPalette {
|
||||
class cOsdObject {
|
||||
friend class cOsdMenu;
|
||||
private:
|
||||
const cFont *font;
|
||||
eDvbFont fontType;
|
||||
u_char *bitmap;
|
||||
bool clearWithBackground;
|
||||
bool isMenu;
|
||||
protected:
|
||||
int width, height;
|
||||
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
||||
bool needsFastResponse;
|
||||
public:
|
||||
cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground = true);
|
||||
virtual ~cBitmap();
|
||||
bool ClearWithBackground(void) { return clearWithBackground; }
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
||||
void SetIndex(int x, int y, u_char Index);
|
||||
void SetPixel(int x, int y, eDvbColor Color);
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
int Width(void) { return width; }
|
||||
int Width(unsigned char c);
|
||||
int Width(const char *s);
|
||||
int Height(void) { return height; }
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||
void Clean(void);
|
||||
void Clear(void);
|
||||
const u_char *Data(int x, int y);
|
||||
cOsdObject(bool FastResponse = false) { isMenu = false; needsFastResponse = FastResponse; }
|
||||
virtual ~cOsdObject() {}
|
||||
bool NeedsFastResponse(void) { return needsFastResponse; }
|
||||
bool IsMenu(void) { return isMenu; }
|
||||
virtual void Show(void) {}
|
||||
virtual eOSState ProcessKey(eKeys Key) { return osUnknown; }
|
||||
};
|
||||
|
||||
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
|
||||
|
||||
class cWindow : public cBitmap {
|
||||
class cOsdMenu : public cOsdObject, public cList<cOsdItem> {
|
||||
private:
|
||||
int handle; // the index within the OSD's window array (0...MAXNUMWINDOWS - 1)
|
||||
int x0, y0;
|
||||
int bpp;
|
||||
bool tiled;
|
||||
bool shown;
|
||||
public:
|
||||
cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled);
|
||||
int X0(void) { return x0; }
|
||||
int Y0(void) { return y0; }
|
||||
int Bpp(void) { return bpp; }
|
||||
bool Tiled(void) { return tiled; }
|
||||
bool Shown(void) { bool s = shown; shown = true; return s; }
|
||||
int Handle(void) { return handle; }
|
||||
bool Contains(int x, int y);
|
||||
void Relocate(int x, int y);
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||
const u_char *Data(int x, int y);
|
||||
};
|
||||
|
||||
typedef int tWindowHandle;
|
||||
|
||||
// '-1' is used as an error return value!
|
||||
#define ALL_WINDOWS (-2)
|
||||
#define ALL_TILED_WINDOWS (-3)
|
||||
#define LAST_CREATED_WINDOW (-4)
|
||||
|
||||
class cOsdBase {
|
||||
private:
|
||||
int numWindows;
|
||||
int x0, y0;
|
||||
cWindow *window[MAXNUMWINDOWS];
|
||||
cWindow *GetWindow(int x, int y);
|
||||
cWindow *GetWindow(tWindowHandle Window);
|
||||
static cSkinDisplayMenu *displayMenu;
|
||||
static int displayMenuCount;
|
||||
static int displayMenuItems;
|
||||
char *title;
|
||||
int cols[cSkinDisplayMenu::MaxTabs];
|
||||
int first, current, marked;
|
||||
cOsdMenu *subMenu;
|
||||
const char *helpRed, *helpGreen, *helpYellow, *helpBlue;
|
||||
char *status;
|
||||
int digit;
|
||||
bool hasHotkeys;
|
||||
protected:
|
||||
cWindow *GetWindowNr(int i) { return i < MAXNUMWINDOWS ? window[i] : NULL; }
|
||||
int NumWindows(void) { return numWindows; }
|
||||
int X0(void) { return x0; }
|
||||
int Y0(void) { return y0; }
|
||||
virtual bool OpenWindow(cWindow *Window) = 0;
|
||||
// Opens the window on the OSD hardware, without actually showing it (the
|
||||
// initial state shall be "hidden").
|
||||
virtual void CommitWindow(cWindow *Window) = 0;
|
||||
// Write any modified data and color definitions to the OSD hardware.
|
||||
// Use the window's Dirty() function to find out which area of data
|
||||
// actually needs to be transferred. If the window has not yet been explicitly
|
||||
// shown through a call to ShowWindow(), no visible activity shall take place.
|
||||
virtual void ShowWindow(cWindow *Window) = 0;
|
||||
// Make the window actually visible on the OSD hardware.
|
||||
virtual void HideWindow(cWindow *Window, bool Hide) = 0;
|
||||
// Temporarily hide the window (if 'Hide' is 'true') or make a previously
|
||||
// hidden window visible again (if 'Hide' is 'false').
|
||||
virtual void MoveWindow(cWindow *Window, int x, int y) = 0;
|
||||
// Move the window to a new location.
|
||||
virtual void CloseWindow(cWindow *Window) = 0;
|
||||
// Close the window and release any OSD hardware resources allocated for it.
|
||||
cSkinDisplayMenu *DisplayMenu(void) { return displayMenu; }
|
||||
const char *hk(const char *s);
|
||||
void SetHasHotkeys(void);
|
||||
virtual void Clear(void);
|
||||
bool SelectableItem(int idx);
|
||||
void SetCurrent(cOsdItem *Item);
|
||||
void RefreshCurrent(void);
|
||||
void DisplayCurrent(bool Current);
|
||||
void CursorUp(void);
|
||||
void CursorDown(void);
|
||||
void PageUp(void);
|
||||
void PageDown(void);
|
||||
void Mark(void);
|
||||
eOSState HotKey(eKeys Key);
|
||||
eOSState AddSubMenu(cOsdMenu *SubMenu);
|
||||
eOSState CloseSubMenu();
|
||||
bool HasSubMenu(void) { return subMenu; }
|
||||
void SetStatus(const char *s);
|
||||
void SetTitle(const char *Title);
|
||||
void SetHelp(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
virtual void Del(int Index);
|
||||
public:
|
||||
cOsdBase(int x, int y);
|
||||
// Initializes the OSD, starting at screen coordinates (x, y).
|
||||
virtual ~cOsdBase();
|
||||
// Destroys all windows and shuts down the OSD.
|
||||
tWindowHandle Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true, bool Tiled = true);
|
||||
// Creates a window at coordinates (x, y), which are relative to the OSD's
|
||||
// origin given in the constructor, with the given width, height and color
|
||||
// depth. ClearWithBackground controls whether the window will be filled with
|
||||
// clrBackground when it is cleared. Setting this to 'false' may be useful
|
||||
// for windows that don't need clrBackground but want to save this color
|
||||
// palette entry for a different color. Tiled controls whether this will
|
||||
// be part of a multi section OSD (with several windows that all have
|
||||
// different color depths and palettes and form one large OSD area), or
|
||||
// whether this is a "standalone" window that will be drawn "in front"
|
||||
// of any windows defined *after* this one (this can be used for highlighting
|
||||
// certain parts of the OSD, as would be done in a 'cursor').
|
||||
// Returns a handle that can be used to identify this window.
|
||||
void AddColor(eDvbColor Color, tWindowHandle Window = LAST_CREATED_WINDOW);
|
||||
// Adds the Color to the color palette of the given window if it is not
|
||||
// already contained in the palette (and if the palette still has free
|
||||
// slots for new colors). The default value LAST_CREATED_WINDOW will
|
||||
// access the most recently created window, without the need of explicitly
|
||||
// using a window handle.
|
||||
void Flush(void);
|
||||
// Actually commits all data of all windows to the OSD.
|
||||
void Clear(tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Clears the given window. If ALL_TILED_WINDOWS is given, only the tiled
|
||||
// windows will be cleared, leaving the standalone windows untouched. If
|
||||
// ALL_WINDOWS is given, the standalone windows will also be cleared.
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Fills the rectangle defined by the upper left (x1, y2) and lower right
|
||||
// (x2, y2) corners with the given Color. If a specific window is given,
|
||||
// the coordinates are relative to that window's upper left corner.
|
||||
// Otherwise they are relative to the upper left corner of the entire OSD.
|
||||
// If all tiled windows are selected, only that window which contains the
|
||||
// point (x1, y1) will actually be filled.
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Sets the pixels within the given window with the data from the given
|
||||
// Bitmap. See Fill() for details about the coordinates.
|
||||
int Width(unsigned char c);
|
||||
// Returns the width (in pixels) of the given character in the current font.
|
||||
int Width(const char *s);
|
||||
// Returns the width (in pixels) of the given string in the current font.
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
// Sets the current font for subsequent Width() and Text() operations.
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Writes the given string at coordinates (x, y) with the given foreground
|
||||
// and background color into the given window (see Fill() for details
|
||||
// about the coordinates).
|
||||
void Relocate(tWindowHandle Window, int x, int y, int NewWidth = -1, int NewHeight = -1);
|
||||
// Moves the given window to the new location at (x, y). If NewWidth and
|
||||
// NewHeight are also given, the window will also be resized to the new
|
||||
// width and height.
|
||||
void Hide(tWindowHandle Window);
|
||||
// Hides the given window.
|
||||
void Show(tWindowHandle Window);
|
||||
// Shows the given window.
|
||||
cOsdMenu(const char *Title, int c0 = 0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0);
|
||||
virtual ~cOsdMenu();
|
||||
int Current(void) { return current; }
|
||||
void Add(cOsdItem *Item, bool Current = false, cOsdItem *After = NULL);
|
||||
void Ins(cOsdItem *Item, bool Current = false, cOsdItem *Before = NULL);
|
||||
virtual void Display(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
#endif //__OSDBASE_H
|
||||
|
4
player.c
4
player.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: player.c 1.6 2002/11/02 14:55:37 kls Exp $
|
||||
* $Id: player.c 1.7 2004/04/16 13:34:11 kls Exp $
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
@ -80,7 +80,7 @@ void cControl::Attach(void)
|
||||
if (cDevice::PrimaryDevice()->AttachPlayer(control->player))
|
||||
control->attached = true;
|
||||
else {
|
||||
Interface->Error(tr("Channel locked (recording)!"));
|
||||
Skins.Message(mtError, tr("Channel locked (recording)!"));
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
|
4
player.h
4
player.h
@ -4,14 +4,14 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: player.h 1.10 2002/11/03 11:27:30 kls Exp $
|
||||
* $Id: player.h 1.11 2004/04/30 13:45:59 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PLAYER_H
|
||||
#define __PLAYER_H
|
||||
|
||||
#include "device.h"
|
||||
#include "osd.h"
|
||||
#include "osdbase.h"
|
||||
|
||||
class cPlayer {
|
||||
friend class cDevice;
|
||||
|
4
plugin.h
4
plugin.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: plugin.h 1.6 2003/05/09 14:57:55 kls Exp $
|
||||
* $Id: plugin.h 1.7 2004/04/30 13:46:21 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PLUGIN_H
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#include "i18n.h"
|
||||
#include "menuitems.h"
|
||||
#include "osd.h"
|
||||
#include "osdbase.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRPLUGINCREATOR(PluginClass) extern "C" void *VDRPluginCreator(void) { return new PluginClass; }
|
||||
|
15
recording.c
15
recording.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.c 1.86 2003/11/08 15:25:35 kls Exp $
|
||||
* $Id: recording.c 1.87 2004/05/07 14:24:18 kls Exp $
|
||||
*/
|
||||
|
||||
#include "recording.h"
|
||||
@ -18,6 +18,7 @@
|
||||
#include "i18n.h"
|
||||
#include "interface.h"
|
||||
#include "remux.h" //XXX+ I_FRAME
|
||||
#include "skins.h"
|
||||
#include "tools.h"
|
||||
#include "videodir.h"
|
||||
|
||||
@ -461,7 +462,7 @@ char *cRecording::SortName(void)
|
||||
return sortBuffer;
|
||||
}
|
||||
|
||||
int cRecording::GetResume(void)
|
||||
int cRecording::GetResume(void) const
|
||||
{
|
||||
if (resume == RESUME_NOT_INITIALIZED) {
|
||||
cResumeFile ResumeFile(FileName());
|
||||
@ -476,7 +477,7 @@ bool cRecording::operator< (const cListObject &ListObject)
|
||||
return strcasecmp(SortName(), r->SortName()) < 0;
|
||||
}
|
||||
|
||||
const char *cRecording::FileName(void)
|
||||
const char *cRecording::FileName(void) const
|
||||
{
|
||||
if (!fileName) {
|
||||
struct tm tm_r;
|
||||
@ -488,7 +489,7 @@ const char *cRecording::FileName(void)
|
||||
return fileName;
|
||||
}
|
||||
|
||||
const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level)
|
||||
const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level) const
|
||||
{
|
||||
char New = NewIndicator && IsNew() ? '*' : ' ';
|
||||
free(titleBuffer);
|
||||
@ -548,7 +549,7 @@ const char *cRecording::PrefixFileName(char Prefix)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cRecording::HierarchyLevels(void)
|
||||
int cRecording::HierarchyLevels(void) const
|
||||
{
|
||||
const char *s = name;
|
||||
int level = 0;
|
||||
@ -559,7 +560,7 @@ int cRecording::HierarchyLevels(void)
|
||||
return level;
|
||||
}
|
||||
|
||||
bool cRecording::IsEdited(void)
|
||||
bool cRecording::IsEdited(void) const
|
||||
{
|
||||
const char *s = strrchr(name, '~');
|
||||
s = !s ? name : s + 1;
|
||||
@ -637,7 +638,7 @@ bool cRecordings::Load(bool Deleted)
|
||||
result = Count() > 0;
|
||||
}
|
||||
else
|
||||
Interface->Error("Error while opening pipe!");
|
||||
Skins.Message(mtError, "Error while opening pipe!");
|
||||
free(cmd);
|
||||
return result;
|
||||
}
|
||||
|
26
recording.h
26
recording.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.h 1.28 2003/10/17 14:27:36 kls Exp $
|
||||
* $Id: recording.h 1.29 2004/05/07 14:24:22 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RECORDING_H
|
||||
@ -34,15 +34,15 @@ public:
|
||||
|
||||
class cRecording : public cListObject {
|
||||
private:
|
||||
int resume;
|
||||
char *titleBuffer;
|
||||
mutable int resume;
|
||||
mutable char *titleBuffer;
|
||||
char *sortBuffer;
|
||||
char *fileName;
|
||||
char *name;
|
||||
mutable char *fileName;
|
||||
mutable char *name;
|
||||
char *summary;
|
||||
char *StripEpisodeName(char *s);
|
||||
char *SortName(void);
|
||||
int GetResume(void);
|
||||
int GetResume(void) const;
|
||||
public:
|
||||
time_t start;
|
||||
int priority;
|
||||
@ -51,14 +51,14 @@ public:
|
||||
cRecording(const char *FileName);
|
||||
~cRecording();
|
||||
virtual bool operator< (const cListObject &ListObject);
|
||||
const char *Name(void) { return name; }
|
||||
const char *FileName(void);
|
||||
const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1);
|
||||
const char *Summary(void) { return summary; }
|
||||
const char *Name(void) const { return name; }
|
||||
const char *FileName(void) const;
|
||||
const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
|
||||
const char *Summary(void) const { return summary; }
|
||||
const char *PrefixFileName(char Prefix);
|
||||
int HierarchyLevels(void);
|
||||
bool IsNew(void) { return GetResume() <= 0; }
|
||||
bool IsEdited(void);
|
||||
int HierarchyLevels(void) const;
|
||||
bool IsNew(void) const { return GetResume() <= 0; }
|
||||
bool IsEdited(void) const;
|
||||
bool WriteSummary(void);
|
||||
bool Delete(void);
|
||||
// Changes the file name so that it will no longer be visible in the "Recordings" menu
|
||||
|
541
skinclassic.c
Normal file
541
skinclassic.c
Normal file
@ -0,0 +1,541 @@
|
||||
/*
|
||||
* skinclassic.c: The 'classic' VDR skin
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinclassic.c 1.1 2004/05/15 14:51:18 kls Exp $
|
||||
*/
|
||||
|
||||
#include "skinclassic.h"
|
||||
#include "font.h"
|
||||
#include "i18n.h"
|
||||
#include "osd.h"
|
||||
#include "themes.h"
|
||||
|
||||
#define ScrollWidth 5
|
||||
|
||||
static cTheme Theme;
|
||||
|
||||
THEME_CLR(Theme, clrBackground, clrGray50);
|
||||
THEME_CLR(Theme, clrButtonRedFg, clrWhite);
|
||||
THEME_CLR(Theme, clrButtonRedBg, clrRed);
|
||||
THEME_CLR(Theme, clrButtonGreenFg, clrBlack);
|
||||
THEME_CLR(Theme, clrButtonGreenBg, clrGreen);
|
||||
THEME_CLR(Theme, clrButtonYellowFg, clrBlack);
|
||||
THEME_CLR(Theme, clrButtonYellowBg, clrYellow);
|
||||
THEME_CLR(Theme, clrButtonBlueFg, clrWhite);
|
||||
THEME_CLR(Theme, clrButtonBlueBg, clrBlue);
|
||||
THEME_CLR(Theme, clrMessageStatusFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMessageStatusBg, clrCyan);
|
||||
THEME_CLR(Theme, clrMessageInfoFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMessageInfoBg, clrGreen);
|
||||
THEME_CLR(Theme, clrMessageWarningFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMessageWarningBg, clrYellow);
|
||||
THEME_CLR(Theme, clrMessageErrorFg, clrWhite);
|
||||
THEME_CLR(Theme, clrMessageErrorBg, clrRed);
|
||||
THEME_CLR(Theme, clrVolumePrompt, clrGreen);
|
||||
THEME_CLR(Theme, clrVolumeBarUpper, clrWhite);
|
||||
THEME_CLR(Theme, clrVolumeBarLower, clrGreen);
|
||||
THEME_CLR(Theme, clrChannelName, clrWhite);
|
||||
THEME_CLR(Theme, clrChannelDate, clrWhite);
|
||||
THEME_CLR(Theme, clrChannelEpgTimeFg, clrWhite);
|
||||
THEME_CLR(Theme, clrChannelEpgTimeBg, clrRed);
|
||||
THEME_CLR(Theme, clrChannelEpgTitle, clrCyan);
|
||||
THEME_CLR(Theme, clrChannelEpgShortText, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuTitleFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuTitleBg, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuDate, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuItemCurrentFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuItemCurrentBg, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuItemSelectable, clrWhite);
|
||||
THEME_CLR(Theme, clrMenuItemNonSelectable, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuEventTime, clrWhite);
|
||||
THEME_CLR(Theme, clrMenuEventVpsFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuEventVpsBg, clrWhite);
|
||||
THEME_CLR(Theme, clrMenuEventTitle, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuEventShortText, clrWhite);
|
||||
THEME_CLR(Theme, clrMenuEventDescription, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuScrollbarTotal, clrWhite);
|
||||
THEME_CLR(Theme, clrMenuScrollbarShown, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuText, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayTitle, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayCurrent, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayTotal, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayModeJump, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayProgressSeen, clrGreen);
|
||||
THEME_CLR(Theme, clrReplayProgressRest, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayProgressSelected, clrRed);
|
||||
THEME_CLR(Theme, clrReplayProgressMark, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayProgressCurrent, clrRed);
|
||||
|
||||
// --- cSkinClassicDisplayChannel --------------------------------------------
|
||||
|
||||
class cSkinClassicDisplayChannel : public cSkinDisplayChannel{
|
||||
private:
|
||||
cOsd *osd;
|
||||
int lineHeight;
|
||||
int timeWidth;
|
||||
public:
|
||||
cSkinClassicDisplayChannel(bool WithInfo);
|
||||
virtual ~cSkinClassicDisplayChannel();
|
||||
virtual void SetChannel(const cChannel *Channel, int Number);
|
||||
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinClassicDisplayChannel::cSkinClassicDisplayChannel(bool WithInfo)
|
||||
{
|
||||
int Lines = WithInfo ? 5 : 1;
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
lineHeight = font->Height();
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - Lines * lineHeight));
|
||||
timeWidth = font->Width("00:00") + 4;
|
||||
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, Lines * lineHeight, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrBackground));
|
||||
}
|
||||
|
||||
cSkinClassicDisplayChannel::~cSkinClassicDisplayChannel()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayChannel::SetChannel(const cChannel *Channel, int Number)
|
||||
{
|
||||
osd->DrawRectangle(0, 0, osd->Width() - 1, lineHeight - 1, Theme.Color(clrBackground));
|
||||
osd->DrawText(2, 0, ChannelString(Channel, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
|
||||
{
|
||||
osd->DrawRectangle(0, lineHeight, timeWidth - 1, osd->Height(), Theme.Color(clrChannelEpgTimeBg));
|
||||
osd->DrawRectangle(timeWidth, lineHeight, osd->Width() - 1, osd->Height(), Theme.Color(clrBackground));
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const cEvent *e = !i ? Present : Following;
|
||||
if (e) {
|
||||
osd->DrawText( 2, (2 * i + 1) * lineHeight, e->GetTimeString(), Theme.Color(clrChannelEpgTimeFg), Theme.Color(clrChannelEpgTimeBg), cFont::GetFont(fontOsd));
|
||||
osd->DrawText(timeWidth + 10, (2 * i + 1) * lineHeight, e->Title(), Theme.Color(clrChannelEpgTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
|
||||
osd->DrawText(timeWidth + 10, (2 * i + 2) * lineHeight, e->ShortText(), Theme.Color(clrChannelEpgShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayChannel::Flush(void)
|
||||
{
|
||||
const char *date = DayDateTime();
|
||||
osd->DrawText(osd->Width() - cFont::GetFont(fontSml)->Width(date) - 2, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml));
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinClassicDisplayMenu -----------------------------------------------
|
||||
|
||||
class cSkinClassicDisplayMenu : public cSkinDisplayMenu {
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1;
|
||||
int y0, y1, y2, y3, y4, y5;
|
||||
int lineHeight;
|
||||
void SetScrollbar(void);
|
||||
public:
|
||||
cSkinClassicDisplayMenu(void);
|
||||
virtual ~cSkinClassicDisplayMenu();
|
||||
virtual void Scroll(bool Up, bool Page);
|
||||
virtual int MaxItems(void);
|
||||
virtual void Clear(void);
|
||||
virtual void SetTitle(const char *Title);
|
||||
virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
virtual void SetMessage(eMessageType Type, const char *Text);
|
||||
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
|
||||
virtual void SetEvent(const cEvent *Event);
|
||||
virtual void SetRecording(const cRecording *Recording);
|
||||
virtual void SetText(const char *Text, bool FixedFont);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinClassicDisplayMenu::cSkinClassicDisplayMenu(void)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
lineHeight = font->Height();
|
||||
x0 = 0;
|
||||
x1 = Setup.OSDWidth;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
y2 = y1 + lineHeight;
|
||||
y5 = Setup.OSDHeight;
|
||||
y4 = y5 - lineHeight;
|
||||
y3 = y4 - lineHeight;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
|
||||
tArea Areas[] = { { x0, y0, x1 - 1, y5 - 1, 4 } };
|
||||
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
else {
|
||||
tArea Areas[] = { { x0, y0, x1 - 1, y1 - 1, 2 },
|
||||
{ x0, y1, x1 - 1, y3 - 1, 2 },
|
||||
{ x0, y3, x1 - 1, y5 - 1, 4 }
|
||||
};
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
}
|
||||
osd->DrawRectangle(x0, y0, x1 - 1, y5 - 1, Theme.Color(clrBackground));
|
||||
}
|
||||
|
||||
cSkinClassicDisplayMenu::~cSkinClassicDisplayMenu()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetScrollbar(void)
|
||||
{
|
||||
if (textScroller.CanScroll()) {
|
||||
int yt = textScroller.Top();
|
||||
int yb = yt + textScroller.Height();
|
||||
int st = yt;
|
||||
int sb = yb;
|
||||
int tt = st + (sb - st) * textScroller.Offset() / textScroller.Total();
|
||||
int tb = tt + (sb - st) * textScroller.Shown() / textScroller.Total();
|
||||
int xl = x1 - ScrollWidth;
|
||||
osd->DrawRectangle(xl, st, x1 - 1, sb, Theme.Color(clrMenuScrollbarTotal));
|
||||
osd->DrawRectangle(xl, tt, x1 - 1, tb, Theme.Color(clrMenuScrollbarShown));
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::Scroll(bool Up, bool Page)
|
||||
{
|
||||
cSkinDisplayMenu::Scroll(Up, Page);
|
||||
SetScrollbar();
|
||||
}
|
||||
|
||||
int cSkinClassicDisplayMenu::MaxItems(void)
|
||||
{
|
||||
return (y3 - y2) / lineHeight;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::Clear(void)
|
||||
{
|
||||
textScroller.Reset();
|
||||
osd->DrawRectangle(x0, y1, x1 - 1, y4 - 1, Theme.Color(clrBackground));
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetTitle(const char *Title)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0);
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int w = x1 - x0;
|
||||
int t0 = x0;
|
||||
int t1 = x0 + w / 4;
|
||||
int t2 = x0 + w / 2;
|
||||
int t3 = x1 - w / 4;
|
||||
int t4 = x1;
|
||||
osd->DrawText(t0, y4, Red, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedBg), font, t1 - t0, 0, taCenter);
|
||||
osd->DrawText(t1, y4, Green, Theme.Color(clrButtonGreenFg), Theme.Color(clrButtonGreenBg), font, t2 - t1, 0, taCenter);
|
||||
osd->DrawText(t2, y4, Yellow, Theme.Color(clrButtonYellowFg), Theme.Color(clrButtonYellowBg), font, t3 - t2, 0, taCenter);
|
||||
osd->DrawText(t3, y4, Blue, Theme.Color(clrButtonBlueFg), Theme.Color(clrButtonBlueBg), font, t4 - t3, 0, taCenter);
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetMessage(eMessageType Type, const char *Text)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
if (Text)
|
||||
osd->DrawText(x0, y3, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x1 - x0, 0, taCenter);
|
||||
else
|
||||
osd->DrawRectangle(x0, y3, x1 - 1, y4 - 1, Theme.Color(clrBackground));
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
|
||||
{
|
||||
int y = y2 + Index * lineHeight;
|
||||
tColor ColorFg, ColorBg;
|
||||
if (Current) {
|
||||
ColorFg = Theme.Color(clrMenuItemCurrentFg);
|
||||
ColorBg = Theme.Color(clrMenuItemCurrentBg);
|
||||
}
|
||||
else {
|
||||
ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
|
||||
ColorBg = Theme.Color(clrBackground);
|
||||
}
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
for (int i = 0; i < MaxTabs; i++) {
|
||||
const char *s = GetTabbedText(Text, i);
|
||||
if (s) {
|
||||
int xt = x0 + Tab(i);
|
||||
osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x1 - xt);
|
||||
}
|
||||
if (!Tab(i + 1))
|
||||
break;
|
||||
}
|
||||
SetEditableWidth(x1 - x0 - Tab(1));
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
|
||||
{
|
||||
if (!Event)
|
||||
return;
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int xl = x0 + 10;
|
||||
int y = y2;
|
||||
cTextScroller ts;
|
||||
char t[32];
|
||||
snprintf(t, sizeof(t), "%s %s - %s", Event->GetDateString(), Event->GetTimeString(), Event->GetEndTimeString());//TODO dayname, no year
|
||||
ts.Set(osd, xl, y, x1 - xl, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
|
||||
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, " VPS: %s", Event->GetVpsString());
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
osd->DrawText(x1 - font->Width(buffer), y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font);
|
||||
free(buffer);
|
||||
}
|
||||
y += ts.Height();
|
||||
y += font->Height();
|
||||
ts.Set(osd, xl, y, x1 - xl, y3 - y, Event->Title(), font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
if (!isempty(Event->ShortText())) {
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
ts.Set(osd, xl, y, x1 - xl, y3 - y, Event->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
}
|
||||
y += font->Height();
|
||||
if (!isempty(Event->Description())) {
|
||||
textScroller.Set(osd, xl, y, x1 - xl - 2 * ScrollWidth, y3 - y, Event->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
|
||||
SetScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetRecording(const cRecording *Recording)
|
||||
{
|
||||
SetText(Recording->Summary(), false); //TODO
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd);
|
||||
textScroller.Set(osd, x0, y2, x1 - x0 - 2 * ScrollWidth, y3 - y2, Text, font, Theme.Color(clrMenuText), Theme.Color(clrBackground));
|
||||
SetScrollbar();
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::Flush(void)
|
||||
{
|
||||
const char *date = DayDateTime();
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
osd->DrawText(x1 - font->Width(date) - 2, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font);
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinClassicDisplayReplay ---------------------------------------------
|
||||
|
||||
class cSkinClassicDisplayReplay : public cSkinDisplayReplay {
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1;
|
||||
int y0, y1, y2, y3;
|
||||
int lastCurrentWidth;
|
||||
public:
|
||||
cSkinClassicDisplayReplay(bool ModeOnly);
|
||||
virtual ~cSkinClassicDisplayReplay();
|
||||
virtual void SetTitle(const char *Title);
|
||||
virtual void SetMode(bool Play, bool Forward, int Speed);
|
||||
virtual void SetProgress(int Current, int Total);
|
||||
virtual void SetCurrent(const char *Current);
|
||||
virtual void SetTotal(const char *Total);
|
||||
virtual void SetJump(const char *Jump);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinClassicDisplayReplay::cSkinClassicDisplayReplay(bool ModeOnly)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int lineHeight = font->Height();
|
||||
lastCurrentWidth = 0;
|
||||
x0 = 0;
|
||||
x1 = Setup.OSDWidth;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
y2 = 2 * lineHeight;
|
||||
y3 = 3 * lineHeight;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y3);
|
||||
tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
|
||||
}
|
||||
|
||||
cSkinClassicDisplayReplay::~cSkinClassicDisplayReplay()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::SetTitle(const char *Title)
|
||||
{
|
||||
osd->DrawText(x0, y0, Title, Theme.Color(clrReplayTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
|
||||
{
|
||||
if (Setup.ShowReplayMode) {
|
||||
const char *Mode;
|
||||
if (Speed == -1) Mode = Play ? " > " : " || ";
|
||||
else if (Play) Mode = Forward ? " X>> " : " <<X ";
|
||||
else Mode = Forward ? " X|> " : " <|X ";
|
||||
char buf[16];
|
||||
strn0cpy(buf, Mode, sizeof(buf));
|
||||
char *p = strchr(buf, 'X');
|
||||
if (p)
|
||||
*p = Speed > 0 ? '1' + Speed - 1 : ' ';
|
||||
SetJump(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::SetProgress(int Current, int Total)
|
||||
{
|
||||
cProgressBar pb(x1 - x0, y2 - y1, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
|
||||
osd->DrawBitmap(x0, y1, pb);
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::SetCurrent(const char *Current)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int w = font->Width(Current);
|
||||
osd->DrawText(x0, y2, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), font, lastCurrentWidth > w ? lastCurrentWidth : 0);
|
||||
lastCurrentWidth = w;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::SetTotal(const char *Total)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
osd->DrawText(x1 - font->Width(Total), y2, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), font);
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::SetJump(const char *Jump)
|
||||
{
|
||||
osd->DrawText(x0 + (x1 - x0) / 4, y2, Jump, Theme.Color(clrReplayModeJump), Theme.Color(clrBackground), cFont::GetFont(fontOsd), (x1 - x0) / 2, 0, taCenter);
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayReplay::Flush(void)
|
||||
{
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinClassicDisplayVolume ---------------------------------------------
|
||||
|
||||
class cSkinClassicDisplayVolume : public cSkinDisplayVolume {
|
||||
private:
|
||||
cOsd *osd;
|
||||
public:
|
||||
cSkinClassicDisplayVolume(void);
|
||||
virtual ~cSkinClassicDisplayVolume();
|
||||
virtual void SetVolume(int Current, int Total, bool Mute);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinClassicDisplayVolume::cSkinClassicDisplayVolume(void)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int lineHeight = font->Height();
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight);
|
||||
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
}
|
||||
|
||||
cSkinClassicDisplayVolume::~cSkinClassicDisplayVolume()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayVolume::SetVolume(int Current, int Total, bool Mute)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
if (Mute) {
|
||||
osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrTransparent);
|
||||
osd->DrawText(0, 0, tr("Mute"), Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
|
||||
}
|
||||
else {
|
||||
const char *Prompt = tr("Volume ");
|
||||
int l = font->Width(Prompt);
|
||||
int p = (osd->Width() - l) * Current / Total;
|
||||
osd->DrawText(0, 0, Prompt, Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
|
||||
osd->DrawRectangle(l, 0, l + p - 1, osd->Height() - 1, Theme.Color(clrVolumeBarLower));
|
||||
osd->DrawRectangle(l + p, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrVolumeBarUpper));
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayVolume::Flush(void)
|
||||
{
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinClassicDisplayMessage --------------------------------------------
|
||||
|
||||
class cSkinClassicDisplayMessage : public cSkinDisplayMessage {
|
||||
private:
|
||||
cOsd *osd;
|
||||
public:
|
||||
cSkinClassicDisplayMessage(void);
|
||||
virtual ~cSkinClassicDisplayMessage();
|
||||
virtual void SetMessage(eMessageType Type, const char *Text);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinClassicDisplayMessage::cSkinClassicDisplayMessage(void)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int lineHeight = font->Height();
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight);
|
||||
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 2 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
}
|
||||
|
||||
cSkinClassicDisplayMessage::~cSkinClassicDisplayMessage()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMessage::SetMessage(eMessageType Type, const char *Text)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, Setup.OSDWidth, 0, taCenter);
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMessage::Flush(void)
|
||||
{
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinClassic ----------------------------------------------------------
|
||||
|
||||
cSkinClassic::cSkinClassic(void)
|
||||
:cSkin("classic", &::Theme)//XXX naming problem???
|
||||
{
|
||||
}
|
||||
|
||||
const char *cSkinClassic::Description(void)
|
||||
{
|
||||
return tr("Classic VDR");
|
||||
}
|
||||
|
||||
cSkinDisplayChannel *cSkinClassic::DisplayChannel(bool WithInfo)
|
||||
{
|
||||
return new cSkinClassicDisplayChannel(WithInfo);
|
||||
}
|
||||
|
||||
cSkinDisplayMenu *cSkinClassic::DisplayMenu(void)
|
||||
{
|
||||
return new cSkinClassicDisplayMenu;
|
||||
}
|
||||
|
||||
cSkinDisplayReplay *cSkinClassic::DisplayReplay(bool ModeOnly)
|
||||
{
|
||||
return new cSkinClassicDisplayReplay(ModeOnly);
|
||||
}
|
||||
|
||||
cSkinDisplayVolume *cSkinClassic::DisplayVolume(void)
|
||||
{
|
||||
return new cSkinClassicDisplayVolume;
|
||||
}
|
||||
|
||||
cSkinDisplayMessage *cSkinClassic::DisplayMessage(void)
|
||||
{
|
||||
return new cSkinClassicDisplayMessage;
|
||||
}
|
26
skinclassic.h
Normal file
26
skinclassic.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* skinclassic.h: The 'classic' VDR skin
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinclassic.h 1.1 2004/04/18 09:38:02 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SKINCLASSIC_H
|
||||
#define __SKINCLASSIC_H
|
||||
|
||||
#include "skins.h"
|
||||
|
||||
class cSkinClassic : public cSkin {
|
||||
public:
|
||||
cSkinClassic(void);
|
||||
virtual const char *Description(void);
|
||||
virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
|
||||
virtual cSkinDisplayMenu *DisplayMenu(void);
|
||||
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
|
||||
virtual cSkinDisplayVolume *DisplayVolume(void);
|
||||
virtual cSkinDisplayMessage *DisplayMessage(void);
|
||||
};
|
||||
|
||||
#endif //__SKINCLASSIC_H
|
201
skins.c
Normal file
201
skins.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* skins.c: The optical appearance of the OSD
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skins.c 1.1 2004/05/15 12:34:38 kls Exp $
|
||||
*/
|
||||
|
||||
#include "skins.h"
|
||||
#include "interface.h"
|
||||
#include "status.h"
|
||||
#include "tools.h"
|
||||
|
||||
// --- cSkinDisplay ----------------------------------------------------------
|
||||
|
||||
cSkinDisplay *cSkinDisplay::current = NULL;
|
||||
|
||||
cSkinDisplay::cSkinDisplay(void)
|
||||
{
|
||||
current = this;
|
||||
editableWidth = 100; //XXX
|
||||
}
|
||||
|
||||
cSkinDisplay::~cSkinDisplay()
|
||||
{
|
||||
current = NULL;
|
||||
}
|
||||
|
||||
// --- cSkinDisplayMenu ------------------------------------------------------
|
||||
|
||||
cSkinDisplayMenu::cSkinDisplayMenu(void)
|
||||
{
|
||||
SetTabs(0);
|
||||
}
|
||||
|
||||
void cSkinDisplayMenu::SetTabs(int Tab1, int Tab2, int Tab3, int Tab4, int Tab5)
|
||||
{
|
||||
tabs[0] = 0;
|
||||
tabs[1] = Tab1 ? tabs[0] + Tab1 : 0;
|
||||
tabs[2] = Tab2 ? tabs[1] + Tab2 : 0;
|
||||
tabs[3] = Tab3 ? tabs[2] + Tab3 : 0;
|
||||
tabs[4] = Tab4 ? tabs[3] + Tab4 : 0;
|
||||
tabs[5] = Tab5 ? tabs[4] + Tab5 : 0;
|
||||
for (int i = 1; i < MaxTabs; i++)
|
||||
tabs[i] *= 12;//XXX average character width of font used for items!!!
|
||||
}
|
||||
|
||||
void cSkinDisplayMenu::Scroll(bool Up, bool Page)
|
||||
{
|
||||
textScroller.Scroll(Up, Page);
|
||||
}
|
||||
|
||||
const char *cSkinDisplayMenu::GetTabbedText(const char *s, int Tab)
|
||||
{
|
||||
if (!s)
|
||||
return NULL;
|
||||
static char buffer[1000];
|
||||
const char *a = s;
|
||||
const char *b = strchrnul(a, '\t');
|
||||
while (*b && Tab-- > 0) {
|
||||
a = b + 1;
|
||||
b = strchrnul(a, '\t');
|
||||
}
|
||||
if (!*b)
|
||||
return (Tab <= 0) ? a : NULL;
|
||||
unsigned int n = b - a;
|
||||
if (n >= sizeof(buffer))
|
||||
n = sizeof(buffer) - 1;
|
||||
strncpy(buffer, a, n);
|
||||
buffer[n] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// --- cSkinDisplayReplay::cProgressBar --------------------------------------
|
||||
|
||||
cSkinDisplayReplay::cProgressBar::cProgressBar(int Width, int Height, int Current, int Total, const cMarks *Marks, tColor ColorSeen, tColor ColorRest, tColor ColorSelected, tColor ColorMark, tColor ColorCurrent)
|
||||
:cBitmap(Width, Height, 2)
|
||||
{
|
||||
total = Total;
|
||||
if (total > 0) {
|
||||
int p = Pos(Current);
|
||||
DrawRectangle(0, 0, p, Height - 1, ColorSeen);
|
||||
DrawRectangle(p + 1, 0, Width - 1, Height - 1, ColorRest);
|
||||
if (Marks) {
|
||||
bool Start = true;
|
||||
for (const cMark *m = Marks->First(); m; m = Marks->Next(m)) {
|
||||
int p1 = Pos(m->position);
|
||||
if (Start) {
|
||||
const cMark *m2 = Marks->Next(m);
|
||||
int p2 = Pos(m2 ? m2->position : total);
|
||||
int h = Height / 3;
|
||||
DrawRectangle(p1, h, p2, Height - h, ColorSelected);
|
||||
}
|
||||
Mark(p1, Start, m->position == Current, ColorMark, ColorCurrent);
|
||||
Start = !Start;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinDisplayReplay::cProgressBar::Mark(int x, bool Start, bool Current, tColor ColorMark, tColor ColorCurrent)
|
||||
{
|
||||
DrawRectangle(x, 0, x, Height() - 1, ColorMark);
|
||||
const int d = Height() / (Current ? 3 : 9);
|
||||
for (int i = 0; i < d; i++) {
|
||||
int h = Start ? i : Height() - 1 - i;
|
||||
DrawRectangle(x - d + i, h, x + d - i, h, Current ? ColorCurrent : ColorMark);
|
||||
}
|
||||
}
|
||||
|
||||
// --- cSkinDisplayReplay ----------------------------------------------------
|
||||
|
||||
cSkinDisplayReplay::cSkinDisplayReplay(void)
|
||||
{
|
||||
marks = NULL;
|
||||
}
|
||||
|
||||
void cSkinDisplayReplay::SetMarks(const cMarks *Marks)
|
||||
{
|
||||
marks = Marks;
|
||||
}
|
||||
|
||||
// --- cSkin -----------------------------------------------------------------
|
||||
|
||||
cSkin::cSkin(const char *Name, cTheme *Theme)
|
||||
{
|
||||
name = strdup(Name);
|
||||
theme = Theme;
|
||||
if (theme)
|
||||
cThemes::Save(name, theme);
|
||||
Skins.Add(this);
|
||||
}
|
||||
|
||||
cSkin::~cSkin()
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
|
||||
// --- cSkins ----------------------------------------------------------------
|
||||
|
||||
cSkins Skins;
|
||||
|
||||
cSkins::cSkins(void)
|
||||
{
|
||||
displayMessage = NULL;
|
||||
}
|
||||
|
||||
cSkins::~cSkins()
|
||||
{
|
||||
delete displayMessage;
|
||||
}
|
||||
|
||||
bool cSkins::SetCurrent(const char *Name)
|
||||
{
|
||||
if (Name) {
|
||||
for (cSkin *Skin = First(); Skin; Skin = Next(Skin)) {
|
||||
if (strcmp(Skin->Name(), Name) == 0) {
|
||||
current = Skin;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
current = First();
|
||||
return current != NULL;
|
||||
}
|
||||
|
||||
eKeys cSkins::Message(eMessageType Type, const char *s, int Seconds)
|
||||
{
|
||||
switch (Type) {
|
||||
case mtInfo: isyslog("info: %s", s); break;
|
||||
case mtError: esyslog("ERROR: %s", s); break;
|
||||
default: ;
|
||||
}
|
||||
if (!cSkinDisplay::Current() && !displayMessage)
|
||||
displayMessage = Current()->DisplayMessage();
|
||||
cSkinDisplay::Current()->SetMessage(Type, s);
|
||||
cSkinDisplay::Current()->Flush();
|
||||
cStatus::MsgOsdStatusMessage(s);
|
||||
eKeys k = kNone;
|
||||
if (Type != mtStatus) {
|
||||
k = Interface->Wait(Seconds);
|
||||
if (displayMessage) {
|
||||
delete displayMessage;
|
||||
displayMessage = NULL;
|
||||
}
|
||||
else
|
||||
cSkinDisplay::Current()->SetMessage(Type, NULL);
|
||||
}
|
||||
else if (!s && displayMessage) {
|
||||
delete displayMessage;
|
||||
displayMessage = NULL;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
void cSkins::Flush(void)
|
||||
{
|
||||
if (cSkinDisplay::Current())
|
||||
cSkinDisplay::Current()->Flush();
|
||||
}
|
297
skins.h
Normal file
297
skins.h
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* skins.h: The optical appearance of the OSD
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skins.h 1.1 2004/05/16 09:40:18 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SKINS_H
|
||||
#define __SKINS_H
|
||||
|
||||
#include "channels.h"
|
||||
#include "epg.h"
|
||||
#include "keys.h"
|
||||
#include "osd.h"
|
||||
#include "recording.h"
|
||||
#include "themes.h"
|
||||
#include "tools.h"
|
||||
|
||||
enum eMessageType { mtStatus = 0, mtInfo, mtWarning, mtError }; // will be used to calculate color offsets!
|
||||
|
||||
class cSkinDisplay {
|
||||
private:
|
||||
static cSkinDisplay *current;
|
||||
int editableWidth; //XXX this is not nice, but how else could we know this value?
|
||||
public:
|
||||
cSkinDisplay(void);
|
||||
virtual ~cSkinDisplay();
|
||||
int EditableWidth(void) { return editableWidth; }
|
||||
void SetEditableWidth(int Width) { editableWidth = Width; }
|
||||
///< If an item is set through a call to cSkinDisplayMenu::SetItem(), this
|
||||
///< function shall be called to set the width of the rightmost tab separated
|
||||
///< field. This information will be used for editable items.
|
||||
virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL) {}
|
||||
///< Sets the color buttons to the given strings, provided this cSkinDisplay
|
||||
///< actually has a color button display.
|
||||
virtual void SetMessage(eMessageType Type, const char *Text) {}
|
||||
///< Sets a one line message Text, with the given Type. Type can be used
|
||||
///< to determine, e.g., the colors for displaying the Text.
|
||||
virtual void Flush(void) {}
|
||||
///< Actually draws the OSD display to the output device.
|
||||
static cSkinDisplay *Current(void) { return current; }
|
||||
///< Returns the currently active cSkinDisplay.
|
||||
};
|
||||
|
||||
class cSkinDisplayChannel : public cSkinDisplay {
|
||||
///< This class is used to display the current channel, together with
|
||||
///< the present and following EPG even. How and to what extent this
|
||||
///< is done is totally up to the derived class.
|
||||
public:
|
||||
virtual void SetChannel(const cChannel *Channel, int Number) = 0;
|
||||
///< Sets the current channel to Channel. If Number is not 0, the
|
||||
///< user is in the process of entering a channel number, which must
|
||||
///< be displayed accordingly.
|
||||
virtual void SetEvents(const cEvent *Present, const cEvent *Following) = 0;
|
||||
///< Sets the Present and Following EPG events. It either of these
|
||||
///< is not available, NULL will be given.
|
||||
/*TODO
|
||||
SetButtons
|
||||
Red = Video options
|
||||
Green = Info now
|
||||
Yellow = Info next
|
||||
Blue = Audio options
|
||||
AudioOptions
|
||||
VideoOptions
|
||||
*/
|
||||
};
|
||||
|
||||
class cSkinDisplayMenu : public cSkinDisplay {
|
||||
///< This class implements the general purpose menu display, which is
|
||||
///< used throughout the program to display information and let the
|
||||
///< user interact with items.
|
||||
///< A menu consists of the following fields, each of which is explicitly
|
||||
///< set by calls to the member functions below:
|
||||
///< - Title: a single line of text, indicating what this menu displays
|
||||
///< - Color buttons: the red, green, yellow and blue buttons, used for
|
||||
///< various functions
|
||||
///< - Message: a one line message, indicating a Status, Info, Warning,
|
||||
///< or Error condition
|
||||
///< - Central area: the main central area of the menu, used to display
|
||||
///< one of the following:
|
||||
///< - Items: a list of single line items, of which the user may be
|
||||
///< able to select one
|
||||
///< - Event: the full information about one EPG event
|
||||
///< - Text: a multi line, scrollable text
|
||||
public:
|
||||
enum { MaxTabs = 6 };
|
||||
private:
|
||||
int tabs[MaxTabs];
|
||||
protected:
|
||||
cTextScroller textScroller;
|
||||
int Tab(int n) { return (n >= 0 && n < MaxTabs) ? tabs[n] : 0; }
|
||||
///< Returns the offset of the given tab from the left border of the
|
||||
///< item display area. The value returned is in pixel.//XXX ncurses???
|
||||
const char *GetTabbedText(const char *s, int Tab);
|
||||
///< Returns the that part of the given string, that follows the given
|
||||
///< Tab (where 0 indicates the beginning of the string). If no such
|
||||
///< part can be found, NULL will be returned.
|
||||
public:
|
||||
cSkinDisplayMenu(void);
|
||||
virtual void SetTabs(int Tab1, int Tab2 = 0, int Tab3 = 0, int Tab4 = 0, int Tab5 = 0);
|
||||
///< Sets the tab columns to the given values, which are the number of
|
||||
///< characters in each column.//XXX ncurses???
|
||||
virtual void Scroll(bool Up, bool Page);
|
||||
///< If this menu contains a text area that can be scrolled, this function
|
||||
///< will be called to actually scroll the text. Up indicates whether the
|
||||
///< text shall be scrolled up or down, and Page is true if it shall be
|
||||
///< scrolled by a full page, rather than a single line. An object of the
|
||||
///< cTextScroller class can be used to implement the scrolling text area.
|
||||
virtual int MaxItems(void) = 0;
|
||||
///< Returns the maximum number of items the menu can display.
|
||||
virtual void Clear(void) = 0;
|
||||
///< Clears the entire central area of the menu.
|
||||
virtual void SetTitle(const char *Title) = 0;
|
||||
///< Sets the title of this menu to Title.
|
||||
virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL) = 0;
|
||||
///< Sets the color buttons to the given strings. If any of the values is
|
||||
///< NULL, any previous text must be removed from the related button.
|
||||
virtual void SetMessage(eMessageType Type, const char *Text) = 0;
|
||||
///< Sets a one line message Text, with the given Type. Type can be used
|
||||
///< to determine, e.g., the colors for displaying the Text.
|
||||
///< If Text is NULL, any previously displayed message must be removed, and
|
||||
///< any previous contents overwritten by the message must be restored.
|
||||
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable) = 0;
|
||||
///< Sets the item at the given Index to Text. Index is between 0 and the
|
||||
///< value returned by MaxItems(), minus one. Text may contain tab characters ('\t'),
|
||||
///< which shall be used to separate the text into several columns, according to the
|
||||
///< values set by a prior call to SetTabs(). If Current is true, this item shall
|
||||
///< be drawn in a way indicating to the user that it is the currently selected
|
||||
///< one. Selectable can be used to display items differently that can't be
|
||||
///< selected by the user.
|
||||
///< Whenever the current status is moved from one item to another,
|
||||
///< this function will be first called for the old current item
|
||||
///< with Current set to false, and then for the new current item
|
||||
///< with Current set to true.
|
||||
/*TODO
|
||||
virtual void SetItem(const cEvent *Event, int Index, bool Current, bool Selectable, bool NowNext???, bool Schedule???);
|
||||
virtual void SetItem(const cTimer *Timer, int Index, bool Current, bool Selectable);
|
||||
virtual void SetItem(const cChannel *Channel, int Index, bool Current, bool Selectable);
|
||||
virtual void SetItem(const cRecording *Recording, int Index, bool Current, bool Selectable);
|
||||
--> false: call SetItem(text)
|
||||
*/
|
||||
virtual void SetEvent(const cEvent *Event) = 0;
|
||||
///< Sets the Event that shall be displayed, using the entire central area
|
||||
///< of the menu. The Event's 'description' shall be displayed using a
|
||||
///< cTextScroller, and the Scroll() function will be called to drive scrolling
|
||||
///< that text if necessary.
|
||||
virtual void SetRecording(const cRecording *Recording) = 0;
|
||||
///< Sets the Recording that shall be displayed, using the entire central area
|
||||
///< of the menu. The Recording's 'summary' shall be displayed using a
|
||||
///< cTextScroller, and the Scroll() function will be called to drive scrolling
|
||||
///< that text if necessary.
|
||||
virtual void SetText(const char *Text, bool FixedFont) = 0;
|
||||
///< Sets the Text that shall be displayed, using the entire central area
|
||||
///< of the menu. The Text shall be displayed using a cTextScroller, and
|
||||
///< the Scroll() function will be called to drive scrolling that text if
|
||||
///< necessary.
|
||||
//XXX ??? virtual void SetHelp(const char *Help) = 0;
|
||||
};
|
||||
|
||||
class cSkinDisplayReplay : public cSkinDisplay {
|
||||
///< This class implements the progress display used during replay of
|
||||
///< a recording.
|
||||
protected:
|
||||
const cMarks *marks;
|
||||
class cProgressBar : public cBitmap {
|
||||
protected:
|
||||
int total;
|
||||
int Pos(int p) { return p * Width() / total; }
|
||||
void Mark(int x, bool Start, bool Current, tColor ColorMark, tColor ColorCurrent);
|
||||
public:
|
||||
cProgressBar(int Width, int Height, int Current, int Total, const cMarks *Marks, tColor ColorSeen, tColor ColorRest, tColor ColorSelected, tColor ColorMark, tColor ColorCurrent);
|
||||
};
|
||||
public:
|
||||
cSkinDisplayReplay(void);
|
||||
virtual void SetMarks(const cMarks *Marks);
|
||||
///< Sets the editing marks to Marks, which shall be used to display the
|
||||
///< progress bar through a cProgressBar object.
|
||||
virtual void SetTitle(const char *Title) = 0;
|
||||
///< Sets the title of the recording.
|
||||
virtual void SetMode(bool Play, bool Forward, int Speed) = 0;
|
||||
///< Sets the current replay mode, which can be used to display some
|
||||
///< indicator, showing the user whether we are currently in normal
|
||||
///< play mode, fast forward etc.
|
||||
virtual void SetProgress(int Current, int Total) = 0;
|
||||
///< This function will be called whenever the position in of the total
|
||||
///< length of the recording has changed. A cProgressBar shall then be
|
||||
///< used to display a progress indicator.
|
||||
virtual void SetCurrent(const char *Current) = 0;
|
||||
///< Sets the current position within the recording, as a user readable
|
||||
///< string if the form "h:mm:ss.ff". The ".ff" part, indicating the
|
||||
///< frame number, is optional and the actual implementation needs to
|
||||
///< take care that it is erased from the display when a Current string
|
||||
///< _with_ ".ff" is followed by one without it.
|
||||
virtual void SetTotal(const char *Total) = 0;
|
||||
///< Sets the total length of the recording, as a user readable
|
||||
///< string if the form "h:mm:ss".
|
||||
virtual void SetJump(const char *Jump) = 0;
|
||||
///< Sets the prompt that allows the user to enter a jump point.
|
||||
///< Jump is a string of the form "Jump: mm:ss". The actual implementation
|
||||
///< needs to be able to handle variations in the length of this
|
||||
///< string, which will occur when the user enters an actual value.
|
||||
///< If Jump is NULL, the jump prompt shall be removed from the display.
|
||||
};
|
||||
|
||||
class cSkinDisplayVolume : public cSkinDisplay {
|
||||
///< This class implements the volume/mute display.
|
||||
public:
|
||||
virtual void SetVolume(int Current, int Total, bool Mute) = 0;
|
||||
///< Sets the volume to the given Current value, which is in the range
|
||||
///< 0...Total. If Mute is true, audio is currently muted and a "mute"
|
||||
///< indicator shall be displayed.
|
||||
};
|
||||
|
||||
class cSkinDisplayMessage : public cSkinDisplay {
|
||||
///< This class implements a simple message display.
|
||||
public:
|
||||
virtual void SetMessage(eMessageType Type, const char *Text) = 0;
|
||||
///< Sets the message to Text. Type can be used to decide how to display
|
||||
///< the message, for instance in which colors.
|
||||
};
|
||||
|
||||
class cSkin : public cListObject {
|
||||
private:
|
||||
char *name;
|
||||
cTheme *theme;
|
||||
public:
|
||||
cSkin(const char *Name, cTheme *Theme = NULL);
|
||||
///< Creates a new skin class, with the given Name and Theme.
|
||||
///< Name will be used to identify this skin in the 'setup.conf'
|
||||
///< file, and is normally not seen by the user. It should
|
||||
///< consist of only lowercase letters and digits.
|
||||
///< Theme must be a static object that survives the entire lifetime
|
||||
///< of this skin.
|
||||
///< The constructor of a derived class shall not set up any data
|
||||
///< structures yet, because whether or not this skin will actually
|
||||
///< be used is not yet known at this point. All actual work shall
|
||||
///< be done in the pure functions below.
|
||||
///< A cSkin object must be created on the heap and shall not be
|
||||
///< explicitly deleted.
|
||||
virtual ~cSkin();
|
||||
const char *Name(void) { return name; }
|
||||
cTheme *Theme(void) { return theme; }
|
||||
virtual const char *Description(void) = 0;
|
||||
///< Returns a user visible, single line description of this skin,
|
||||
///< which may consist of arbitrary text and can, if the skin
|
||||
///< implementation wishes to do so, be internationalized.
|
||||
///< The actual text shouldn't be too long, so that it can be
|
||||
///< fully displayed in the Setup/OSD menu.
|
||||
virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo) = 0;
|
||||
///< Creates and returns a new object for displaying the current
|
||||
///< channel. WithInfo indicates whether it shall display only
|
||||
///< the basic channel data, or also information about the present
|
||||
///< and following EPG event.
|
||||
///< The caller must delete the object after use.
|
||||
virtual cSkinDisplayMenu *DisplayMenu(void) = 0;
|
||||
///< Creates and returns a new object for displaying a menu.
|
||||
///< The caller must delete the object after use.
|
||||
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly) = 0;
|
||||
///< Creates and returns a new object for displaying replay progress.
|
||||
///< ModeOnly indicates whether this should be a full featured replay
|
||||
///< display, or just a replay mode indicator.
|
||||
///< The caller must delete the object after use.
|
||||
virtual cSkinDisplayVolume *DisplayVolume(void) = 0;
|
||||
///< Creates and returns a new object for displaying the current volume.
|
||||
///< The caller must delete the object after use.
|
||||
virtual cSkinDisplayMessage *DisplayMessage(void) = 0;
|
||||
///< Creates and returns a new object for displaying a message.
|
||||
///< The caller must delete the object after use.
|
||||
};
|
||||
|
||||
class cSkins : public cList<cSkin> {
|
||||
private:
|
||||
cSkin *current;
|
||||
cSkinDisplayMessage *displayMessage;
|
||||
public:
|
||||
cSkins(void);
|
||||
~cSkins();
|
||||
bool SetCurrent(const char *Name = NULL);
|
||||
///< Sets the current skin to the one indicated by name.
|
||||
///< If no such skin can be found, the first one will be used.
|
||||
cSkin *Current(void) { return current; }
|
||||
///< Returns a pointer to the current skin.
|
||||
bool IsOpen(void) { return cSkinDisplay::Current(); }
|
||||
///< Returns true if there is currently a skin display object active.
|
||||
eKeys Message(eMessageType Type, const char *s, int Seconds = 0);
|
||||
///< Displays the given message, either through a currently visible
|
||||
///< display object that is capable of doing so, or by creating a
|
||||
///< temporary cSkinDisplayMessage object.
|
||||
void Flush(void);
|
||||
///< Flushes the currently active cSkinDisplay, if any.
|
||||
};
|
||||
|
||||
extern cSkins Skins;
|
||||
|
||||
#endif //__SKINS_H
|
879
skinsttng.c
Normal file
879
skinsttng.c
Normal file
@ -0,0 +1,879 @@
|
||||
/*
|
||||
* skinsttng.c: A VDR skin with ST:TNG Panels
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinsttng.c 1.1 2004/05/16 09:27:35 kls Exp $
|
||||
*/
|
||||
|
||||
// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
|
||||
// registered in the United States Patent and Trademark Office.
|
||||
// No infringement intended.
|
||||
|
||||
#include "skinsttng.h"
|
||||
#include "font.h"
|
||||
#include "osd.h"
|
||||
#include "menu.h"
|
||||
#include "themes.h"
|
||||
|
||||
#include "symbols/arrowdown.xpm"
|
||||
#include "symbols/arrowup.xpm"
|
||||
#include "symbols/audio.xpm"
|
||||
#include "symbols/dolbydigital.xpm"
|
||||
#include "symbols/encrypted.xpm"
|
||||
#include "symbols/ffwd.xpm"
|
||||
#include "symbols/ffwd1.xpm"
|
||||
#include "symbols/ffwd2.xpm"
|
||||
#include "symbols/ffwd3.xpm"
|
||||
#include "symbols/frew.xpm"
|
||||
#include "symbols/frew1.xpm"
|
||||
#include "symbols/frew2.xpm"
|
||||
#include "symbols/frew3.xpm"
|
||||
#include "symbols/mute.xpm"
|
||||
#include "symbols/pause.xpm"
|
||||
#include "symbols/play.xpm"
|
||||
#include "symbols/radio.xpm"
|
||||
#include "symbols/recording.xpm"
|
||||
#include "symbols/sfwd.xpm"
|
||||
#include "symbols/sfwd1.xpm"
|
||||
#include "symbols/sfwd2.xpm"
|
||||
#include "symbols/sfwd3.xpm"
|
||||
#include "symbols/srew.xpm"
|
||||
#include "symbols/srew1.xpm"
|
||||
#include "symbols/srew2.xpm"
|
||||
#include "symbols/srew3.xpm"
|
||||
#include "symbols/teletext.xpm"
|
||||
#include "symbols/volume.xpm"
|
||||
|
||||
#define Roundness 10
|
||||
#define Gap 5
|
||||
#define ScrollWidth 5
|
||||
|
||||
static cTheme Theme;
|
||||
|
||||
THEME_CLR(Theme, clrBackground, clrGray50);
|
||||
THEME_CLR(Theme, clrButtonRedFg, clrWhite);
|
||||
THEME_CLR(Theme, clrButtonRedBg, clrRed);
|
||||
THEME_CLR(Theme, clrButtonGreenFg, clrBlack);
|
||||
THEME_CLR(Theme, clrButtonGreenBg, clrGreen);
|
||||
THEME_CLR(Theme, clrButtonYellowFg, clrBlack);
|
||||
THEME_CLR(Theme, clrButtonYellowBg, clrYellow);
|
||||
THEME_CLR(Theme, clrButtonBlueFg, clrWhite);
|
||||
THEME_CLR(Theme, clrButtonBlueBg, clrBlue);
|
||||
THEME_CLR(Theme, clrMessageFrame, clrYellow);
|
||||
THEME_CLR(Theme, clrMessageStatusFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMessageStatusBg, clrCyan);
|
||||
THEME_CLR(Theme, clrMessageInfoFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMessageInfoBg, clrGreen);
|
||||
THEME_CLR(Theme, clrMessageWarningFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMessageWarningBg, clrYellow);
|
||||
THEME_CLR(Theme, clrMessageErrorFg, clrWhite);
|
||||
THEME_CLR(Theme, clrMessageErrorBg, clrRed);
|
||||
THEME_CLR(Theme, clrVolumeFrame, clrYellow);
|
||||
THEME_CLR(Theme, clrVolumeSymbol, clrBlack);
|
||||
THEME_CLR(Theme, clrVolumeBarUpper, 0xFFBC8024);
|
||||
THEME_CLR(Theme, clrVolumeBarLower, 0xFF248024);
|
||||
THEME_CLR(Theme, clrChannelFrame, clrYellow);
|
||||
THEME_CLR(Theme, clrChannelName, clrBlack);
|
||||
THEME_CLR(Theme, clrChannelDate, clrBlack);
|
||||
THEME_CLR(Theme, clrChannelSymbolOn, clrBlack);
|
||||
THEME_CLR(Theme, clrChannelSymbolOff, 0xFFBC8024);
|
||||
THEME_CLR(Theme, clrChannelSymbolRecFg, clrWhite);
|
||||
THEME_CLR(Theme, clrChannelSymbolRecBg, clrRed);
|
||||
THEME_CLR(Theme, clrChannelEpgTime, clrBlack);
|
||||
THEME_CLR(Theme, clrChannelEpgTitle, clrCyan);
|
||||
THEME_CLR(Theme, clrChannelEpgShortText, clrYellow);
|
||||
THEME_CLR(Theme, clrChannelTimebarSeen, clrYellow);
|
||||
THEME_CLR(Theme, clrChannelTimebarRest, clrGray50);
|
||||
THEME_CLR(Theme, clrMenuFrame, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuTitle, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuDate, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuItemCurrentFg, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuItemCurrentBg, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuItemSelectable, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuItemNonSelectable, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuEventTime, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuEventVps, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuEventTitle, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuEventShortText, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuEventDescription, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuScrollbarTotal, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuScrollbarShown, clrCyan);
|
||||
THEME_CLR(Theme, clrMenuScrollbarArrow, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuText, clrCyan);
|
||||
THEME_CLR(Theme, clrReplayFrame, clrYellow);
|
||||
THEME_CLR(Theme, clrReplayTitle, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayMode, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayCurrent, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayTotal, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayJump, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayProgressSeen, clrGreen);
|
||||
THEME_CLR(Theme, clrReplayProgressRest, clrWhite);
|
||||
THEME_CLR(Theme, clrReplayProgressSelected, clrRed);
|
||||
THEME_CLR(Theme, clrReplayProgressMark, clrBlack);
|
||||
THEME_CLR(Theme, clrReplayProgressCurrent, clrRed);
|
||||
|
||||
// --- cSkinSTTNGDisplayChannel ----------------------------------------------
|
||||
|
||||
class cSkinSTTNGDisplayChannel : public cSkinDisplayChannel{
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
int y0, y1, y2, y3, y4, y5, y6, y7;
|
||||
bool withInfo;
|
||||
int lineHeight;
|
||||
tColor frameColor;
|
||||
const cEvent *present;
|
||||
int lastSeen;
|
||||
static cBitmap bmTeletext, bmRadio, bmAudio, bmDolbyDigital, bmEncrypted, bmRecording;
|
||||
public:
|
||||
cSkinSTTNGDisplayChannel(bool WithInfo);
|
||||
virtual ~cSkinSTTNGDisplayChannel();
|
||||
virtual void SetChannel(const cChannel *Channel, int Number);
|
||||
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cBitmap cSkinSTTNGDisplayChannel::bmTeletext(teletext_xpm);
|
||||
cBitmap cSkinSTTNGDisplayChannel::bmRadio(radio_xpm);
|
||||
cBitmap cSkinSTTNGDisplayChannel::bmAudio(audio_xpm);
|
||||
cBitmap cSkinSTTNGDisplayChannel::bmDolbyDigital(dolbydigital_xpm);
|
||||
cBitmap cSkinSTTNGDisplayChannel::bmEncrypted(encrypted_xpm);
|
||||
cBitmap cSkinSTTNGDisplayChannel::bmRecording(recording_xpm);
|
||||
|
||||
cSkinSTTNGDisplayChannel::cSkinSTTNGDisplayChannel(bool WithInfo)
|
||||
{
|
||||
present = NULL;
|
||||
lastSeen = -1;
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
withInfo = WithInfo;
|
||||
lineHeight = font->Height();
|
||||
frameColor = Theme.Color(clrChannelFrame);
|
||||
if (withInfo) {
|
||||
x0 = 0;
|
||||
x1 = x0 + font->Width("00:00") + 4;
|
||||
x2 = x1 + Roundness;
|
||||
x3 = x2 + Gap;
|
||||
x7 = Setup.OSDWidth;
|
||||
x6 = x7 - lineHeight / 2;
|
||||
x5 = x6 - lineHeight / 2;
|
||||
x4 = x5 - Gap;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
y2 = y1 + Roundness;
|
||||
y3 = y2 + Gap;
|
||||
y4 = y3 + 4 * lineHeight;
|
||||
y5 = y4 + Gap;
|
||||
y6 = y5 + Roundness;
|
||||
y7 = y6 + cFont::GetFont(fontSml)->Height();
|
||||
int yt = (y0 + y1) / 2;
|
||||
int yb = (y6 + y7) / 2;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y7));
|
||||
tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground));
|
||||
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
|
||||
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
|
||||
osd->DrawRectangle(x6, y0, x7 - 1, yt - 1, clrTransparent);
|
||||
osd->DrawRectangle(x6, yb, x7 - 1, y7 - 1, clrTransparent);
|
||||
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 2);
|
||||
osd->DrawRectangle(x1, y0, x4 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
||||
osd->DrawRectangle(x0, y1, x1 - 1, y2 - 1, frameColor);
|
||||
osd->DrawEllipse (x1, y1, x2 - 1, y2 - 1, frameColor, -2);
|
||||
osd->DrawRectangle(x0, y3, x1 - 1, y4 - 1, frameColor);
|
||||
osd->DrawRectangle(x0, y5, x1 - 1, y6 - 1, frameColor);
|
||||
osd->DrawEllipse (x1, y5, x2 - 1, y6 - 1, frameColor, -3);
|
||||
osd->DrawEllipse (x0, y6, x1 - 1, y7 - 1, frameColor, 3);
|
||||
osd->DrawRectangle(x1, y6, x4 - 1, y7 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y6, x6 - 1, y7 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y6, x7 - 1, y7 - 1, frameColor, 5);
|
||||
}
|
||||
else {
|
||||
x0 = 0;
|
||||
x1 = lineHeight / 2;
|
||||
x2 = lineHeight;
|
||||
x3 = x2 + Gap;
|
||||
x7 = Setup.OSDWidth;
|
||||
x6 = x7 - lineHeight / 2;
|
||||
x5 = x6 - lineHeight / 2;
|
||||
x4 = x5 - Gap;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y1));
|
||||
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent);
|
||||
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
|
||||
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
||||
}
|
||||
}
|
||||
|
||||
cSkinSTTNGDisplayChannel::~cSkinSTTNGDisplayChannel()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayChannel::SetChannel(const cChannel *Channel, int Number)
|
||||
{
|
||||
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
|
||||
int x = x4 - 5;
|
||||
if (Channel && !Channel->GroupSep()) {
|
||||
int d = 3;
|
||||
bool rec = cRecordControls::Active();
|
||||
x -= bmRecording.Width() + d;
|
||||
osd->DrawBitmap(x, y0 + (y1 - y0 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : frameColor);
|
||||
x -= bmEncrypted.Width() + d;
|
||||
osd->DrawBitmap(x, y0 + (y1 - y0 - bmEncrypted.Height()) / 2, bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
||||
x -= bmDolbyDigital.Width() + d;
|
||||
osd->DrawBitmap(x, y0 + (y1 - y0 - bmDolbyDigital.Height()) / 2, bmDolbyDigital, Theme.Color(Channel->Dpid1() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
||||
x -= bmAudio.Width() + d;
|
||||
osd->DrawBitmap(x, y0 + (y1 - y0 - bmAudio.Height()) / 2, bmAudio, Theme.Color(Channel->Apid2() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
||||
if (Channel->Vpid()) {
|
||||
x -= bmTeletext.Width() + d;
|
||||
osd->DrawBitmap(x, y0 + (y1 - y0 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
||||
}
|
||||
else {
|
||||
x -= bmRadio.Width() + d;
|
||||
osd->DrawBitmap(x, y0 + (y1 - y0 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor);
|
||||
}
|
||||
}
|
||||
osd->DrawText(x3 + 2, y0, ChannelString(Channel, Number), Theme.Color(clrChannelName), frameColor, cFont::GetFont(fontOsd), x - x3 - 2);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
|
||||
{
|
||||
if (!withInfo)
|
||||
return;
|
||||
if (present != Present)
|
||||
lastSeen = -1;
|
||||
present = Present;
|
||||
osd->DrawRectangle(x0, y3, x1 - 1, y4 - 1, frameColor);
|
||||
osd->DrawRectangle(x3, y3, x7 - 1, y4 - 1, Theme.Color(clrBackground));
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const cEvent *e = !i ? Present : Following;
|
||||
if (e) {
|
||||
osd->DrawText(x0 + 2, y3 + 2 * i * lineHeight, e->GetTimeString(), Theme.Color(clrChannelEpgTime), frameColor, cFont::GetFont(fontOsd));
|
||||
osd->DrawText(x3 + 2, y3 + 2 * i * lineHeight, e->Title(), Theme.Color(clrChannelEpgTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), x4 - x3 - 2);
|
||||
osd->DrawText(x3 + 2, y3 + (2 * i + 1) * lineHeight, e->ShortText(), Theme.Color(clrChannelEpgShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), x4 - x3 - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayChannel::Flush(void)
|
||||
{
|
||||
if (withInfo) {
|
||||
const char *date = DayDateTime();
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
osd->DrawText(x4 - font->Width(date) - 2, y7 - font->Height(date), date, Theme.Color(clrChannelDate), frameColor, font);
|
||||
|
||||
int seen = 0;
|
||||
if (present) {
|
||||
time_t t = time(NULL);
|
||||
if (t > present->StartTime())
|
||||
seen = min(y4 - y3 - 1, int((y4 - y3) * double(t - present->StartTime()) / present->Duration()));
|
||||
}
|
||||
if (seen != lastSeen) {
|
||||
osd->DrawRectangle(x1 + Gap, y3, x1 + Gap + ScrollWidth - 1, y4 - 1, Theme.Color(clrChannelTimebarRest));
|
||||
if (seen)
|
||||
osd->DrawRectangle(x1 + Gap, y3, x1 + Gap + ScrollWidth - 1, y3 + seen, Theme.Color(clrChannelTimebarSeen));
|
||||
lastSeen = seen;
|
||||
}
|
||||
}
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinSTTNGDisplayMenu -------------------------------------------------
|
||||
|
||||
class cSkinSTTNGDisplayMenu : public cSkinDisplayMenu {
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
int y0, y1, y2, y3, y4, y5, y6, y7;
|
||||
int lineHeight;
|
||||
tColor frameColor;
|
||||
int currentIndex;
|
||||
bool message;
|
||||
void SetScrollbar(void);
|
||||
public:
|
||||
cSkinSTTNGDisplayMenu(void);
|
||||
virtual ~cSkinSTTNGDisplayMenu();
|
||||
virtual void Scroll(bool Up, bool Page);
|
||||
virtual int MaxItems(void);
|
||||
virtual void Clear(void);
|
||||
virtual void SetTitle(const char *Title);
|
||||
virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
virtual void SetMessage(eMessageType Type, const char *Text);
|
||||
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
|
||||
virtual void SetEvent(const cEvent *Event);
|
||||
virtual void SetRecording(const cRecording *Recording);
|
||||
virtual void SetText(const char *Text, bool FixedFont);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinSTTNGDisplayMenu::cSkinSTTNGDisplayMenu(void)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
lineHeight = font->Height();
|
||||
frameColor = Theme.Color(clrMenuFrame);
|
||||
currentIndex = -1;
|
||||
message = false;
|
||||
x0 = 0;
|
||||
x1 = lineHeight / 2;
|
||||
x2 = x1 + Roundness;
|
||||
x3 = x2 + Gap;
|
||||
x7 = Setup.OSDWidth;
|
||||
x6 = x7 - lineHeight / 2;
|
||||
x5 = x6 - lineHeight / 2;
|
||||
x4 = x5 - Gap;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
y2 = y1 + Roundness;
|
||||
y3 = y2 + Gap;
|
||||
y7 = Setup.OSDHeight;
|
||||
y6 = y7 - cFont::GetFont(fontSml)->Height();
|
||||
y5 = y6 - Roundness;
|
||||
y4 = y5 - Gap;
|
||||
int yt = (y0 + y1) / 2;
|
||||
int yb = (y6 + y7) / 2;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
|
||||
tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 4 } };
|
||||
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
else {
|
||||
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 2 },
|
||||
{ x0, y1, x7 - 1, y6 - 1, 2 },
|
||||
{ x0, y6, x7 - 1, y7 - 1, 4 }
|
||||
};
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
/*TODO
|
||||
tArea Areas[] = { { x0, y0, x7 - 1, y3 - 1, 2 },
|
||||
{ x0, y3, x3 - 1, y4 - 1, 1 },
|
||||
{ x3, y3, x5 - 1, y4 - 1, 2 },
|
||||
{ x0, y4, x7 - 1, y7 - 1, 4 }
|
||||
};
|
||||
*/
|
||||
}
|
||||
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground));
|
||||
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
|
||||
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
|
||||
osd->DrawRectangle(x6, y0, x7 - 1, yt - 1, clrTransparent);
|
||||
osd->DrawRectangle(x6, yb, x7 - 1, y7 - 1, clrTransparent);
|
||||
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 2);
|
||||
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
||||
osd->DrawRectangle(x0, y1, x1 - 1, y6 - 1, frameColor);
|
||||
osd->DrawEllipse (x1, y1, x2 - 1, y2 - 1, frameColor, -2);
|
||||
osd->DrawEllipse (x1, y5, x2 - 1, y6 - 1, frameColor, -3);
|
||||
osd->DrawEllipse (x0, y6, x1 - 1, y7 - 1, frameColor, 3);
|
||||
osd->DrawRectangle(x1, y6, x2 - 1, y7 - 1, frameColor);
|
||||
osd->DrawRectangle(x3, y6, x4 - 1, y7 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y6, x6 - 1, y7 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y6, x7 - 1, y7 - 1, frameColor, 5);
|
||||
}
|
||||
|
||||
cSkinSTTNGDisplayMenu::~cSkinSTTNGDisplayMenu()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetScrollbar(void)
|
||||
{
|
||||
if (textScroller.CanScroll()) {
|
||||
int h = lineHeight;
|
||||
int yt = textScroller.Top();
|
||||
int yb = yt + textScroller.Height();
|
||||
int st = yt + h + Gap;
|
||||
int sb = yb - h - Gap;
|
||||
int tt = st + (sb - st) * textScroller.Offset() / textScroller.Total();
|
||||
int tb = tt + (sb - st) * textScroller.Shown() / textScroller.Total();
|
||||
osd->DrawRectangle(x5, st, x5 + ScrollWidth - 1, sb, Theme.Color(clrMenuScrollbarTotal));
|
||||
osd->DrawRectangle(x5, tt, x5 + ScrollWidth - 1, tb, Theme.Color(clrMenuScrollbarShown));
|
||||
osd->DrawRectangle(x5, yt, x6 - 1, yt + h - 1, frameColor);
|
||||
osd->DrawEllipse (x6, yt, x7 - 1, yt + h - 1, frameColor, 5);
|
||||
osd->DrawRectangle(x5, yb - h, x6 - 1, yb - 1, frameColor);
|
||||
osd->DrawEllipse (x6, yb - h, x7 - 1, yb - 1, frameColor, 5);
|
||||
if (textScroller.CanScrollUp()) {
|
||||
cBitmap bm(arrowup_xpm);
|
||||
osd->DrawBitmap(x5 + (x7 - x5 - bm.Width()) / 2 - 2, yt + (h - bm.Height()) / 2, bm, Theme.Color(clrMenuScrollbarArrow), frameColor);
|
||||
}
|
||||
if (textScroller.CanScrollDown()) {
|
||||
cBitmap bm(arrowdown_xpm);
|
||||
osd->DrawBitmap(x5 + (x7 - x5 - bm.Width()) / 2 - 2, yb - h + (h - bm.Height()) / 2, bm, Theme.Color(clrMenuScrollbarArrow), frameColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::Scroll(bool Up, bool Page)
|
||||
{
|
||||
cSkinDisplayMenu::Scroll(Up, Page);
|
||||
SetScrollbar();
|
||||
}
|
||||
|
||||
int cSkinSTTNGDisplayMenu::MaxItems(void)
|
||||
{
|
||||
return (y4 - y3 - 2 * Roundness) / lineHeight;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::Clear(void)
|
||||
{
|
||||
textScroller.Reset();
|
||||
osd->DrawRectangle(x1, y3, x7 - 1, y4 - 1, Theme.Color(clrBackground));
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetTitle(const char *Title)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
const char *VDR = " VDR";
|
||||
int w = font->Width(VDR);
|
||||
osd->DrawText(x3 + 5, y0, Title, Theme.Color(clrMenuTitle), frameColor, font, x4 - w - x3 - 5);
|
||||
osd->DrawText(x4 - w, y0, VDR, frameColor, clrBlack, font);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||
{
|
||||
const char *date = DayDateTime();
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
int d = 10;
|
||||
int d2 = d / 2;
|
||||
int t4 = x4 - font->Width(date) - 2;
|
||||
int w = t4 - x3;
|
||||
int t0 = x3 + d2;
|
||||
int t1 = x3 + w / 4;
|
||||
int t2 = x3 + w / 2;
|
||||
int t3 = t4 - w / 4;
|
||||
osd->DrawRectangle(t0 + d2, y6, t1 - d2, y7 - 1, clrBlack);
|
||||
osd->DrawRectangle(t1 + d2, y6, t2 - d2, y7 - 1, clrBlack);
|
||||
osd->DrawRectangle(t2 + d2, y6, t3 - d2, y7 - 1, clrBlack);
|
||||
osd->DrawRectangle(t3 + d2, y6, t4 - d2, y7 - 1, clrBlack);
|
||||
osd->DrawText(t0 + d, y6, Red, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedBg), font, t1 - t0 - 2 * d, 0, taCenter);
|
||||
osd->DrawText(t1 + d, y6, Green, Theme.Color(clrButtonGreenFg), Theme.Color(clrButtonGreenBg), font, t2 - t1 - 2 * d, 0, taCenter);
|
||||
osd->DrawText(t2 + d, y6, Yellow, Theme.Color(clrButtonYellowFg), Theme.Color(clrButtonYellowBg), font, t3 - t2 - 2 * d, 0, taCenter);
|
||||
osd->DrawText(t3 + d, y6, Blue, Theme.Color(clrButtonBlueFg), Theme.Color(clrButtonBlueBg), font, t4 - t3 - 2 * d, 0, taCenter);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetMessage(eMessageType Type, const char *Text)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
if (Text) {
|
||||
osd->SaveRegion(x3, y6, x4 - 1, y7 - 1);
|
||||
osd->DrawText(x3, y6, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x4 - x3, 0, taCenter);
|
||||
message = true;
|
||||
}
|
||||
else {
|
||||
osd->RestoreRegion();
|
||||
message = false;
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
|
||||
{
|
||||
int y = y3 + Roundness + Index * lineHeight;
|
||||
tColor ColorFg, ColorBg;
|
||||
if (Current) {
|
||||
ColorFg = Theme.Color(clrMenuItemCurrentFg);
|
||||
ColorBg = Theme.Color(clrMenuItemCurrentBg);
|
||||
osd->DrawEllipse (x1, y - Roundness, x2 - 1, y - 1, frameColor, -3);
|
||||
osd->DrawRectangle(x1, y, x2 - 1, y + lineHeight - 1, frameColor);
|
||||
osd->DrawEllipse (x1, y + lineHeight, x2 - 1, y + lineHeight + Roundness - 1, frameColor, -2);
|
||||
osd->DrawRectangle(x3, y, x4 - 1, y + lineHeight - 1, ColorBg);
|
||||
currentIndex = Index;
|
||||
}
|
||||
else {
|
||||
ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
|
||||
ColorBg = Theme.Color(clrBackground);
|
||||
if (currentIndex == Index) {
|
||||
osd->DrawRectangle(x1, y - Roundness, x2 - 1, y + lineHeight + Roundness - 1, Theme.Color(clrBackground));
|
||||
osd->DrawRectangle(x3, y, x4 - 1, y + lineHeight - 1, Theme.Color(clrBackground));
|
||||
}
|
||||
}
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
for (int i = 0; i < MaxTabs; i++) {
|
||||
const char *s = GetTabbedText(Text, i);
|
||||
if (s) {
|
||||
int xt = x3 + 5 + Tab(i);
|
||||
osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x4 - xt);
|
||||
}
|
||||
if (!Tab(i + 1))
|
||||
break;
|
||||
}
|
||||
SetEditableWidth(x4 - x3 - 5 - Tab(1));
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetEvent(const cEvent *Event)
|
||||
{
|
||||
if (!Event)
|
||||
return;
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int xl = x3 + 5;
|
||||
int y = y3;
|
||||
cTextScroller ts;
|
||||
char t[32];
|
||||
snprintf(t, sizeof(t), "%s %s - %s", Event->GetDateString(), Event->GetTimeString(), Event->GetEndTimeString());//TODO dayname, no year
|
||||
ts.Set(osd, xl, y, x4 - xl, y4 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
|
||||
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, " VPS: %s", Event->GetVpsString());
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
osd->DrawText(x4 - font->Width(buffer), y, buffer, Theme.Color(clrMenuEventVps), frameColor, font);
|
||||
int yb = y + font->Height();
|
||||
osd->DrawRectangle(x5, y, x6 - 1, yb - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y, x7 - 1, yb - 1, frameColor, 5);
|
||||
free(buffer);
|
||||
}
|
||||
y += ts.Height();
|
||||
y += font->Height();
|
||||
ts.Set(osd, xl, y, x4 - xl, y4 - y, Event->Title(), font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
if (!isempty(Event->ShortText())) {
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
ts.Set(osd, xl, y, x4 - xl, y4 - y, Event->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
}
|
||||
y += font->Height();
|
||||
if (!isempty(Event->Description())) {
|
||||
int yt = y;
|
||||
int yb = y4 - Roundness;
|
||||
textScroller.Set(osd, xl, yt, x4 - xl, yb - yt, Event->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
|
||||
yb = yt + textScroller.Height();
|
||||
osd->DrawEllipse (x1, yt - Roundness, x2, yt, frameColor, -3);
|
||||
osd->DrawRectangle(x1, yt, x2, yb, frameColor);
|
||||
osd->DrawEllipse (x1, yb, x2, yb + Roundness, frameColor, -2);
|
||||
SetScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetRecording(const cRecording *Recording)
|
||||
{
|
||||
SetText(Recording->Summary(), false); //XXX
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetText(const char *Text, bool FixedFont)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd);
|
||||
font = cFont::GetFont(fontSml);//XXX -> make a way to let the text define which font to use
|
||||
textScroller.Set(osd, x3, y3, x4 - x3, y4 - y3, Text, font, Theme.Color(clrMenuText), Theme.Color(clrBackground));
|
||||
SetScrollbar();
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::Flush(void)
|
||||
{
|
||||
if (!message) {
|
||||
const char *date = DayDateTime();
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
osd->DrawText(x4 - font->Width(date) - 2, y7 - font->Height(date), date, Theme.Color(clrMenuDate), frameColor, font);
|
||||
}
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinSTTNGDisplayReplay -----------------------------------------------
|
||||
|
||||
class cSkinSTTNGDisplayReplay : public cSkinDisplayReplay {
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
int y0, y1, y2, y3, y4, y5, y6, y7;
|
||||
tColor frameColor;
|
||||
int lastCurrentWidth;
|
||||
public:
|
||||
cSkinSTTNGDisplayReplay(bool ModeOnly);
|
||||
virtual ~cSkinSTTNGDisplayReplay();
|
||||
virtual void SetTitle(const char *Title);
|
||||
virtual void SetMode(bool Play, bool Forward, int Speed);
|
||||
virtual void SetProgress(int Current, int Total);
|
||||
virtual void SetCurrent(const char *Current);
|
||||
virtual void SetTotal(const char *Total);
|
||||
virtual void SetJump(const char *Jump);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
#define SymbolWidth 30
|
||||
#define SymbolHeight 30
|
||||
|
||||
cSkinSTTNGDisplayReplay::cSkinSTTNGDisplayReplay(bool ModeOnly)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
int lineHeight = font->Height();
|
||||
frameColor = Theme.Color(clrReplayFrame);
|
||||
lastCurrentWidth = 0;
|
||||
cBitmap bm(play_xpm);
|
||||
x0 = 0;
|
||||
x1 = max(SymbolWidth, bm.Width());
|
||||
x2 = x1 + Roundness;
|
||||
x3 = x2 + Gap;
|
||||
x7 = Setup.OSDWidth;
|
||||
x6 = x7 - lineHeight / 2;
|
||||
x5 = x6 - lineHeight / 2;
|
||||
x4 = x5 - Gap;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
y2 = y1 + Roundness;
|
||||
y3 = y2 + Gap;
|
||||
y4 = y3 + max(SymbolHeight, bm.Height());
|
||||
y5 = y4 + Gap;
|
||||
y6 = y5 + Roundness;
|
||||
y7 = y6 + font->Height();
|
||||
int yt = (y0 + y1) / 2;
|
||||
int yb = (y6 + y7) / 2;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y7);
|
||||
tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
|
||||
if (!ModeOnly) {
|
||||
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
|
||||
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
|
||||
osd->DrawRectangle(x6, y0, x7 - 1, yt - 1, clrTransparent);
|
||||
osd->DrawRectangle(x6, yb, x7 - 1, y7 - 1, clrTransparent);
|
||||
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 2);
|
||||
osd->DrawRectangle(x1, y0, x4 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
||||
osd->DrawRectangle(x0, y1, x1 - 1, y2 - 1, frameColor);
|
||||
osd->DrawEllipse (x1, y1, x2 - 1, y2 - 1, frameColor, -2);
|
||||
}
|
||||
osd->DrawRectangle(x0, y3, x1 - 1, y4 - 1, frameColor);
|
||||
if (!ModeOnly) {
|
||||
osd->DrawRectangle(x0, y5, x1 - 1, y6 - 1, frameColor);
|
||||
osd->DrawEllipse (x1, y5, x2 - 1, y6 - 1, frameColor, -3);
|
||||
osd->DrawEllipse (x0, y6, x1 - 1, y7 - 1, frameColor, 3);
|
||||
osd->DrawRectangle(x1, y6, x4 - 1, y7 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y6, x6 - 1, y7 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y6, x7 - 1, y7 - 1, frameColor, 5);
|
||||
}
|
||||
}
|
||||
|
||||
cSkinSTTNGDisplayReplay::~cSkinSTTNGDisplayReplay()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayReplay::SetTitle(const char *Title)
|
||||
{
|
||||
osd->DrawText(x3 + 5, y0, Title, Theme.Color(clrReplayTitle), frameColor, cFont::GetFont(fontSml), x4 - x3 - 5);
|
||||
}
|
||||
|
||||
static char **ReplaySymbols[2][2][5] = {
|
||||
{ { pause_xpm, srew_xpm, srew1_xpm, srew2_xpm, srew3_xpm },
|
||||
{ pause_xpm, sfwd_xpm, sfwd1_xpm, sfwd2_xpm, sfwd3_xpm }, },
|
||||
{ { play_xpm, frew_xpm, frew1_xpm, frew2_xpm, frew3_xpm },
|
||||
{ play_xpm, ffwd_xpm, ffwd1_xpm, ffwd2_xpm, ffwd3_xpm } }
|
||||
};
|
||||
|
||||
void cSkinSTTNGDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
|
||||
{
|
||||
if (Speed < -1)
|
||||
Speed = -1;
|
||||
if (Speed > 3)
|
||||
Speed = 3;
|
||||
cBitmap bm(ReplaySymbols[Play][Forward][Speed + 1]);
|
||||
osd->DrawBitmap(x0 + (x1 - x0 - bm.Width()) / 2, y3 + (y4 - y3 - bm.Height()) / 2, bm, Theme.Color(clrReplayMode), frameColor);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayReplay::SetProgress(int Current, int Total)
|
||||
{
|
||||
cProgressBar pb(x4 - x3, y4 - y3, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
|
||||
osd->DrawBitmap(x3, y3, pb);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayReplay::SetCurrent(const char *Current)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
int w = font->Width(Current);
|
||||
osd->DrawText(x3, y6, Current, Theme.Color(clrReplayCurrent), frameColor, font, lastCurrentWidth > w ? lastCurrentWidth : 0);
|
||||
lastCurrentWidth = w;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayReplay::SetTotal(const char *Total)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
osd->DrawText(x4 - font->Width(Total) - 5, y6, Total, Theme.Color(clrReplayTotal), frameColor, font);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayReplay::SetJump(const char *Jump)
|
||||
{
|
||||
osd->DrawText(x0 + (x4 - x0) / 4, y6, Jump, Theme.Color(clrReplayJump), frameColor, cFont::GetFont(fontSml), (x4 - x3) / 2, 0, taCenter);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayReplay::Flush(void)
|
||||
{
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinSTTNGDisplayVolume -----------------------------------------------
|
||||
|
||||
class cSkinSTTNGDisplayVolume : public cSkinDisplayVolume {
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
int y0, y1;
|
||||
tColor frameColor;
|
||||
int mute;
|
||||
public:
|
||||
cSkinSTTNGDisplayVolume(void);
|
||||
virtual ~cSkinSTTNGDisplayVolume();
|
||||
virtual void SetVolume(int Current, int Total, bool Mute);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinSTTNGDisplayVolume::cSkinSTTNGDisplayVolume(void)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int lineHeight = font->Height();
|
||||
frameColor = Theme.Color(clrVolumeFrame);
|
||||
mute = -1;
|
||||
x0 = 0;
|
||||
x1 = lineHeight / 2;
|
||||
x2 = lineHeight;
|
||||
x3 = x2 + Gap;
|
||||
x7 = Setup.OSDWidth;
|
||||
x6 = x7 - lineHeight / 2;
|
||||
x5 = x6 - lineHeight / 2;
|
||||
x4 = x5 - Gap;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y1);
|
||||
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 4 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent);
|
||||
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
|
||||
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
||||
}
|
||||
|
||||
cSkinSTTNGDisplayVolume::~cSkinSTTNGDisplayVolume()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayVolume::SetVolume(int Current, int Total, bool Mute)
|
||||
{
|
||||
int xl = x3 + 5;
|
||||
int xr = x4 - 5;
|
||||
int yt = y0 + 3;
|
||||
int yb = y1 - 3;
|
||||
if (mute != Mute) {
|
||||
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
|
||||
mute = Mute;
|
||||
}
|
||||
cBitmap bm(Mute ? mute_xpm : volume_xpm);
|
||||
osd->DrawBitmap(xl, y0 + (y1 - y0 - bm.Height()) / 2, bm, Theme.Color(clrVolumeSymbol), frameColor);
|
||||
if (!Mute) {
|
||||
xl += bm.Width() + 5;
|
||||
int w = (y1 - y0) / 3;
|
||||
int d = 3;
|
||||
int n = (xr - xl + d) / (w + d);
|
||||
int x = xr - n * (w + d);
|
||||
tColor Color = Theme.Color(clrVolumeBarLower);
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (Total * i >= Current * n)
|
||||
Color = Theme.Color(clrVolumeBarUpper);
|
||||
osd->DrawRectangle(x, yt, x + w - 1, yb - 1, Color);
|
||||
x += w + d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayVolume::Flush(void)
|
||||
{
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinSTTNGDisplayMessage ----------------------------------------------
|
||||
|
||||
class cSkinSTTNGDisplayMessage : public cSkinDisplayMessage {
|
||||
private:
|
||||
cOsd *osd;
|
||||
int x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
int y0, y1;
|
||||
public:
|
||||
cSkinSTTNGDisplayMessage(void);
|
||||
virtual ~cSkinSTTNGDisplayMessage();
|
||||
virtual void SetMessage(eMessageType Type, const char *Text);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cSkinSTTNGDisplayMessage::cSkinSTTNGDisplayMessage(void)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int lineHeight = font->Height();
|
||||
tColor frameColor = Theme.Color(clrMessageFrame);
|
||||
x0 = 0;
|
||||
x1 = lineHeight / 2;
|
||||
x2 = lineHeight;
|
||||
x3 = x2 + Gap;
|
||||
x7 = Setup.OSDWidth;
|
||||
x6 = x7 - lineHeight / 2;
|
||||
x5 = x6 - lineHeight / 2;
|
||||
x4 = x5 - Gap;
|
||||
y0 = 0;
|
||||
y1 = lineHeight;
|
||||
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y1);
|
||||
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 2 } };
|
||||
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
||||
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent);
|
||||
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
|
||||
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
|
||||
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
||||
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
||||
}
|
||||
|
||||
cSkinSTTNGDisplayMessage::~cSkinSTTNGDisplayMessage()
|
||||
{
|
||||
delete osd;
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMessage::SetMessage(eMessageType Type, const char *Text)
|
||||
{
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
osd->DrawText(x3, y0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x4 - x3, 0, taCenter);
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMessage::Flush(void)
|
||||
{
|
||||
osd->Flush();
|
||||
}
|
||||
|
||||
// --- cSkinSTTNG ------------------------------------------------------------
|
||||
|
||||
cSkinSTTNG::cSkinSTTNG(void)
|
||||
:cSkin("sttng", &::Theme)//XXX naming problem???
|
||||
{
|
||||
}
|
||||
|
||||
const char *cSkinSTTNG::Description(void)
|
||||
{
|
||||
return tr("ST:TNG Panels");
|
||||
}
|
||||
|
||||
cSkinDisplayChannel *cSkinSTTNG::DisplayChannel(bool WithInfo)
|
||||
{
|
||||
return new cSkinSTTNGDisplayChannel(WithInfo);
|
||||
}
|
||||
|
||||
cSkinDisplayMenu *cSkinSTTNG::DisplayMenu(void)
|
||||
{
|
||||
return new cSkinSTTNGDisplayMenu;
|
||||
}
|
||||
|
||||
cSkinDisplayReplay *cSkinSTTNG::DisplayReplay(bool ModeOnly)
|
||||
{
|
||||
return new cSkinSTTNGDisplayReplay(ModeOnly);
|
||||
}
|
||||
|
||||
cSkinDisplayVolume *cSkinSTTNG::DisplayVolume(void)
|
||||
{
|
||||
return new cSkinSTTNGDisplayVolume;
|
||||
}
|
||||
|
||||
cSkinDisplayMessage *cSkinSTTNG::DisplayMessage(void)
|
||||
{
|
||||
return new cSkinSTTNGDisplayMessage;
|
||||
}
|
26
skinsttng.h
Normal file
26
skinsttng.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* skinsttng.h: A VDR skin with ST:TNG Panels
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinsttng.h 1.1 2004/04/18 09:38:47 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SKINSTTNG_H
|
||||
#define __SKINSTTNG_H
|
||||
|
||||
#include "skins.h"
|
||||
|
||||
class cSkinSTTNG : public cSkin {
|
||||
public:
|
||||
cSkinSTTNG(void);
|
||||
virtual const char *Description(void);
|
||||
virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
|
||||
virtual cSkinDisplayMenu *DisplayMenu(void);
|
||||
virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
|
||||
virtual cSkinDisplayVolume *DisplayVolume(void);
|
||||
virtual cSkinDisplayMessage *DisplayMessage(void);
|
||||
};
|
||||
|
||||
#endif //__SKINSTTNG_H
|
17
symbols/arrowdown.xpm
Normal file
17
symbols/arrowdown.xpm
Normal file
@ -0,0 +1,17 @@
|
||||
/* XPM */
|
||||
static char * arrowdown_xpm[] = {
|
||||
"12 12 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"++++++++++++",
|
||||
"++++++++++++",
|
||||
".++++++++++.",
|
||||
".++++++++++.",
|
||||
"..++++++++..",
|
||||
"..++++++++..",
|
||||
"...++++++...",
|
||||
"...++++++...",
|
||||
"....++++....",
|
||||
"....++++....",
|
||||
".....++.....",
|
||||
".....++....."};
|
17
symbols/arrowup.xpm
Normal file
17
symbols/arrowup.xpm
Normal file
@ -0,0 +1,17 @@
|
||||
/* XPM */
|
||||
static char * arrowup_xpm[] = {
|
||||
"12 12 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
".....++.....",
|
||||
".....++.....",
|
||||
"....++++....",
|
||||
"....++++....",
|
||||
"...++++++...",
|
||||
"...++++++...",
|
||||
"..++++++++..",
|
||||
"..++++++++..",
|
||||
".++++++++++.",
|
||||
".++++++++++.",
|
||||
"++++++++++++",
|
||||
"++++++++++++"};
|
23
symbols/audio.xpm
Normal file
23
symbols/audio.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static char * audio_xpm[] = {
|
||||
"27 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"...........................",
|
||||
"...........................",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..++...................++..",
|
||||
"..++...................++..",
|
||||
"..++...++++.....++++...++..",
|
||||
"..++..++..++...++..++..++..",
|
||||
"..++.++....++.++....++.++..",
|
||||
"..++..++..++...++..++..++..",
|
||||
"..++...++++.....++++...++..",
|
||||
"..++...................++..",
|
||||
"..++...................++..",
|
||||
"..++...................++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"...........................",
|
||||
"..........................."};
|
23
symbols/dolbydigital.xpm
Normal file
23
symbols/dolbydigital.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static char * dolbydigital_xpm[] = {
|
||||
"27 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"...........................",
|
||||
"...........................",
|
||||
"..+++++++++++.+++++++++++..",
|
||||
"..++.++++++++.++++++++.++..",
|
||||
"..++...++++++.++++++...++..",
|
||||
"..++.....++++.++++.....++..",
|
||||
"..++......+++.+++......++..",
|
||||
"..++.......++.++.......++..",
|
||||
"..++.......++.++.......++..",
|
||||
"..++.......++.++.......++..",
|
||||
"..++.......++.++.......++..",
|
||||
"..++......+++.+++......++..",
|
||||
"..++.....++++.++++.....++..",
|
||||
"..++...++++++.++++++...++..",
|
||||
"..++.++++++++.++++++++.++..",
|
||||
"..+++++++++++.+++++++++++..",
|
||||
"...........................",
|
||||
"..........................."};
|
23
symbols/encrypted.xpm
Normal file
23
symbols/encrypted.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static char * encrypted_xpm[] = {
|
||||
"27 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"...........................",
|
||||
"...........................",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..++...................++..",
|
||||
"..++...................++..",
|
||||
"..++............++++...++..",
|
||||
"..++...........++..++..++..",
|
||||
"..++.+++++++++++....++.++..",
|
||||
"..++.+++++++++++....++.++..",
|
||||
"..++..+++......++..++..++..",
|
||||
"..++..+++.......++++...++..",
|
||||
"..++...................++..",
|
||||
"..++...................++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"...........................",
|
||||
"..........................."};
|
31
symbols/ffwd.xpm
Normal file
31
symbols/ffwd.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * ffwd_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..++......++................",
|
||||
"..+++.....+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..++++++....++++............",
|
||||
"..++++++++...+++++..........",
|
||||
"..+++++++++....++++.........",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..++++++++++++....++++......",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..+++++++++++++++....++++...",
|
||||
"..++++++++++++++++....++++..",
|
||||
"..++++++++++++++++....++++..",
|
||||
"..+++++++++++++++....++++...",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++....++++......",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..+++++++++....++++.........",
|
||||
"..++++++++...+++++..........",
|
||||
"..++++++....++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++.....+++...............",
|
||||
"..++......++................",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/ffwd1.xpm
Normal file
31
symbols/ffwd1.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * ffwd1_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..++......++................",
|
||||
"..+++.....+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..++++++....++++............",
|
||||
"..++++++++...+++++..........",
|
||||
"..+++++++++....++++.........",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..++++++++++++....++++......",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++++.....++++...",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++....++++......",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..+++++++++....++++.........",
|
||||
"..++++++++...+++++..........",
|
||||
"..++++++....++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++.....+++...............",
|
||||
"..++......++................",
|
||||
"............................",
|
||||
"..++++++....................",
|
||||
"..++++++....................",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/ffwd2.xpm
Normal file
31
symbols/ffwd2.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * ffwd2_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..++......++................",
|
||||
"..+++.....+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..++++++....++++............",
|
||||
"..++++++++...+++++..........",
|
||||
"..+++++++++....++++.........",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..++++++++++++....++++......",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++++.....++++...",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++....++++......",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..+++++++++....++++.........",
|
||||
"..++++++++...+++++..........",
|
||||
"..++++++....++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++.....+++...............",
|
||||
"..++......++................",
|
||||
"............................",
|
||||
"..++++++...++++++...........",
|
||||
"..++++++...++++++...........",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/ffwd3.xpm
Normal file
31
symbols/ffwd3.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * ffwd3_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..++......++................",
|
||||
"..+++.....+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..++++++....++++............",
|
||||
"..++++++++...+++++..........",
|
||||
"..+++++++++....++++.........",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..++++++++++++....++++......",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++++.....++++...",
|
||||
"..++++++++++++++...+++++....",
|
||||
"..++++++++++++....++++......",
|
||||
"..+++++++++++...+++++.......",
|
||||
"..+++++++++....++++.........",
|
||||
"..++++++++...+++++..........",
|
||||
"..++++++....++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++.....+++...............",
|
||||
"..++......++................",
|
||||
"............................",
|
||||
"..++++++...++++++...++++++..",
|
||||
"..++++++...++++++...++++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/frew.xpm
Normal file
31
symbols/frew.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * frew_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++......++..",
|
||||
"...............+++.....+++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++....++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"...++++....+++++++++++++++..",
|
||||
"..++++....++++++++++++++++..",
|
||||
"..++++....++++++++++++++++..",
|
||||
"...++++....+++++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
"............++++....++++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++.....+++..",
|
||||
"................++......++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/frew1.xpm
Normal file
31
symbols/frew1.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * frew1_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++......++..",
|
||||
"...............+++.....+++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++....++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"...++++.....++++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
"............++++....++++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++.....+++..",
|
||||
"................++......++..",
|
||||
"............................",
|
||||
"....................++++++..",
|
||||
"....................++++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/frew2.xpm
Normal file
31
symbols/frew2.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * frew2_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++......++..",
|
||||
"...............+++.....+++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++....++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"...++++.....++++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
"............++++....++++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++.....+++..",
|
||||
"................++......++..",
|
||||
"............................",
|
||||
"...........++++++...++++++..",
|
||||
"...........++++++...++++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/frew3.xpm
Normal file
31
symbols/frew3.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * frew3_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++......++..",
|
||||
"...............+++.....+++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++....++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"...++++.....++++++++++++++..",
|
||||
"....+++++...++++++++++++++..",
|
||||
"......++++....++++++++++++..",
|
||||
".......+++++...+++++++++++..",
|
||||
".........++++....+++++++++..",
|
||||
"..........+++++...++++++++..",
|
||||
"............++++....++++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++.....+++..",
|
||||
"................++......++..",
|
||||
"............................",
|
||||
"..++++++...++++++...++++++..",
|
||||
"..++++++...++++++...++++++..",
|
||||
"............................",
|
||||
"............................"};
|
25
symbols/mute.xpm
Normal file
25
symbols/mute.xpm
Normal file
@ -0,0 +1,25 @@
|
||||
/* XPM */
|
||||
static char * mute_xpm[] = {
|
||||
"26 20 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"......++.......++.......++",
|
||||
"......+++....++++......+++",
|
||||
".......+++..+++++.....+++.",
|
||||
"........+++..+.++....+++..",
|
||||
".......+.+++...++...+++...",
|
||||
".....++++.+++..++..+++....",
|
||||
"++++++++...+++....+++.....",
|
||||
"+++++++.....+++..+++......",
|
||||
"++...++......++++++.......",
|
||||
"++...++.......++++........",
|
||||
"++...++.......++++........",
|
||||
"++...++......++++++.......",
|
||||
"+++++++.....+++..+++......",
|
||||
"++++++++...+++....+++.....",
|
||||
".....++++.+++..++..+++....",
|
||||
".......+.+++...++...+++...",
|
||||
"........+++..+.++....+++..",
|
||||
".......+++..+++++.....+++.",
|
||||
"......+++....++++......+++",
|
||||
"......++.......++.......++"};
|
31
symbols/pause.xpm
Normal file
31
symbols/pause.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * pause_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"......+++++......+++++......",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/play.xpm
Normal file
31
symbols/play.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * play_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"......++....................",
|
||||
"......+++...................",
|
||||
"......+++++.................",
|
||||
"......++++++................",
|
||||
"......++++++++..............",
|
||||
"......+++++++++.............",
|
||||
"......+++++++++++...........",
|
||||
"......++++++++++++..........",
|
||||
"......++++++++++++++........",
|
||||
"......+++++++++++++++.......",
|
||||
"......++++++++++++++++......",
|
||||
"......++++++++++++++++......",
|
||||
"......+++++++++++++++.......",
|
||||
"......++++++++++++++........",
|
||||
"......++++++++++++..........",
|
||||
"......+++++++++++...........",
|
||||
"......+++++++++.............",
|
||||
"......++++++++..............",
|
||||
"......++++++................",
|
||||
"......+++++.................",
|
||||
"......+++...................",
|
||||
"......++....................",
|
||||
"............................",
|
||||
"............................"};
|
23
symbols/radio.xpm
Normal file
23
symbols/radio.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static char * radio_xpm[] = {
|
||||
"27 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"...........................",
|
||||
"............+++++..........",
|
||||
"............+++++++++......",
|
||||
"............+++++++++++....",
|
||||
"............+++...++++++...",
|
||||
"............+++.....++++...",
|
||||
"............+++.....+++....",
|
||||
"............+++.....++.....",
|
||||
"............+++............",
|
||||
"............+++............",
|
||||
"............+++............",
|
||||
"......+++++++++............",
|
||||
"...+++++++++++++...........",
|
||||
"..+++++++++++++++..........",
|
||||
"..+++++++++++++++..........",
|
||||
"...+++++++++++++...........",
|
||||
".....++++++++++............",
|
||||
"..........................."};
|
23
symbols/recording.xpm
Normal file
23
symbols/recording.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static char * recording_xpm[] = {
|
||||
"27 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"...........................",
|
||||
"...........................",
|
||||
"..++++++...++++++..++++++..",
|
||||
"..+++++++.+++++++.+++++++..",
|
||||
"..++...++.++......++.......",
|
||||
"..++...++.++......++.......",
|
||||
"..++...++.++......++.......",
|
||||
"..++...++.++......++.......",
|
||||
"..++++++..+++++...++.......",
|
||||
"..++++....+++++...++.......",
|
||||
"..++.++...++......++.......",
|
||||
"..++..++..++......++.......",
|
||||
"..++...++.++......++.......",
|
||||
"..++...++.++......++.......",
|
||||
"..++...++.+++++++.+++++++..",
|
||||
"..++...++..++++++..++++++..",
|
||||
"...........................",
|
||||
"..........................."};
|
31
symbols/sfwd.xpm
Normal file
31
symbols/sfwd.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * sfwd_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..+++++...++................",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...+++++++++++++++...",
|
||||
"..+++++...++++++++++++++++..",
|
||||
"..+++++...++++++++++++++++..",
|
||||
"..+++++...+++++++++++++++...",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...++................",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/sfwd1.xpm
Normal file
31
symbols/sfwd1.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * sfwd1_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..+++++...++................",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...+++++++++++++++...",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...++................",
|
||||
"............................",
|
||||
"..++++++....................",
|
||||
"..++++++....................",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/sfwd2.xpm
Normal file
31
symbols/sfwd2.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * sfwd2_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..+++++...++................",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...+++++++++++++++...",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...++................",
|
||||
"............................",
|
||||
"..++++++...++++++...........",
|
||||
"..++++++...++++++...........",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/sfwd3.xpm
Normal file
31
symbols/sfwd3.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * sfwd3_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"..+++++...++................",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...+++++++++++++++...",
|
||||
"..+++++...++++++++++++++....",
|
||||
"..+++++...++++++++++++......",
|
||||
"..+++++...+++++++++++.......",
|
||||
"..+++++...+++++++++.........",
|
||||
"..+++++...++++++++..........",
|
||||
"..+++++...++++++............",
|
||||
"..+++++...+++++.............",
|
||||
"..+++++...+++...............",
|
||||
"..+++++...++................",
|
||||
"............................",
|
||||
"..++++++...++++++...++++++..",
|
||||
"..++++++...++++++...++++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/srew.xpm
Normal file
31
symbols/srew.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * srew_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"...+++++++++++++++...+++++..",
|
||||
"..++++++++++++++++...+++++..",
|
||||
"..++++++++++++++++...+++++..",
|
||||
"...+++++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
"................++...+++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/srew1.xpm
Normal file
31
symbols/srew1.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * srew1_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"...+++++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
"................++...+++++..",
|
||||
"............................",
|
||||
"....................++++++..",
|
||||
"....................++++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/srew2.xpm
Normal file
31
symbols/srew2.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * srew2_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"...+++++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
"................++...+++++..",
|
||||
"............................",
|
||||
"...........++++++...++++++..",
|
||||
"...........++++++...++++++..",
|
||||
"............................",
|
||||
"............................"};
|
31
symbols/srew3.xpm
Normal file
31
symbols/srew3.xpm
Normal file
@ -0,0 +1,31 @@
|
||||
/* XPM */
|
||||
static char * srew3_xpm[] = {
|
||||
"28 26 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"............................",
|
||||
"............................",
|
||||
"................++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"...+++++++++++++++...+++++..",
|
||||
"....++++++++++++++...+++++..",
|
||||
"......++++++++++++...+++++..",
|
||||
".......+++++++++++...+++++..",
|
||||
".........+++++++++...+++++..",
|
||||
"..........++++++++...+++++..",
|
||||
"............++++++...+++++..",
|
||||
".............+++++...+++++..",
|
||||
"...............+++...+++++..",
|
||||
"................++...+++++..",
|
||||
"............................",
|
||||
"..++++++...++++++...++++++..",
|
||||
"..++++++...++++++...++++++..",
|
||||
"............................",
|
||||
"............................"};
|
23
symbols/teletext.xpm
Normal file
23
symbols/teletext.xpm
Normal file
@ -0,0 +1,23 @@
|
||||
/* XPM */
|
||||
static char * teletext_xpm[] = {
|
||||
"27 18 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"...........................",
|
||||
"...........................",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..++...................++..",
|
||||
"..++..+++++++++++++++..++..",
|
||||
"..++..+++++++++++++++..++..",
|
||||
"..++...................++..",
|
||||
"..++..+++++++++++++++..++..",
|
||||
"..++..+++++++++++++++..++..",
|
||||
"..++...................++..",
|
||||
"..++..+++++++++++++++..++..",
|
||||
"..++..+++++++++++++++..++..",
|
||||
"..++...................++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"..+++++++++++++++++++++++..",
|
||||
"...........................",
|
||||
"..........................."};
|
19
symbols/volume.xpm
Normal file
19
symbols/volume.xpm
Normal file
@ -0,0 +1,19 @@
|
||||
/* XPM */
|
||||
static char * volume_xpm[] = {
|
||||
"28 14 2 1",
|
||||
". c #FFFFFF",
|
||||
"+ c #000000",
|
||||
"..........................++",
|
||||
"........................++++",
|
||||
"......................++++++",
|
||||
"....................++++++++",
|
||||
"..................++++++++++",
|
||||
"................++++++++++++",
|
||||
"..............++++++++++++++",
|
||||
"............++++++++++++++++",
|
||||
"..........++++++++++++++++++",
|
||||
"........++++++++++++++++++++",
|
||||
"......++++++++++++++++++++++",
|
||||
"....++++++++++++++++++++++++",
|
||||
"..++++++++++++++++++++++++++",
|
||||
"++++++++++++++++++++++++++++"};
|
305
themes.c
Normal file
305
themes.c
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* themes.c: Color themes used by skins
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: themes.c 1.1 2004/05/16 09:43:14 kls Exp $
|
||||
*/
|
||||
|
||||
#include "themes.h"
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "tools.h"
|
||||
|
||||
// --- cTheme ----------------------------------------------------------------
|
||||
|
||||
cTheme::cTheme(void)
|
||||
{
|
||||
name = strdup("default");
|
||||
memset(descriptions, 0, sizeof(descriptions));
|
||||
memset(colorNames, 0, sizeof(colorNames));
|
||||
memset(colorValues, 0, sizeof(colorValues));
|
||||
descriptions[0] = strdup("Default");
|
||||
}
|
||||
|
||||
cTheme::~cTheme()
|
||||
{
|
||||
free(name);
|
||||
for (int i = 0; i < I18nNumLanguages; i++)
|
||||
free(descriptions[i]);
|
||||
for (int i = 0; i < MaxThemeColors; i++)
|
||||
free(colorNames[i]);
|
||||
}
|
||||
|
||||
bool cTheme::FileNameOk(const char *FileName, bool SetName)
|
||||
{
|
||||
const char *error = NULL;
|
||||
if (!isempty(FileName)) {
|
||||
const char *d = strrchr(FileName, '/');
|
||||
if (d)
|
||||
FileName = d + 1;
|
||||
const char *n = strchr(FileName, '-');
|
||||
if (n) {
|
||||
if (n > FileName) {
|
||||
if (!strchr(++n, '-')) {
|
||||
const char *e = strchr(n, '.');
|
||||
if (e && strcmp(e, ".theme") == 0) {
|
||||
if (e - n >= 1) {
|
||||
// FileName is ok
|
||||
if (SetName) {
|
||||
free(name);
|
||||
name = strndup(n, e - n);
|
||||
}
|
||||
}
|
||||
else
|
||||
error = "missing theme name";
|
||||
}
|
||||
else
|
||||
error = "invalid extension";
|
||||
}
|
||||
else
|
||||
error = "too many '-'";
|
||||
}
|
||||
else
|
||||
error = "missing skin name";
|
||||
}
|
||||
else
|
||||
error = "missing '-'";
|
||||
}
|
||||
else
|
||||
error = "empty";
|
||||
if (error)
|
||||
esyslog("ERROR: invalid theme file name (%s): '%s'", error, FileName);
|
||||
return !error;
|
||||
}
|
||||
|
||||
const char *cTheme::Description(void)
|
||||
{
|
||||
char *s = descriptions[Setup.OSDLanguage];
|
||||
if (!s)
|
||||
s = descriptions[0];
|
||||
return s ? s : name;
|
||||
}
|
||||
|
||||
bool cTheme::Load(const char *FileName, bool OnlyDescriptions)
|
||||
{
|
||||
if (!FileNameOk(FileName, true))
|
||||
return false;
|
||||
bool result = false;
|
||||
if (!OnlyDescriptions)
|
||||
isyslog("loading %s", FileName);
|
||||
FILE *f = fopen(FileName, "r");
|
||||
if (f) {
|
||||
int line = 0;
|
||||
result = true;
|
||||
char *s;
|
||||
const char *error = NULL;
|
||||
while ((s = readline(f)) != NULL) {
|
||||
line++;
|
||||
char *p = strchr(s, '#');
|
||||
if (p)
|
||||
*p = 0;
|
||||
s = stripspace(skipspace(s));
|
||||
if (!isempty(s)) {
|
||||
char *n = s;
|
||||
char *v = strchr(s, '=');
|
||||
if (v) {
|
||||
*v++ = 0;
|
||||
n = stripspace(skipspace(n));
|
||||
v = stripspace(skipspace(v));
|
||||
if (strstr(n, "Description") == n) {
|
||||
int lang = 0;
|
||||
char *l = strchr(n, '.');
|
||||
if (l)
|
||||
lang = I18nLanguageIndex(++l);
|
||||
if (lang >= 0)
|
||||
descriptions[lang] = strdup(v);
|
||||
else
|
||||
error = "invalid language code";
|
||||
}
|
||||
else if (!OnlyDescriptions) {
|
||||
for (int i = 0; i < MaxThemeColors; i++) {
|
||||
if (colorNames[i]) {
|
||||
if (strcmp(n, colorNames[i]) == 0) {
|
||||
char *p = NULL;
|
||||
errno = 0;
|
||||
tColor c = strtoul(v, &p, 16);
|
||||
if (!errno && !*p)
|
||||
colorValues[i] = c;
|
||||
else
|
||||
error = "invalid color value";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = "unknown color name";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
error = "missing value";
|
||||
}
|
||||
if (error) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
esyslog("ERROR: error in %s, line %d%s%s\n", FileName, line, error ? ": " : "", error ? error : "");
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(FileName);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cTheme::Save(const char *FileName)
|
||||
{
|
||||
if (!FileNameOk(FileName))
|
||||
return false;
|
||||
bool result = true;
|
||||
cSafeFile f(FileName);
|
||||
if (f.Open()) {
|
||||
for (int i = 0; i < I18nNumLanguages; i++) {
|
||||
if (descriptions[i])
|
||||
fprintf(f, "Description%s%.*s = %s\n", i ? "." : "", 3, i ? I18nLanguageCode(i) : "", descriptions[i]);
|
||||
}
|
||||
for (int i = 0; i < MaxThemeColors; i++) {
|
||||
if (colorNames[i])
|
||||
fprintf(f, "%s = %08X\n", colorNames[i], colorValues[i]);
|
||||
}
|
||||
if (!f.Close())
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
int cTheme::AddColor(const char *Name, tColor Color)
|
||||
{
|
||||
for (int i = 0; i < MaxThemeColors; i++) {
|
||||
if (colorNames[i]) {
|
||||
if (strcmp(Name, colorNames[i]) == 0) {
|
||||
colorValues[i] = Color;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
colorNames[i] = strdup(Name);
|
||||
colorValues[i] = Color;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
tColor cTheme::Color(int Subject)
|
||||
{
|
||||
return (Subject >= 0 && Subject < MaxThemeColors) ? colorValues[Subject] : 0;
|
||||
}
|
||||
|
||||
// --- cThemes ---------------------------------------------------------------
|
||||
|
||||
char *cThemes::themesDirectory = NULL;
|
||||
|
||||
cThemes::cThemes(void)
|
||||
{
|
||||
numThemes = 0;
|
||||
names = 0;
|
||||
fileNames = NULL;
|
||||
descriptions = NULL;
|
||||
}
|
||||
|
||||
cThemes::~cThemes()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void cThemes::Clear(void)
|
||||
{
|
||||
for (int i = 0; i < numThemes; i++) {
|
||||
free(names[i]);
|
||||
free(fileNames[i]);
|
||||
free(descriptions[i]);
|
||||
}
|
||||
free(names);
|
||||
free(fileNames);
|
||||
free(descriptions);
|
||||
numThemes = 0;
|
||||
names = 0;
|
||||
fileNames = NULL;
|
||||
descriptions = NULL;
|
||||
}
|
||||
|
||||
bool cThemes::Load(const char *SkinName)
|
||||
{
|
||||
Clear();
|
||||
if (themesDirectory) {
|
||||
DIR *d = opendir(themesDirectory);
|
||||
if (d) {
|
||||
struct dirent *e;
|
||||
while ((e = readdir(d)) != NULL) {
|
||||
if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
|
||||
if (strstr(e->d_name, SkinName) == e->d_name && e->d_name[strlen(SkinName)] == '-') {
|
||||
const char *FileName = AddDirectory(themesDirectory, e->d_name);
|
||||
cTheme Theme;
|
||||
if (Theme.Load(FileName, true)) {
|
||||
names = (char **)realloc(names, (numThemes + 1) * sizeof(char *));
|
||||
names[numThemes] = strdup(Theme.Name());
|
||||
fileNames = (char **)realloc(fileNames, (numThemes + 1) * sizeof(char *));
|
||||
fileNames[numThemes] = strdup(FileName);
|
||||
descriptions = (char **)realloc(descriptions, (numThemes + 1) * sizeof(char *));
|
||||
descriptions[numThemes] = strdup(Theme.Description());
|
||||
numThemes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
return numThemes > 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int cThemes::GetThemeIndex(const char *Description)
|
||||
{
|
||||
int index = 0;
|
||||
for (int i = 0; i < numThemes; i++) {
|
||||
if (strcmp(descriptions[i], Description) == 0)
|
||||
return i;
|
||||
if (strcmp(descriptions[i], "Default") == 0)
|
||||
index = 1;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void cThemes::SetThemesDirectory(const char *ThemesDirectory)
|
||||
{
|
||||
free(themesDirectory);
|
||||
themesDirectory = strdup(ThemesDirectory);
|
||||
MakeDirs(themesDirectory, true);
|
||||
}
|
||||
|
||||
void cThemes::Load(const char *SkinName, const char *ThemeName, cTheme *Theme)
|
||||
{
|
||||
char *FileName = NULL;
|
||||
asprintf(&FileName, "%s/%s-%s.theme", themesDirectory, SkinName, ThemeName);
|
||||
if (access(FileName, F_OK) == 0) // the file exists
|
||||
Theme->Load(FileName);
|
||||
free(FileName);
|
||||
}
|
||||
|
||||
void cThemes::Save(const char *SkinName, cTheme *Theme)
|
||||
{
|
||||
char *FileName = NULL;
|
||||
asprintf(&FileName, "%s/%s-%s.theme", themesDirectory, SkinName, Theme->Name());
|
||||
if (access(FileName, F_OK) != 0) // the file does not exist
|
||||
Theme->Save(FileName);
|
||||
free(FileName);
|
||||
}
|
82
themes.h
Normal file
82
themes.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* themes.h: Color themes used by skins
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: themes.h 1.1 2004/05/15 14:22:16 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __THEMES_H
|
||||
#define __THEMES_H
|
||||
|
||||
#include "i18n.h"
|
||||
#include "osd.h"
|
||||
|
||||
class cTheme {
|
||||
public:
|
||||
enum { MaxThemeColors = 128 };
|
||||
private:
|
||||
char *name;
|
||||
char *descriptions[I18nNumLanguages];
|
||||
char *colorNames[MaxThemeColors];
|
||||
tColor colorValues[MaxThemeColors];
|
||||
bool FileNameOk(const char *FileName, bool SetName = false);
|
||||
public:
|
||||
cTheme(void);
|
||||
///< Creates a new theme class.
|
||||
~cTheme();
|
||||
const char *Name(void) { return name; }
|
||||
const char *Description(void);
|
||||
///< Returns a user visible, single line description of this theme.
|
||||
///< The actual text shouldn't be too long, so that it can be
|
||||
///< fully displayed in the Setup/OSD menu.
|
||||
bool Load(const char *FileName, bool OnlyDescriptions = false);
|
||||
///< Loads the theme data from the given file.
|
||||
bool Save(const char *FileName);
|
||||
///< Saves the theme data to the given file.
|
||||
///< FileName must be in the form "<skin>-<theme>.theme", where <skin>
|
||||
///< is the name of the skin this theme applies to, and <theme> is the
|
||||
///< actual theme name, which will be used to identify this theme in the
|
||||
///< 'setup.conf', and is normally not seen by the user. It should
|
||||
///< consist of only lowercase letters and digits.
|
||||
int AddColor(const char *Name, tColor Color);
|
||||
///< Adds a color with the given Name to this theme, initializes it
|
||||
///< with Color and returns an index into the color array that can
|
||||
///< be used in a call to Color() later. The index returned from the
|
||||
///< first call to AddColor() is 0, and subsequent calls will return
|
||||
///< values that are incremented by 1 with every call.
|
||||
///< If a color entry with the given Name already exists, its value
|
||||
///< will be overwritten with Color and the returned index will be
|
||||
///< that of the existing entry.
|
||||
tColor Color(int Subject);
|
||||
///< Returns the color for the given Subject. Subject must be one of
|
||||
///< the values returned by a previous call to AddColor().
|
||||
};
|
||||
|
||||
// A helper macro that simplifies defining theme colors.
|
||||
#define THEME_CLR(Theme, Subject, Color) static const int Subject = Theme.AddColor(#Subject, Color)
|
||||
|
||||
class cThemes {
|
||||
private:
|
||||
int numThemes;
|
||||
char **names;
|
||||
char **fileNames;
|
||||
char **descriptions;
|
||||
static char *themesDirectory;
|
||||
void Clear(void);
|
||||
public:
|
||||
cThemes(void);
|
||||
~cThemes();
|
||||
bool Load(const char *SkinName);
|
||||
int NumThemes(void) { return numThemes; }
|
||||
const char *Name(int Index) { return Index < numThemes ? names[Index] : NULL; }
|
||||
const char *FileName(int Index) { return Index < numThemes ? fileNames[Index] : NULL; }
|
||||
const char * const *Descriptions(void) { return descriptions; }
|
||||
int GetThemeIndex(const char *Description);
|
||||
static void SetThemesDirectory(const char *ThemesDirectory);
|
||||
static void Load(const char *SkinName, const char *ThemeName, cTheme *Theme);
|
||||
static void Save(const char *SkinName, cTheme *Theme);
|
||||
};
|
||||
|
||||
#endif //__THEMES_H
|
44
vdr.5
44
vdr.5
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 1.26 2004/02/24 12:36:35 kls Exp $
|
||||
.\" $Id: vdr.5 1.27 2004/05/15 09:24:57 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "1 Jun 2003" "1.2.0" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
@ -505,6 +505,48 @@ Examples:
|
||||
The file \fIsetup.conf\fR contains the basic configuration options for \fBvdr\fR.
|
||||
Each line contains one option in the format "Name = Value".
|
||||
See the MANUAL file for a description of the available options.
|
||||
.SS THEMES
|
||||
The files \fIthemes/<skin>-<theme>.theme\fR in the config directory contain the
|
||||
color theme definitions for the various skins. In the actual file names \fI<skin>\fR
|
||||
will be replaced by the name if the skin this theme belongs to, and \fI<theme>\fR
|
||||
will be the name of this theme.
|
||||
Each line in a theme file contains one option in the format "Name = Value".
|
||||
Anything after (and including) a '#' character is comment.
|
||||
|
||||
The definitions in a theme file are either \fBcolors\fR or a \fBdescription\fR.
|
||||
.br
|
||||
\fBColors\fR are in the form
|
||||
|
||||
\fBclrTitle = FF123456\fR
|
||||
|
||||
where the name (clrTitle) is one of the names defined in the source code of
|
||||
the \fBskin\fR that uses this theme, through the \fBTHEME_CLR()\fR macro.
|
||||
The value (FF123456) is an eight digit hex number that consist of four bytes,
|
||||
representing alpha (transparency), red, green and blue component of the color.
|
||||
An alpha value of 00 means the color will be completely transparent, while FF
|
||||
means it will be opaque. An RGB value of 000000 results in black, while FFFFFF
|
||||
is white.
|
||||
|
||||
A \fBdescription\fR can be given as
|
||||
|
||||
\fBDescription = Shades of blue\fR
|
||||
|
||||
and will be used in the Setup/OSD menu to select a theme for a given skin.
|
||||
The description should give the user an idea what this theme will be like
|
||||
(for instance, in the given example it would use various shades of blue),
|
||||
and shouldn't be too long to make sure it fits on the Setup screen.
|
||||
The default description always should be given in English. If you want,
|
||||
you can provide language specific descriptions as
|
||||
|
||||
\fBDescription.eng = Shades of blue\fR
|
||||
.br
|
||||
\fBDescription.ger = Blautöne\fR
|
||||
|
||||
where the language code (as defined in VDR/i18n.c) is added to the keyword
|
||||
"Description", separated by a dot. You can enter as many language specific
|
||||
descriptions as there are languages defined in VDR/i18n.h.
|
||||
If a theme file doesn't contain a Description, the name of the theme (as
|
||||
given in the theme's file name) will be used.
|
||||
.SS AUDIO/VIDEO DATA
|
||||
The files \fI001.vdr\fR...\fI255.vdr\fR are the actual recorded MPEG data
|
||||
files. In order to keep the size of an individual file below a given limit,
|
||||
|
51
vdr.c
51
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.180 2004/03/14 14:25:02 kls Exp $
|
||||
* $Id: vdr.c 1.181 2004/05/16 10:12:43 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -45,11 +45,14 @@
|
||||
#include "keys.h"
|
||||
#include "lirc.h"
|
||||
#include "menu.h"
|
||||
#include "osd.h"
|
||||
#include "osdbase.h"
|
||||
#include "plugin.h"
|
||||
#include "rcu.h"
|
||||
#include "recording.h"
|
||||
#include "skinclassic.h"
|
||||
#include "skinsttng.h"
|
||||
#include "sources.h"
|
||||
#include "themes.h"
|
||||
#include "timers.h"
|
||||
#include "tools.h"
|
||||
#include "transfer.h"
|
||||
@ -310,7 +313,6 @@ int main(int argc, char *argv[])
|
||||
// Daemon mode:
|
||||
|
||||
if (DaemonMode) {
|
||||
#if !defined(DEBUG_OSD)
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "%m\n");
|
||||
@ -322,10 +324,6 @@ int main(int argc, char *argv[])
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
#else
|
||||
fprintf(stderr, "vdr: can't run in daemon mode with DEBUG_OSD on!\n");
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
else if (Terminal) {
|
||||
// Claim new controlling terminal
|
||||
@ -348,6 +346,7 @@ int main(int argc, char *argv[])
|
||||
ConfigDirectory = VideoDirectory;
|
||||
|
||||
cPlugin::SetConfigDirectory(ConfigDirectory);
|
||||
cThemes::SetThemesDirectory(AddDirectory(ConfigDirectory, "themes"));
|
||||
|
||||
Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
|
||||
if (!(Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true) &&
|
||||
@ -416,10 +415,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// OSD:
|
||||
|
||||
cOsd::Initialize();
|
||||
|
||||
// User interface:
|
||||
|
||||
Interface = new cInterface(SVDRPport);
|
||||
@ -429,6 +424,13 @@ int main(int argc, char *argv[])
|
||||
if (!PluginManager.StartPlugins())
|
||||
return 2;
|
||||
|
||||
// Skins:
|
||||
|
||||
new cSkinClassic;
|
||||
new cSkinSTTNG;
|
||||
Skins.SetCurrent(Setup.OSDSkin);
|
||||
cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
|
||||
|
||||
// Remote Controls:
|
||||
#if defined(REMOTE_RCU)
|
||||
new cRcuRemote("/dev/ttyS1");
|
||||
@ -586,7 +588,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
// CAM control:
|
||||
if (!Menu && !Interface->IsOpen())
|
||||
if (!Menu && !cOsd::IsOpen())
|
||||
Menu = CamControl();
|
||||
// User Input:
|
||||
cOsdObject *Interact = Menu ? Menu : cControl::Control();
|
||||
@ -646,7 +648,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
cDevice::PrimaryDevice()->SetVolume(NORMALKEY(key) == kVolDn ? -VOLUMEDELTA : VOLUMEDELTA);
|
||||
if (!Menu && !Interface->IsOpen())
|
||||
if (!Menu && !cOsd::IsOpen())
|
||||
Menu = Temp = cDisplayVolume::Create();
|
||||
cDisplayVolume::Process(key);
|
||||
key = kNone; // nobody else needs to see these keys
|
||||
@ -657,7 +659,7 @@ int main(int argc, char *argv[])
|
||||
DELETENULL(Menu);
|
||||
Temp = NULL;
|
||||
if (!cRecordControls::PauseLiveVideo())
|
||||
Interface->Error(tr("No free DVB device to record!"));
|
||||
Skins.Message(mtError, tr("No free DVB device to record!"));
|
||||
key = kNone; // nobody else needs to see this key
|
||||
}
|
||||
break;
|
||||
@ -665,9 +667,9 @@ int main(int argc, char *argv[])
|
||||
case kRecord:
|
||||
if (!cControl::Control()) {
|
||||
if (cRecordControls::Start())
|
||||
;//XXX Interface->Info(tr("Recording"));
|
||||
;//XXX Skins.Message(mtInfo, tr("Recording"));
|
||||
else
|
||||
Interface->Error(tr("No free DVB device to record!"));
|
||||
Skins.Message(mtError, tr("No free DVB device to record!"));
|
||||
key = kNone; // nobody else needs to see this key
|
||||
}
|
||||
break;
|
||||
@ -677,7 +679,7 @@ int main(int argc, char *argv[])
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
if (!Shutdown) {
|
||||
Interface->Error(tr("Can't shutdown - option '-s' not given!"));
|
||||
Skins.Message(mtError, tr("Can't shutdown - option '-s' not given!"));
|
||||
break;
|
||||
}
|
||||
if (cRecordControls::Active()) {
|
||||
@ -699,14 +701,14 @@ int main(int argc, char *argv[])
|
||||
cControl::Shutdown(); // just in case
|
||||
Temp = NULL;
|
||||
if (!cRecordControls::PauseLiveVideo())
|
||||
Interface->Error(tr("No free DVB device to record!"));
|
||||
Skins.Message(mtError, tr("No free DVB device to record!"));
|
||||
break;
|
||||
case osRecord: DELETENULL(Menu);
|
||||
Temp = NULL;
|
||||
if (cRecordControls::Start())
|
||||
;//XXX Interface->Info(tr("Recording"));
|
||||
;//XXX Skins.Message(mtInfo, tr("Recording"));
|
||||
else
|
||||
Interface->Error(tr("No free DVB device to record!"));
|
||||
Skins.Message(mtError, tr("No free DVB device to record!"));
|
||||
break;
|
||||
case osRecordings:
|
||||
DELETENULL(Menu);
|
||||
@ -728,7 +730,7 @@ int main(int argc, char *argv[])
|
||||
DELETENULL(Menu);
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
Interface->Info(tr("Switching primary DVB..."));
|
||||
Skins.Message(mtInfo, tr("Switching primary DVB..."));
|
||||
cDevice::SetPrimaryDevice(Setup.PrimaryDVB);
|
||||
break;
|
||||
case osPlugin: DELETENULL(Menu);
|
||||
@ -789,9 +791,9 @@ int main(int argc, char *argv[])
|
||||
EITScanner.Process();
|
||||
if (!cCutter::Active() && cCutter::Ended()) {
|
||||
if (cCutter::Error())
|
||||
Interface->Error(tr("Editing process failed!"));
|
||||
Skins.Message(mtError, tr("Editing process failed!"));
|
||||
else
|
||||
Interface->Info(tr("Editing process finished"));
|
||||
Skins.Message(mtInfo, tr("Editing process finished"));
|
||||
}
|
||||
}
|
||||
if (!Interact && ((!cRecordControls::Active() && !cCutter::Active() && (!Interface->HasSVDRPConnection() || UserShutdown)) || ForceShutdown)) {
|
||||
@ -862,9 +864,10 @@ int main(int argc, char *argv[])
|
||||
delete Menu;
|
||||
cControl::Shutdown();
|
||||
delete Interface;
|
||||
cOsd::Shutdown();
|
||||
cOsdProvider::Shutdown();
|
||||
Remotes.Clear();
|
||||
Audios.Clear();
|
||||
Skins.Clear();
|
||||
Setup.CurrentChannel = cDevice::CurrentChannel();
|
||||
Setup.CurrentVolume = cDevice::CurrentVolume();
|
||||
Setup.Save();
|
||||
|
Loading…
Reference in New Issue
Block a user