From 5500959f4f73c21cef8910b3815b4ee3fa1327dd Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 3 Jun 2012 12:44:00 +0200 Subject: Version 1.7.28 Original announce message: VDR developer version 1.7.28 is now available at ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.28.tar.bz2 A 'diff' against the previous version is available at ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.27-1.7.28.diff MD5 checksums: 3ccff2dcc42d112e23dd64f2c39f02f1 vdr-1.7.28.tar.bz2 7249ead4aca4b24e53d49d11c67e1613 vdr-1.7.27-1.7.28.diff WARNING: ======== This is a developer version. Even though I use it in my productive environment. I strongly recommend that you only use it under controlled conditions and for testing and debugging. The new default skin "LCARS" displays the signal strengths and qualities of all devices in its main menu. For devices that have an stb0899 frontend chip (like the TT-budget S2-3200) retrieving this information from the driver is rather slow, which results in a sluggish response to user input in the main menu. To speed this up you may want to apply the patches from From the HISTORY file: - Fixed cPixmapMemory::DrawEllipse() for quadrants -1 and -4. - Fixed getting the maximum short channel name length in case there are no short names at all (reported by Derek Kelly). - The new function cDevice::DeviceType() returns a string identifying the type of the given device. - Now limiting the number of characters of a channel's (short) name to 16 in the schedules menus, to keep that column from getting overly wide in case there is a channel with a very long name that has no short name. - Fixed EPG scan on systems with only a single DVB device that use software output (reported by Juergen Lock). - Skins can now inquire the menu category for which their cSkinDisplayMenu is currently being used. This can be done either through a call to cSkinDisplayMenu::MenuCategory() or by reimplementing cSkinDisplayMenu::SetMenuCategory(). This information allows a skin to use special icons or decorations for the various types of menus in VDR. - The new setup option "DVB/Standard compliance" can be used to switch between different variations of the DVB standard (thanks to Rolf Ahrenberg). Currently there is "DVB" (for the original DVB standard) and "ANSI/SCTE", which is used to properly handle certain private stream types. - The disk usage is no longer automatically added to the title of the main and "Recordings" menus. This has always been a mekeshift solution and it is now up to the individual skin if, where and how it wants to display this information. A skin can use the new cVideoDiskUsage class to implement such a display. For compatibility, the default skins "Classic VDR", "ST:TNG Panels" and "Text mode" (i.e. curses) have been changed to behave like before. Other skins may want to display the disk usage in totally different ways. - A cOsdMenu can now handle skins that display different numbers of items in the various menu categories. - OSD and skin are now reinitialized after a plugin setup page has been confirmed, to have them react immediately in case any change to a plugin's setup parameter has an effect on the OSD. - The Timers list is now marked as modified whenever a recording starts or ends. - Fixed cDevice::StillPicture(), making sure it doesn't call the derived class's function if no buffer has been allocated (reported by Marcus Roscher). - Fixed the SVDRP command UPDR, which didn't update the global recordings list (reported by Lars Hanisch). - cControl::Control() now has an additional boolean parameter, which can be set to true to get the current player control even if it is hidden. - The new functions cControl::GetRecording() and cControl::GetHeader() can be used to retrieve information about what the current player is playing. - Fixed a possible high CPU load when pausing replay (thanks to Reinhard Nissl). - Fixed character comparisons in cSubtitleObject::DecodeCharacterString() (reported by Reinhard Mantey). - Renamed the function cString::sprintf(const char *fmt, va_list &ap) to vsprintf(), because it might inadvertently be called with a 'char *' as the second argument on some compilers and cause a crash (reported by Sundararaj Reel). - Removed the "bondedMasterFailed" mechanism from cDvbTuner, because it caused problems with the EPG scan in case a transponder is not receivable in a setup with bonded devices (reported by Michael Schneider). - Making sure setup strings don't contain any newline characters (thanks to Joachim Wilke). - The new member function cSkinDisplayReplay::SetRecording() allows a skin to display more information about the currently played recording. - Fixed a mismatched 'delete' in cSchedules::SetEpgDataFileName() (thanks to Reinhard Mantey). - The DrawText() functions of the OSD now accept the new alignment flag taBorder, which triggers keeping a proper distance from the edge that taLeft or taRight aligns to. - Fixed checking for UTF-8 support in cFont::Bidi() (reported by Torsten Lang). - If a recording has no info file, the 'title' of the recording's info is now set to the recording's name. - cVector::Clear() now reinitializes any previously used members. - Fixed resetting CAMs (thanks to Marco Skambraks). - The new function RgbShade() (include osd.h) can be used to generate a brighter or darker version of a given color. - The new class cSortedTimers can be used to quickly get a list of all timers, sorted by their start time. - The new skin "LCARS" is an enhanced version of the "ST:TNG" skin (which is still there in its original layout, for those who don't like the LCARS skin, or can't use it due to OSD limitations). The LCARS skin utilizes the new "menu category" feature to display additional information on the main menu page. It shows upcoming timers and the system's devices, as well as which device is recording which timers. The upper pane of the main menu displays the programme data in live and replay mode, and a progress bar. An indicator on the right side of the device list shows which device is currently used for live viewing, and whether it is in transfer mode. The individual device displays show the device number, the device type, which CAM (if any ) is currently assigned to the device, and the signal strength and quality. On the left side of the OSD there is a permanent display of the current date and time, the disk usage and the system load. "LCARS" is the new default skin of VDR. It requires at least a 4bpp (16 color) full screen OSD, but you can still operate it if your OSD can handle only fewer colors (in which case you may want to switch to the "ST:TNG" or "Classic VDR" skin). - Finally removed the code marked with __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS and LEGACY_CRECEIVER. - Now making sure that the "small font" is never larger than the "osd font". - Fixed font handling with fontconfig 2.9.0 or newer (thanks to Joerg Bornkessel). - Extended the interface to the script that gets called for recordings, so that in the "edited" case it also provides the name of the original recording (thanks to Christian Richter). - Added DeleteEvent() to the EPG handler interface, so that an EPG handler can trigger deleting of an event (thanks to Christian Kaiser). - Speeded up opening menus on systems with many (several thousands) of recordings, by caching the information whether a recording is stored on the video directory file system within the cRecording data (based on a patch from Torsten Lang). --- CONTRIBUTORS | 38 + HISTORY | 98 +- INSTALL | 17 +- MANUAL | 5 + Makefile | 4 +- PLUGINS/src/dvbhddevice/dvbhdffdevice.c | 173 +-- PLUGINS/src/dvbhddevice/hdffosd.c | 104 +- PLUGINS/src/pictures/HISTORY | 4 + PLUGINS/src/pictures/pictures.c | 4 +- PLUGINS/src/pictures/player.c | 7 +- PLUGINS/src/pictures/player.h | 3 +- PLUGINS/src/skincurses/HISTORY | 5 + PLUGINS/src/skincurses/skincurses.c | 20 +- channels.c | 4 +- ci.c | 3 +- config.c | 11 +- config.h | 21 +- cutter.c | 4 +- device.c | 13 +- device.h | 8 +- dvbdevice.c | 48 +- dvbdevice.h | 3 +- dvbplayer.c | 4 +- dvbsubtitle.c | 4 +- eit.c | 7 +- eitscan.c | 4 +- epg.c | 15 +- epg.h | 8 +- font.c | 9 +- menu.c | 156 +-- menu.h | 12 +- menuitems.c | 3 +- osd.c | 38 +- osd.h | 12 +- osdbase.c | 14 +- osdbase.h | 6 +- pat.c | 68 +- player.c | 16 +- player.h | 19 +- po/ar.po | 38 +- po/ca_ES.po | 38 +- po/cs_CZ.po | 38 +- po/da_DK.po | 38 +- po/de_DE.po | 38 +- po/el_GR.po | 38 +- po/es_ES.po | 38 +- po/et_EE.po | 38 +- po/fi_FI.po | 38 +- po/fr_FR.po | 38 +- po/hr_HR.po | 38 +- po/hu_HU.po | 38 +- po/it_IT.po | 38 +- po/lt_LT.po | 38 +- po/mk_MK.po | 38 +- po/nl_NL.po | 38 +- po/nn_NO.po | 38 +- po/pl_PL.po | 38 +- po/pt_PT.po | 38 +- po/ro_RO.po | 38 +- po/ru_RU.po | 38 +- po/sk_SK.po | 38 +- po/sl_SI.po | 38 +- po/sr_SR.po | 38 +- po/sv_SE.po | 38 +- po/tr_TR.po | 38 +- po/uk_UA.po | 38 +- po/zh_CN.po | 38 +- receiver.c | 18 +- receiver.h | 9 +- recording.c | 37 +- recording.h | 14 +- skinclassic.c | 20 +- skinlcars.c | 2114 +++++++++++++++++++++++++++++++ skinlcars.h | 27 + skins.c | 13 +- skins.h | 20 +- skinsttng.c | 20 +- svdrp.c | 34 +- svdrp.h | 4 +- thread.c | 4 +- timers.c | 19 +- timers.h | 7 +- tools.c | 13 +- tools.h | 22 +- vdr.c | 4 +- videodir.c | 42 +- videodir.h | 40 +- 87 files changed, 3812 insertions(+), 725 deletions(-) create mode 100644 skinlcars.c create mode 100644 skinlcars.h diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 54bb679..baa09ee 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1140,6 +1140,7 @@ Rolf Ahrenberg for suggesting to change the Green button in the "Edit timer" menu from "Once" to "Single" for fixing reduced bpp support for DVB subtitles + for implementing "DVB Standard compliance" handling Ralf Klueber for reporting a bug in cutting a recording if there is only a single editing mark @@ -1309,6 +1310,7 @@ Reinhard Nissl for making cEITScanner process new transponders before old ones, to make sure transponder changes are recognized for helping to debug switching into time shift mode when pausing live video + for fixing a possible high CPU load when pausing replay Richard Robson for reporting freezing replay if a timer starts while in Transfer Mode from the @@ -1782,6 +1784,7 @@ Joachim Wilke for modifying cCharSetConv so that it can be used to convert from "whatever VDR uses" to a given code for adding some missing 'const' to cDevice + for making sure setup strings don't contain any newline characters Sascha Klek for reporting a problem with the '0' key in the "Day" item of the "Timers" menu @@ -2591,6 +2594,9 @@ Sundararaj Reel for reporting a memory leak in cRecordings::ScanVideoDir() in case there are too many link levels for reporting a bug in cListBase::Move() in case From and To are equal + for reporting a problem with the function cString::sprintf(const char *fmt, va_list &ap), + that might inadvertently be called with a 'char *' as the second argument on some + compilers and cause a crash Ales Jurik for reporting broken SI data on Czech/Slovak channels after changing the default @@ -2663,6 +2669,8 @@ Derek Kelly (user.vdr@gmail.com) could not be determined after resuming recording for reporting a problem with detecting frames for channels that split frames into several payloads + for reporting a problem with getting the maximum short channel name length in case there + are no short names at all Marcel Unbehaun for adding cRecordingInfo::GetEvent() @@ -2720,6 +2728,7 @@ Lars Hanisch for suggesting to assign the source character 'V' to "Analog Video" for a patch that was used to implement SCR (Satellite Channel Routing) for implementing the SVDRP command 'UPDR' + for reporting that the SVDRP command UPDR didn't update the global recordings list Alex Lasnier for adding tuning support for ATSC devices @@ -2771,6 +2780,7 @@ Dominik Strasser Joerg Bornkessel for adding LDFLAGS to the linker calls in the Makefiles + for fixing font handling with fontconfig 2.9.0 or newer Andreas Oberritter for suggesting to retrieve the include path to the freetype2 header files @@ -2790,6 +2800,8 @@ Gerald Dachs Juergen Lock for fixing cUnbufferedFile::Seek() in case it is compiled without USE_FADVISE + for reporting a problem with EPG scan on systems with only a single DVB device that + use software output Sergiu Dotenco for reporting a missing initialization in sDvbSpuRect @@ -2849,6 +2861,9 @@ Torsten Lang of EPG data from BSkyB's "MTV MUSIC" for suggesting to make BIDI support check at runtime whether the system runs with UTF-8 + for reporting a bug in checking for UTF-8 support in cFont::Bidi() + for a patch that was used to implement caching the information whether a recording + is stored on the video directory file system within the cRecording data Christian Ruppert for some improvements to the Makefiles @@ -2862,3 +2877,26 @@ Ralf Schueler from version 1.7.8 to 1.6.0-3 for backporting "Fixed cRecordings::DelByName() to avoid compilation errors with gcc 4.4" from version 1.7.9 to 1.6.0-3 + +Marcus Roscher + for reporting a problem with cDevice::StillPicture(), which called the derived class's + function even if no buffer has been allocated + +Reinhard Mantey + for reporting a problem with character comparisons in + cSubtitleObject::DecodeCharacterString() + for fixing a mismatched 'delete' in cSchedules::SetEpgDataFileName() + +Michael Schneider + for reporting a problem with the EPG scan in case a transponder is not receivable in + a setup with bonded devices + +Marco Skambraks + for fixing resetting CAMs + +Christian Richter + for extending the interface to the script that gets called for recordings, so that in + the "edited" case it also provides the name of the original recording + +Christian Kaiser + for adding DeleteEvent() to the EPG handler interface diff --git a/HISTORY b/HISTORY index 1a1c8a6..23412f8 100644 --- a/HISTORY +++ b/HISTORY @@ -6603,7 +6603,7 @@ Video Disk Recorder Revision History - Now using pkg-config to get fribidi, freetype and fontconfig cflags and libs (thanks to Ville Skyttä). - The Makefile now also installs the include files (thanks to Ville Skyttä). -- Added handling of "ANSI/SCTE 57" descriptors (thanks too Rolf Ahrenberg). +- Added handling of "ANSI/SCTE 57" descriptors (thanks to Rolf Ahrenberg). - Avoiding an unecessary call to Recordings.ResetResume() (thanks to Reinhard Nissl). @@ -7051,3 +7051,99 @@ Video Disk Recorder Revision History - Reverted some improvements to Make.config.template (thanks to Christian Ruppert). - Fixed handling IDLEPRIORITY in cDvbDevice::ProvidesChannel() (thanks to Frank Schmirler). + +2012-06-03: Version 1.7.28 + +- Fixed cPixmapMemory::DrawEllipse() for quadrants -1 and -4. +- Fixed getting the maximum short channel name length in case there are no short names + at all (reported by Derek Kelly). +- The new function cDevice::DeviceType() returns a string identifying the type of + the given device. +- Now limiting the number of characters of a channel's (short) name to 16 in the + schedules menus, to keep that column from getting overly wide in case there is + a channel with a very long name that has no short name. +- Fixed EPG scan on systems with only a single DVB device that use software output + (reported by Juergen Lock). +- Skins can now inquire the menu category for which their cSkinDisplayMenu is currently + being used. This can be done either through a call to cSkinDisplayMenu::MenuCategory() + or by reimplementing cSkinDisplayMenu::SetMenuCategory(). This information allows a + skin to use special icons or decorations for the various types of menus in VDR. +- The new setup option "DVB/Standard compliance" can be used to switch between different + variations of the DVB standard (thanks to Rolf Ahrenberg). Currently there is "DVB" + (for the original DVB standard) and "ANSI/SCTE", which is used to properly handle + certain private stream types. +- The disk usage is no longer automatically added to the title of the main and + "Recordings" menus. This has always been a mekeshift solution and it is now up + to the individual skin if, where and how it wants to display this information. + A skin can use the new cVideoDiskUsage class to implement such a display. For + compatibility, the default skins "Classic VDR", "ST:TNG Panels" and "Text mode" + (i.e. curses) have been changed to behave like before. Other skins may want to + display the disk usage in totally different ways. +- A cOsdMenu can now handle skins that display different numbers of items in the + various menu categories. +- OSD and skin are now reinitialized after a plugin setup page has been confirmed, + to have them react immediately in case any change to a plugin's setup parameter + has an effect on the OSD. +- The Timers list is now marked as modified whenever a recording starts or ends. +- Fixed cDevice::StillPicture(), making sure it doesn't call the derived class's + function if no buffer has been allocated (reported by Marcus Roscher). +- Fixed the SVDRP command UPDR, which didn't update the global recordings list + (reported by Lars Hanisch). +- cControl::Control() now has an additional boolean parameter, which can be set to + true to get the current player control even if it is hidden. +- The new functions cControl::GetRecording() and cControl::GetHeader() can be used + to retrieve information about what the current player is playing. +- Fixed a possible high CPU load when pausing replay (thanks to Reinhard Nissl). +- Fixed character comparisons in cSubtitleObject::DecodeCharacterString() (reported + by Reinhard Mantey). +- Renamed the function cString::sprintf(const char *fmt, va_list &ap) to vsprintf(), + because it might inadvertently be called with a 'char *' as the second argument on + some compilers and cause a crash (reported by Sundararaj Reel). +- Removed the "bondedMasterFailed" mechanism from cDvbTuner, because it caused + problems with the EPG scan in case a transponder is not receivable in a setup with + bonded devices (reported by Michael Schneider). +- Making sure setup strings don't contain any newline characters (thanks to Joachim + Wilke). +- The new member function cSkinDisplayReplay::SetRecording() allows a skin to display + more information about the currently played recording. +- Fixed a mismatched 'delete' in cSchedules::SetEpgDataFileName() (thanks to Reinhard + Mantey). +- The DrawText() functions of the OSD now accept the new alignment flag taBorder, + which triggers keeping a proper distance from the edge that taLeft or taRight + aligns to. +- Fixed checking for UTF-8 support in cFont::Bidi() (reported by Torsten Lang). +- If a recording has no info file, the 'title' of the recording's info is now set + to the recording's name. +- cVector::Clear() now reinitializes any previously used members. +- Fixed resetting CAMs (thanks to Marco Skambraks). +- The new function RgbShade() (include osd.h) can be used to generate a brighter or + darker version of a given color. +- The new class cSortedTimers can be used to quickly get a list of all timers, sorted + by their start time. +- The new skin "LCARS" is an enhanced version of the "ST:TNG" skin (which is still + there in its original layout, for those who don't like the LCARS skin, or can't use + it due to OSD limitations). The LCARS skin utilizes the new "menu category" feature + to display additional information on the main menu page. It shows upcoming timers + and the system's devices, as well as which device is recording which timers. The + upper pane of the main menu displays the programme data in live and replay mode, + and a progress bar. An indicator on the right side of the device list shows which + device is currently used for live viewing, and whether it is in transfer mode. + The individual device displays show the device number, the device type, which CAM + (if any ) is currently assigned to the device, and the signal strength and quality. + On the left side of the OSD there is a permanent display of the current date and + time, the disk usage and the system load. + "LCARS" is the new default skin of VDR. It requires at least a 4bpp (16 color) full + screen OSD, but you can still operate it if your OSD can handle only fewer colors + (in which case you may want to switch to the "ST:TNG" or "Classic VDR" skin). +- Finally removed the code marked with __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS + and LEGACY_CRECEIVER. +- Now making sure that the "small font" is never larger than the "osd font". +- Fixed font handling with fontconfig 2.9.0 or newer (thanks to Joerg Bornkessel). +- Extended the interface to the script that gets called for recordings, so that in + the "edited" case it also provides the name of the original recording (thanks to + Christian Richter). +- Added DeleteEvent() to the EPG handler interface, so that an EPG handler can trigger + deleting of an event (thanks to Christian Kaiser). +- Speeded up opening menus on systems with many (several thousands) of recordings, by + caching the information whether a recording is stored on the video directory file + system within the cRecording data (based on a patch from Torsten Lang). diff --git a/INSTALL b/INSTALL index 1096a31..e155f9b 100644 --- a/INSTALL +++ b/INSTALL @@ -88,6 +88,15 @@ vdr:123:respawn:/usr/local/bin/vdr --terminal=/dev/tty8 -w 60 See the man page vdr(1) for complete information about all command line options. +Standard compliance +------------------- + +Basically VDR works according to the DVB standard, but there are countries/providers +that use other standards, which in some details deviate from the DVB standard. +This makes it necessary to handle things differently in some areas, depending on +which standard is actually used. If this is the case in your area, you may need +to adjust the option "DVB/Standard compliance" in the Setup menu accordingly. + Locale ------ @@ -235,8 +244,8 @@ You can use the '-r' option to define a program or script that gets called before and after a recording is performed, and after an editing process has finished. -The program will be called with two string parameters. The first parameter -is one of +The program will be called with two or three (in case of "edited") string +parameters. The first parameter is one of before if this is *before* a recording starts after if this is *after* a recording has finished @@ -244,7 +253,8 @@ is one of and the second parameter contains the full name of the recording's directory (which may not yet exists at that moment in the "before" case). -In the "edited" case it will be the name of the edited version. +In the "edited" case it will be the name of the edited version (second +parameter) and the name of the source version (third parameter). Within this program you can do anything you would like to do before and/or after a recording or after an editing process. However, the program must return @@ -265,6 +275,7 @@ case "$1" in ;; edited) echo "Edited recording $2" + echo "Source recording $3" ;; *) echo "ERROR: unknown state: $1" diff --git a/MANUAL b/MANUAL index 5240628..a33f3bf 100644 --- a/MANUAL +++ b/MANUAL @@ -674,6 +674,11 @@ Version 1.6 from the primary DVB interface, so that the viewer will be disturbed as little as possible. + Standard Compliance = 0 + Defines the standard compliance mode: + 0 = DVB + 1 = ANSI/SCTE + Video format = 4:3 The video format (or aspect ratio) of the tv set in use (4:3 or 16:9). diff --git a/Makefile b/Makefile index 019a004..a0458d4 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # See the main source file 'vdr.c' for copyright information and # how to reach the author. # -# $Id: Makefile 2.26 2012/03/11 15:33:57 kls Exp $ +# $Id: Makefile 2.27 2012/04/15 13:21:31 kls Exp $ .DELETE_ON_ERROR: @@ -44,7 +44,7 @@ OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o d dvbplayer.o dvbspu.o dvbsubtitle.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\ receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\ - skinclassic.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\ + skinclassic.o skinlcars.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\ timers.o tools.o transfer.o vdr.o videodir.o ifndef NO_KBD diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c index ced24f5..f8b47bd 100644 --- a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c +++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: dvbhdffdevice.c 1.41 2012/03/07 13:52:41 kls Exp $ + * $Id: dvbhdffdevice.c 1.43 2012/05/08 11:40:32 kls Exp $ */ #include @@ -50,7 +50,7 @@ cDvbHdFfDevice::cDvbHdFfDevice(int Adapter, int Frontend) mHdffCmdIf = new HDFF::cHdffCmdIf(fd_osd); /* reset some stuff in case the VDR was killed before and had no chance - to clean up. */ + to clean up. */ mHdffCmdIf->CmdOsdReset(); mHdffCmdIf->CmdAvSetVideoSpeed(0, 100); @@ -183,68 +183,72 @@ void cDvbHdFfDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect) gHdffSetup.GetOsdSize(Width, Height, PixelAspect); } -/*TODO obsolete? -bool cDvbHdFfDevice::SetAudioBypass(bool On) -{ - if (setTransferModeForDolbyDigital != 1) - return false; - return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0; -} -TODO*/ - bool cDvbHdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On) { - if (Handle->pid) { - dmx_pes_filter_params pesFilterParams; - memset(&pesFilterParams, 0, sizeof(pesFilterParams)); - if (On) { - if (Handle->handle < 0) { - Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true); - if (Handle->handle < 0) { - LOG_ERROR; - return false; - } - } - if (Type == ptPcr) - mHdffCmdIf->CmdAvSetPcrPid(0, Handle->pid); - else if (Type == ptVideo) { - if (Handle->streamType == 0x1B) - mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_H264); - else - mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_MPEG2); - } - else if (Type == ptAudio) - mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1); - else if (Type == ptDolby) - mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AC3); - if (!(Type <= ptDolby && Handle->used <= 1)) { - pesFilterParams.pid = Handle->pid; - pesFilterParams.input = DMX_IN_FRONTEND; - pesFilterParams.output = DMX_OUT_TS_TAP; - pesFilterParams.pes_type= DMX_PES_OTHER; - pesFilterParams.flags = DMX_IMMEDIATE_START; - if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) { - LOG_ERROR; - return false; - } - } + //printf("SetPid Type %d, On %d, PID %5d, streamtype %d, handle %d, used %d\n", Type, On, Handle->pid, Handle->streamType, Handle->handle, Handle->used); + if (Handle->pid) { + dmx_pes_filter_params pesFilterParams; + memset(&pesFilterParams, 0, sizeof(pesFilterParams)); + if (On) { + if (Handle->handle < 0) { + Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true); + if (Handle->handle < 0) { + LOG_ERROR; + return false; + } + } + if (Type == ptPcr) + mHdffCmdIf->CmdAvSetPcrPid(0, Handle->pid); + else if (Type == ptVideo) { + if (Handle->streamType == 0x1B) + mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_H264); + else + mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_MPEG2); + } + else if (Type == ptAudio) { + if (Handle->streamType == 0x03) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1); + else if (Handle->streamType == 0x04) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG2); + else if (Handle->streamType == SI::AC3DescriptorTag) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AC3); + else if (Handle->streamType == SI::EnhancedAC3DescriptorTag) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_EAC3); + else if (Handle->streamType == 0x0F) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AAC); + else if (Handle->streamType == 0x11) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_HE_AAC); + else + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1); + } + if (!(Type <= ptDolby && Handle->used <= 1)) { + pesFilterParams.pid = Handle->pid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pes_type= DMX_PES_OTHER; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) { + LOG_ERROR; + return false; + } + } } - else if (!Handle->used) { - CHECK(ioctl(Handle->handle, DMX_STOP)); - if (Type == ptPcr) - mHdffCmdIf->CmdAvSetPcrPid(0, 0); - else if (Type == ptVideo) - mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1); - else if (Type == ptAudio) - mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1); - else if (Type == ptDolby) - mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_AC3); - //TODO missing setting to 0x1FFF??? see cDvbDevice::SetPid() - close(Handle->handle); - Handle->handle = -1; + else if (!Handle->used) { + CHECK(ioctl(Handle->handle, DMX_STOP)); + if (Type == ptPcr) + mHdffCmdIf->CmdAvSetPcrPid(0, 0); + else if (Type == ptVideo) + mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1); + else if (Type == ptAudio) + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1); + else if (Type == ptDolby) + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_AC3); + //TODO missing setting to 0x1FFF??? see cDvbDevice::SetPid() + close(Handle->handle); + Handle->handle = -1; } - } - return true; + } + return true; } void cDvbHdFfDevice::TurnOffLiveMode(bool LiveView) @@ -286,6 +290,8 @@ bool cDvbHdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber())) StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN; + //printf("SetChannelDevice Transfer %d, Live %d\n", StartTransferMode, LiveView); + bool TurnOnLivePIDs = !StartTransferMode && LiveView; // Turn off live PIDs if necessary: @@ -301,13 +307,10 @@ bool cDvbHdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) // PID settings: if (TurnOnLivePIDs) { - //SetAudioBypass(false);//TODO obsolete? - if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo, Channel->Vtype()) && AddPid(apid, ptAudio))) { + if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo, Channel->Vtype()) && AddPid(apid ? apid : dpid, ptAudio, apid ? 0 : Channel->Dtype(0)))) { esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1); return false; } - if (IsPrimaryDevice()) - AddPid(Channel->Tpid(), ptTeletext);//TODO obsolete? } else if (StartTransferMode) cControl::Launch(new cTransferControl(this, Channel)); @@ -338,27 +341,31 @@ void cDvbHdFfDevice::SetDigitalAudioDevice(bool On) void cDvbHdFfDevice::SetAudioTrackDevice(eTrackType Type) { - //printf("SetAudioTrackDevice %d\n", Type); - const tTrackId *TrackId = GetTrack(Type); - if (TrackId && TrackId->id) { - if (IS_AUDIO_TRACK(Type)) { + //printf("SetAudioTrackDevice %d\n", Type); + const tTrackId *TrackId = GetTrack(Type); + if (TrackId && TrackId->id) { + int streamType = 0; + cChannel * channel = Channels.GetByNumber(CurrentChannel()); + if (channel) { + if (IS_AUDIO_TRACK(Type)) + streamType = channel->Atype(Type - ttAudioFirst); + else if (IS_DOLBY_TRACK(Type)) + streamType = channel->Dtype(Type - ttDolbyFirst); + } + //printf("SetAudioTrackDevice new %d %d, current %d\n", TrackId->id, streamType, pidHandles[ptAudio].pid); if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) { - DetachAll(pidHandles[ptAudio].pid); - if (CamSlot()) - CamSlot()->SetPid(pidHandles[ptAudio].pid, false); - pidHandles[ptAudio].pid = TrackId->id; - SetPid(&pidHandles[ptAudio], ptAudio, true); - if (CamSlot()) { - CamSlot()->SetPid(pidHandles[ptAudio].pid, true); - CamSlot()->StartDecrypting(); - } - } - } - else if (IS_DOLBY_TRACK(Type)) { - pidHandles[ptDolby].pid = TrackId->id; - SetPid(&pidHandles[ptDolby], ptDolby, true); + DetachAll(pidHandles[ptAudio].pid); + if (CamSlot()) + CamSlot()->SetPid(pidHandles[ptAudio].pid, false); + pidHandles[ptAudio].pid = TrackId->id; + pidHandles[ptAudio].streamType = streamType; + SetPid(&pidHandles[ptAudio], ptAudio, true); + if (CamSlot()) { + CamSlot()->SetPid(pidHandles[ptAudio].pid, true); + CamSlot()->StartDecrypting(); + } } - } + } } bool cDvbHdFfDevice::CanReplay(void) const diff --git a/PLUGINS/src/dvbhddevice/hdffosd.c b/PLUGINS/src/dvbhddevice/hdffosd.c index a492275..0b95707 100644 --- a/PLUGINS/src/dvbhddevice/hdffosd.c +++ b/PLUGINS/src/dvbhddevice/hdffosd.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: hdffosd.c 1.12 2011/12/04 15:31:41 kls Exp $ + * $Id: hdffosd.c 1.15 2012/05/17 13:29:50 kls Exp $ */ #include "hdffosd.h" @@ -40,7 +40,6 @@ private: int mDispHeight; bool shown; bool mChanged; - bool mBitmapModified; uint32_t mDisplay; tFontFace mFontFaces[MAX_NUM_FONTFACES]; tFont mFonts[MAX_NUM_FONTS]; @@ -53,7 +52,6 @@ protected: public: cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level); virtual ~cHdffOsd(); - cBitmap *GetBitmap(int Area); virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); virtual eOsdError SetAreas(const tArea *Areas, int NumAreas); virtual void SaveRegion(int x1, int y1, int x2, int y2); @@ -79,9 +77,8 @@ cHdffOsd::cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level) mTop = Top; shown = false; mChanged = false; - mBitmapModified = false; mBitmapPalette = HDFF_INVALID_HANDLE; - config.FontKerning = false; + config.FontKerning = true; config.FontAntialiasing = Setup.AntiAlias ? true : false; mHdffCmdIf->CmdOsdConfigure(&config); @@ -126,14 +123,6 @@ cHdffOsd::~cHdffOsd() mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay); } -cBitmap * cHdffOsd::GetBitmap(int Area) -{ - //printf("GetBitmap %d\n", Area); - mChanged = true; - mBitmapModified = true; - return cOsd::GetBitmap(Area); -} - eOsdError cHdffOsd::CanHandleAreas(const tArea *Areas, int NumAreas) { eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); @@ -150,6 +139,9 @@ eOsdError cHdffOsd::CanHandleAreas(const tArea *Areas, int NumAreas) eOsdError cHdffOsd::SetAreas(const tArea *Areas, int NumAreas) { + eOsdError error; + cBitmap * bitmap; + for (int i = 0; i < NumAreas; i++) { //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp); @@ -160,7 +152,14 @@ eOsdError cHdffOsd::SetAreas(const tArea *Areas, int NumAreas) mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); shown = false; } - return cOsd::SetAreas(Areas, NumAreas); + error = cOsd::SetAreas(Areas, NumAreas); + + for (int i = 0; (bitmap = GetBitmap(i)) != NULL; i++) + { + bitmap->Clean(); + } + + return error; } void cHdffOsd::SetActive(bool On) @@ -186,25 +185,22 @@ void cHdffOsd::SaveRegion(int x1, int y1, int x2, int y2) { mHdffCmdIf->CmdOsdSaveRegion(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1); mChanged = true; - mBitmapModified = false; } void cHdffOsd::RestoreRegion(void) { mHdffCmdIf->CmdOsdRestoreRegion(mDisplay); mChanged = true; - mBitmapModified = false; } void cHdffOsd::DrawPixel(int x, int y, tColor Color) { //printf("DrawPixel\n"); - mBitmapModified = false; } void cHdffOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay) { - //printf("DrawBitmap %d %d %d\n", x, y, Overlay); + //printf("DrawBitmap %d %d %d x %d\n", x, y, Bitmap.Width(), Bitmap.Height()); int i; int numColors; const tColor * colors = Bitmap.Colors(numColors); @@ -230,37 +226,21 @@ void cHdffOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, t mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette, HDFF_COLOR_FORMAT_ARGB, 0, numColors, mBitmapColors); } - mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y, - (uint8_t *) Bitmap.Data(0, 0), Bitmap.Width(), Bitmap.Height(), - Bitmap.Width() * Bitmap.Height(), HDFF_COLOR_TYPE_CLUT8, mBitmapPalette); -#if 0 - uint32_t * tmpBitmap = new uint32_t[Bitmap.Width() * Bitmap.Height()]; - for (int ix = 0; ix < Bitmap.Width(); ix++) + int width = Bitmap.Width(); + int height = Bitmap.Height(); + int chunk = MAX_BITMAP_SIZE / width; + if (chunk > height) + chunk = height; + for (int yc = 0; yc < height; yc += chunk) { - for (int iy = 0; iy < Bitmap.Height(); iy++) - { - const tIndex * pixel = Bitmap.Data(ix, iy); - tColor color = Bitmap.Color(*pixel); - if (!Overlay || *pixel != 0) - { - if (ColorFg || ColorBg) - { - if (*pixel == 0) - color = ColorBg; - else if (*pixel == 1) - color = ColorFg; - } - tmpBitmap[Bitmap.Width() * iy + ix] = color; - } - } + int hc = chunk; + if (yc + hc > height) + hc = height - yc; + mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y + yc, + (uint8_t *) Bitmap.Data(0, yc), width, hc, + width * hc, HDFF_COLOR_TYPE_CLUT8, mBitmapPalette); } - mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y, - (uint8_t *) tmpBitmap, Bitmap.Width(), Bitmap.Height(), - Bitmap.Width() * Bitmap.Height() * 4, HDFF::colorTypeARGB8888, InvalidHandle); - delete[] tmpBitmap; -#endif mChanged = true; - mBitmapModified = false; } void cHdffOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment) @@ -365,11 +345,16 @@ void cHdffOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor Colo if (Width) { if ((Alignment & taLeft) != 0) - ; + { + if ((Alignment & taBorder) != 0) + x += max(h / TEXT_ALIGN_BORDER, 1); + } else if ((Alignment & taRight) != 0) { if (w < Width) x += Width - w; + if ((Alignment & taBorder) != 0) + x -= max(h / TEXT_ALIGN_BORDER, 1); } else { // taCentered @@ -413,14 +398,12 @@ void cHdffOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor Colo mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, false, 0, 0, 0, 0); //Font->DrawText(this, x, y, s, ColorFg, ColorBg, limit); mChanged = true; - mBitmapModified = false; } void cHdffOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color) { mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1, Color); mChanged = true; - mBitmapModified = false; } void cHdffOsd::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants) @@ -511,14 +494,12 @@ void cHdffOsd::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Qua } mHdffCmdIf->CmdOsdDrawEllipse(mDisplay, mLeft + cx, mTop + cy, rx, ry, Color, flags); mChanged = true; - mBitmapModified = false; } void cHdffOsd::DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type) { //printf("DrawSlope\n"); mChanged = true; - mBitmapModified = false; } void cHdffOsd::Flush(void) @@ -526,23 +507,30 @@ void cHdffOsd::Flush(void) if (!Active()) return; - if (!mChanged) - return; - //printf("Flush\n"); - if (mBitmapModified) + cBitmap * Bitmap; + + for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { - cBitmap *Bitmap; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) + int x1; + int y1; + int x2; + int y2; + + if (Bitmap->Dirty(x1, y1, x2, y2)) { + //printf("dirty %d %d, %d %d\n", x1, y1, x2, y2); DrawBitmap(0, 0, *Bitmap); + Bitmap->Clean(); } } + if (!mChanged) + return; + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); mChanged = false; - mBitmapModified = false; } diff --git a/PLUGINS/src/pictures/HISTORY b/PLUGINS/src/pictures/HISTORY index e0826ee..9426283 100644 --- a/PLUGINS/src/pictures/HISTORY +++ b/PLUGINS/src/pictures/HISTORY @@ -71,3 +71,7 @@ VDR Plugin 'pictures' Revision History 2012-02-27: Version 0.1.2 - Removed an obsolete command line option. + +2012-04-2r8 Version 0.1.3 + +- Added cPictureControl::GetHeader(). diff --git a/PLUGINS/src/pictures/pictures.c b/PLUGINS/src/pictures/pictures.c index 27febdf..77df0d9 100644 --- a/PLUGINS/src/pictures/pictures.c +++ b/PLUGINS/src/pictures/pictures.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: pictures.c 2.5 2012/02/27 11:40:15 kls Exp $ + * $Id: pictures.c 2.6 2012/04/28 11:58:42 kls Exp $ */ #include @@ -11,7 +11,7 @@ #include "menu.h" #include "player.h" -static const char *VERSION = "0.1.2"; +static const char *VERSION = "0.1.3"; static const char *DESCRIPTION = trNOOP("A simple picture viewer"); static const char *MAINMENUENTRY = trNOOP("Pictures"); diff --git a/PLUGINS/src/pictures/player.c b/PLUGINS/src/pictures/player.c index 4b289ac..6048d4c 100644 --- a/PLUGINS/src/pictures/player.c +++ b/PLUGINS/src/pictures/player.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: player.c 2.1 2011/02/20 17:15:25 kls Exp $ + * $Id: player.c 2.2 2012/04/28 11:58:15 kls Exp $ */ #include "player.h" @@ -204,6 +204,11 @@ void cPictureControl::DisplayCaption(void) osd->Flush(); } +cString cPictureControl::GetHeader(void) +{ + return tr("Pictures"); +} + eOSState cPictureControl::ProcessKey(eKeys Key) { switch (Key) { diff --git a/PLUGINS/src/pictures/player.h b/PLUGINS/src/pictures/player.h index 67a274d..7a0b401 100644 --- a/PLUGINS/src/pictures/player.h +++ b/PLUGINS/src/pictures/player.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: player.h 2.0 2008/01/12 16:21:57 kls Exp $ + * $Id: player.h 2.1 2012/04/28 11:56:01 kls Exp $ */ #ifndef _PLAYER_H @@ -39,6 +39,7 @@ private: public: cPictureControl(cPictureEntry *Pictures, const cPictureEntry *PictureEntry, bool SlideShow = false); virtual ~cPictureControl(); + virtual cString GetHeader(void); virtual eOSState ProcessKey(eKeys Key); static bool Active(void) { return active > 0; } static const char *LastDisplayed(void); diff --git a/PLUGINS/src/skincurses/HISTORY b/PLUGINS/src/skincurses/HISTORY index 0ba892e..deb011b 100644 --- a/PLUGINS/src/skincurses/HISTORY +++ b/PLUGINS/src/skincurses/HISTORY @@ -96,3 +96,8 @@ VDR Plugin 'skincurses' Revision History 2012-03-11: Version 0.1.11 - Adapted menu column widths of 'skincurses' to the wider HD OSD sizes. + +2012-04-23: Version 0.1.12 + +- Now displaying disk usage in the title of the main and "Recordings" menu, + which is no longer done by the VDR core. diff --git a/PLUGINS/src/skincurses/skincurses.c b/PLUGINS/src/skincurses/skincurses.c index 1f120c7..587d0b9 100644 --- a/PLUGINS/src/skincurses/skincurses.c +++ b/PLUGINS/src/skincurses/skincurses.c @@ -3,15 +3,16 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: skincurses.c 2.8 2012/03/11 14:42:52 kls Exp $ + * $Id: skincurses.c 2.9 2012/04/23 08:53:13 kls Exp $ */ #include #include #include #include +#include -static const char *VERSION = "0.1.11"; +static const char *VERSION = "0.1.12"; static const char *DESCRIPTION = trNOOP("A text only skin"); static const char *MAINMENUENTRY = NULL; @@ -262,6 +263,9 @@ void cSkinCursesDisplayChannel::Flush(void) class cSkinCursesDisplayMenu : public cSkinDisplayMenu { private: cOsd *osd; + cString title; + int lastDiskUsageState; + void DrawTitle(void); void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown); void SetTextScrollbar(void); public: @@ -285,6 +289,7 @@ public: cSkinCursesDisplayMenu::cSkinCursesDisplayMenu(void) { osd = new cCursesOsd(0, 0); + lastDiskUsageState = -1; osd->DrawRectangle(0, 0, ScOsdWidth - 1, ScOsdHeight - 1, clrBackground); } @@ -332,9 +337,16 @@ void cSkinCursesDisplayMenu::Clear(void) textScroller.Reset(); } +void cSkinCursesDisplayMenu::DrawTitle(void) +{ + bool WithDisk = MenuCategory() == mcMain || MenuCategory() == mcRecording; + osd->DrawText(0, 0, WithDisk ? cString::sprintf("%s - %s", *title, *cVideoDiskUsage::String()) : title, clrBlack, clrCyan, &Font, ScOsdWidth); +} + void cSkinCursesDisplayMenu::SetTitle(const char *Title) { - osd->DrawText(0, 0, Title, clrBlack, clrCyan, &Font, ScOsdWidth); + title = Title; + DrawTitle(); } void cSkinCursesDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) @@ -475,6 +487,8 @@ void cSkinCursesDisplayMenu::SetText(const char *Text, bool FixedFont) void cSkinCursesDisplayMenu::Flush(void) { + if (cVideoDiskUsage::HasChanged(lastDiskUsageState)) + DrawTitle(); cString date = DayDateTime(); osd->DrawText(ScOsdWidth - Utf8StrLen(date) - 2, 0, date, clrBlack, clrCyan, &Font); osd->Flush(); diff --git a/channels.c b/channels.c index 4108b7b..65e5134 100644 --- a/channels.c +++ b/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 2.21 2012/03/11 13:29:06 kls Exp $ + * $Id: channels.c 2.22 2012/04/01 09:27:08 kls Exp $ */ #include "channels.h" @@ -955,7 +955,7 @@ int cChannels::MaxShortChannelNameLength(void) if (!maxShortChannelNameLength) { for (cChannel *channel = First(); channel; channel = Next(channel)) { if (!channel->GroupSep()) - maxShortChannelNameLength = max(Utf8StrLen(channel->ShortName()), maxShortChannelNameLength); + maxShortChannelNameLength = max(Utf8StrLen(channel->ShortName(true)), maxShortChannelNameLength); } } return maxShortChannelNameLength; diff --git a/ci.c b/ci.c index 0135d07..ebed320 100644 --- a/ci.c +++ b/ci.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.c 2.8 2012/02/29 10:24:41 kls Exp $ + * $Id: ci.c 2.9 2012/05/29 11:13:40 kls Exp $ */ #include "ci.h" @@ -1715,6 +1715,7 @@ bool cCamSlot::Reset(void) if (ciAdapter->Reset(slotIndex)) { resetTime = time(NULL); dbgprotocol("ok.\n"); + lastModuleStatus = msReset; return true; } dbgprotocol("failed!\n"); diff --git a/config.c b/config.c index 302a45b..b6c4b42 100644 --- a/config.c +++ b/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 2.20 2012/02/29 10:15:54 kls Exp $ + * $Id: config.c 2.22 2012/05/11 11:06:57 kls Exp $ */ #include "config.h" @@ -309,9 +309,9 @@ cSetupLine::cSetupLine(void) cSetupLine::cSetupLine(const char *Name, const char *Value, const char *Plugin) { - name = strdup(Name); - value = strdup(Value); - plugin = Plugin ? strdup(Plugin) : NULL; + name = strreplace(strdup(Name), '\n', 0); + value = strreplace(strdup(Value), '\n', 0); + plugin = Plugin ? strreplace(strdup(Plugin), '\n', 0) : NULL; } cSetupLine::~cSetupLine() @@ -391,6 +391,7 @@ cSetup::cSetup(void) SetSystemTime = 0; TimeSource = 0; TimeTransponder = 0; + StandardCompliance = STANDARD_DVB; MarginStart = 2; MarginStop = 10; AudioLanguages[0] = -1; @@ -585,6 +586,7 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value); else if (!strcasecmp(Name, "TimeSource")) TimeSource = cSource::FromString(Value); else if (!strcasecmp(Name, "TimeTransponder")) TimeTransponder = atoi(Value); + else if (!strcasecmp(Name, "StandardCompliance")) StandardCompliance = atoi(Value); else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value); else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value); else if (!strcasecmp(Name, "AudioLanguages")) return ParseLanguages(Value, AudioLanguages); @@ -682,6 +684,7 @@ bool cSetup::Save(void) Store("SetSystemTime", SetSystemTime); Store("TimeSource", cSource::ToString(TimeSource)); Store("TimeTransponder", TimeTransponder); + Store("StandardCompliance", StandardCompliance); Store("MarginStart", MarginStart); Store("MarginStop", MarginStop); StoreLanguages("AudioLanguages", AudioLanguages); diff --git a/config.h b/config.h index 9d65397..e283d77 100644 --- a/config.h +++ b/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 2.45 2012/03/11 10:41:44 kls Exp $ + * $Id: config.h 2.47 2012/04/15 10:45:32 kls Exp $ */ #ifndef __CONFIG_H @@ -22,13 +22,13 @@ // VDR's own version number: -#define VDRVERSION "1.7.27" -#define VDRVERSNUM 10727 // Version * 10000 + Major * 100 + Minor +#define VDRVERSION "1.7.28" +#define VDRVERSNUM 10728 // Version * 10000 + Major * 100 + Minor // The plugin API's version number: -#define APIVERSION "1.7.27" -#define APIVERSNUM 10727 // Version * 10000 + Major * 100 + Minor +#define APIVERSION "1.7.28" +#define APIVERSNUM 10728 // Version * 10000 + Major * 100 + Minor // When loading plugins, VDR searches them by their APIVERSION, which // may be smaller than VDRVERSION in case there have been no changes to @@ -52,6 +52,16 @@ #define MaxSkinName 16 #define MaxThemeName 16 +// Basically VDR works according to the DVB standard, but there are countries/providers +// that use other standards, which in some details deviate from the DVB standard. +// This makes it necessary to handle things differently in some areas, depending on +// which standard is actually used. The following macros are used to distinguish +// these cases (make sure to adjust cMenuSetupDVB::standardComplianceTexts accordingly +// when adding a new standard): + +#define STANDARD_DVB 0 +#define STANDARD_ANSISCTE 1 + typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2) class cSVDRPhost : public cListObject { @@ -255,6 +265,7 @@ public: int SetSystemTime; int TimeSource; int TimeTransponder; + int StandardCompliance; int MarginStart, MarginStop; int AudioLanguages[I18N_MAX_LANGUAGES + 1]; int DisplaySubtitles; diff --git a/cutter.c b/cutter.c index 320d554..eb8f820 100644 --- a/cutter.c +++ b/cutter.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: cutter.c 2.11 2012/02/16 12:08:39 kls Exp $ + * $Id: cutter.c 2.12 2012/06/02 13:46:55 kls Exp $ */ #include "cutter.h" @@ -270,7 +270,7 @@ bool cCutter::Active(const char *FileName) error = cuttingThread->Error(); Stop(); if (!error) - cRecordingUserCommand::InvokeCommand(RUC_EDITEDRECORDING, editedVersionName); + cRecordingUserCommand::InvokeCommand(RUC_EDITEDRECORDING, editedVersionName, originalVersionName); originalVersionName = NULL; editedVersionName = NULL; ended = true; diff --git a/device.c b/device.c index 00645cf..9c382a1 100644 --- a/device.c +++ b/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 2.58 2012/03/13 09:48:14 kls Exp $ + * $Id: device.c 2.60 2012/04/26 09:40:36 kls Exp $ */ #include "device.h" @@ -162,6 +162,11 @@ int cDevice::DeviceNumber(void) const return -1; } +cString cDevice::DeviceType(void) const +{ + return ""; +} + cString cDevice::DeviceName(void) const { return ""; @@ -1176,8 +1181,10 @@ void cDevice::StillPicture(const uchar *Data, int Length) return; } } - StillPicture(buf, Size); - free(buf); + if (buf) { + StillPicture(buf, Size); + free(buf); + } } } diff --git a/device.h b/device.h index 987dfd2..f279fda 100644 --- a/device.h +++ b/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 2.38 2012/03/13 10:17:16 kls Exp $ + * $Id: device.h 2.39 2012/04/04 09:48:21 kls Exp $ */ #ifndef __DEVICE_H @@ -201,6 +201,12 @@ public: ///< Returns the card index of this device (0 ... MAXDEVICES - 1). int DeviceNumber(void) const; ///< Returns the number of this device (0 ... numDevices). + virtual cString DeviceType(void) const; + ///< Returns a string identifying the type of this device (like "DVB-S"). + ///< If this device can receive different delivery systems, the returned + ///< string shall be that of the currently used system. + ///< The length of the returned string should not exceed 6 characters. + ///< The default implementation returns an empty string. virtual cString DeviceName(void) const; ///< Returns a string identifying the name of this device. ///< The default implementation returns an empty string. diff --git a/dvbdevice.c b/dvbdevice.c index 65e9a4b..55cb912 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 2.69 2012/03/25 10:41:45 kls Exp $ + * $Id: dvbdevice.c 2.71 2012/05/09 08:33:59 kls Exp $ */ #include "dvbdevice.h" @@ -285,6 +285,7 @@ class cDvbTuner : public cThread { private: static cMutex bondMutex; enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked }; + int frontendType; const cDvbDevice *device; int fd_frontend; int adapter, frontend; @@ -302,7 +303,6 @@ private: cCondVar newSet; cDvbTuner *bondedTuner; bool bondedMaster; - bool bondedMasterFailed; bool SetFrontendType(const cChannel *Channel); cString GetBondingParams(const cChannel *Channel = NULL) const; void ClearEventQueue(void) const; @@ -314,6 +314,7 @@ private: public: cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend); virtual ~cDvbTuner(); + int FrontendType(void) const { return frontendType; } bool Bond(cDvbTuner *Tuner); void UnBond(void); bool BondingOk(const cChannel *Channel, bool ConsiderOccupied = false) const; @@ -331,6 +332,7 @@ cMutex cDvbTuner::bondMutex; cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend) { + frontendType = SYS_UNDEFINED; device = Device; fd_frontend = Fd_Frontend; adapter = Adapter; @@ -345,7 +347,6 @@ cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int tunerStatus = tsIdle; bondedTuner = NULL; bondedMaster = false; - bondedMasterFailed = false; SetDescription("tuner on frontend %d/%d", adapter, frontend); Start(); } @@ -435,12 +436,8 @@ cDvbTuner *cDvbTuner::GetBondedMaster(void) if (!bondedTuner) return this; // an unbonded tuner is always "master" cMutexLock MutexLock(&bondMutex); - if (bondedMaster) { - if (!bondedMasterFailed) - return this; - else - bondedMaster = false; - } + if (bondedMaster) + return this; // This tuner is bonded, but it's not the master, so let's see if there is a master at all: if (cDvbTuner *t = bondedTuner) { while (t != this) { @@ -450,18 +447,9 @@ cDvbTuner *cDvbTuner::GetBondedMaster(void) } } // None of the other bonded tuners is master, so make this one the master: - cDvbTuner *t = this; - if (bondedMasterFailed) { - // This one has failed, so switch to the next one: - t = bondedTuner; - t->bondedMasterFailed = false; - cMutexLock MutexLock(&t->mutex); - t->channel = channel; - t->tunerStatus = tsSet; - } - t->bondedMaster = true; - dsyslog("tuner %d/%d is now bonded master", t->adapter, t->frontend); - return t; + bondedMaster = true; + dsyslog("tuner %d/%d is now bonded master", adapter, frontend); + return this; } bool cDvbTuner::IsTunedTo(const cChannel *Channel) const @@ -733,7 +721,7 @@ bool cDvbTuner::SetFrontend(void) cDvbTransponderParameters dtp(channel.Parameters()); // Determine the required frontend type: - int frontendType = GetRequiredDeliverySystem(&channel, &dtp); + frontendType = GetRequiredDeliverySystem(&channel, &dtp); if (frontendType == SYS_UNDEFINED) return false; @@ -875,9 +863,6 @@ void cDvbTuner::Action(void) isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder()); lastTimeoutReport = time(NULL); } - cMutexLock MutexLock(&bondMutex); - if (bondedTuner && bondedMaster) - bondedMasterFailed = true; // give an other tuner a chance in case the sat cable was disconnected continue; } WaitTime = 100; // allows for a quick change from tsTuned to tsLocked @@ -977,7 +962,7 @@ int cDvbDevice::setTransferModeForDolbyDigital = 1; cMutex cDvbDevice::bondMutex; const char *DeliverySystemNames[] = { - "UNDEFINED", + "", "DVB-C", "DVB-C", "DVB-T", @@ -1090,6 +1075,17 @@ bool cDvbDevice::Probe(int Adapter, int Frontend) return true; } +cString cDvbDevice::DeviceType(void) const +{ + if (dvbTuner) { + if (dvbTuner->FrontendType() != SYS_UNDEFINED) + return DeliverySystemNames[dvbTuner->FrontendType()]; + if (numDeliverySystems) + return DeliverySystemNames[deliverySystems[0]]; // to have some reasonable default + } + return ""; +} + cString cDvbDevice::DeviceName(void) const { return frontendInfo.name; diff --git a/dvbdevice.h b/dvbdevice.h index c53a208..7da9c56 100644 --- a/dvbdevice.h +++ b/dvbdevice.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.h 2.25 2012/03/13 10:11:15 kls Exp $ + * $Id: dvbdevice.h 2.26 2012/03/31 11:13:31 kls Exp $ */ #ifndef __DVBDEVICE_H @@ -138,6 +138,7 @@ public: int Adapter(void) const { return adapter; } int Frontend(void) const { return frontend; } virtual bool Ready(void); + virtual cString DeviceType(void) const; virtual cString DeviceName(void) const; static bool BondDevices(const char *Bondings); ///< Bonds the devices as defined in the given Bondings string. diff --git a/dvbplayer.c b/dvbplayer.c index 2bf27a3..b325c98 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 2.26 2012/03/12 14:36:55 kls Exp $ + * $Id: dvbplayer.c 2.27 2012/05/06 11:02:35 kls Exp $ */ #include "dvbplayer.h" @@ -408,7 +408,7 @@ void cDvbPlayer::Action(void) Goto(0, true); while (Running()) { if (WaitingForData) - nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data + WaitingForData = !nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data else if (Sleep) { cPoller Poller; DevicePoll(Poller, 10); diff --git a/dvbsubtitle.c b/dvbsubtitle.c index ab755c4..9955069 100644 --- a/dvbsubtitle.c +++ b/dvbsubtitle.c @@ -7,7 +7,7 @@ * Original author: Marco Schluessler * With some input from the "subtitle plugin" by Pekka Virtanen * - * $Id: dvbsubtitle.c 2.31 2012/03/16 11:56:56 kls Exp $ + * $Id: dvbsubtitle.c 2.32 2012/05/08 08:17:17 kls Exp $ */ @@ -217,7 +217,7 @@ void cSubtitleObject::DecodeCharacterString(const uchar *Data, int NumberOfCodes char txt[NumberOfCodes + 1]; char *p = txt; for (int i = 2; i < NumberOfCodes; ++i) { - char c = Data[i * 2 + 1] & 0xFF; + uchar c = Data[i * 2 + 1] & 0xFF; if (c == 0) break; if (' ' <= c && c <= '~' || c == '\n' || 0xA0 <= c) diff --git a/eit.c b/eit.c index cf64e89..3cc097e 100644 --- a/eit.c +++ b/eit.c @@ -8,7 +8,7 @@ * Robert Schneider and Rolf Hakenes . * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg . * - * $Id: eit.c 2.16 2012/03/14 10:11:15 kls Exp $ + * $Id: eit.c 2.17 2012/06/02 14:05:22 kls Exp $ */ #include "eit.h" @@ -290,6 +290,11 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo channel->SetLinkChannels(LinkChannels); Modified = true; EpgHandlers.HandleEvent(pEvent); + + if (EpgHandlers.DeleteEvent(pEvent)) { + pSchedule->DelEvent(pEvent); + pEvent = NULL; + } } if (Tid == 0x4E) { if (Empty && getSectionNumber() == 0) diff --git a/eitscan.c b/eitscan.c index 0ebaaee..027bf44 100644 --- a/eitscan.c +++ b/eitscan.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: eitscan.c 2.6 2012/03/07 13:54:34 kls Exp $ + * $Id: eitscan.c 2.7 2012/04/07 14:39:28 kls Exp $ */ #include "eitscan.h" @@ -148,7 +148,7 @@ void cEITScanner::Process(void) if (Channel) { if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= CA_ENCRYPTED_MIN) { if (Device->ProvidesTransponder(Channel)) { - if (!Device->Receiving()) { + if (Device->Priority() < 0) { bool MaySwitchTransponder = Device->MaySwitchTransponder(Channel); if (MaySwitchTransponder || Device->ProvidesTransponderExclusively(Channel) && now - lastActivity > Setup.EPGScanTimeout * 3600) { if (!MaySwitchTransponder) { diff --git a/epg.c b/epg.c index f5c9b3a..8e2af14 100644 --- a/epg.c +++ b/epg.c @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.c 2.12 2012/03/10 13:14:27 kls Exp $ + * $Id: epg.c 2.14 2012/06/02 14:08:12 kls Exp $ */ #include "epg.h" @@ -1125,7 +1125,7 @@ cSchedulesLock::~cSchedulesLock() // --- cSchedules ------------------------------------------------------------ cSchedules cSchedules::schedules; -const char *cSchedules::epgDataFileName = NULL; +char *cSchedules::epgDataFileName = NULL; time_t cSchedules::lastCleanup = time(NULL); time_t cSchedules::lastDump = time(NULL); time_t cSchedules::modified = 0; @@ -1137,7 +1137,7 @@ const cSchedules *cSchedules::Schedules(cSchedulesLock &SchedulesLock) void cSchedules::SetEpgDataFileName(const char *FileName) { - delete epgDataFileName; + free(epgDataFileName); epgDataFileName = FileName ? strdup(FileName) : NULL; } @@ -1429,6 +1429,15 @@ void cEpgHandlers::HandleEvent(cEvent *Event) } } +bool cEpgHandlers::DeleteEvent(const cEvent *Event) +{ + for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { + if (eh->DeleteEvent(Event)) + return true; + } + return false; +} + void cEpgHandlers::SortSchedule(cSchedule *Schedule) { for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { diff --git a/epg.h b/epg.h index e4cec9b..fc05c22 100644 --- a/epg.h +++ b/epg.h @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.h 2.8 2012/03/10 13:50:10 kls Exp $ + * $Id: epg.h 2.10 2012/06/02 14:07:51 kls Exp $ */ #ifndef __EPG_H @@ -192,7 +192,7 @@ class cSchedules : public cList { private: cRwLock rwlock; static cSchedules schedules; - static const char *epgDataFileName; + static char *epgDataFileName; static time_t lastCleanup; static time_t lastDump; static time_t modified; @@ -258,6 +258,9 @@ public: virtual bool HandleEvent(cEvent *Event) { return false; } ///< After all modifications of the Event have been done, the EPG handler ///< can take a final look at it. + virtual bool DeleteEvent(const cEvent *Event) { return false; } + ///< After the complete processing of the Event is finished, an EPG handler + ///< can decide that this Event shall be deleted from its schedule. virtual bool SortSchedule(cSchedule *Schedule) { return false; } ///< Sorts the Schedule after the complete table has been processed. virtual bool DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version) { return false; } @@ -280,6 +283,7 @@ public: void SetVps(cEvent *Event, time_t Vps); void FixEpgBugs(cEvent *Event); void HandleEvent(cEvent *Event); + bool DeleteEvent(const cEvent *Event); void SortSchedule(cSchedule *Schedule); void DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version); }; diff --git a/font.c b/font.c index 706a017..0bcdc9b 100644 --- a/font.c +++ b/font.c @@ -6,7 +6,7 @@ * * BiDi support by Osama Alrawab @2008 Tripoli-Libya. * - * $Id: font.c 2.10 2012/03/02 10:47:45 kls Exp $ + * $Id: font.c 2.13 2012/06/02 13:38:28 kls Exp $ */ #include "font.h" @@ -412,7 +412,7 @@ const cFont *cFont::GetFont(eDvbFont Font) if (!fonts[Font]) { switch (Font) { case fontOsd: SetFont(Font, Setup.FontOsd, Setup.FontOsdSize); break; - case fontSml: SetFont(Font, Setup.FontSml, Setup.FontSmlSize); break; + case fontSml: SetFont(Font, Setup.FontSml, min(Setup.FontSmlSize, Setup.FontOsdSize)); break; case fontFix: SetFont(Font, Setup.FontFix, Setup.FontFixSize); break; default: esyslog("ERROR: unknown Font %d (%s %d)", Font, __FUNCTION__, __LINE__); } @@ -482,7 +482,8 @@ cString cFont::GetFontFileName(const char *FontName) FcPatternAddBool(pat, FC_SCALABLE, FcTrue); FcConfigSubstitute(NULL, pat, FcMatchPattern); FcDefaultSubstitute(pat); - FcFontSet *fontset = FcFontSort(NULL, pat, FcFalse, NULL, NULL); + FcResult fresult; + FcFontSet *fontset = FcFontSort(NULL, pat, FcFalse, NULL, &fresult); if (fontset) { for (int i = 0; i < fontset->nfont; i++) { FcBool scalable; @@ -508,7 +509,7 @@ cString cFont::GetFontFileName(const char *FontName) #ifdef BIDI cString cFont::Bidi(const char *Ltr) { - if (cCharSetConv::SystemCharacterTable()) { // bidi requires UTF-8 + if (!cCharSetConv::SystemCharacterTable()) { // bidi requires UTF-8 fribidi_set_mirroring(true); fribidi_set_reorder_nsm(false); FriBidiCharSet fribidiCharset = FRIBIDI_CHAR_SET_UTF8; diff --git a/menu.c b/menu.c index ad1cac3..ed07b7e 100644 --- a/menu.c +++ b/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 2.45 2012/03/13 13:14:38 kls Exp $ + * $Id: menu.c 2.54 2012/05/12 13:08:23 kls Exp $ */ #include "menu.h" @@ -34,7 +34,6 @@ #define MAXWAIT4EPGINFO 3 // seconds #define MODETIMEOUT 3 // seconds -#define DISKSPACECHEK 5 // seconds between disk space checks #define NEWTIMERLIMIT 120 // seconds until the start time of a new timer created from the Schedule menu, // within which it will go directly into the "Edit timer" menu to allow // further parameter settings @@ -47,50 +46,10 @@ #define CAMRESPONSETIMEOUT 5 // seconds to wait for a response from a CAM #define MINFREEDISK 300 // minimum free disk space (in MB) required to start recording #define NODISKSPACEDELTA 300 // seconds between "Not enough disk space to start recording!" messages +#define MAXCHNAMWIDTH 16 // maximum number of characters of channels' short names shown in schedules menus #define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 1) -#define CHNAMWIDTH (Channels.MaxShortChannelNameLength() + 1) - -// --- cFreeDiskSpace -------------------------------------------------------- - -#define MB_PER_MINUTE 25.75 // this is just an estimate! - -class cFreeDiskSpace { -private: - static time_t lastDiskSpaceCheck; - static int lastFreeMB; - static cString freeDiskSpaceString; -public: - static bool HasChanged(bool ForceCheck = false); - static const char *FreeDiskSpaceString(void) { HasChanged(); return freeDiskSpaceString; } - }; - -time_t cFreeDiskSpace::lastDiskSpaceCheck = 0; -int cFreeDiskSpace::lastFreeMB = 0; -cString cFreeDiskSpace::freeDiskSpaceString; - -cFreeDiskSpace FreeDiskSpace; - -bool cFreeDiskSpace::HasChanged(bool ForceCheck) -{ - if (ForceCheck || time(NULL) - lastDiskSpaceCheck > DISKSPACECHEK) { - int FreeMB; - int Percent = VideoDiskSpace(&FreeMB); - lastDiskSpaceCheck = time(NULL); - if (ForceCheck || FreeMB != lastFreeMB) { - int MBperMinute = Recordings.MBperMinute(); - if (MBperMinute <= 0) - MBperMinute = MB_PER_MINUTE; - int Minutes = int(double(FreeMB) / MBperMinute); - int Hours = Minutes / 60; - Minutes %= 60; - freeDiskSpaceString = cString::sprintf("%s %d%% - %2d:%02d %s", tr("Disk"), Percent, Hours, Minutes, tr("free")); - lastFreeMB = FreeMB; - return true; - } - } - return false; -} +#define CHNAMWIDTH (min(MAXCHNAMWIDTH, Channels.MaxShortChannelNameLength() + 1)) // --- cMenuEditCaItem ------------------------------------------------------- @@ -213,6 +172,7 @@ public: cMenuEditChannel::cMenuEditChannel(cChannel *Channel, bool New) :cOsdMenu(tr("Edit channel"), 16) { + SetMenuCategory(mcChannel); channel = Channel; sourceParam = NULL; *name = 0; @@ -390,6 +350,7 @@ public: cMenuChannels::cMenuChannels(void) :cOsdMenu(tr("Channels"), CHNUMWIDTH) { + SetMenuCategory(mcChannel); number = 0; Setup(); Channels.IncBeingEdited(); @@ -585,6 +546,7 @@ eOSState cMenuChannels::ProcessKey(eKeys Key) cMenuText::cMenuText(const char *Title, const char *Text, eDvbFont Font) :cOsdMenu(Title) { + SetMenuCategory(mcText); text = NULL; font = Font; SetText(Text); @@ -673,6 +635,7 @@ public: cMenuEditFolder::cMenuEditFolder(const char *Dir, cList *List, cNestedItem *Folder) :cOsdMenu(Folder ? tr("Edit folder") : tr("New folder"), 12) { + SetMenuCategory(mcFolder); list = List; folder = Folder; if (folder) { @@ -745,6 +708,7 @@ eOSState cMenuEditFolder::ProcessKey(eKeys Key) cMenuFolder::cMenuFolder(const char *Title, cNestedItemList *NestedItemList, const char *Path) :cOsdMenu(Title) { + SetMenuCategory(mcFolder); list = nestedItemList = NestedItemList; firstFolder = NULL; editing = false; @@ -756,6 +720,7 @@ cMenuFolder::cMenuFolder(const char *Title, cNestedItemList *NestedItemList, con cMenuFolder::cMenuFolder(const char *Title, cList *List, cNestedItemList *NestedItemList, const char *Dir, const char *Path) :cOsdMenu(Title) { + SetMenuCategory(mcFolder); list = List; nestedItemList = NestedItemList; dir = Dir; @@ -906,6 +871,7 @@ eOSState cMenuFolder::ProcessKey(eKeys Key) cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New) :cOsdMenu(tr("Edit timer"), 12) { + SetMenuCategory(mcTimer); file = NULL; day = firstday = NULL; timer = Timer; @@ -1104,6 +1070,7 @@ public: cMenuTimers::cMenuTimers(void) :cOsdMenu(tr("Timers"), 2, CHNUMWIDTH, 10, 6, 6) { + SetMenuCategory(mcTimer); helpKeys = -1; for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { timer->SetEventFromSchedule(); // make sure the event is current @@ -1242,6 +1209,7 @@ eOSState cMenuTimers::ProcessKey(eKeys Key) cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch, bool Buttons) :cOsdMenu(tr("Event")) { + SetMenuCategory(mcEvent); event = Event; if (event) { cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true); @@ -1389,6 +1357,7 @@ const cEvent *cMenuWhatsOn::scheduleEvent = NULL; cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr) :cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, CHNAMWIDTH, 6, 4) { + SetMenuCategory(mcSchedule); now = Now; helpKeys = -1; timerState = 0; @@ -1553,6 +1522,7 @@ public: cMenuSchedule::cMenuSchedule(void) :cOsdMenu("") { + SetMenuCategory(mcSchedule); now = next = false; otherChannel = 0; helpKeys = -1; @@ -1810,6 +1780,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key) cMenuCommands::cMenuCommands(const char *Title, cList *Commands, const char *Parameters) :cOsdMenu(Title) { + SetMenuCategory(mcCommand); result = NULL; SetHasHotkeys(); commands = Commands; @@ -1939,6 +1910,7 @@ public: cMenuCam::cMenuCam(cCamSlot *CamSlot) :cOsdMenu("", 1) // tab necessary for enquiry! { + SetMenuCategory(mcCam); camSlot = CamSlot; ciMenu = NULL; ciEnquiry = NULL; @@ -2118,6 +2090,7 @@ public: cMenuRecording::cMenuRecording(const cRecording *Recording, bool WithButtons) :cOsdMenu(tr("Recording info")) { + SetMenuCategory(mcRecording); recording = Recording; withButtons = WithButtons; if (withButtons) @@ -2212,13 +2185,13 @@ void cMenuRecordingItem::IncrementCounter(bool New) cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus) :cOsdMenu(Base ? Base : tr("Recordings"), 9, 6, 6) { + SetMenuCategory(mcRecording); base = Base ? strdup(Base) : NULL; level = Setup.RecordingDirs ? Level : -1; Recordings.StateChanged(recordingsState); // just to get the current state helpKeys = -1; Display(); // this keeps the higher level menus from showing up briefly when pressing 'Back' during replay Set(); - SetFreeDiskDisplay(true); if (Current() < 0) SetCurrent(First()); else if (OpenSubMenus && cReplayControl::LastReplayed() && Open(true)) @@ -2233,16 +2206,6 @@ cMenuRecordings::~cMenuRecordings() free(base); } -bool cMenuRecordings::SetFreeDiskDisplay(bool Force) -{ - if (FreeDiskSpace.HasChanged(Force)) { - //XXX -> skin function!!! - SetTitle(cString::sprintf("%s - %s", base ? base : tr("Recordings"), FreeDiskSpace.FreeDiskSpaceString())); - return true; - } - return false; -} - void cMenuRecordings::SetHelpKeys(void) { cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); @@ -2305,7 +2268,6 @@ void cMenuRecordings::Set(bool Refresh) } } free(LastItemText); - Refresh |= SetFreeDiskDisplay(Refresh); if (Refresh) Display(); } @@ -2343,7 +2305,7 @@ eOSState cMenuRecordings::Play(void) else { cRecording *recording = GetRecording(ri); if (recording) { - cReplayControl::SetRecording(recording->FileName(), recording->Title()); + cReplayControl::SetRecording(recording->FileName()); return osReplay; } } @@ -2411,7 +2373,7 @@ eOSState cMenuRecordings::Delete(void) Recordings.DelByName(ri->FileName()); cOsdMenu::Del(Current()); SetHelpKeys(); - SetFreeDiskDisplay(true); + cVideoDiskUsage::ForceCheck(); Display(); if (!Count()) return osBack; @@ -2484,8 +2446,6 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key) Display(); } if (!HasSubMenu()) { - if (HadSubMenu) - SetFreeDiskDisplay(); if (Key != kNone) SetHelpKeys(); } @@ -2767,6 +2727,7 @@ private: void Setup(void); const char *videoDisplayFormatTexts[3]; const char *updateChannelsTexts[6]; + const char *standardComplianceTexts[2]; public: cMenuSetupDVB(void); virtual eOSState ProcessKey(eKeys Key); @@ -2789,6 +2750,8 @@ cMenuSetupDVB::cMenuSetupDVB(void) updateChannelsTexts[3] = tr("names and PIDs"); updateChannelsTexts[4] = tr("add new channels"); updateChannelsTexts[5] = tr("add new transponders"); + standardComplianceTexts[0] = "DVB"; + standardComplianceTexts[1] = "ANSI/SCTE"; SetSection(tr("DVB")); SetHelp(NULL, tr("Button$Audio"), tr("Button$Subtitles"), NULL); @@ -2802,6 +2765,7 @@ void cMenuSetupDVB::Setup(void) Clear(); Add(new cMenuEditIntItem( tr("Setup.DVB$Primary DVB interface"), &data.PrimaryDVB, 1, cDevice::NumDevices())); + Add(new cMenuEditStraItem(tr("Setup.DVB$Standard compliance"), &data.StandardCompliance, 2, standardComplianceTexts)); Add(new cMenuEditBoolItem(tr("Setup.DVB$Video format"), &data.VideoFormat, "4:3", "16:9")); if (data.VideoFormat == 0) Add(new cMenuEditStraItem(tr("Setup.DVB$Video display format"), &data.VideoDisplayFormat, 3, videoDisplayFormatTexts)); @@ -3222,8 +3186,13 @@ eOSState cMenuSetupPlugins::ProcessKey(eKeys Key) } } } - else if (state == osContinue) + else if (state == osContinue) { Store(); + // Reinitialize OSD and skin, in case any plugin setup change has an influence on these: + cOsdProvider::UpdateOsdSize(true); + SetDisplayMenu(); + Display(); + } } return state; } @@ -3242,6 +3211,7 @@ public: cMenuSetup::cMenuSetup(void) :cOsdMenu("") { + SetMenuCategory(mcSetup); Set(); } @@ -3326,6 +3296,7 @@ cOsdObject *cMenuMain::pluginOsdObject = NULL; cMenuMain::cMenuMain(eOSState State) :cOsdMenu("") { + SetMenuCategory(mcMain); replaying = false; stopReplayItem = NULL; cancelEditingItem = NULL; @@ -3394,13 +3365,6 @@ bool cMenuMain::Update(bool Force) { bool result = false; - // Title with disk usage: - if (FreeDiskSpace.HasChanged(Force)) { - //XXX -> skin function!!! - SetTitle(cString::sprintf("%s - %s", tr("VDR"), FreeDiskSpace.FreeDiskSpaceString())); - result = true; - } - bool NewReplaying = cControl::Control() != NULL; if (Force || NewReplaying != replaying) { replaying = NewReplaying; @@ -4130,6 +4094,8 @@ eOSState cDisplaySubtitleTracks::ProcessKey(eKeys Key) cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) { + // Whatever happens here, the timers will be modified in some way... + Timers.SetModified(); // We're going to manipulate an event here, so we need to prevent // others from modifying any EPG data: cSchedulesLock SchedulesLock; @@ -4144,7 +4110,6 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) if (!timer) { timer = new cTimer(true, Pause); Timers.Add(timer); - Timers.SetModified(); instantId = cString::sprintf(cDevice::NumDevices() > 1 ? "%s - %d" : "%s", timer->Channel()->Name(), device->CardIndex() + 1); } timer->SetPending(true); @@ -4166,9 +4131,8 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) } else { Timers.Del(timer); - Timers.SetModified(); if (!cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo() - cReplayControl::SetRecording(fileName, Recording.Name()); + cReplayControl::SetRecording(fileName); } timer = NULL; return; @@ -4183,7 +4147,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) Recording.WriteInfo(); cStatus::MsgRecording(device, Recording.Name(), Recording.FileName(), true); if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo() - cReplayControl::SetRecording(fileName, Recording.Name()); + cReplayControl::SetRecording(fileName); Recordings.AddByName(fileName); return; } @@ -4194,7 +4158,6 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) timer->SetDeferred(DEFERTIMER); if (!Timer) { Timers.Del(timer); - Timers.SetModified(); timer = NULL; } } @@ -4244,6 +4207,7 @@ void cRecordControl::Stop(bool ExecuteUserCommand) cStatus::MsgRecording(device, NULL, fileName, false); if (ExecuteUserCommand) cRecordingUserCommand::InvokeCommand(RUC_AFTERRECORDING, fileName); + Timers.SetModified(); } } @@ -4337,7 +4301,7 @@ void cRecordControls::Stop(const char *InstantId) bool cRecordControls::PauseLiveVideo(void) { Skins.Message(mtStatus, tr("Pausing live video...")); - cReplayControl::SetRecording(NULL, NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed() + cReplayControl::SetRecording(NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed() if (Start(NULL, true)) { cReplayControl *rc = new cReplayControl(true); cControl::Launch(rc); @@ -4373,6 +4337,15 @@ cRecordControl *cRecordControls::GetRecordControl(const char *FileName) return NULL; } +cRecordControl *cRecordControls::GetRecordControl(const cTimer *Timer) +{ + for (int i = 0; i < MAXRECORDCONTROLS; i++) { + if (RecordControls[i] && RecordControls[i]->Timer() == Timer) + return RecordControls[i]; + } + return NULL; +} + void cRecordControls::Process(time_t t) { for (int i = 0; i < MAXRECORDCONTROLS; i++) { @@ -4429,8 +4402,7 @@ bool cRecordControls::StateChanged(int &State) // --- cReplayControl -------------------------------------------------------- cReplayControl *cReplayControl::currentReplayControl = NULL; -char *cReplayControl::fileName = NULL; -char *cReplayControl::title = NULL; +cString cReplayControl::fileName; cReplayControl::cReplayControl(bool PauseLive) :cDvbPlayerControl(fileName, PauseLive) @@ -4460,7 +4432,7 @@ cReplayControl::~cReplayControl() void cReplayControl::Stop(void) { - if (Setup.DelTimeshiftRec && fileName) { + if (Setup.DelTimeshiftRec && *fileName) { cRecordControl* rc = cRecordControls::GetRecordControl(fileName); if (rc && rc->InstantId()) { if (Active()) { @@ -4473,7 +4445,7 @@ void cReplayControl::Stop(void) Timers.SetModified(); } cDvbPlayerControl::Stop(); - cRecording *recording = Recordings.GetByName(fileName);; + cRecording *recording = Recordings.GetByName(fileName); if (recording) { if (recording->Delete()) { Recordings.DelByName(fileName); @@ -4490,17 +4462,14 @@ void cReplayControl::Stop(void) cDvbPlayerControl::Stop(); } -void cReplayControl::SetRecording(const char *FileName, const char *Title) +void cReplayControl::SetRecording(const char *FileName) { - free(fileName); - free(title); - fileName = FileName ? strdup(FileName) : NULL; - title = Title ? strdup(Title) : NULL; + fileName = FileName; } const char *cReplayControl::NowReplaying(void) { - return currentReplayControl ? fileName : NULL; + return currentReplayControl ? *fileName : NULL; } const char *cReplayControl::LastReplayed(void) @@ -4510,10 +4479,8 @@ const char *cReplayControl::LastReplayed(void) void cReplayControl::ClearLastReplayed(const char *FileName) { - if (fileName && FileName && strcmp(fileName, FileName) == 0) { - free(fileName); + if (*fileName && FileName && strcmp(fileName, FileName) == 0) fileName = NULL; - } } void cReplayControl::ShowTimed(int Seconds) @@ -4585,8 +4552,10 @@ bool cReplayControl::ShowProgress(bool Initial) visible = true; } if (Initial) { - if (title) - displayReplay->SetTitle(title); + if (*fileName) { + if (cRecording *Recording = Recordings.GetByName(fileName)) + displayReplay->SetRecording(Recording); + } lastCurrent = lastTotal = -1; } if (Current != lastCurrent || Total != lastTotal) { @@ -4758,7 +4727,7 @@ void cReplayControl::MarkMove(bool Forward) void cReplayControl::EditCut(void) { - if (fileName) { + if (*fileName) { Hide(); if (!cCutter::Active()) { if (!marks.Count()) @@ -4800,6 +4769,13 @@ cOsdObject *cReplayControl::GetInfo(void) return NULL; } +const cRecording *cReplayControl::GetRecording(void) +{ + if (const cRecording *Recording = Recordings.GetByName(LastReplayed())) + return Recording; + return NULL; +} + eOSState cReplayControl::ProcessKey(eKeys Key) { if (!Active()) diff --git a/menu.h b/menu.h index bb05b3b..99f88d0 100644 --- a/menu.h +++ b/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 2.5 2012/03/08 13:11:40 kls Exp $ + * $Id: menu.h 2.9 2012/05/12 11:48:04 kls Exp $ */ #ifndef __MENU_H @@ -196,7 +196,6 @@ private: int level; int recordingsState; int helpKeys; - bool SetFreeDiskDisplay(bool Force = false); void SetHelpKeys(void); void Set(bool Refresh = false); bool Open(bool OpenSubMenus = false); @@ -243,6 +242,9 @@ public: static bool PauseLiveVideo(void); static const char *GetInstantId(const char *LastInstantId); static cRecordControl *GetRecordControl(const char *FileName); + static cRecordControl *GetRecordControl(const cTimer *Timer); + ///< Returns the cRecordControl for the given Timer. + ///< If there is no cRecordControl for Timer, NULL is returned. static void Process(time_t t); static void ChannelDataModified(cChannel *Channel); static bool Active(void); @@ -267,8 +269,7 @@ private: void TimeSearch(void); void ShowTimed(int Seconds = 0); static cReplayControl *currentReplayControl; - static char *fileName; - static char *title; + static cString fileName; void ShowMode(void); bool ShowProgress(bool Initial); void MarkToggle(void); @@ -281,11 +282,12 @@ public: virtual ~cReplayControl(); void Stop(void); virtual cOsdObject *GetInfo(void); + virtual const cRecording *GetRecording(void); virtual eOSState ProcessKey(eKeys Key); virtual void Show(void); virtual void Hide(void); bool Visible(void) { return visible; } - static void SetRecording(const char *FileName, const char *Title); + static void SetRecording(const char *FileName); static const char *NowReplaying(void); static const char *LastReplayed(void); static void ClearLastReplayed(const char *FileName); diff --git a/menuitems.c b/menuitems.c index ba205c0..416c2be 100644 --- a/menuitems.c +++ b/menuitems.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menuitems.c 2.13 2012/03/13 11:21:57 kls Exp $ + * $Id: menuitems.c 2.14 2012/04/08 11:20:37 kls Exp $ */ #include "menuitems.h" @@ -1126,6 +1126,7 @@ eOSState cMenuEditMapItem::ProcessKey(eKeys Key) cMenuSetupPage::cMenuSetupPage(void) :cOsdMenu("", 33) { + SetMenuCategory(mcSetup); plugin = NULL; } diff --git a/osd.c b/osd.c index 49b7dce..37ee310 100644 --- a/osd.c +++ b/osd.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 2.27 2012/03/05 10:28:01 kls Exp $ + * $Id: osd.c 2.31 2012/06/02 13:32:38 kls Exp $ */ #include "osd.h" @@ -40,6 +40,16 @@ tColor HsvToColor(double H, double S, double V) } } +tColor RgbShade(tColor Color, double Factor) +{ + double f = fabs(constrain(Factor, -1.0, 1.0)); + double w = Factor > 0 ? f * 0xFF : 0; + return (Color & 0xFF000000) | + (min(0xFF, int((1 - f) * ((Color >> 16) & 0xFF) + w + 0.5)) << 16) | + (min(0xFF, int((1 - f) * ((Color >> 8) & 0xFF) + w + 0.5)) << 8) | + (min(0xFF, int((1 - f) * ( Color & 0xFF) + w + 0.5)) ); +} + #define USE_ALPHA_LUT #ifdef USE_ALPHA_LUT // Alpha blending with lookup table (by Reinhard Nissl ) @@ -553,11 +563,15 @@ void cBitmap::DrawText(int x, int y, const char *s, tColor ColorFg, tColor Color if (Width || Height) { limit = x + cw - x0; if (Width) { - if ((Alignment & taLeft) != 0) - ; + if ((Alignment & taLeft) != 0) { + if ((Alignment & taBorder) != 0) + x += max(h / TEXT_ALIGN_BORDER, 1); + } else if ((Alignment & taRight) != 0) { if (w < Width) x += Width - w; + if ((Alignment & taBorder) != 0) + x -= max(h / TEXT_ALIGN_BORDER, 1); } else { // taCentered if (w < Width) @@ -1280,11 +1294,15 @@ void cPixmapMemory::DrawText(const cPoint &Point, const char *s, tColor ColorFg, if (Width || Height) { limit = x + cw; if (Width) { - if ((Alignment & taLeft) != 0) - ; + if ((Alignment & taLeft) != 0) { + if ((Alignment & taBorder) != 0) + x += max(h / TEXT_ALIGN_BORDER, 1); + } else if ((Alignment & taRight) != 0) { if (w < Width) x += Width - w; + if ((Alignment & taBorder) != 0) + x -= max(h / TEXT_ALIGN_BORDER, 1); } else { // taCentered if (w < Width) @@ -1382,10 +1400,10 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants) case 0: case 6: DrawRectangle(cRect(cx - x, cy - y, 2 * x + 1, 1), Color); if (Quadrants == 6) break; case 8: DrawRectangle(cRect(cx - x, cy + y, 2 * x + 1, 1), Color); break; - case -1: DrawRectangle(cRect(cx + x, cy - y, x2 - x + 1, 1), Color); break; + case -1: DrawRectangle(cRect(cx + x, cy - y, rx - x + 1, 1), Color); break; case -2: DrawRectangle(cRect(x1, cy - y, cx - x - x1 + 1, 1), Color); break; case -3: DrawRectangle(cRect(x1, cy + y, cx - x - x1 + 1, 1), Color); break; - case -4: DrawRectangle(cRect(cx + x, cy + y, x2 - x + 1, 1), Color); break; + case -4: DrawRectangle(cRect(cx + x, cy + y, rx - x + 1, 1), Color); break; default: ; } y++; @@ -1417,10 +1435,10 @@ void cPixmapMemory::DrawEllipse(const cRect &Rect, tColor Color, int Quadrants) case 0: case 6: DrawRectangle(cRect(cx - x, cy - y, 2 * x + 1, 1), Color); if (Quadrants == 6) break; case 8: DrawRectangle(cRect(cx - x, cy + y, 2 * x + 1, 1), Color); break; - case -1: DrawRectangle(cRect(cx + x, cy - y, x2 - x + 1, 1), Color); break; + case -1: DrawRectangle(cRect(cx + x, cy - y, rx - x + 1, 1), Color); break; case -2: DrawRectangle(cRect(x1, cy - y, cx - x - x1 + 1, 1), Color); break; case -3: DrawRectangle(cRect(x1, cy + y, cx - x - x1 + 1, 1), Color); break; - case -4: DrawRectangle(cRect(cx + x, cy + y, x2 - x + 1, 1), Color); break; + case -4: DrawRectangle(cRect(cx + x, cy + y, rx - x + 1, 1), Color); break; default: ; } x++; @@ -1988,7 +2006,7 @@ void cOsdProvider::UpdateOsdSize(bool Force) Setup.FontSmlSize = int(round(Height * Setup.FontSmlSizeP)); cFont::SetFont(fontOsd, Setup.FontOsd, Setup.FontOsdSize); cFont::SetFont(fontFix, Setup.FontFix, Setup.FontFixSize); - cFont::SetFont(fontSml, Setup.FontSml, Setup.FontSmlSize); + cFont::SetFont(fontSml, Setup.FontSml, min(Setup.FontSmlSize, Setup.FontOsdSize)); oldWidth = Width; oldHeight = Height; oldAspect = Aspect; diff --git a/osd.h b/osd.h index f5f8b65..06c020a 100644 --- a/osd.h +++ b/osd.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.h 2.15 2011/12/04 13:38:17 kls Exp $ + * $Id: osd.h 2.17 2012/06/02 10:32:38 kls Exp $ */ #ifndef __OSD_H @@ -25,6 +25,7 @@ #define ALPHA_TRANSPARENT 0x00 #define ALPHA_OPAQUE 0xFF #define IS_OPAQUE(c) ((c >> 24) == ALPHA_OPAQUE) +#define TEXT_ALIGN_BORDER 10 // fraction of the font height used for sizing border enum { //AARRGGBB @@ -69,6 +70,14 @@ inline tColor RgbToColor(double R, double G, double B) return RgbToColor(uint8_t(0xFF * R), uint8_t(0xFF * G), uint8_t(0xFF * B)); } +tColor RgbShade(tColor Color, double Factor); + ///< Returns a brighter (Factor > 0) or darker (Factor < 0) version + ///< of the given Color. + ///< If Factor is 0.0, the return value is the unchanged Color, + ///< If Factor is 1.0, white is returned. + ///< If Factor is -1.0, black is returned. + ///< The alpha value of Color is returned unchanged. + tColor HsvToColor(double H, double S, double V); ///< Converts the given Hue (0..360), Saturation (0..1) and Value (0..1) ///< to an RGB tColor value. The alpha value of the result is 0x00, so @@ -151,6 +160,7 @@ enum eTextAlignment { taCenter = 0x00, taRight = 0x02, taTop = 0x04, taBottom = 0x08, + taBorder = 0x10, // keeps some distance from the left or right alignment edge taDefault = taTop | taLeft }; diff --git a/osdbase.c b/osdbase.c index 0a4dc32..3743730 100644 --- a/osdbase.c +++ b/osdbase.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osdbase.c 2.4 2012/03/02 15:49:57 kls Exp $ + * $Id: osdbase.c 2.6 2012/04/23 09:41:22 kls Exp $ */ #include "osdbase.h" @@ -72,14 +72,15 @@ void cOsdObject::Show(void) 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) { isMenu = true; digit = 0; hasHotkeys = false; + displayMenuItems = 0; title = NULL; + menuCategory = mcUnknown; SetTitle(Title); SetCols(c0, c1, c2, c3, c4); first = 0; @@ -103,6 +104,11 @@ cOsdMenu::~cOsdMenu() DELETENULL(displayMenu); } +void cOsdMenu::SetMenuCategory(eMenuCategory MenuCategory) +{ + menuCategory = MenuCategory; +} + void cOsdMenu::SetDisplayMenu(void) { if (displayMenu) { @@ -110,7 +116,6 @@ void cOsdMenu::SetDisplayMenu(void) delete displayMenu; } displayMenu = Skins.Current()->DisplayMenu(); - displayMenuItems = displayMenu->MaxItems(); } const char *cOsdMenu::hk(const char *s) @@ -212,6 +217,9 @@ void cOsdMenu::Display(void) displayMenu->SetMessage(mtStatus, NULL); displayMenu->Clear(); cStatus::MsgOsdClear(); + if (menuCategory != displayMenu->MenuCategory()) + displayMenu->SetMenuCategory(menuCategory); + displayMenuItems = displayMenu->MaxItems(); displayMenu->SetTabs(cols[0], cols[1], cols[2], cols[3], cols[4]);//XXX displayMenu->SetTitle(title); cStatus::MsgOsdTitle(title); diff --git a/osdbase.h b/osdbase.h index b9d22ae..a2e9914 100644 --- a/osdbase.h +++ b/osdbase.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osdbase.h 2.2 2012/03/02 15:49:57 kls Exp $ + * $Id: osdbase.h 2.4 2012/04/23 09:40:07 kls Exp $ */ #ifndef __OSDBASE_H @@ -86,10 +86,11 @@ class cOsdMenu : public cOsdObject, public cList { private: static cSkinDisplayMenu *displayMenu; static int displayMenuCount; - static int displayMenuItems; + int displayMenuItems; char *title; int cols[cSkinDisplayMenu::MaxTabs]; int first, current, marked; + eMenuCategory menuCategory; cOsdMenu *subMenu; const char *helpRed, *helpGreen, *helpYellow, *helpBlue; bool helpDisplayed; @@ -128,6 +129,7 @@ public: cOsdMenu(const char *Title, int c0 = 0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0); virtual ~cOsdMenu(); virtual bool NeedsFastResponse(void) { return subMenu ? subMenu->NeedsFastResponse() : cOsdObject::NeedsFastResponse(); } + void SetMenuCategory(eMenuCategory MenuCategory); int Current(void) const { return current; } void Add(cOsdItem *Item, bool Current = false, cOsdItem *After = NULL); void Ins(cOsdItem *Item, bool Current = false, cOsdItem *Before = NULL); diff --git a/pat.c b/pat.c index d9b93f6..826e0ea 100644 --- a/pat.c +++ b/pat.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.c 2.17 2012/03/02 10:56:45 kls Exp $ + * $Id: pat.c 2.18 2012/04/15 09:54:53 kls Exp $ */ #include "pat.h" @@ -456,37 +456,47 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } } break; - case 0x80: // STREAMTYPE_USER_PRIVATE - DigiCipher II VIDEO (ANSI/SCTE 57) - Vpid = esPid; - Ppid = pmt.getPCRPid(); - Vtype = 0x02; // compression based upon MPEG-2 - ProcessCaDescriptors = true; - break; - case 0x81: // STREAMTYPE_USER_PRIVATE - ATSC A/53 AUDIO (ANSI/SCTE 57) - { - char lang[MAXLANGCODE1] = { 0 }; - SI::Descriptor *d; - for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { - switch (d->getDescriptorTag()) { - case SI::ISO639LanguageDescriptorTag: { - SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; - strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1); - } - break; - default: ; + case 0x80: // STREAMTYPE_USER_PRIVATE + if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // DigiCipher II VIDEO (ANSI/SCTE 57) + Vpid = esPid; + Ppid = pmt.getPCRPid(); + Vtype = 0x02; // compression based upon MPEG-2 + ProcessCaDescriptors = true; + break; + } + // fall through + case 0x81: // STREAMTYPE_USER_PRIVATE + if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // ATSC A/53 AUDIO (ANSI/SCTE 57) + char lang[MAXLANGCODE1] = { 0 }; + SI::Descriptor *d; + for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { + switch (d->getDescriptorTag()) { + case SI::ISO639LanguageDescriptorTag: { + SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; + strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1); + } + break; + default: ; + } + delete d; } - delete d; + if (NumDpids < MAXDPIDS) { + Dpids[NumDpids] = esPid; + Dtypes[NumDpids] = SI::AC3DescriptorTag; + strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1); + NumDpids++; + } + ProcessCaDescriptors = true; + break; } - if (NumDpids < MAXDPIDS) { - Dpids[NumDpids] = esPid; - Dtypes[NumDpids] = SI::AC3DescriptorTag; - strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1); - NumDpids++; + // fall through + case 0x82: // STREAMTYPE_USER_PRIVATE + if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // STANDARD SUBTITLE (ANSI/SCTE 27) + //TODO + break; } - ProcessCaDescriptors = true; - } - break; - case 0x82 ... 0xFF: // STREAMTYPE_USER_PRIVATE + // fall through + case 0x83 ... 0xFF: // STREAMTYPE_USER_PRIVATE { char lang[MAXLANGCODE1] = { 0 }; bool IsAc3 = false; diff --git a/player.c b/player.c index 3490565..5c95f4e 100644 --- a/player.c +++ b/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 2.0 2007/07/20 15:25:24 kls Exp $ + * $Id: player.c 2.2 2012/04/28 11:52:50 kls Exp $ */ #include "player.h" @@ -60,10 +60,20 @@ cOsdObject *cControl::GetInfo(void) return NULL; } -cControl *cControl::Control(void) +const cRecording *cControl::GetRecording(void) +{ + return NULL; +} + +cString cControl::GetHeader(void) +{ + return ""; +} + +cControl *cControl::Control(bool Hidden) { cMutexLock MutexLock(&mutex); - return (control && !control->hidden) ? control : NULL; + return (control && (!control->hidden || Hidden)) ? control : NULL; } void cControl::Launch(cControl *Control) diff --git a/player.h b/player.h index 77d00d5..01bc958 100644 --- a/player.h +++ b/player.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: player.h 2.4 2009/03/08 12:29:10 kls Exp $ + * $Id: player.h 2.6 2012/04/28 13:04:17 kls Exp $ */ #ifndef __PLAYER_H @@ -86,13 +86,28 @@ public: virtual ~cControl(); virtual void Hide(void) = 0; virtual cOsdObject *GetInfo(void); + ///< Returns an OSD object that displays information about the currently + ///< played programme. If no such information is available, NULL will be + ///< returned. + virtual const cRecording *GetRecording(void); + ///< Returns the cRecording that is currently being replayed, or NULL if + ///< this player is not playing a cRecording. + virtual cString GetHeader(void); + ///< This can be used by players that don't play a cRecording, but rather + ///< do something completely different. The resulting string may be used by + ///< skins as a last resort, in case they want to display the state of the + ///< current player. The return value is expected to be a short, single line + ///< string. The default implementation returns an empty string. double FramesPerSecond(void) { return player->FramesPerSecond(); } bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return player->GetIndex(Current, Total, SnapToIFrame); } bool GetReplayMode(bool &Play, bool &Forward, int &Speed) { return player->GetReplayMode(Play, Forward, Speed); } static void Launch(cControl *Control); static void Attach(void); static void Shutdown(void); - static cControl *Control(void); + static cControl *Control(bool Hidden = false); + ///< Returns the current replay control (if any) in case it is currently + ///< visible. If Hidden is true, the control will be returned even if it is + ///< currently hidden. }; #endif //__PLAYER_H diff --git a/po/ar.po b/po/ar.po index 1723eab..414e6b6 100644 --- a/po/ar.po +++ b/po/ar.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-10-16 11:16-0400\n" "Last-Translator: Osama Alrawab \n" "Language-Team: Arabic \n" @@ -517,12 +517,6 @@ msgstr "المستخدم 8" msgid "Key$User9" msgstr "المستخدم 9" -msgid "Disk" -msgstr "القرص الصلب" - -msgid "free" -msgstr "مساحة حرة" - msgid "Free To Air" msgstr "غير مشÙر" @@ -944,6 +938,9 @@ msgstr "الترجمة" msgid "Setup.DVB$Primary DVB interface" msgstr "كرت الستالايت الاولى" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "نوع الÙيديو " @@ -1174,9 +1171,6 @@ msgstr " ايقا٠التسجيل " msgid "Schedule" msgstr "جدولة" -msgid "VDR" -msgstr "" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " ايقا٠الاعادة" @@ -1307,6 +1301,24 @@ msgstr "الصوت " msgid "Classic VDR" msgstr "VDR تقليدى " +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG شاشة " @@ -1370,3 +1382,9 @@ msgstr "اضغط اى زر لالغاء اعادة التشغيل" #, c-format msgid "VDR will shut down in %s minutes" msgstr "البرنامج سيقوم بالاغلاق بعد%s دقيقة " + +msgid "Disk" +msgstr "القرص الصلب" + +msgid "free" +msgstr "مساحة حرة" diff --git a/po/ca_ES.po b/po/ca_ES.po index 801a399..cd017b2 100644 --- a/po/ca_ES.po +++ b/po/ca_ES.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-03-02 19:02+0100\n" "Last-Translator: Luca Olivetti \n" "Language-Team: Catalan \n" @@ -512,12 +512,6 @@ msgstr "Usuari 8" msgid "Key$User9" msgstr "Usuari 9" -msgid "Disk" -msgstr "Disc" - -msgid "free" -msgstr "lliure" - msgid "Free To Air" msgstr "No codificat" @@ -926,6 +920,9 @@ msgstr "Subt msgid "Setup.DVB$Primary DVB interface" msgstr "Tarja DVB primària" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Format del vídeo" @@ -1150,9 +1147,6 @@ msgstr " Aturar la gravaci msgid "Schedule" msgstr "Guia de Programació" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Aturar la reproducció" @@ -1282,6 +1276,24 @@ msgstr "Volum " msgid "Classic VDR" msgstr "VDR clasico" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Quadres ST:TNG" @@ -1344,3 +1356,9 @@ msgstr "Prem qualsevol tecla per cancel #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR s'apagarà en %s minuts" + +msgid "Disk" +msgstr "Disc" + +msgid "free" +msgstr "lliure" diff --git a/po/cs_CZ.po b/po/cs_CZ.po index 50697d1..2feacbe 100644 --- a/po/cs_CZ.po +++ b/po/cs_CZ.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.14\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2010-05-06 11:00+0200\n" "Last-Translator: Radek Šťastný \n" "Language-Team: Czech \n" @@ -511,12 +511,6 @@ msgstr "Uživatel8" msgid "Key$User9" msgstr "Uživatel9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "volno" - msgid "Free To Air" msgstr "volný" @@ -925,6 +919,9 @@ msgstr "Titulky" msgid "Setup.DVB$Primary DVB interface" msgstr "Primární DVB zařízení" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Formát videa" @@ -1149,9 +1146,6 @@ msgstr " Zastavit nahrávání " msgid "Schedule" msgstr "Program (EPG)" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Zastavit pÅ™ehrávání" @@ -1281,6 +1275,24 @@ msgstr "Hlasitost " msgid "Classic VDR" msgstr "Klasické VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG konzola" @@ -1343,3 +1355,9 @@ msgstr "Jakákoliv klávesa zruší restart" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR se vypne za %s minut" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "volno" diff --git a/po/da_DK.po b/po/da_DK.po index 0777ee7..b5681b0 100644 --- a/po/da_DK.po +++ b/po/da_DK.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n" "Last-Translator: Mogens Elneff \n" "Language-Team: Danish \n" @@ -509,12 +509,6 @@ msgstr "Bruger8" msgid "Key$User9" msgstr "Bruger9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "fri" - msgid "Free To Air" msgstr "Free To Air" @@ -923,6 +917,9 @@ msgstr "Undertekster" msgid "Setup.DVB$Primary DVB interface" msgstr "Primær DVB enhed" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video format" @@ -1147,9 +1144,6 @@ msgstr " Stop optagelse " msgid "Schedule" msgstr "Programoversigt" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Stop afspilning" @@ -1279,6 +1273,24 @@ msgstr "Lydstyrke " msgid "Classic VDR" msgstr "Klassisk VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG konsol" @@ -1341,3 +1353,9 @@ msgstr "Tryk vilk #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR slukker om %s minutter" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "fri" diff --git a/po/de_DE.po b/po/de_DE.po index 6bcee52..088dbaf 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2010-01-16 16:46+0100\n" "Last-Translator: Klaus Schmidinger \n" "Language-Team: German \n" @@ -509,12 +509,6 @@ msgstr "Benutzer8" msgid "Key$User9" msgstr "Benutzer9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "frei" - msgid "Free To Air" msgstr "frei empfangbar" @@ -923,6 +917,9 @@ msgstr "Untertitel" msgid "Setup.DVB$Primary DVB interface" msgstr "Primäres DVB-Interface" +msgid "Setup.DVB$Standard compliance" +msgstr "Standardkonformität" + msgid "Setup.DVB$Video format" msgstr "Videoformat" @@ -1147,9 +1144,6 @@ msgstr " Aufzeichnung beenden " msgid "Schedule" msgstr "Programm" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Wiedergabe beenden" @@ -1279,6 +1273,24 @@ msgstr "Lautst msgid "Classic VDR" msgstr "Klassischer VDR" +msgid "DISK" +msgstr "PLATTE" + +msgid "LOAD" +msgstr "LAST" + +msgid "TIMERS" +msgstr "TIMER" + +msgid "DEVICES" +msgstr "EMPFÄNGER" + +msgid "LIVE" +msgstr "LIVE" + +msgid "PLAY" +msgstr "WIEDERGABE" + msgid "ST:TNG Panels" msgstr "ST:TNG-Konsolen" @@ -1341,3 +1353,9 @@ msgstr "Taste dr #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR wird in %s Minuten abgeschaltet" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "frei" diff --git a/po/el_GR.po b/po/el_GR.po index f2bd7ff..bb53086 100644 --- a/po/el_GR.po +++ b/po/el_GR.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n" "Last-Translator: Dimitrios Dimitrakos \n" "Language-Team: Greek \n" @@ -509,12 +509,6 @@ msgstr "" msgid "Key$User9" msgstr "" -msgid "Disk" -msgstr "Äßóêïò" - -msgid "free" -msgstr "Åëåýèåñïò" - msgid "Free To Air" msgstr "" @@ -923,6 +917,9 @@ msgstr "" msgid "Setup.DVB$Primary DVB interface" msgstr "Êýñéá DVB êÜñôá" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "ÌïñöÞ ïèüíçò" @@ -1147,9 +1144,6 @@ msgstr " msgid "Schedule" msgstr "Ðñüãñáììá" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " ÔÝëïò áíáðáñáãùãÞò" @@ -1279,6 +1273,24 @@ msgstr " msgid "Classic VDR" msgstr "Êëáóéêü VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ÌïñöÝò ST:TNG" @@ -1341,3 +1353,9 @@ msgstr "" #, c-format msgid "VDR will shut down in %s minutes" msgstr "" + +msgid "Disk" +msgstr "Äßóêïò" + +msgid "free" +msgstr "Åëåýèåñïò" diff --git a/po/es_ES.po b/po/es_ES.po index 3260e24..93ca669 100644 --- a/po/es_ES.po +++ b/po/es_ES.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-03-02 19:02+0100\n" "Last-Translator: Luca Olivetti \n" "Language-Team: Spanish \n" @@ -510,12 +510,6 @@ msgstr "Usuario 8" msgid "Key$User9" msgstr "Usuario 9" -msgid "Disk" -msgstr "Disco" - -msgid "free" -msgstr "libre" - msgid "Free To Air" msgstr "en abierto" @@ -924,6 +918,9 @@ msgstr "Subt msgid "Setup.DVB$Primary DVB interface" msgstr "Interfaz DVB primario" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Formato de vídeo" @@ -1148,9 +1145,6 @@ msgstr " Parar grabaci msgid "Schedule" msgstr "Guía de Programación" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Parar reprodución" @@ -1280,6 +1274,24 @@ msgstr "Volumen " msgid "Classic VDR" msgstr "VDR clásico" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Paneles ST:TNG" @@ -1342,3 +1354,9 @@ msgstr "Pulse cualquier tecla para cancelar reinicio" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR se apagará en %s minutos" + +msgid "Disk" +msgstr "Disco" + +msgid "free" +msgstr "libre" diff --git a/po/et_EE.po b/po/et_EE.po index c808011..cfd61f0 100644 --- a/po/et_EE.po +++ b/po/et_EE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n" "Last-Translator: Arthur Konovalov \n" "Language-Team: Estonian \n" @@ -509,12 +509,6 @@ msgstr "Lisaklahv8" msgid "Key$User9" msgstr "Lisaklahv9" -msgid "Disk" -msgstr "Ketas" - -msgid "free" -msgstr "vaba" - msgid "Free To Air" msgstr "FTA" @@ -923,6 +917,9 @@ msgstr "Subtiitrid" msgid "Setup.DVB$Primary DVB interface" msgstr "Esmane DVB seade" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "TV külgsuhe" @@ -1147,9 +1144,6 @@ msgstr " Lõpetada salvestamine " msgid "Schedule" msgstr "Kava" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Lõpetada taasesitamine" @@ -1279,6 +1273,24 @@ msgstr "Helitugevus " msgid "Classic VDR" msgstr "Classic VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Panels" @@ -1341,3 +1353,9 @@ msgstr "Restardi katkestamiseks vajuta suvalist klahvi" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR lülitub välja %s minuti pärast" + +msgid "Disk" +msgstr "Ketas" + +msgid "free" +msgstr "vaba" diff --git a/po/fi_FI.po b/po/fi_FI.po index 4e9ba73..af24f81 100644 --- a/po/fi_FI.po +++ b/po/fi_FI.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2007-08-15 15:52+0200\n" "Last-Translator: Rolf Ahrenberg \n" "Language-Team: Finnish \n" @@ -512,12 +512,6 @@ msgstr "Lisänäppäin 8" msgid "Key$User9" msgstr "Lisänäppäin 9" -msgid "Disk" -msgstr "Levy" - -msgid "free" -msgstr "vapaana" - msgid "Free To Air" msgstr "vapaa" @@ -926,6 +920,9 @@ msgstr "Tekstitys" msgid "Setup.DVB$Primary DVB interface" msgstr "Ensisijainen DVB-sovitin" +msgid "Setup.DVB$Standard compliance" +msgstr "Noudatettava standardi" + msgid "Setup.DVB$Video format" msgstr "Kuvasuhde" @@ -1150,9 +1147,6 @@ msgstr " Lopeta tallennus " msgid "Schedule" msgstr "Ohjelmisto" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Lopeta toisto" @@ -1282,6 +1276,24 @@ msgstr "Äänenvoimakkuus " msgid "Classic VDR" msgstr "Klassinen VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG konsoli" @@ -1344,3 +1356,9 @@ msgstr "Peru uudelleenkäynnistys painamalla mitä tahansa näppäintä" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR sammuu %s minuutin kuluttua" + +msgid "Disk" +msgstr "Levy" + +msgid "free" +msgstr "vapaana" diff --git a/po/fr_FR.po b/po/fr_FR.po index 4673b2e..44b2fa3 100644 --- a/po/fr_FR.po +++ b/po/fr_FR.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-02-27 18:14+0100\n" "Last-Translator: Jean-Claude Repetto \n" "Language-Team: French \n" @@ -515,12 +515,6 @@ msgstr "Utilisateur8" msgid "Key$User9" msgstr "Utilisateur9" -msgid "Disk" -msgstr "Disque" - -msgid "free" -msgstr "restant" - msgid "Free To Air" msgstr "En clair" @@ -929,6 +923,9 @@ msgstr "Sous-titres" msgid "Setup.DVB$Primary DVB interface" msgstr "Carte DVB primaire" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Format vidéo" @@ -1153,9 +1150,6 @@ msgstr " Arr msgid "Schedule" msgstr "Programmes" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Arrêter la lecture" @@ -1285,6 +1279,24 @@ msgstr "Volume " msgid "Classic VDR" msgstr "VDR classique" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Consoles ST:TNG" @@ -1347,3 +1359,9 @@ msgstr "Appuyer sur une touche pour annuler le red #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR s'arrêtera dans %s minutes" + +msgid "Disk" +msgstr "Disque" + +msgid "free" +msgstr "restant" diff --git a/po/hr_HR.po b/po/hr_HR.po index 91499ca..541c64e 100644 --- a/po/hr_HR.po +++ b/po/hr_HR.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-03-17 19:00+0100\n" "Last-Translator: Adrian Caval \n" "Language-Team: Croatian \n" @@ -511,12 +511,6 @@ msgstr "Korisnik8" msgid "Key$User9" msgstr "Korisnik9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "slobodno" - msgid "Free To Air" msgstr "Slobodno" @@ -925,6 +919,9 @@ msgstr "Titlovi" msgid "Setup.DVB$Primary DVB interface" msgstr "Primarni DVB ureðaj" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video format" @@ -1149,9 +1146,6 @@ msgstr " Prekini snimanje " msgid "Schedule" msgstr "Raspored" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Prekini reprodukciju" @@ -1281,6 +1275,24 @@ msgstr "Glasno msgid "Classic VDR" msgstr "Klasièni VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Panele" @@ -1343,3 +1355,9 @@ msgstr "Pritisnite jednu tipku za poni #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR æe se iskljuèiti za %s minuta" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "slobodno" diff --git a/po/hu_HU.po b/po/hu_HU.po index 595fa6b..c7814ee 100644 --- a/po/hu_HU.po +++ b/po/hu_HU.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2012-01-02 11:54+0200\n" "Last-Translator: István Füley \n" "Language-Team: Hungarian \n" @@ -512,12 +512,6 @@ msgstr "Felhaszn msgid "Key$User9" msgstr "Felhasználó9" -msgid "Disk" -msgstr "Lemez" - -msgid "free" -msgstr "szabad" - msgid "Free To Air" msgstr "Kódolatlan" @@ -926,6 +920,9 @@ msgstr "Feliratok" msgid "Setup.DVB$Primary DVB interface" msgstr "Elsõ DVB interface" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video formátum" @@ -1151,9 +1148,6 @@ msgstr " Felv msgid "Schedule" msgstr "Mûsorújság" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Lejátszást befejzni" @@ -1283,6 +1277,24 @@ msgstr "Hanger msgid "Classic VDR" msgstr "Klasszikus VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Konzol" @@ -1345,3 +1357,9 @@ msgstr "Nyomj egy gombot az #, c-format msgid "VDR will shut down in %s minutes" msgstr "A VDR leáll %s perc múlva" + +msgid "Disk" +msgstr "Lemez" + +msgid "free" +msgstr "szabad" diff --git a/po/it_IT.po b/po/it_IT.po index 54beaca..8027cb2 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2012-03-19 01:08+0100\n" "Last-Translator: Diego Pierotto \n" "Language-Team: Italian \n" @@ -516,12 +516,6 @@ msgstr "Utente8" msgid "Key$User9" msgstr "Utente9" -msgid "Disk" -msgstr "Disco" - -msgid "free" -msgstr "disponibili" - msgid "Free To Air" msgstr "in chiaro" @@ -930,6 +924,9 @@ msgstr "Sottotitoli" msgid "Setup.DVB$Primary DVB interface" msgstr "Scheda DVB primaria" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Formato video" @@ -1154,9 +1151,6 @@ msgstr " Ferma registrazione " msgid "Schedule" msgstr "Programmi" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Ferma riproduzione" @@ -1286,6 +1280,24 @@ msgstr "Volume " msgid "Classic VDR" msgstr "VDR Classico" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Consolle ST:TNG" @@ -1348,3 +1360,9 @@ msgstr "Premi un tasto per annullare il riavvio" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR si spegnerà tra %s minuti" + +msgid "Disk" +msgstr "Disco" + +msgid "free" +msgstr "disponibili" diff --git a/po/lt_LT.po b/po/lt_LT.po index 50cd11d..03d3508 100644 --- a/po/lt_LT.po +++ b/po/lt_LT.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.16\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2010-10-30 11:55+0200\n" "Last-Translator: Valdemaras Pipiras \n" "Language-Team: Lithuanian \n" @@ -509,12 +509,6 @@ msgstr "Vartotojas8" msgid "Key$User9" msgstr "Vartotojas9" -msgid "Disk" -msgstr "Diskas" - -msgid "free" -msgstr "laisva" - msgid "Free To Air" msgstr "Nekoduotas kanalas" @@ -923,6 +917,9 @@ msgstr "Subtitrai" msgid "Setup.DVB$Primary DVB interface" msgstr "PirminiÄ— DVB įvestis" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video formatas" @@ -1147,9 +1144,6 @@ msgstr " Sustabdyti įraÅ¡inÄ—jimÄ… " msgid "Schedule" msgstr "Programa" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Sustabdyti kartojimÄ…" @@ -1279,6 +1273,24 @@ msgstr "Garsas " msgid "Classic VDR" msgstr "Klasikinis VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Skydeliai" @@ -1341,3 +1353,9 @@ msgstr "Paspauskit bet kurį mygtukÄ… kad sustabdytumÄ—te perkrovimÄ…" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR iÅ¡sijungs per %s minutes" + +msgid "Disk" +msgstr "Diskas" + +msgid "free" +msgstr "laisva" diff --git a/po/mk_MK.po b/po/mk_MK.po index 94935c8..e62fac8 100644 --- a/po/mk_MK.po +++ b/po/mk_MK.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR-1.7.14\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2010-03-11 00:54+0100\n" "Last-Translator: Dimitar Petrovski \n" "Language-Team: Macedonian \n" @@ -510,12 +510,6 @@ msgstr "КориÑник8" msgid "Key$User9" msgstr "КориÑник9" -msgid "Disk" -msgstr "ДиÑк" - -msgid "free" -msgstr "Ñлободен" - msgid "Free To Air" msgstr "Слободно" @@ -924,6 +918,9 @@ msgstr "Титл" msgid "Setup.DVB$Primary DVB interface" msgstr "Примарен DVB уред" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Видео формат" @@ -1148,9 +1145,6 @@ msgstr " Запри Ñнимање " msgid "Schedule" msgstr "РаÑпоред" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Запри пуштање" @@ -1280,6 +1274,24 @@ msgstr "ГлаÑ" msgid "Classic VDR" msgstr "КлаÑичен VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Панели" @@ -1342,3 +1354,9 @@ msgstr "ПритиÑнете копче за откажување на реÑÑ‚ #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR ќе Ñе иÑклучи за %s минути" + +msgid "Disk" +msgstr "ДиÑк" + +msgid "free" +msgstr "Ñлободен" diff --git a/po/nl_NL.po b/po/nl_NL.po index 20ee0cb..9d1fcde 100644 --- a/po/nl_NL.po +++ b/po/nl_NL.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-02-26 17:20+0100\n" "Last-Translator: Johan Schuring \n" "Language-Team: Dutch \n" @@ -513,12 +513,6 @@ msgstr "Gebruiker8" msgid "Key$User9" msgstr "Gebruiker9" -msgid "Disk" -msgstr "Schijf" - -msgid "free" -msgstr "vrij" - msgid "Free To Air" msgstr "Vrij te ontvangen" @@ -927,6 +921,9 @@ msgstr "Ondertiteling" msgid "Setup.DVB$Primary DVB interface" msgstr "Eerste DVB kaart" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Videoformaat" @@ -1151,9 +1148,6 @@ msgstr " Stop opnemen " msgid "Schedule" msgstr "Programmagids" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Stop afspelen" @@ -1283,6 +1277,24 @@ msgstr "Volume " msgid "Classic VDR" msgstr "VDR Klassiek" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Consoles" @@ -1345,3 +1357,9 @@ msgstr "Druk een willekeurige toets om herstarten af te breken" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR zal na %s minuten uitschakelen" + +msgid "Disk" +msgstr "Schijf" + +msgid "free" +msgstr "vrij" diff --git a/po/nn_NO.po b/po/nn_NO.po index a51967b..44940e0 100644 --- a/po/nn_NO.po +++ b/po/nn_NO.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n" "Last-Translator: Truls Slevigen \n" "Language-Team: Norwegian Nynorsk \n" @@ -510,12 +510,6 @@ msgstr "" msgid "Key$User9" msgstr "" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "ledig" - msgid "Free To Air" msgstr "" @@ -924,6 +918,9 @@ msgstr "" msgid "Setup.DVB$Primary DVB interface" msgstr "Hoved DVB-enhet" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "TV-Format" @@ -1148,9 +1145,6 @@ msgstr " Stopp opptak fra " msgid "Schedule" msgstr "Programmer" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Stopp avspilling" @@ -1280,6 +1274,24 @@ msgstr "Volum " msgid "Classic VDR" msgstr "" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "" @@ -1342,3 +1354,9 @@ msgstr "" #, c-format msgid "VDR will shut down in %s minutes" msgstr "" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "ledig" diff --git a/po/pl_PL.po b/po/pl_PL.po index 5471341..90a1762 100644 --- a/po/pl_PL.po +++ b/po/pl_PL.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-03-09 12:59+0100\n" "Last-Translator: Michael Rakowski \n" "Language-Team: Polish \n" @@ -510,12 +510,6 @@ msgstr "U msgid "Key$User9" msgstr "U¿ytkownik 9" -msgid "Disk" -msgstr "Dysk" - -msgid "free" -msgstr "wolnego" - msgid "Free To Air" msgstr "nieszyfrowany" @@ -924,6 +918,9 @@ msgstr "Napisy" msgid "Setup.DVB$Primary DVB interface" msgstr "Pierwszy interfejs DVB" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Format obrazu" @@ -1148,9 +1145,6 @@ msgstr " Zatrzymaj nagrywanie " msgid "Schedule" msgstr "Program" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Zatrzymaj odtwarzanie" @@ -1280,6 +1274,24 @@ msgstr "G msgid "Classic VDR" msgstr "Klasyczny VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Panel ST:TNG" @@ -1342,3 +1354,9 @@ msgstr "Naci #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR zostanie wy³±czony za %s minut" + +msgid "Disk" +msgstr "Dysk" + +msgid "free" +msgstr "wolnego" diff --git a/po/pt_PT.po b/po/pt_PT.po index 360a095..c201761 100644 --- a/po/pt_PT.po +++ b/po/pt_PT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.15\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2010-03-28 22:49+0100\n" "Last-Translator: Cris Silva \n" "Language-Team: Portuguese \n" @@ -510,12 +510,6 @@ msgstr "Defini msgid "Key$User9" msgstr "Definição9" -msgid "Disk" -msgstr "Disco" - -msgid "free" -msgstr "livre" - msgid "Free To Air" msgstr "FTA" @@ -924,6 +918,9 @@ msgstr "Legendas" msgid "Setup.DVB$Primary DVB interface" msgstr "Placa DVB primária" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Formato de vídeo" @@ -1148,9 +1145,6 @@ msgstr " Parar grava msgid "Schedule" msgstr "Programação" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Parar reprodução" @@ -1280,6 +1274,24 @@ msgstr "Volume " msgid "Classic VDR" msgstr "VDR Clássico" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Consola ST:TNG" @@ -1342,3 +1354,9 @@ msgstr "Pressione qualquer tecla para cancelar o reinicio" #, c-format msgid "VDR will shut down in %s minutes" msgstr "O VDR vai desligar daqui a %s minutos" + +msgid "Disk" +msgstr "Disco" + +msgid "free" +msgstr "livre" diff --git a/po/ro_RO.po b/po/ro_RO.po index 7d875d5..64aadc8 100644 --- a/po/ro_RO.po +++ b/po/ro_RO.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.12\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2011-03-10 23:52+0100\n" "Last-Translator: Lucian Muresan \n" "Language-Team: Romanian \n" @@ -512,12 +512,6 @@ msgstr "Utilizator8" msgid "Key$User9" msgstr "Utilizator9" -msgid "Disk" -msgstr "Disc" - -msgid "free" -msgstr "liber" - msgid "Free To Air" msgstr "FTA (necriptat)" @@ -926,6 +920,9 @@ msgstr "Subtitrare" msgid "Setup.DVB$Primary DVB interface" msgstr "Dispozitiv DVB primar" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Format video" @@ -1150,9 +1147,6 @@ msgstr " Opre msgid "Schedule" msgstr "Program (EPG)" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Opreºte redarea" @@ -1282,6 +1276,24 @@ msgstr "Volum " msgid "Classic VDR" msgstr "VDR clasic" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "Cons. ST:TNG" @@ -1344,3 +1356,9 @@ msgstr "Ap #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR se va închide în %s minute" + +msgid "Disk" +msgstr "Disc" + +msgid "free" +msgstr "liber" diff --git a/po/ru_RU.po b/po/ru_RU.po index 203cb00..f3cd5c3 100644 --- a/po/ru_RU.po +++ b/po/ru_RU.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-12-15 14:37+0100\n" "Last-Translator: Oleg Roitburd \n" "Language-Team: Russian \n" @@ -510,12 +510,6 @@ msgstr " msgid "Key$User9" msgstr "¿ÞÛì×ÞÒÐâÕÛì9" -msgid "Disk" -msgstr "´ØáÚ" - -msgid "free" -msgstr "áÒÞÑÞÔÝÞ" - msgid "Free To Air" msgstr "FTA (ÝÕ×ÐÚÞÔØàÞÒÐÝÞ)" @@ -924,6 +918,9 @@ msgstr " msgid "Setup.DVB$Primary DVB interface" msgstr "¾áÝÞÒÝÞÕ DVB-ãáâàÞÙáâÒÞ" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "ÄÞàÜÐâ ÒØÔÕÞ" @@ -1148,9 +1145,6 @@ msgstr " msgid "Schedule" msgstr "ÂÕÛÕÓØÔ" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " ¿àÕÚàÐâØâì ÒÞáßàÞØ×ÒÕÔÕÝØÕ" @@ -1280,6 +1274,24 @@ msgstr " msgid "Classic VDR" msgstr "ºÛÐááØçÕáÚØÙ" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG ßÐÝÕÛØ" @@ -1342,3 +1354,9 @@ msgstr " #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR ÒëÚÛîçØâáï çÕàÕ× %s ÜØÝãâ" + +msgid "Disk" +msgstr "´ØáÚ" + +msgid "free" +msgstr "áÒÞÑÞÔÝÞ" diff --git a/po/sk_SK.po b/po/sk_SK.po index 65dc7bd..985435d 100644 --- a/po/sk_SK.po +++ b/po/sk_SK.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.16\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2011-02-15 16:29+0100\n" "Last-Translator: Milan Hrala \n" "Language-Team: Slovak \n" @@ -509,12 +509,6 @@ msgstr "U msgid "Key$User9" msgstr "U¾ívateµ9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "volne" - msgid "Free To Air" msgstr "volne ¹íriteµný" @@ -923,6 +917,9 @@ msgstr "Titulky" msgid "Setup.DVB$Primary DVB interface" msgstr "Hlavné DVB rozhranie" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Formát videa" @@ -1147,9 +1144,6 @@ msgstr " Zastavi msgid "Schedule" msgstr "TV program" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Zastavi» prehrávanie" @@ -1279,6 +1273,24 @@ msgstr "Hlasitos msgid "Classic VDR" msgstr "Klasické VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG panely" @@ -1341,3 +1353,9 @@ msgstr "ktor #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR sa vypne za %s minút" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "volne" diff --git a/po/sl_SI.po b/po/sl_SI.po index b785143..8b25fc3 100644 --- a/po/sl_SI.po +++ b/po/sl_SI.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-02-28 19:44+0100\n" "Last-Translator: Matjaz Thaler \n" "Language-Team: Slovenian \n" @@ -510,12 +510,6 @@ msgstr "Uporabnik8" msgid "Key$User9" msgstr "Uporabnik9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "prosto" - msgid "Free To Air" msgstr "nekodiran" @@ -924,6 +918,9 @@ msgstr "Podnapisi" msgid "Setup.DVB$Primary DVB interface" msgstr "Primarna naprava" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video format" @@ -1148,9 +1145,6 @@ msgstr " Prekini snemanje " msgid "Schedule" msgstr "Program" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Prekini predvajanje" @@ -1280,6 +1274,24 @@ msgstr "Glasnost " msgid "Classic VDR" msgstr "Klasièni VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Konsola" @@ -1342,3 +1354,9 @@ msgstr "Pritisni katerokoli tipko za preklic ponovnega zagona" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR se bo zaustavil v %s minutah" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "prosto" diff --git a/po/sr_SR.po b/po/sr_SR.po index d5f7e9a..39bc9d2 100644 --- a/po/sr_SR.po +++ b/po/sr_SR.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2011-01-09 15:57+0100\n" "Last-Translator: Milan Cvijanoviæ \n" "Language-Team: Serbian \n" @@ -511,12 +511,6 @@ msgstr "Korisnik8" msgid "Key$User9" msgstr "Korisnik9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "slobodno" - msgid "Free To Air" msgstr "Slobodno" @@ -942,6 +936,9 @@ msgstr "Titlovi" msgid "Setup.DVB$Primary DVB interface" msgstr "Primarni DVB ureðaj" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video format" @@ -1171,9 +1168,6 @@ msgstr " Zaustavi snimanje " msgid "Schedule" msgstr "Raspored Programa" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Zaustavi reprodukciju" @@ -1305,6 +1299,24 @@ msgstr "Ja msgid "Classic VDR" msgstr "Klasièni VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG Panele" @@ -1368,3 +1380,9 @@ msgstr "Pritisni jedan taster za poni #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR se iskljuèuje za %s minuta" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "slobodno" diff --git a/po/sv_SE.po b/po/sv_SE.po index 4e9aba8..7987755 100644 --- a/po/sv_SE.po +++ b/po/sv_SE.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-03-12 18:25+0100\n" "Last-Translator: Magnus Andersson \n" "Language-Team: Swedish \n" @@ -512,12 +512,6 @@ msgstr "Anv msgid "Key$User9" msgstr "Användare9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "ledigt" - msgid "Free To Air" msgstr "Okodad" @@ -926,6 +920,9 @@ msgstr "Knapp$Textning" msgid "Setup.DVB$Primary DVB interface" msgstr "Primär DVB enhet" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video format" @@ -1150,9 +1147,6 @@ msgstr " Avsluta inspelning " msgid "Schedule" msgstr "Program" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Avsluta uppspelning" @@ -1282,6 +1276,24 @@ msgstr "Volym " msgid "Classic VDR" msgstr "Klassisk VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG konsol" @@ -1344,3 +1356,9 @@ msgstr "Tryck valfri knapp f #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR kommer att stängas ned om %s minuter" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "ledigt" diff --git a/po/tr_TR.po b/po/tr_TR.po index c11769b..163b823 100644 --- a/po/tr_TR.po +++ b/po/tr_TR.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2008-02-28 00:33+0100\n" "Last-Translator: Oktay Yolgeçen \n" "Language-Team: Turkish \n" @@ -509,12 +509,6 @@ msgstr "Kullan msgid "Key$User9" msgstr "Kullanýcý9" -msgid "Disk" -msgstr "Disk" - -msgid "free" -msgstr "boþ" - msgid "Free To Air" msgstr "Þifresiz" @@ -923,6 +917,9 @@ msgstr "Altyaz msgid "Setup.DVB$Primary DVB interface" msgstr "Primer DVB arayüzü" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Video formatý" @@ -1147,9 +1144,6 @@ msgstr " msgid "Schedule" msgstr "Program" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Gösteriþi bitir" @@ -1279,6 +1273,24 @@ msgstr "Vol msgid "Classic VDR" msgstr "Klasik VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG paneli" @@ -1341,3 +1353,9 @@ msgstr "Yeniden ba #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR %s dakikada kapanacak" + +msgid "Disk" +msgstr "Disk" + +msgid "free" +msgstr "boþ" diff --git a/po/uk_UA.po b/po/uk_UA.po index e175282..588cf7a 100644 --- a/po/uk_UA.po +++ b/po/uk_UA.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.7.7\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2010-04-25 16:35+0200\n" "Last-Translator: Yarema aka Knedlyk \n" "Language-Team: Ukrainian \n" @@ -509,12 +509,6 @@ msgstr "КориÑтувач8" msgid "Key$User9" msgstr "КориÑтувач8" -msgid "Disk" -msgstr "ДиÑк" - -msgid "free" -msgstr "вільно" - msgid "Free To Air" msgstr "FTA (незакодовано)" @@ -923,6 +917,9 @@ msgstr "Субтитри" msgid "Setup.DVB$Primary DVB interface" msgstr "ОÑновний DVB-приÑтрій" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "Формат відео" @@ -1147,9 +1144,6 @@ msgstr " Зупинити Ð·Ð°Ð¿Ð¸Ñ " msgid "Schedule" msgstr "Телегід" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr " Зупинити програваннÑ" @@ -1279,6 +1273,24 @@ msgstr "ГучніÑÑ‚ÑŒ " msgid "Classic VDR" msgstr "КлаÑичний VDR" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG панелі" @@ -1341,3 +1353,9 @@ msgstr "ÐатиÑніть будь-Ñку кнопку Ð´Ð»Ñ Ð²Ñ–Ð´Ð¼Ñ–Ð½Ð¸ п #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR виключитьÑÑ Ñ‡ÐµÑ€ÐµÐ· %s хвилин" + +msgid "Disk" +msgstr "ДиÑк" + +msgid "free" +msgstr "вільно" diff --git a/po/zh_CN.po b/po/zh_CN.po index b878937..d087946 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.6.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-08 14:37+0100\n" +"POT-Creation-Date: 2012-06-02 15:10+0200\n" "PO-Revision-Date: 2009-09-23 23:50+0800\n" "Last-Translator: Nan Feng \n" "Language-Team: Chinese (simplified) \n" @@ -512,12 +512,6 @@ msgstr "用户8" msgid "Key$User9" msgstr "用户9" -msgid "Disk" -msgstr "硬盘已使用" - -msgid "free" -msgstr "å¯å½•åƒæ—¶é—´" - msgid "Free To Air" msgstr "剩余空间" @@ -926,6 +920,9 @@ msgstr "字幕" msgid "Setup.DVB$Primary DVB interface" msgstr "使用中å«æ˜Ÿå¡æŽ¥å£" +msgid "Setup.DVB$Standard compliance" +msgstr "" + msgid "Setup.DVB$Video format" msgstr "视频格å¼" @@ -1150,9 +1147,6 @@ msgstr "是å¦åœæ­¢å½•åƒ?" msgid "Schedule" msgstr "任务列表" -msgid "VDR" -msgstr "VDR" - #. TRANSLATORS: note the leading blank! msgid " Stop replaying" msgstr "åœæ­¢å›žæ”¾" @@ -1282,6 +1276,24 @@ msgstr "音é‡è°ƒæ•´" msgid "Classic VDR" msgstr "ç»å…¸VDRé¢æ¿" +msgid "DISK" +msgstr "" + +msgid "LOAD" +msgstr "" + +msgid "TIMERS" +msgstr "" + +msgid "DEVICES" +msgstr "" + +msgid "LIVE" +msgstr "" + +msgid "PLAY" +msgstr "" + msgid "ST:TNG Panels" msgstr "ST:TNG é¢æ¿" @@ -1344,3 +1356,9 @@ msgstr "请按任æ„é”®é‡å¯" #, c-format msgid "VDR will shut down in %s minutes" msgstr "VDR系统将è¦åœ¨%s分钟关闭" + +msgid "Disk" +msgstr "硬盘已使用" + +msgid "free" +msgstr "å¯å½•åƒæ—¶é—´" diff --git a/receiver.c b/receiver.c index 372cb2c..bde60e4 100644 --- a/receiver.c +++ b/receiver.c @@ -4,27 +4,13 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: receiver.c 2.5 2012/02/29 11:49:36 kls Exp $ + * $Id: receiver.c 2.7 2012/06/02 13:20:38 kls Exp $ */ #include "receiver.h" #include #include "tools.h" -#ifdef LEGACY_CRECEIVER -cReceiver::cReceiver(tChannelID ChannelID, int Priority, int Pid, const int *Pids1, const int *Pids2, const int *Pids3) -{ - device = NULL; - channelID = ChannelID; - priority = constrain(Priority, MINPRIORITY, MAXPRIORITY); - numPids = 0; - AddPid(Pid); - AddPids(Pids1); - AddPids(Pids2); - AddPids(Pids3); -} -#endif - cReceiver::cReceiver(const cChannel *Channel, int Priority) { device = NULL; @@ -83,7 +69,7 @@ bool cReceiver::SetPids(const cChannel *Channel) AddPids(Channel->Dpids()) && AddPids(Channel->Spids()); } -return true; + return true; } bool cReceiver::WantsPid(int Pid) diff --git a/receiver.h b/receiver.h index efa7be8..eb2f32a 100644 --- a/receiver.h +++ b/receiver.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: receiver.h 2.6 2012/03/11 15:25:40 kls Exp $ + * $Id: receiver.h 2.8 2012/06/02 13:20:44 kls Exp $ */ #ifndef __RECEIVER_H @@ -14,8 +14,6 @@ #define MAXRECEIVEPIDS 64 // the maximum number of PIDs per receiver -//#define LEGACY_CRECEIVER // Code enclosed with this macro is deprecated and may be removed in a future version - class cReceiver { friend class cDevice; private: @@ -40,9 +38,6 @@ protected: ///< will be delivered only ONCE, so the cReceiver must make sure that ///< it will be able to buffer the data if necessary. public: -#ifdef LEGACY_CRECEIVER - cReceiver(tChannelID ChannelID, int Priority, int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL); -#endif cReceiver(const cChannel *Channel = NULL, int Priority = MINPRIORITY); ///< Creates a new receiver for the given Channel with the given Priority. ///< If Channel is not NULL, its pids are set by a call to SetPids(). @@ -62,7 +57,7 @@ public: ///< Adds the given Pids to the list of PIDs of this receiver. bool SetPids(const cChannel *Channel); ///< Sets the PIDs of this receiver to those of the given Channel, - ///< replacing and previously stored PIDs. If Channel is NULL, all + ///< replacing any previously stored PIDs. If Channel is NULL, all ///< PIDs will be cleared. Parameters in the Setup may control whether ///< certain types of PIDs (like Dolby Digital, for instance) are ///< actually set. The Channel's ID is stored and can later be retrieved diff --git a/recording.c b/recording.c index e1f7ec9..2a73645 100644 --- a/recording.c +++ b/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 2.53 2012/03/13 13:17:57 kls Exp $ + * $Id: recording.c 2.56 2012/06/03 09:51:27 kls Exp $ */ #include "recording.h" @@ -153,7 +153,7 @@ void AssertFreeDiskSpace(int Priority, bool Force) cRecording *r = DeletedRecordings.First(); cRecording *r0 = NULL; while (r) { - if (IsOnVideoDirectoryFileSystem(r->FileName())) { // only remove recordings that will actually increase the free video disk space + if (r->IsOnVideoDirectoryFileSystem()) { // only remove recordings that will actually increase the free video disk space if (!r0 || r->Start() < r0->Start()) r0 = r; } @@ -180,7 +180,7 @@ void AssertFreeDiskSpace(int Priority, bool Force) cRecording *r = Recordings.First(); cRecording *r0 = NULL; while (r) { - if (IsOnVideoDirectoryFileSystem(r->FileName())) { // only delete recordings that will actually increase the free video disk space + if (r->IsOnVideoDirectoryFileSystem()) { // only delete recordings that will actually increase the free video disk space if (!r->IsEdited() && r->Lifetime() < MAXLIFETIME) { // edited recordings and recordings with MAXLIFETIME live forever if ((r->Lifetime() == 0 && Priority > r->Priority()) || // the recording has no guaranteed lifetime and the new recording has higher priority (r->Lifetime() > 0 && (time(NULL) - r->Start()) / SECSINDAY >= r->Lifetime())) { // the recording's guaranteed lifetime has expired @@ -617,6 +617,7 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event) channel = Timer->Channel()->Number(); instanceId = InstanceId; isPesRecording = false; + isOnVideoDirectoryFileSystem = -1; // unknown framesPerSecond = DEFAULTFRAMESPERSECOND; numFrames = -1; deleted = 0; @@ -677,6 +678,7 @@ cRecording::cRecording(const char *FileName) priority = MAXPRIORITY; // assume maximum in case there is no info file lifetime = MAXLIFETIME; isPesRecording = false; + isOnVideoDirectoryFileSystem = -1; // unknown framesPerSecond = DEFAULTFRAMESPERSECOND; numFrames = -1; deleted = 0; @@ -723,7 +725,9 @@ cRecording::cRecording(const char *FileName) } fclose(f); } - else if (errno != ENOENT) + else if (errno == ENOENT) + info->ownEvent->SetTitle(name); + else LOG_ERROR_STR(*InfoFileName); #ifdef SUMMARYFALLBACK // fall back to the old 'summary.vdr' if there was no 'info.vdr': @@ -950,6 +954,13 @@ bool cRecording::IsEdited(void) const return *s == '%'; } +bool cRecording::IsOnVideoDirectoryFileSystem(void) const +{ + if (isOnVideoDirectoryFileSystem < 0) + isOnVideoDirectoryFileSystem = ::IsOnVideoDirectoryFileSystem(FileName()); + return isOnVideoDirectoryFileSystem; +} + void cRecording::ReadInfo(void) { info->Read(); @@ -1251,7 +1262,7 @@ int cRecordings::TotalFileSizeMB(void) LOCK_THREAD; for (cRecording *recording = First(); recording; recording = Next(recording)) { int FileSizeMB = recording->FileSizeMB(); - if (FileSizeMB > 0 && IsOnVideoDirectoryFileSystem(recording->FileName())) + if (FileSizeMB > 0 && recording->IsOnVideoDirectoryFileSystem()) size += FileSizeMB; } return size; @@ -1263,7 +1274,7 @@ double cRecordings::MBperMinute(void) int length = 0; LOCK_THREAD; for (cRecording *recording = First(); recording; recording = Next(recording)) { - if (IsOnVideoDirectoryFileSystem(recording->FileName())) { + if (recording->IsOnVideoDirectoryFileSystem()) { int FileSizeMB = recording->FileSizeMB(); if (FileSizeMB > 0) { int LengthInSeconds = recording->LengthInSeconds(); @@ -1422,13 +1433,17 @@ cMark *cMarks::GetNext(int Position) const char *cRecordingUserCommand::command = NULL; -void cRecordingUserCommand::InvokeCommand(const char *State, const char *RecordingFileName) +void cRecordingUserCommand::InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName) { if (command) { - cString cmd = cString::sprintf("%s %s \"%s\"", command, State, *strescape(RecordingFileName, "\\\"$")); - isyslog("executing '%s'", *cmd); - SystemExec(cmd); - } + cString cmd; + if (SourceFileName) + cmd = cString::sprintf("%s %s \"%s\" \"%s\"", command, State, *strescape(RecordingFileName, "\\\"$"), *strescape(SourceFileName, "\\\"$")); + else + cmd = cString::sprintf("%s %s \"%s\"", command, State, *strescape(RecordingFileName, "\\\"$")); + isyslog("executing '%s'", *cmd); + SystemExec(cmd); + } } // --- cIndexFileGenerator --------------------------------------------------- diff --git a/recording.h b/recording.h index 5f94ee2..56659ed 100644 --- a/recording.h +++ b/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 2.30 2012/03/13 12:41:05 kls Exp $ + * $Id: recording.h 2.33 2012/06/03 09:49:09 kls Exp $ */ #ifndef __RECORDING_H @@ -22,8 +22,6 @@ #define TIMERMACRO_TITLE "TITLE" #define TIMERMACRO_EPISODE "EPISODE" -//#define __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS // Code enclosed with this macro is deprecated and may be removed in a future version - extern bool VfatFileSystem; extern int InstanceId; @@ -93,6 +91,7 @@ private: int channel; int instanceId; bool isPesRecording; + mutable int isOnVideoDirectoryFileSystem; // -1 = unknown, 0 = no, 1 = yes double framesPerSecond; cRecordingInfo *info; cRecording(const cRecording&); // can't copy cRecording @@ -100,9 +99,6 @@ private: static char *StripEpisodeName(char *s); char *SortName(void) const; int GetResume(void) const; -#ifdef __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS -public: -#endif time_t start; int priority; int lifetime; @@ -135,6 +131,7 @@ public: bool IsNew(void) const { return GetResume() <= 0; } bool IsEdited(void) const; bool IsPesRecording(void) const { return isPesRecording; } + bool IsOnVideoDirectoryFileSystem(void) const; void ReadInfo(void); bool WriteInfo(void); void SetStartTime(time_t Start); @@ -208,9 +205,6 @@ class cMark : public cListObject { friend class cMarks; // for sorting private: double framesPerSecond; -#ifdef __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS -public: -#endif int position; cString comment; public: @@ -251,7 +245,7 @@ private: static const char *command; public: static void SetCommand(const char *Command) { command = Command; } - static void InvokeCommand(const char *State, const char *RecordingFileName); + static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName = NULL); }; // The maximum size of a single frame (up to HDTV 1920x1080): diff --git a/skinclassic.c b/skinclassic.c index 49f0bcb..64944de 100644 --- a/skinclassic.c +++ b/skinclassic.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: skinclassic.c 2.6 2011/08/21 11:02:06 kls Exp $ + * $Id: skinclassic.c 2.7 2012/04/23 08:48:03 kls Exp $ */ #include "skinclassic.h" @@ -12,6 +12,7 @@ #include "i18n.h" #include "osd.h" #include "themes.h" +#include "videodir.h" #define ScrollWidth (Setup.FontOsdSize / 4) #define TextFrame (Setup.FontOsdSize / 10) @@ -170,7 +171,10 @@ private: int y0, y1, y2, y3, y4, y5; int lineHeight; int dateWidth; + cString title; cString lastDate; + int lastDiskUsageState; + void DrawTitle(void); void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown); void SetTextScrollbar(void); public: @@ -196,6 +200,7 @@ cSkinClassicDisplayMenu::cSkinClassicDisplayMenu(void) { const cFont *font = cFont::GetFont(fontOsd); lineHeight = font->Height(); + lastDiskUsageState = -1; dateWidth = 0; x0 = 0; x1 = x0 + 2 * TextSpacing; @@ -270,10 +275,17 @@ void cSkinClassicDisplayMenu::Clear(void) osd->DrawRectangle(x0, y1, x3 - 1, y4 - 1, Theme.Color(clrBackground)); } -void cSkinClassicDisplayMenu::SetTitle(const char *Title) +void cSkinClassicDisplayMenu::DrawTitle(void) { const cFont *font = cFont::GetFont(fontOsd); - osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x3 - x0 - dateWidth); + bool WithDisk = MenuCategory() == mcMain || MenuCategory() == mcRecording; + osd->DrawText(x0, y0, WithDisk ? cString::sprintf("%s - %s", *title, *cVideoDiskUsage::String()) : title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x3 - x0 - dateWidth); +} + +void cSkinClassicDisplayMenu::SetTitle(const char *Title) +{ + title = Title; + DrawTitle(); } void cSkinClassicDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) @@ -422,6 +434,8 @@ const cFont *cSkinClassicDisplayMenu::GetTextAreaFont(bool FixedFont) const void cSkinClassicDisplayMenu::Flush(void) { + if (cVideoDiskUsage::HasChanged(lastDiskUsageState)) + DrawTitle(); cString date = DayDateTime(); if (!*lastDate || strcmp(date, lastDate)) { const cFont *font = cFont::GetFont(fontOsd); diff --git a/skinlcars.c b/skinlcars.c new file mode 100644 index 0000000..a602923 --- /dev/null +++ b/skinlcars.c @@ -0,0 +1,2114 @@ +/* + * skinlcars.c: A VDR skin with Star Trek's "LCARS" layout + * + * See the main source file 'vdr.c' for copyright information and + * how to reach the author. + * + * $Id: skinlcars.c 2.2 2012/06/03 10:17:00 kls Exp $ + */ + +// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures, +// registered in the United States Patent and Trademark Office, all rights reserved. +// The LCARS system is based upon the designs of Michael Okuda and his Okudagrams. +// +// "LCARS" is short for "Library Computer Access and Retrieval System". +// Some resources used for writing this skin can be found at +// http://www.lcars.org.uk +// http://www.lcarsdeveloper.com +// http://www.lcarscom.net +// http://lds-jedi.deviantart.com/art/LCARS-Swept-Tutorial-213936938 +// http://lds-jedi.deviantart.com/art/LCARS-Button-Tutorial-210783437 +// http://zelldenver.deviantart.com/art/LCARS-Color-Standard-179565780 +// http://www.lcars47.com +// http://www.bracercom.com/tutorial/content/CoherentLCARSInterface/LCARSCoherentInterface.html +// http://www.bracercom.com/tutorial/content/lcars_manifesto/the_lcars_manifesto.html + +#include "skinlcars.h" +#include "font.h" +#include "menu.h" +#include "osd.h" +#include "themes.h" +#include "videodir.h" + +#include "symbols/arrowdown.xpm" +#include "symbols/arrowup.xpm" +#include "symbols/audio.xpm" +#include "symbols/audioleft.xpm" +#include "symbols/audioright.xpm" +#include "symbols/audiostereo.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 Gap (Setup.FontOsdSize / 5 & ~1) // must be even +#define TextFrame (Setup.FontOsdSize / TEXT_ALIGN_BORDER) +#define TextSpacing (2 * TextFrame) +#define SymbolSpacing TextSpacing +#define ShowSeenExtent (Setup.FontOsdSize / 5) // pixels by which the "seen" bar extends out of the frame + +#define DISKUSAGEALERTLIMIT 95 // percent of disk usage above which the display goes into alert mode +#define SIGNALDISPLAYDELTA 2 // seconds between subsequent device signal displays + +static cTheme Theme; + +// Color domains: + +#define CLR_BACKGROUND 0x99000000 +#define CLR_MAIN_FRAME 0xFFF1DF6F +#define CLR_CHANNEL_FRAME 0xFFFFCC99 +#define CLR_REPLAY_FRAME 0xFFCC6666 +#define CLR_DATE 0xFF99CCFF +#define CLR_MENU_ITEMS 0xFFFFBC57 +#define CLR_TIMER 0xFF99CCFF +#define CLR_DEVICE 0xFFF1B1AF +#define CLR_CHANNEL_NAME 0xFF99CCFF +#define CLR_EVENT_TITLE 0xFF99CCFF +#define CLR_EVENT_TIME 0xFFFFCC66 +#define CLR_EVENT_SHORTTEXT 0xFFFFCC66 +#define CLR_TEXT 0xFF99CCFF +#define CLR_TRACK 0xFFFFCC66 +#define CLR_SEEN 0xFFCC99CC +#define CLR_ALERT 0xFFFF0000 +#define CLR_EXPOSED 0xFF990000 +#define CLR_WHITE 0xFFFFFFFF +#define CLR_RED 0xFFB20000 +#define CLR_GREEN 0xFF00B200 +#define CLR_YELLOW 0xFFB2B200 +#define CLR_BLUE 0xFF0000B2 +#define CLR_BLACK 0xFF000000 + +// General colors: + +THEME_CLR(Theme, clrBackground, CLR_BACKGROUND); +THEME_CLR(Theme, clrDateFg, CLR_BLACK); +THEME_CLR(Theme, clrDateBg, CLR_DATE); +THEME_CLR(Theme, clrTimerFg, CLR_BLACK); +THEME_CLR(Theme, clrTimerBg, CLR_TIMER); +THEME_CLR(Theme, clrDeviceFg, CLR_BLACK); +THEME_CLR(Theme, clrDeviceBg, CLR_DEVICE); +THEME_CLR(Theme, clrSignalValue, CLR_GREEN); +THEME_CLR(Theme, clrSignalRest, CLR_RED); +THEME_CLR(Theme, clrSeen, CLR_SEEN); +THEME_CLR(Theme, clrTrackName, CLR_TRACK); +THEME_CLR(Theme, clrAlertFg, CLR_WHITE); +THEME_CLR(Theme, clrAlertBg, CLR_ALERT); +THEME_CLR(Theme, clrChannelName, CLR_CHANNEL_NAME); +THEME_CLR(Theme, clrEventTitle, CLR_EVENT_TITLE); +THEME_CLR(Theme, clrEventTime, CLR_EVENT_TIME); +THEME_CLR(Theme, clrEventShortText, CLR_EVENT_SHORTTEXT); +THEME_CLR(Theme, clrEventDescription, CLR_TEXT); + +// Buttons: + +THEME_CLR(Theme, clrButtonRedFg, CLR_WHITE); +THEME_CLR(Theme, clrButtonRedBg, CLR_RED); +THEME_CLR(Theme, clrButtonGreenFg, CLR_BLACK); +THEME_CLR(Theme, clrButtonGreenBg, CLR_GREEN); +THEME_CLR(Theme, clrButtonYellowFg, CLR_BLACK); +THEME_CLR(Theme, clrButtonYellowBg, CLR_YELLOW); +THEME_CLR(Theme, clrButtonBlueFg, CLR_WHITE); +THEME_CLR(Theme, clrButtonBlueBg, CLR_BLUE); + +// Messages: + +THEME_CLR(Theme, clrMessageStatusFg, CLR_WHITE); +THEME_CLR(Theme, clrMessageStatusBg, CLR_BLUE); +THEME_CLR(Theme, clrMessageInfoFg, CLR_BLACK); +THEME_CLR(Theme, clrMessageInfoBg, CLR_GREEN); +THEME_CLR(Theme, clrMessageWarningFg, CLR_BLACK); +THEME_CLR(Theme, clrMessageWarningBg, CLR_YELLOW); +THEME_CLR(Theme, clrMessageErrorFg, CLR_WHITE); +THEME_CLR(Theme, clrMessageErrorBg, CLR_RED); + +// Volume: + +THEME_CLR(Theme, clrVolumeFrame, CLR_MAIN_FRAME); +THEME_CLR(Theme, clrVolumeSymbol, CLR_BLACK); +THEME_CLR(Theme, clrVolumeBarUpper, RgbShade(CLR_MAIN_FRAME, -0.2)); +THEME_CLR(Theme, clrVolumeBarLower, CLR_GREEN); + +// Channel display: + +THEME_CLR(Theme, clrChannelFrameFg, CLR_BLACK); +THEME_CLR(Theme, clrChannelFrameBg, CLR_CHANNEL_FRAME); +THEME_CLR(Theme, clrChannelSymbolOn, CLR_BLACK); +THEME_CLR(Theme, clrChannelSymbolOff, RgbShade(CLR_CHANNEL_FRAME, -0.2)); +THEME_CLR(Theme, clrChannelSymbolRecFg, CLR_WHITE); +THEME_CLR(Theme, clrChannelSymbolRecBg, CLR_RED); + +// Menu: + +THEME_CLR(Theme, clrMenuFrameFg, CLR_BLACK); +THEME_CLR(Theme, clrMenuFrameBg, CLR_MAIN_FRAME); +THEME_CLR(Theme, clrMenuTitle, CLR_MAIN_FRAME); +THEME_CLR(Theme, clrMenuMainBracket, CLR_MENU_ITEMS); +THEME_CLR(Theme, clrMenuTimerRecording, CLR_DEVICE); +THEME_CLR(Theme, clrMenuDeviceRecording, CLR_TIMER); +THEME_CLR(Theme, clrMenuItemCurrentFg, CLR_BLACK); +THEME_CLR(Theme, clrMenuItemCurrentBg, CLR_MENU_ITEMS); +THEME_CLR(Theme, clrMenuItemSelectable, CLR_MENU_ITEMS); +THEME_CLR(Theme, clrMenuItemNonSelectable, CLR_TEXT); +THEME_CLR(Theme, clrMenuScrollbarTotal, CLR_MENU_ITEMS); +THEME_CLR(Theme, clrMenuScrollbarShown, CLR_SEEN); +THEME_CLR(Theme, clrMenuScrollbarArrow, CLR_BLACK); +THEME_CLR(Theme, clrMenuText, CLR_TEXT); + +// Replay display: + +THEME_CLR(Theme, clrReplayFrameFg, CLR_BLACK); +THEME_CLR(Theme, clrReplayFrameBg, CLR_REPLAY_FRAME); +THEME_CLR(Theme, clrReplayPosition, CLR_SEEN); +THEME_CLR(Theme, clrReplayJumpFg, CLR_BLACK); +THEME_CLR(Theme, clrReplayJumpBg, CLR_SEEN); +THEME_CLR(Theme, clrReplayProgressSeen, CLR_SEEN); +THEME_CLR(Theme, clrReplayProgressRest, RgbShade(CLR_WHITE, -0.2)); +THEME_CLR(Theme, clrReplayProgressSelected, CLR_EXPOSED); +THEME_CLR(Theme, clrReplayProgressMark, CLR_BLACK); +THEME_CLR(Theme, clrReplayProgressCurrent, CLR_EXPOSED); + +// Track display: + +THEME_CLR(Theme, clrTrackFrameFg, CLR_BLACK); +THEME_CLR(Theme, clrTrackFrameBg, CLR_TRACK); +THEME_CLR(Theme, clrTrackItemFg, CLR_BLACK); +THEME_CLR(Theme, clrTrackItemBg, RgbShade(CLR_TRACK, 0.5)); +THEME_CLR(Theme, clrTrackItemCurrentFg, CLR_BLACK); +THEME_CLR(Theme, clrTrackItemCurrentBg, CLR_TRACK); + +// --- Helper functions ------------------------------------------------------ + +static cOsd *CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1) +{ + cOsd *Osd = cOsdProvider::NewOsd(Left, Top); + int Bpp[] = { 32, 8, 4, 2, 1 }; + tArea Area = { x0, y0, x1, y1, 0 }; + for (unsigned int i = 0; i < sizeof(Bpp) / sizeof(int); i++) { + Area.bpp = Bpp[i]; + if (Osd->CanHandleAreas(&Area, 1) == oeOk) { + Osd->SetAreas(&Area, 1); + break; + } + } + return Osd; +} + +static cFont *CreateTinyFont(int LineHeight) +{ + // Creates a font that is not higher than half of LineHeight. + LineHeight /= 2; + int Height = LineHeight; + for (;;) { + cFont *TinyFont = cFont::CreateFont(Setup.FontOsd, Height); + if (Height < 2 || TinyFont->Height() <= LineHeight) + return TinyFont; + delete TinyFont; + Height -= 1; + } +} + +static bool DrawDeviceData(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &xs, const cFont *TinyFont, cString &LastDeviceType, cCamSlot *&LastCamSlot, bool Initial) +{ + cString DeviceType = Device->DeviceType(); + cCamSlot *CamSlot = Device->CamSlot(); + if (Initial || strcmp(DeviceType, LastDeviceType) || CamSlot != LastCamSlot) { + const cFont *font = cFont::GetFont(fontOsd); + tColor ColorFg = Theme.Color(clrDeviceFg); + tColor ColorBg = Theme.Color(clrDeviceBg); + Osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, ColorBg); + int x = x0; + // Device number: + cString Nr = itoa(Device->DeviceNumber() + 1); + int w = max(font->Width(Nr), y1 - y0); + Osd->DrawText(x, y0, Nr, ColorFg, ColorBg, font, w, y1 - y0, taCenter); + x += w; + // Device type: + Osd->DrawText(x, y0, DeviceType, ColorFg, ColorBg, TinyFont); + xs = max(xs, x + TinyFont->Width(DeviceType)); + LastDeviceType = DeviceType; + // CAM: + if (CamSlot) { + cString s = cString::sprintf("CAM %d", CamSlot->SlotNumber()); + Osd->DrawText(x, y1 - TinyFont->Height(), s, ColorFg, ColorBg, TinyFont); + xs = max(xs, x + TinyFont->Width(s)); + } + LastCamSlot = CamSlot; + return true; + } + return false; +} + +static void DrawDeviceSignal(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &LastSignalStrength, int &LastSignalQuality, bool Initial) +{ + int SignalStrength = Device->SignalStrength(); + int SignalQuality = Device->SignalQuality(); + int d = max((y1 - y0) / 10, 1); + int x00 = x0 + d; + int x01 = x1 - d; + int h = (y1 - y0 - 3 * d) / 2; + int w = x01 - x00; + int y00 = y0 + d; + int y01 = y00 + h; + int y03 = y1 - d; + int y02 = y03 - h; + if (SignalStrength >= 0 && (Initial || SignalStrength != LastSignalStrength)) { + int s = SignalStrength * w / 100; + Osd->DrawRectangle(x00, y00, x00 + s - 1, y01 - 1, Theme.Color(clrSignalValue)); + Osd->DrawRectangle(x00 + s, y00, x01 - 1, y01 - 1, Theme.Color(clrSignalRest)); + LastSignalStrength = SignalStrength; + } + if (SignalQuality >= 0 && (Initial || SignalQuality != LastSignalQuality)) { + int q = SignalQuality * w / 100; + Osd->DrawRectangle(x00, y02, x00 + q - 1, y03 - 1, Theme.Color(clrSignalValue)); + Osd->DrawRectangle(x00 + q, y02, x01 - 1, y03 - 1, Theme.Color(clrSignalRest)); + LastSignalQuality = SignalQuality; + } +} + +// --- cSkinLCARSDisplayChannel ---------------------------------------------- + +class cSkinLCARSDisplayChannel : public cSkinDisplayChannel { +private: + cOsd *osd; + int xc00, xc01, xc02, xc03, xc04, xc05, xc06, xc07, xc08, xc09, xc10, xc11, xc12, xc13, xc14, xc15; + int yc00, yc01, yc02, yc03, yc04, yc05, yc06, yc07, yc08, yc09, yc10, yc11, yc12; + int xs; // starting column for signal display + bool withInfo; + int lineHeight; + cFont *tinyFont; + cFont *tallFont; + tColor frameColor; + bool message; + const cEvent *present; + bool initial; + cString lastDate; + int lastSeen; + int lastDeviceNumber; + cString lastDeviceType; + cCamSlot *lastCamSlot; + int lastSignalStrength; + int lastSignalQuality; + time_t lastSignalDisplay; + tTrackId lastTrackId; + static cBitmap bmTeletext, bmRadio, bmAudio, bmDolbyDigital, bmEncrypted, bmRecording; + void DrawDate(void); + void DrawTrack(void); + void DrawSeen(int Current, int Total); + void DrawDevice(void); + void DrawSignal(void); +public: + cSkinLCARSDisplayChannel(bool WithInfo); + virtual ~cSkinLCARSDisplayChannel(); + virtual void SetChannel(const cChannel *Channel, int Number); + virtual void SetEvents(const cEvent *Present, const cEvent *Following); + virtual void SetMessage(eMessageType Type, const char *Text); + virtual void Flush(void); + }; + +cBitmap cSkinLCARSDisplayChannel::bmTeletext(teletext_xpm); +cBitmap cSkinLCARSDisplayChannel::bmRadio(radio_xpm); +cBitmap cSkinLCARSDisplayChannel::bmAudio(audio_xpm); +cBitmap cSkinLCARSDisplayChannel::bmDolbyDigital(dolbydigital_xpm); +cBitmap cSkinLCARSDisplayChannel::bmEncrypted(encrypted_xpm); +cBitmap cSkinLCARSDisplayChannel::bmRecording(recording_xpm); + +cSkinLCARSDisplayChannel::cSkinLCARSDisplayChannel(bool WithInfo) +{ + tallFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize * 1.8); + initial = true; + present = NULL; + lastSeen = -1; + lastDeviceNumber = -1; + lastCamSlot = NULL; + lastSignalStrength = -1; + lastSignalQuality = -1; + lastSignalDisplay = 0; + memset(&lastTrackId, 0, sizeof(lastTrackId)); + const cFont *font = cFont::GetFont(fontOsd); + withInfo = WithInfo; + lineHeight = font->Height(); + tinyFont = CreateTinyFont(lineHeight); + frameColor = Theme.Color(clrChannelFrameBg); + message = false; + int d = 5 * lineHeight; + xc00 = 0; + xc01 = xc00 + d / 2; + xc02 = xc00 + d; + xc03 = xc02 + lineHeight; + xc04 = xc02 + d / 4; + xc05 = xc02 + d; + xc06 = xc05 + Gap; + xc15 = cOsd::OsdWidth(); + xc14 = xc15 - lineHeight; + xc13 = xc14 - Gap; + xc07 = (xc15 + xc00) / 2; + xc08 = xc07 + Gap; + xc09 = xc08 + lineHeight; + xc10 = xc09 + Gap; + xc11 = (xc10 + xc13 + Gap) / 2; + xc12 = xc11 + Gap; + + yc00 = 0; + yc01 = yc00 + lineHeight; + yc02 = yc01 + lineHeight; + yc03 = yc02 + Gap; + yc04 = yc03 + 2 * lineHeight; + yc05 = yc04 + Gap; + yc06 = yc05 + 2 * lineHeight; + + yc07 = yc06 + Gap; + yc12 = yc07 + 3 * lineHeight + Gap / 2; + yc11 = yc12 - lineHeight; + yc10 = yc11 - lineHeight; + yc09 = yc11 - d / 4; + yc08 = yc12 - d / 2; + + xs = 0; + + int y1 = withInfo ? yc12 : yc02; + int y0 = cOsd::OsdTop() + (Setup.ChannelInfoPos ? 0 : cOsd::OsdHeight() - y1); + osd = CreateOsd(cOsd::OsdLeft(), y0, xc00, yc00, xc15 - 1, y1 - 1); + osd->DrawRectangle(xc00, yc00, xc15 - 1, y1 - 1, Theme.Color(clrBackground)); + // Rectangles: + osd->DrawRectangle(xc00, yc00, xc02 - 1, yc02 - 1, frameColor); + if (withInfo) { + osd->DrawRectangle(xc00, yc03, xc02 - 1, yc04 - 1, frameColor); + osd->DrawRectangle(xc00, yc05, xc02 - 1, yc06 - 1, frameColor); + // Elbow: + osd->DrawRectangle(xc00, yc07, xc01 - 1, yc08 - 1, frameColor); + osd->DrawRectangle(xc00, yc08, xc01 - 1, yc12 - 1, clrTransparent); + osd->DrawEllipse (xc00, yc08, xc01 - 1, yc12 - 1, frameColor, 3); + osd->DrawRectangle(xc01, yc07, xc02 - 1, yc12 - 1, frameColor); + osd->DrawEllipse (xc02, yc09, xc04 - 1, yc11 - 1, frameColor, -3); + osd->DrawRectangle(xc02, yc11, xc05 - 1, yc12 - 1, frameColor); + // Status area: + osd->DrawRectangle(xc06, yc11 + lineHeight / 2, xc07 - 1, yc12 - 1, frameColor); + osd->DrawRectangle(xc08, yc11, xc09 - 1, yc12 - 1, frameColor); + osd->DrawRectangle(xc10, yc11, xc11 - 1, yc12 - 1, Theme.Color(clrDeviceBg)); + osd->DrawRectangle(xc12, yc11, xc13 - 1, yc12 - 1, Theme.Color(clrDateBg)); + osd->DrawRectangle(xc14, yc11, xc14 + lineHeight / 2 - 1, yc12 - 1, frameColor); + osd->DrawRectangle(xc14 + lineHeight / 2, yc11 + lineHeight / 2, xc15 - 1, yc12 - 1, clrTransparent); + osd->DrawEllipse (xc14 + lineHeight / 2, yc11, xc15 - 1, yc12 - 1, frameColor, 5); + } + // Icons: + osd->DrawRectangle(xc14, yc00, xc14 + lineHeight / 2 - 1, yc01 - 1, frameColor); + osd->DrawRectangle(xc14 + lineHeight / 2, yc00, xc15 - 1, yc00 + lineHeight / 2 - 1, clrTransparent); + osd->DrawEllipse (xc14 + lineHeight / 2, yc00, xc15 - 1, yc01 - 1, frameColor, 5); +} + +cSkinLCARSDisplayChannel::~cSkinLCARSDisplayChannel() +{ + delete tallFont; + delete tinyFont; + delete osd; +} + +void cSkinLCARSDisplayChannel::DrawDate(void) +{ + cString s = DayDateTime(); + if (initial || strcmp(s, lastDate)) { + osd->DrawText(xc12, yc11, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xc13 - xc12, lineHeight, taRight | taBorder); + lastDate = s; + } +} + +void cSkinLCARSDisplayChannel::DrawTrack(void) +{ + cDevice *Device = cDevice::PrimaryDevice(); + const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack()); + if (!Track && *lastTrackId.description || Track && strcmp(lastTrackId.description, Track->description)) { + osd->DrawText(xc03, yc07, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc07 - xc03); + strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description)); + } +} + +void cSkinLCARSDisplayChannel::DrawSeen(int Current, int Total) +{ + int Seen = min(xc07 - xc06, int((xc07 - xc06) * double(Current) / Total)); + if (initial || Seen != lastSeen) { + int y0 = yc11 - ShowSeenExtent; + int y1 = yc11 + lineHeight / 2 - Gap / 2; + osd->DrawRectangle(xc06, y0, xc06 + Seen - 1, y1 - 1, Theme.Color(clrSeen)); + osd->DrawRectangle(xc06 + Seen, y0, xc07 - 1, y1 - 1, Theme.Color(clrBackground)); + lastSeen = Seen; + } +} + +void cSkinLCARSDisplayChannel::DrawDevice(void) +{ + const cDevice *Device = cDevice::ActualDevice(); + if (DrawDeviceData(osd, Device, xc10, yc11, xc11, yc12, xs, tinyFont, lastDeviceType, lastCamSlot, Device->DeviceNumber() != lastDeviceNumber)) { + lastDeviceNumber = Device->DeviceNumber(); + // Make sure signal meters are redrawn: + lastSignalStrength = -1; + lastSignalQuality = -1; + lastSignalDisplay = 0; + } +} + +void cSkinLCARSDisplayChannel::DrawSignal(void) +{ + time_t Now = time(NULL); + if (Now != lastSignalDisplay) { + DrawDeviceSignal(osd, cDevice::ActualDevice(), xs + lineHeight / 2, yc11, xc11, yc12, lastSignalStrength, lastSignalQuality, initial); + lastSignalDisplay = Now; + } +} + +void cSkinLCARSDisplayChannel::SetChannel(const cChannel *Channel, int Number) +{ + int x = xc13; + int xi = x - SymbolSpacing - + bmRecording.Width() - SymbolSpacing - + bmEncrypted.Width() - SymbolSpacing - + bmDolbyDigital.Width() - SymbolSpacing - + bmAudio.Width() - SymbolSpacing - + max(bmTeletext.Width(), bmRadio.Width()) - SymbolSpacing; + osd->DrawRectangle(xi, yc00, xc13 - 1, yc01 - 1, frameColor); + if (Channel && !Channel->GroupSep()) { + bool rec = cRecordControls::Active(); + x -= bmRecording.Width() + SymbolSpacing; + osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : frameColor); + x -= bmEncrypted.Width() + SymbolSpacing; + osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmEncrypted.Height()) / 2, bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor); + x -= bmDolbyDigital.Width() + SymbolSpacing; + osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmDolbyDigital.Height()) / 2, bmDolbyDigital, Theme.Color(Channel->Dpid(0) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor); + x -= bmAudio.Width() + SymbolSpacing; + osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmAudio.Height()) / 2, bmAudio, Theme.Color(Channel->Apid(1) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor); + if (Channel->Vpid()) { + x -= bmTeletext.Width() + SymbolSpacing; + osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor); + } + else if (Channel->Apid(0)) { + x -= bmRadio.Width() + SymbolSpacing; + osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor); + } + } + cString ChNumber(""); + cString ChName(""); + if (Channel) { + ChName = Channel->Name(); + if (!Channel->GroupSep()) + ChNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : ""); + } + else if (Number) + ChNumber = cString::sprintf("%d-", Number); + else + ChName = ChannelString(NULL, NULL); + osd->DrawText(xc00, yc00, ChNumber, Theme.Color(clrChannelFrameFg), frameColor, tallFont, xc02 - xc00, yc02 - yc00, taTop | taRight | taBorder); + osd->DrawText(xc03, yc00, ChName, Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xi - xc03 - lineHeight, 0, taTop | taLeft); + lastSignalDisplay = 0; + if (withInfo) + DrawDevice(); +} + +void cSkinLCARSDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following) +{ + if (!withInfo) + return; + if (present != Present) + lastSeen = -1; + present = Present; + for (int i = 0; i < 2; i++) { + const cEvent *e = !i ? Present : Following; + int y = !i ? yc03 : yc05; + if (e) { + osd->DrawText(xc00, y, e->GetTimeString(), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - xc00, 0, taRight | taBorder); + osd->DrawText(xc03, y, e->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc13 - xc03); + osd->DrawText(xc03, y + lineHeight, e->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xc13 - xc03); + } + else { + osd->DrawRectangle(xc00, y, xc02 - 1, y + lineHeight, frameColor); + osd->DrawRectangle(xc02, y, xc13 - 1, y + 2 * lineHeight, Theme.Color(clrBackground)); + } + } +} + +void cSkinLCARSDisplayChannel::SetMessage(eMessageType Type, const char *Text) +{ + if (Text) { + int y0 = yc11 - ShowSeenExtent; + int y1 = yc11; + osd->SaveRegion(xc06, y0, xc13 - 1, yc12 - 1); + osd->DrawRectangle(xc06, y0, xc07, y1 - 1, Theme.Color(clrBackground)); // clears the "seen" bar + osd->DrawText(xc06, yc11, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xc13 - xc06, yc12 - yc11, taCenter); + } + else + osd->RestoreRegion(); +} + +void cSkinLCARSDisplayChannel::Flush(void) +{ + if (withInfo) { + if (!message) { + DrawDate(); + DrawTrack(); + DrawDevice(); + DrawSignal(); + } + int Current = 0; + int Total = 0; + if (present) { + time_t t = time(NULL); + if (t > present->StartTime()) + Current = t - present->StartTime(); + Total = present->Duration(); + } + DrawSeen(Current, Total); + } + osd->Flush(); + initial = false; +} + +// --- cSkinLCARSDisplayMenu ------------------------------------------------- + +class cSkinLCARSDisplayMenu : public cSkinDisplayMenu { +private: + cOsd *osd; + int xa00, xa01, xa02, xa03, xa04, xa05, xa06, xa07, xa08, xa09; + int yt00, yt01, yt02, yt03, yt04, yt05, yt06; + int yc00, yc01, yc02, yc03, yc04, yc05, yc06, yc07, yc08, yc09, yc10, yc11; + int yb00, yb01, yb02, yb03, yb04, yb05, yb06, yb07, yb08, yb09, yb10, yb11, yb12, yb13, yb14, yb15; + int xm00, xm01, xm02, xm03, xm04, xm05, xm06, xm07, xm08; + int ym00, ym01, ym02, ym03, ym04, ym05, ym06, ym07; + int xs00, xs01, xs02, xs03, xs04, xs05, xs06, xs07, xs08, xs09, xs10, xs11, xs12, xs13; + int ys00, ys01, ys02, ys03, ys04, ys05; + int xi00, xi01, xi02, xi03; + int yi00, yi01; + int xb00, xb01, xb02, xb03, xb04, xb05, xb06, xb07, xb08, xb09, xb10, xb11, xb12, xb13, xb14, xb15; + int xd00, xd01, xd02, xd03, xd04, xd05, xd06, xd07; + int yd00, yd01, yd02, yd03, yd04, yd05; + int xs; // starting column for signal display + int lineHeight; + cFont *tinyFont; + cFont *tallFont; + tColor frameColor; + int currentIndex; + cVector deviceOffset; + cVector deviceRecording; + cString lastDeviceType[MAXDEVICES]; + cVector lastCamSlot; + cVector lastSignalStrength; + cVector lastSignalQuality; + bool initial; + enum eCurrentMode { cmUnknown, cmLive, cmPlay }; + eCurrentMode lastMode; + cString lastDate; + int lastDiskUsageState; + bool lastDiskAlert; + double lastSystemLoad; + int lastTimersState; + time_t lastSignalDisplay; + int lastLiveIndicatorY; + bool lastLiveIndicatorTransferring; + const cChannel *lastChannel; + const cEvent *lastEvent; + const cRecording *lastRecording; + cString lastHeader; + int lastSeen; + static cBitmap bmArrowUp, bmArrowDown, bmTransferMode; + void DrawMainFrameUpper(tColor Color); + void DrawMainFrameLower(void); + void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font); + void DrawMenuFrame(void); + void DrawMainBracket(void); + void DrawStatusElbows(void); + void DrawDate(void); + void DrawDisk(void); + void DrawLoad(void); + void DrawFrameDisplay(void); + void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown); + void DrawTimer(const cTimer *Timer, int y, bool MultiRec); + void DrawTimers(void); + void DrawDevice(const cDevice *Device); + void DrawDevices(void); + void DrawLiveIndicator(void); + void DrawSignals(void); + void DrawLive(const cChannel *Channel); + void DrawPlay(cControl *Control); + void DrawInfo(const cEvent *Event, bool WithTime); + void DrawSeen(int Current, int Total); + void DrawTextScrollbar(void); +public: + cSkinLCARSDisplayMenu(void); + virtual ~cSkinLCARSDisplayMenu(); + virtual void Scroll(bool Up, bool Page); + virtual int MaxItems(void); + virtual void Clear(void); + virtual void SetMenuCategory(eMenuCategory MenuCategory); + 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 SetScrollbar(int Total, int Offset); + virtual void SetEvent(const cEvent *Event); + virtual void SetRecording(const cRecording *Recording); + virtual void SetText(const char *Text, bool FixedFont); + virtual int GetTextAreaWidth(void) const; + virtual const cFont *GetTextAreaFont(bool FixedFont) const; + virtual void Flush(void); + }; + +cBitmap cSkinLCARSDisplayMenu::bmArrowUp(arrowup_xpm); +cBitmap cSkinLCARSDisplayMenu::bmArrowDown(arrowdown_xpm); +cBitmap cSkinLCARSDisplayMenu::bmTransferMode(play_xpm); + +cSkinLCARSDisplayMenu::cSkinLCARSDisplayMenu(void) +{ + tallFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize * 1.8); + initial = true; + lastMode = cmUnknown; + lastChannel = NULL; + lastEvent = NULL; + lastRecording = NULL; + lastSeen = -1; + lastTimersState = -1; + lastSignalDisplay = 0; + lastLiveIndicatorY = -1; + lastLiveIndicatorTransferring = false; + lastDiskUsageState = -1; + lastDiskAlert = false; + lastSystemLoad = -1; + const cFont *font = cFont::GetFont(fontOsd); + lineHeight = font->Height(); + tinyFont = CreateTinyFont(lineHeight); + frameColor = Theme.Color(clrMenuFrameBg); + currentIndex = -1; + // The outer frame: + int d = 5 * lineHeight; + xa00 = 0; + xa01 = xa00 + d / 2; + xa02 = xa00 + d; + xa03 = xa02 + lineHeight; + xa04 = xa02 + d / 4; + xa05 = xa02 + d; + xa06 = xa05 + Gap; + xa09 = cOsd::OsdWidth(); + xa08 = xa09 - lineHeight; + xa07 = xa08 - Gap; + + yt00 = 0; + yt01 = yt00 + lineHeight; + yt02 = yt01 + lineHeight; + yt03 = yt01 + d / 4; + yt04 = yt02 + Gap; + yt05 = yt00 + d / 2; + yt06 = yt04 + 2 * lineHeight; + + yc00 = yt06 + Gap; + yc05 = yc00 + 3 * lineHeight + Gap / 2; + yc04 = yc05 - lineHeight; + yc03 = yc04 - lineHeight; + yc02 = yc04 - d / 4; + yc01 = yc05 - d / 2; + + yc06 = yc05 + Gap; + yc07 = yc06 + lineHeight; + yc08 = yc07 + lineHeight; + yc09 = yc07 + d / 4; + yc10 = yc06 + d / 2; + yc11 = yc06 + 3 * lineHeight + Gap / 2; + + yb00 = yc11 + Gap; + yb01 = yb00 + 2 * lineHeight; + yb02 = yb01 + Gap; + yb03 = yb02 + 2 * lineHeight; + yb04 = yb03 + Gap; + yb05 = yb04 + 2 * lineHeight; + yb06 = yb05 + Gap; + yb07 = yb06 + 2 * lineHeight; + yb08 = yb07 + Gap; + + yb15 = cOsd::OsdHeight(); + yb14 = yb15 - lineHeight; + yb13 = yb14 - lineHeight; + yb12 = yb14 - d / 4; + yb11 = yb15 - d / 2; + yb10 = yb13 - Gap - 2 * lineHeight; + yb09 = yb10 - Gap; + + // Compensate for large font size: + if (yb09 - yb08 < 2 * lineHeight) { + yb08 = yb06; + yb06 = 0; // drop empty rectangle + } + if (yb09 - yb08 < 2 * lineHeight) { + yb05 = yb09; + yb08 = 0; // drop "LCARS" display + } + if (yb05 - yb04 < 2 * lineHeight) { + yb03 = yb09; + yb04 = 0; // drop "LOAD" display + } + if (yb03 - yb02 < 2 * lineHeight) { + yb01 = yb09; + yb02 = 0; // drop "DISK" display + } + // Anything else is just insanely large... + + // The main command menu: + xm00 = xa03; + xm01 = xa05; + xm02 = xa06; + xm08 = (xa09 + xa00) / 2; + xm07 = xm08 - lineHeight; + xm06 = xm07 - lineHeight / 2; + xm05 = xm06 - lineHeight / 2; + xm04 = xm05 - lineHeight; + xm03 = xm04 - Gap; + ym00 = yc08; + ym01 = ym00 + lineHeight / 2; + ym02 = ym01 + lineHeight / 2; + ym03 = ym02 + Gap; + ym07 = yb15; + ym06 = ym07 - lineHeight / 2; + ym05 = ym06 - lineHeight / 2; + ym04 = ym05 - Gap; + + // The status area: + xs00 = xm08 + Gap + lineHeight + Gap; + xs13 = xa09; + xs12 = xa08; + xs11 = xa07; + xs05 = (xs00 + xs11 + Gap) / 2; + xs04 = xs05 - lineHeight / 2; + xs03 = xs04 - lineHeight / 2; + xs02 = xs03 - 2 * lineHeight; + xs01 = xs02 - Gap; + xs06 = xs05 + Gap; + xs07 = xs06 + lineHeight / 2; + xs08 = xs07 + lineHeight / 2; + xs09 = xs08 + 2 * lineHeight; + xs10 = xs09 + Gap; + ys00 = yc06; + ys01 = ys00 + lineHeight; + ys02 = ys01 + lineHeight / 2; + ys04 = ys01 + lineHeight; + ys03 = ys04 - Gap; + ys05 = yb15; + + // The color buttons in submenus: + xb00 = xa06; + xb15 = xa07; + int w = (xa08 - xa06) / 4; + xb01 = xb00 + lineHeight / 2; + xb02 = xb01 + Gap; + xb04 = xb00 + w; + xb03 = xb04 - Gap; + xb05 = xb04 + lineHeight / 2; + xb06 = xb05 + Gap; + xb08 = xb04 + w; + xb07 = xb08 - Gap; + xb09 = xb08 + lineHeight / 2; + xb10 = xb09 + Gap; + xb12 = xb08 + w; + xb11 = xb12 - Gap; + xb13 = xb12 + lineHeight / 2; + xb14 = xb13 + Gap;; + + // The color buttons in the main menu: + int r = lineHeight; + xd07 = xa09; + xd06 = xd07 - r; + xd05 = xd06 - 4 * r; + xd04 = xd05 - r; + xd03 = xd04 - Gap; + xd02 = xd03 - r; + xd01 = xd02 - 4 * r; + xd00 = xd01 - r; + yd00 = yt00; + yd05 = yc04 - Gap; + yd04 = yd05 - 2 * r; + yd03 = yd04 - Gap; + yd02 = yd03 - 2 * r; + yd01 = yd02 - Gap; + + xs = 0; + + osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop(), xa00, yt00, xa09 - 1, yb15 - 1); +} + +cSkinLCARSDisplayMenu::~cSkinLCARSDisplayMenu() +{ + delete tallFont; + delete tinyFont; + delete osd; +} + +void cSkinLCARSDisplayMenu::SetMenuCategory(eMenuCategory MenuCategory) +{ + if (initial || MenuCategory != cSkinDisplayMenu::MenuCategory()) { + cSkinDisplayMenu::SetMenuCategory(MenuCategory); + initial = true; + osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, Theme.Color(clrBackground)); + if (MenuCategory == mcMain) { + yi00 = ym03; + yi01 = ym04; + xi00 = xm00; + xi01 = xm03; + xi02 = xm04; + xi03 = xm05; + lastTimersState = -1; + DrawMainFrameLower(); + DrawMainBracket(); + DrawStatusElbows(); + } + else { + yi00 = yt02; + yi01 = yb13; + xi00 = xa03; + xi01 = xa07; + xi02 = xa08; + xi03 = xa09; + DrawMenuFrame(); + } + } +} + +void cSkinLCARSDisplayMenu::DrawMainFrameUpper(tColor Color) +{ + // Top left rectangles: + osd->DrawRectangle(xa00, yt00, xa02 - 1, yt02 - 1, Color); + osd->DrawRectangle(xa00, yt04, xa02 - 1, yt06 - 1, Color); + // Upper elbow: + osd->DrawRectangle(xa00, yc00, xa01 - 1, yc01 - 1, Color); + osd->DrawEllipse (xa00, yc01, xa01 - 1, yc05 - 1, Color, 3); + osd->DrawRectangle(xa01, yc00, xa02 - 1, yc05 - 1, Color); + osd->DrawEllipse (xa02, yc02, xa04 - 1, yc04 - 1, Color, -3); + osd->DrawRectangle(xa02, yc04, xa05 - 1, yc05 - 1, Color); + // Upper delimiter: + osd->DrawRectangle(xa06, yc04 + lineHeight / 2, xm08 - 1, yc05 - 1, Color); + osd->DrawRectangle(xm08 + Gap, yc04, xs00 - Gap - 1, yc05 - 1, Color); + osd->DrawRectangle(xs00, yc04, xs05 - 1, yc05 - 1, Color); + osd->DrawRectangle(xs06, yc04, xa07 - 1, yc05 - 1, Color); + osd->DrawRectangle(xa08, yc04, xa09 - 1, yc05 - 1, Color); +} + +void cSkinLCARSDisplayMenu::DrawMainFrameLower(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + // Lower elbow: + osd->DrawRectangle(xa00, yc10, xa01 - 1, yc11 - 1, frameColor); + osd->DrawEllipse (xa00, yc06, xa01 - 1, yc10 - 1, frameColor, 2); + osd->DrawRectangle(xa01, yc06, xa02 - 1, yc11 - 1, frameColor); + osd->DrawEllipse (xa02, yc07, xa04 - 1, yc09 - 1, frameColor, -2); + osd->DrawRectangle(xa02, yc06, xa05 - 1, yc07 - 1, frameColor); + // Lower delimiter: + osd->DrawRectangle(xa06, yc06, xm08 - 1, yc07 - lineHeight / 2 - 1, frameColor); + osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor); + osd->DrawRectangle(xa08, yc06, xa09 - 1, yc07 - 1, frameColor); + // VDR version: + osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor); + osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); + osd->DrawText(xa00, yb15 - lineHeight, VDRVERSION, Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); +} + +void cSkinLCARSDisplayMenu::DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font) +{ + int h = y1 - y0; + osd->DrawEllipse(x0, y0, x1 - 1, y1 - 1, ColorBg, 7); + osd->DrawText(x1 + Gap, y0, Text, ColorFg, ColorBg, Font, x2 - x1 - Gap, h, taBottom | taRight); + osd->DrawEllipse(x2, y0, x3 - 1, y1 - 1, ColorBg, 5); +} + +void cSkinLCARSDisplayMenu::DrawMenuFrame(void) +{ + // Upper elbow: + osd->DrawRectangle(xa00, yt05, xa01 - 1, yt06 - 1, frameColor); + osd->DrawRectangle(xa00, yt00, xa01 - 1, yt05 - 1, clrTransparent); + osd->DrawEllipse (xa00, yt00, xa01 - 1, yt05 - 1, frameColor, 2); + osd->DrawRectangle(xa01, yt00, xa02 - 1, yt06 - 1, frameColor); + osd->DrawEllipse (xa02, yt01, xa04 - 1, yt03 - 1, frameColor, -2); + osd->DrawRectangle(xa02, yt00, xa05 - 1, yt01 - 1, frameColor); + osd->DrawRectangle(xa06, yt00, xa07 - 1, yt01 - 1, frameColor); + osd->DrawRectangle(xa08, yt00, xa08 + lineHeight / 2 - 1, yt01 - 1, frameColor); + osd->DrawRectangle(xa08 + lineHeight / 2, yt00, xa09 - 1, yt00 + lineHeight / 2 - 1, clrTransparent); + osd->DrawEllipse (xa08 + lineHeight / 2, yt00, xa09 - 1, yt01 - 1, frameColor, 5); + // Center part: + osd->DrawRectangle(xa00, yc00, xa02 - 1, yc11 - 1, frameColor); + // Lower elbow: + osd->DrawRectangle(xa00, yb10, xa02 - 1, yb11 - 1, frameColor); + osd->DrawRectangle(xa00, yb11, xa01 - 1, yb15 - 1, clrTransparent); + osd->DrawEllipse (xa00, yb11, xa01 - 1, yb15 - 1, frameColor, 3); + osd->DrawRectangle(xa01, yb11, xa02 - 1, yb15 - 1, frameColor); + osd->DrawEllipse (xa02, yb12, xa04 - 1, yb14 - 1, frameColor, -3); + osd->DrawRectangle(xa02, yb14, xa05 - 1, yb15 - 1, frameColor); + osd->DrawRectangle(xa08, yb14, xa08 + lineHeight / 2 - 1, yb15 - 1, frameColor); + osd->DrawRectangle(xa08 + lineHeight / 2, yb14 + lineHeight / 2, xa09 - 1, yb15 - 1, clrTransparent); + osd->DrawEllipse (xa08 + lineHeight / 2, yb14, xa09 - 1, yb15 - 1, frameColor, 5); + osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); + // Color buttons: + osd->DrawRectangle(xb00, yb14, xb01 - 1, yb15 - 1, Theme.Color(clrButtonRedBg)); + osd->DrawRectangle(xb04, yb14, xb05 - 1, yb15 - 1, Theme.Color(clrButtonGreenBg)); + osd->DrawRectangle(xb08, yb14, xb09 - 1, yb15 - 1, Theme.Color(clrButtonYellowBg)); + osd->DrawRectangle(xb12, yb14, xb13 - 1, yb15 - 1, Theme.Color(clrButtonBlueBg)); +} + +void cSkinLCARSDisplayMenu::DrawDate(void) +{ + cString s = DayDateTime(); + if (initial || strcmp(s, lastDate)) { + const cFont *font = cFont::GetFont(fontOsd); + tColor ColorFg = Theme.Color(clrDateFg); + tColor ColorBg = Theme.Color(clrDateBg); + lastDate = s; + const char *t = strrchr(s, ' '); + osd->DrawText(xa00, yb01 - lineHeight, t, ColorFg, ColorBg, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + s.Truncate(t - s); + osd->DrawText(xa00, yb00, s, ColorFg, ColorBg, font, xa02 - xa00, yb01 - yb00 - lineHeight, taTop | taRight | taBorder); + } +} + +void cSkinLCARSDisplayMenu::DrawDisk(void) +{ + if (yb02) { + if (cVideoDiskUsage::HasChanged(lastDiskUsageState) || initial) { // must call HasChanged() first, or it shows an outdated value in the 'initial' case! + const cFont *font = cFont::GetFont(fontOsd); + int DiskUsage = cVideoDiskUsage::UsedPercent(); + bool DiskAlert = DiskUsage > DISKUSAGEALERTLIMIT; + tColor ColorFg = DiskAlert ? Theme.Color(clrAlertFg) : Theme.Color(clrMenuFrameFg); + tColor ColorBg = DiskAlert ? Theme.Color(clrAlertBg) : frameColor; + if (initial || DiskAlert != lastDiskAlert) + osd->DrawText(xa00, yb02, tr("DISK"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb03 - yb02, taTop | taLeft | taBorder); + osd->DrawText(xa01, yb02, itoa(DiskUsage), ColorFg, ColorBg, font, xa02 - xa01, lineHeight, taBottom | taRight | taBorder); + osd->DrawText(xa00, yb03 - lineHeight, cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60), ColorFg, ColorBg, font, xa02 - xa00, 0, taBottom | taRight | taBorder); + lastDiskAlert = DiskAlert; + } + } +} + +void cSkinLCARSDisplayMenu::DrawLoad(void) +{ + if (yb04) { + tColor ColorFg = Theme.Color(clrMenuFrameFg); + tColor ColorBg = frameColor; + if (initial) + osd->DrawText(xa00, yb04, tr("LOAD"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb05 - yb04, taTop | taLeft | taBorder); + double SystemLoad; + if (getloadavg(&SystemLoad, 1) > 0) { + if (initial || SystemLoad != lastSystemLoad) { + osd->DrawText(xa00, yb05 - lineHeight, cString::sprintf("%.1f", SystemLoad), ColorFg, ColorBg, cFont::GetFont(fontOsd), xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + lastSystemLoad = SystemLoad; + } + } + } +} + +void cSkinLCARSDisplayMenu::DrawMainBracket(void) +{ + tColor Color = Theme.Color(clrMenuMainBracket); + osd->DrawRectangle(xm00, ym00, xm01 - 1, ym01 - 1, Color); + osd->DrawRectangle(xm02, ym00, xm07 - 1, ym01 - 1, Color); + osd->DrawEllipse (xm07, ym00, xm08 - 1, ym02 - 1, Color, 1); + osd->DrawEllipse (xm06, ym01, xm07 - 1, ym02 - 1, Color, -1); + osd->DrawRectangle(xm07, ym03, xm08 - 1, ym04 - 1, Color); + osd->DrawEllipse (xm06, ym05, xm07 - 1, ym06 - 1, Color, -4); + osd->DrawEllipse (xm07, ym05, xm08 - 1, ym07 - 1, Color, 4); + osd->DrawRectangle(xm02, ym06, xm07 - 1, ym07 - 1, Color); + osd->DrawRectangle(xm00, ym06, xm01 - 1, ym07 - 1, Color); +} + +void cSkinLCARSDisplayMenu::DrawStatusElbows(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + osd->DrawText (xs00, ys00, tr("TIMERS"), Theme.Color(clrMenuFrameFg), frameColor, font, xs01 - xs00, lineHeight, taBottom | taLeft | taBorder); + osd->DrawRectangle(xs02, ys00, xs03 - 1, ys01 - 1, frameColor); + osd->DrawEllipse (xs03, ys00, xs05 - 1, ys01 - 1, frameColor, 1); + osd->DrawEllipse (xs03, ys01, xs04 - 1, ys02 - 1, frameColor, -1); + osd->DrawRectangle(xs04, ys01, xs05 - 1, ys03 - 1, frameColor); + osd->DrawRectangle(xs04, ys04, xs05 - 1, ys05 - 1, frameColor); + osd->DrawText (xs10, ys00, tr("DEVICES"), Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs10, lineHeight, taBottom | taRight | taBorder); + osd->DrawRectangle(xs08, ys00, xs09 - 1, ys01 - 1, frameColor); + osd->DrawEllipse (xs06, ys00, xs08 - 1, ys01 - 1, frameColor, 2); + osd->DrawEllipse (xs07, ys01, xs08 - 1, ys02 - 1, frameColor, -2); + osd->DrawRectangle(xs06, ys01, xs07 - 1, ys03 - 1, frameColor); + osd->DrawRectangle(xs06, ys04, xs07 - 1, ys05 - 1, frameColor); + osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor); +} + +void cSkinLCARSDisplayMenu::DrawFrameDisplay(void) +{ + DrawDate(); + DrawDisk(); + DrawLoad(); + if (initial) { + if (yb06) + osd->DrawRectangle(xa00, yb06, xa02 - 1, yb07 - 1, frameColor); + if (yb08) { + const cFont *font = cFont::GetFont(fontOsd); + osd->DrawRectangle(xa00, yb08, xa02 - 1, yb09 - 1, frameColor); + osd->DrawText(xa00, yb09 - lineHeight, "LCARS", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + } + } +} + +void cSkinLCARSDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown) +{ + int x0, x1, tt, tb; + tColor ClearColor; + if (MenuCategory() == mcMain) { + x0 = xm07; + x1 = xm08; + tt = ym03; + tb = ym04; + ClearColor = Theme.Color(clrMenuMainBracket); + } + else { + x0 = xa02 + Gap; + x1 = x0 + lineHeight / 2; + tt = yc00; + tb = yc11; + ClearColor = Theme.Color(clrBackground); + int d = TextFrame; + if (CanScrollUp) + osd->DrawBitmap(xa02 - bmArrowUp.Width() - d, yc00 + d, bmArrowUp, Theme.Color(clrMenuScrollbarArrow), frameColor); + else + osd->DrawRectangle(xa02 - bmArrowUp.Width() - d, yc00 + d, xa02 - d - 1, yc00 + d + bmArrowUp.Height() - 1, frameColor); + if (CanScrollDown) + osd->DrawBitmap(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), bmArrowDown, Theme.Color(clrMenuScrollbarArrow), frameColor); + else + osd->DrawRectangle(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), xa02 - d - 1, yc11 - d - 1, frameColor); + } + if (Total > 0 && Total > Shown) { + int sw = x1 - x0; + int sh = max(int((tb - tt) * double(Shown) / Total + 0.5), sw); + int st = min(int(tt + (tb - tt) * double(Offset) / Total + 0.5), tb - sh); + int sb = min(st + sh, tb); + osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, Theme.Color(clrMenuScrollbarTotal)); + osd->DrawRectangle(x0, st, x1 - 1, sb - 1, Theme.Color(clrMenuScrollbarShown)); + } + else if (MenuCategory() != mcMain) + osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, ClearColor); +} + +void cSkinLCARSDisplayMenu::DrawTimer(const cTimer *Timer, int y, bool MultiRec) +{ + // The timer data: + bool Alert = !Timer->Recording() && Timer->Pending(); + tColor ColorFg = Alert ? Theme.Color(clrAlertFg) : Theme.Color(clrTimerFg); + tColor ColorBg = Alert ? Theme.Color(clrAlertFg) : Theme.Color(clrTimerBg); + osd->DrawRectangle(xs00, y, xs03 - 1, y + lineHeight - 1, ColorBg); + cString Date; + if (Timer->Recording()) + Date = cString::sprintf("-%s", *TimeString(Timer->StopTime())); + else { + time_t Now = time(NULL); + cString Today = WeekDayName(Now); + cString Time = TimeString(Timer->StartTime()); + cString Day = WeekDayName(Timer->StartTime()); + if (Timer->StartTime() > Now + 6 * SECSINDAY) + Date = DayDateTime(Timer->StartTime()); + else if (strcmp(Day, Today) != 0) + Date = cString::sprintf("%s %s", *Day, *Time); + else + Date = Time; + } + if (Timer->Flags() & tfVps) + Date = cString::sprintf("VPS %s", *Date); + const cChannel *Channel = Timer->Channel(); + const cEvent *Event = Timer->Event(); + int d = max(TextFrame / 2, 1); + if (Channel) { + osd->DrawText(xs00 + d, y, Channel->Name(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - d); + osd->DrawText(xs03 - tinyFont->Width(Date) - d, y, Date, ColorFg, ColorBg, tinyFont); + } + if (Event) + osd->DrawText(xs00 + d, y + lineHeight - tinyFont->Height(), Event->Title(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - 2 * d); + // The timer recording indicator: + if (Timer->Recording()) + osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording)); +} + +void cSkinLCARSDisplayMenu::DrawTimers(void) +{ + if (Timers.Modified(lastTimersState)) { + deviceRecording.Clear(); + const cFont *font = cFont::GetFont(fontOsd); + osd->DrawRectangle(xs00, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground)); + osd->DrawRectangle(xs07, ys04, xs13 - 1, ys05 - 1, Theme.Color(clrBackground)); + cSortedTimers SortedTimers; + cVector FreeDeviceSlots; + int y = ys04; + // Timers and recording devices: + while (1) { + int NumTimers = 0; + const cDevice *Device = NULL; + for (int i = 0; i < SortedTimers.Size(); i++) { + if (y + lineHeight > ys05) + break; + if (const cTimer *Timer = SortedTimers[i]) { + if (Timer->Recording()) { + if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) { + if (!Device || Device == RecordControl->Device()) { + DrawTimer(Timer, y, NumTimers > 0); + NumTimers++; + if (!Device) { + Device = RecordControl->Device(); + deviceOffset[Device->DeviceNumber()] = y; + deviceRecording[Device->DeviceNumber()] = true; + } + else + FreeDeviceSlots.Append(y); + y += lineHeight + Gap; + } + else + continue; + } + SortedTimers[i] = NULL; + } + else if (!Device) { + DrawTimer(Timer, y, false); + FreeDeviceSlots.Append(y); + y += lineHeight + Gap; + SortedTimers[i] = NULL; + } + } + } + if (!Device) + break; + } + // Devices currently not recording: + int Slot = 0; + for (int i = 0; i < cDevice::NumDevices(); i++) { + if (const cDevice *Device = cDevice::GetDevice(i)) { + if (!deviceRecording[Device->DeviceNumber()]) { + if (Slot < FreeDeviceSlots.Size()) { + y = FreeDeviceSlots[Slot]; + Slot++; + } + if (y + lineHeight > ys05) + break; + deviceOffset[Device->DeviceNumber()] = y; + y += lineHeight + Gap; + } + } + } + osd->DrawText(xs02, ys00, itoa(Timers.Count()), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder); + osd->DrawText(xs08, ys00, itoa(cDevice::NumDevices()), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder); + lastSignalDisplay = 0; + initial = true; // forces redrawing of devices + } +} + +void cSkinLCARSDisplayMenu::DrawDevice(const cDevice *Device) +{ + int dn = Device->DeviceNumber(); + int y = deviceOffset[dn]; + if (y + lineHeight <= ys05) { + if (DrawDeviceData(osd, Device, xs08, y, xs11, y + lineHeight, xs, tinyFont, lastDeviceType[dn], lastCamSlot[dn], initial)) { + // Make sure signal meters are redrawn: + lastSignalStrength[dn] = -1; + lastSignalQuality[dn] = -1; + lastSignalDisplay = 0; + } + // The device recording indicator: + if (deviceRecording[dn]) + osd->DrawRectangle(xs07 + Gap / 2, y, xs08 - Gap - 1, y + lineHeight - 1, Theme.Color(clrMenuDeviceRecording)); + } +} + +void cSkinLCARSDisplayMenu::DrawDevices(void) +{ + for (int i = 0; i < cDevice::NumDevices(); i++) { + if (const cDevice *Device = cDevice::GetDevice(i)) + DrawDevice(Device); + } +} + +void cSkinLCARSDisplayMenu::DrawLiveIndicator(void) +{ + cDevice *Device = cDevice::PrimaryDevice(); + int y = -1; + bool Transferring = Device->Transferring(); + if (!Device->Replaying() || Transferring) + y = deviceOffset[cDevice::ActualDevice()->DeviceNumber()]; + if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) { + if (lastLiveIndicatorY >= 0) + osd->DrawRectangle(xs12, lastLiveIndicatorY, xs13 - 1, lastLiveIndicatorY + lineHeight - 1, Theme.Color(clrBackground)); + if (y >= 0) { + osd->DrawRectangle(xs12, y, xs12 + lineHeight / 2 - 1, y + lineHeight - 1, frameColor); + osd->DrawEllipse (xs12 + lineHeight / 2, y, xs13 - 1, y + lineHeight - 1, frameColor, 5); + if (Transferring) + osd->DrawBitmap((xs12 + xs13 - bmTransferMode.Width()) / 2, y + (lineHeight - bmTransferMode.Height()) / 2, bmTransferMode, Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg)); + } + lastLiveIndicatorY = y; + lastLiveIndicatorTransferring = Transferring; + } +} + +void cSkinLCARSDisplayMenu::DrawSignals(void) +{ + time_t Now = time(NULL); + if (initial || Now - lastSignalDisplay >= SIGNALDISPLAYDELTA) { + for (int i = 0; i < cDevice::NumDevices(); i++) { + if (const cDevice *Device = cDevice::GetDevice(i)) { + if (int y = deviceOffset[i]) + DrawDeviceSignal(osd, Device, xs + lineHeight / 2, y, xs11, y + lineHeight, lastSignalStrength[i], lastSignalQuality[i], initial); + } + } + lastSignalDisplay = Now; + } +} + +void cSkinLCARSDisplayMenu::DrawLive(const cChannel *Channel) +{ + if (lastMode != cmLive) { + initial = true; + lastMode = cmLive; + } + if (initial) { + DrawMainFrameUpper(Theme.Color(clrChannelFrameBg)); + osd->DrawText(xd00, yd00, tr("LIVE"), Theme.Color(clrChannelFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder); + } + if (initial || Channel != lastChannel) { + osd->DrawText(xa00, yt00, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt02 - yt00, taTop | taRight | taBorder); + osd->DrawText(xa03, yt00, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft); + lastChannel = Channel; + } + // The current programme: + cSchedulesLock SchedulesLock; + if (const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock)) { + if (const cSchedule *Schedule = Schedules->GetSchedule(Channel)) { + const cEvent *Event = Schedule->GetPresentEvent(); + if (initial || Event != lastEvent) { + DrawInfo(Event, true); + lastEvent = Event; + lastSeen = -1; + } + int Current = 0; + int Total = 0; + if (Event) { + time_t t = time(NULL); + if (t > Event->StartTime()) + Current = t - Event->StartTime(); + Total = Event->Duration(); + } + DrawSeen(Current, Total); + } + } +} + +void cSkinLCARSDisplayMenu::DrawPlay(cControl *Control) +{ + if (lastMode != cmPlay) { + initial = true; + lastMode = cmPlay; + } + if (initial) { + DrawMainFrameUpper(Theme.Color(clrReplayFrameBg)); + osd->DrawText(xd00, yd00, tr("PLAY"), Theme.Color(clrReplayFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder); + } + // The current progress: + int Current = 0; + int Total = 0; + if (Control->GetIndex(Current, Total)) + DrawSeen(Current, Total); + // The current programme: + if (const cRecording *Recording = Control->GetRecording()) { + if (initial || Recording != lastRecording) { + const cFont *font = cFont::GetFont(fontOsd); + if (const cRecordingInfo *Info = Recording->Info()) { + osd->DrawText(xa03, yt00, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft); + DrawInfo(Info->GetEvent(), false); + } + else + osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03, 0, taTop | taLeft); + osd->DrawText(xa00, yt04, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder); + osd->DrawText(xa00, yt06 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taBottom | taRight | taBorder); + lastRecording = Recording; + } + } + else { + cString Header = Control->GetHeader(); + if (!*lastHeader || strcmp(Header, lastHeader)) { + osd->DrawText(xa03, yt00, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft); + lastHeader = Header; + } + } +} + +void cSkinLCARSDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime) +{ + if (Event) { + const cFont *font = cFont::GetFont(fontOsd); + int y = yt04; + osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03 - lineHeight, lineHeight, taBottom | taLeft); + y += lineHeight; + osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd00 - xa03 - lineHeight, lineHeight, taTop | taLeft); + if (WithTime) { + osd->DrawText(xa00, yt04, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder); + osd->DrawText(xa00, yt06 - lineHeight, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + } + } +} + +void cSkinLCARSDisplayMenu::DrawSeen(int Current, int Total) +{ + int Seen = min(xm08 - xm02, int((xm08 - xm02) * double(Current) / Total)); + if (initial || Seen != lastSeen) { + int y0 = yc04 - ShowSeenExtent; + int y1 = yc04 + lineHeight / 2 - Gap / 2; + osd->DrawRectangle(xm02, y0, xm02 + Seen - 1, y1 - 1, Theme.Color(clrSeen)); + osd->DrawRectangle(xm02 + Seen, y0, xm08 - 1, y1 - 1, Theme.Color(clrBackground)); + lastSeen = Seen; + } +} + +void cSkinLCARSDisplayMenu::DrawTextScrollbar(void) +{ + if (textScroller.CanScroll()) + DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.CanScrollUp(), textScroller.CanScrollDown()); +} + +void cSkinLCARSDisplayMenu::Scroll(bool Up, bool Page) +{ + cSkinDisplayMenu::Scroll(Up, Page); + DrawTextScrollbar(); +} + +int cSkinLCARSDisplayMenu::MaxItems(void) +{ + if (MenuCategory() == mcMain) + return (ym04 - ym03) / lineHeight; + else + return (yb13 - yt02) / lineHeight; +} + +void cSkinLCARSDisplayMenu::Clear(void) +{ + textScroller.Reset(); + osd->DrawRectangle(xi00, yi00, xi03 - 1, yi01 - 1, Theme.Color(clrBackground)); +} + +void cSkinLCARSDisplayMenu::SetTitle(const char *Title) +{ + if (MenuCategory() != mcMain) { + const cFont *font = cFont::GetFont(fontOsd); + int w = font->Width(Title); + osd->DrawRectangle(xa06, yt00, xa07 - w - Gap - 1, yt01 - 1, frameColor); + osd->DrawText(xa07 - w - Gap, yt00, Title, Theme.Color(clrMenuTitle), Theme.Color(clrBackground), font, w + Gap, yt01 - yt00, taRight); + } +} + +void cSkinLCARSDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) +{ + const cFont *font = cFont::GetFont(fontSml); + if (MenuCategory() == mcMain) { + DrawMainButton(Red, xd00, xd01, xd02, xd03, yd02, yd03, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedBg), font); + DrawMainButton(Green, xd04, xd05, xd06, xd07, yd02, yd03, Theme.Color(clrButtonGreenFg), Theme.Color(clrButtonGreenBg), font); + DrawMainButton(Yellow, xd00, xd01, xd02, xd03, yd04, yd05, Theme.Color(clrButtonYellowFg), Theme.Color(clrButtonYellowBg), font); + DrawMainButton(Blue, xd04, xd05, xd06, xd07, yd04, yd05, Theme.Color(clrButtonBlueFg), Theme.Color(clrButtonBlueBg), font); + } + else { + int h = yb15 - yb14; + osd->DrawText(xb02, yb14, Red, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedBg), font, xb03 - xb02, h, taLeft | taBorder); + osd->DrawText(xb06, yb14, Green, Theme.Color(clrButtonGreenFg), Theme.Color(clrButtonGreenBg), font, xb07 - xb06, h, taLeft | taBorder); + osd->DrawText(xb10, yb14, Yellow, Theme.Color(clrButtonYellowFg), Theme.Color(clrButtonYellowBg), font, xb11 - xb10, h, taLeft | taBorder); + osd->DrawText(xb14, yb14, Blue, Theme.Color(clrButtonBlueFg), Theme.Color(clrButtonBlueBg), font, xb15 - xb14, h, taLeft | taBorder); + } +} + +void cSkinLCARSDisplayMenu::SetMessage(eMessageType Type, const char *Text) +{ + if (Text) { + osd->SaveRegion(xb00, yb14, xb15 - 1, yb15 - 1); + osd->DrawText(xb00, yb14, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xb15 - xb00, yb15 - yb14, taCenter); + } + else + osd->RestoreRegion(); +} + +void cSkinLCARSDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) +{ + int y = yi00 + Index * lineHeight; + tColor ColorFg, ColorBg; + if (Current) { + ColorFg = Theme.Color(clrMenuItemCurrentFg); + ColorBg = Theme.Color(clrMenuItemCurrentBg); + osd->DrawRectangle(xi00, y, xi01 - 1, y + lineHeight - 1, ColorBg); + osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg); + osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, y + lineHeight - 1, ColorBg, 5); + currentIndex = Index; + } + else { + ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable); + ColorBg = Theme.Color(clrBackground); + if (currentIndex == Index) + osd->DrawRectangle(xi00, y, xi03 - 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 = xi00 + TextSpacing + Tab(i); + osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xi01 - xt); + } + if (!Tab(i + 1)) + break; + } + SetEditableWidth(xi02 - xi00 - TextSpacing - Tab(1)); +} + +void cSkinLCARSDisplayMenu::SetScrollbar(int Total, int Offset) +{ + DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total); +} + +void cSkinLCARSDisplayMenu::SetEvent(const cEvent *Event) +{ + if (!Event) + return; + const cFont *font = cFont::GetFont(fontOsd); + int xl = xi00; + int y = yi00; + cTextScroller ts; + char t[32]; + snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString()); + ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground)); + if (Event->Vps() && Event->Vps() != Event->StartTime()) { + cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString()); + const cFont *font = cFont::GetFont(fontSml); + int w = font->Width(buffer); + osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w); + int yb = y + font->Height(); + osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor); + osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5); + } + y += ts.Height(); + if (Event->ParentalRating()) { + cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString()); + const cFont *font = cFont::GetFont(fontSml); + int w = font->Width(buffer); + osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w); + int yb = y + font->Height(); + osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor); + osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5); + } + y += font->Height(); + ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->Title(), font, Theme.Color(clrEventTitle), Theme.Color(clrBackground)); + y += ts.Height(); + if (!isempty(Event->ShortText())) { + const cFont *font = cFont::GetFont(fontSml); + ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground)); + y += ts.Height(); + } + y += font->Height(); + if (!isempty(Event->Description())) { + int yt = y; + int yb = yi01; + textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Event->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground)); + DrawTextScrollbar(); + } +} + +void cSkinLCARSDisplayMenu::SetRecording(const cRecording *Recording) +{ + if (!Recording) + return; + const cRecordingInfo *Info = Recording->Info(); + const cFont *font = cFont::GetFont(fontOsd); + int xl = xi00; + int y = yi00; + cTextScroller ts; + char t[32]; + snprintf(t, sizeof(t), "%s %s", *DateString(Recording->Start()), *TimeString(Recording->Start())); + ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground)); + y += ts.Height(); + if (Info->GetEvent()->ParentalRating()) { + cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString()); + const cFont *font = cFont::GetFont(fontSml); + int w = font->Width(buffer); + osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w); + int yb = y + font->Height(); + osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor); + osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5); + } + y += font->Height(); + const char *Title = Info->Title(); + if (isempty(Title)) + Title = Recording->Name(); + ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Title, font, Theme.Color(clrEventTitle), Theme.Color(clrBackground)); + y += ts.Height(); + if (!isempty(Info->ShortText())) { + const cFont *font = cFont::GetFont(fontSml); + ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Info->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground)); + y += ts.Height(); + } + y += font->Height(); + if (!isempty(Info->Description())) { + int yt = y; + int yb = yi01; + textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Info->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground)); + DrawTextScrollbar(); + } +} + +void cSkinLCARSDisplayMenu::SetText(const char *Text, bool FixedFont) +{ + textScroller.Set(osd, xi00, yi00, GetTextAreaWidth(), yi01 - yi00, Text, GetTextAreaFont(FixedFont), Theme.Color(clrMenuText), Theme.Color(clrBackground)); + DrawTextScrollbar(); +} + +int cSkinLCARSDisplayMenu::GetTextAreaWidth(void) const +{ + return xi01 - xi00; +} + +const cFont *cSkinLCARSDisplayMenu::GetTextAreaFont(bool FixedFont) const +{ + const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd); + //XXX -> make a way to let the text define which font to use + return font; +} + +void cSkinLCARSDisplayMenu::Flush(void) +{ + if (MenuCategory() == mcMain) { + cDevice *Device = cDevice::PrimaryDevice(); + if (!Device->Replaying() || Device->Transferring()) { + const cChannel *Channel = Channels.GetByNumber(cDevice::PrimaryDevice()->CurrentChannel()); + DrawLive(Channel); + } + else if (cControl *Control = cControl::Control(true)) + DrawPlay(Control); + DrawTimers(); + DrawDevices(); + DrawLiveIndicator(); + DrawSignals(); + } + DrawFrameDisplay(); + osd->Flush(); + initial = false; +} + +// --- cSkinLCARSDisplayReplay ----------------------------------------------- + +class cSkinLCARSDisplayReplay : public cSkinDisplayReplay { +private: + cOsd *osd; + int xp00, xp01, xp02, xp03, xp04, xp05, xp06, xp07, xp08, xp09, xp10, xp11, xp12, xp13, xp14, xp15; + int yp00, yp01, yp02, yp03, yp04, yp05, yp06, yp07, yp08, yp09; + bool modeOnly; + int lineHeight; + tColor frameColor; + cString lastDate; + tTrackId lastTrackId; + void DrawDate(void); + void DrawTrack(void); +public: + cSkinLCARSDisplayReplay(bool ModeOnly); + virtual ~cSkinLCARSDisplayReplay(); + virtual void SetRecording(const cRecording *Recording); + 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 SetMessage(eMessageType Type, const char *Text); + virtual void Flush(void); + }; + +cSkinLCARSDisplayReplay::cSkinLCARSDisplayReplay(bool ModeOnly) +{ + const cFont *font = cFont::GetFont(fontOsd); + modeOnly = ModeOnly; + lineHeight = font->Height(); + frameColor = Theme.Color(clrReplayFrameBg); + int d = 5 * lineHeight; + xp00 = 0; + xp01 = xp00 + d / 2; + xp02 = xp00 + d; + xp03 = xp02 + lineHeight; + xp04 = xp02 + d / 4; + xp05 = xp02 + d; + xp06 = xp05 + Gap; + xp15 = cOsd::OsdWidth(); + xp14 = xp15 - lineHeight; + xp13 = xp14 - Gap; + xp07 = (xp15 + xp00) / 2; + xp08 = xp07 + Gap; + xp09 = xp08 + lineHeight; + xp10 = xp09 + Gap; + xp11 = (xp10 + xp13 + Gap) / 2; + xp12 = xp11 + Gap; + + yp00 = 0; + yp01 = yp00 + 2 * lineHeight; + yp02 = yp01 + Gap; + yp03 = yp02 + 2 * lineHeight; + + yp04 = yp03 + Gap; + yp09 = yp04 + 3 * lineHeight + Gap / 2; + yp08 = yp09 - lineHeight; + yp07 = yp08 - lineHeight; + yp06 = yp08 - d / 4; + yp05 = yp09 - d / 2; + + osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - yp09, xp00, yp00, xp15 - 1, yp09 - 1); + osd->DrawRectangle(xp00, yp00, xp15 - 1, yp09 - 1, modeOnly ? clrTransparent : Theme.Color(clrBackground)); + // Rectangles: + if (!modeOnly) + osd->DrawRectangle(xp00, yp00, xp02 - 1, yp01 - 1, frameColor); + osd->DrawRectangle(xp00, yp02, xp02 - 1, yp03 - 1, frameColor); + if (!modeOnly) { + // Elbow: + osd->DrawRectangle(xp00, yp04, xp01 - 1, yp05 - 1, frameColor); + osd->DrawRectangle(xp00, yp05, xp01 - 1, yp09 - 1, clrTransparent); + osd->DrawEllipse (xp00, yp05, xp01 - 1, yp09 - 1, frameColor, 3); + osd->DrawRectangle(xp01, yp04, xp02 - 1, yp09 - 1, frameColor); + osd->DrawEllipse (xp02, yp06, xp04 - 1, yp08 - 1, frameColor, -3); + osd->DrawRectangle(xp02, yp08, xp05 - 1, yp09 - 1, frameColor); + // Status area: + osd->DrawRectangle(xp06, yp08, xp07 - 1, yp09 - 1, frameColor); + osd->DrawRectangle(xp08, yp08, xp09 - 1, yp09 - 1, frameColor); + osd->DrawRectangle(xp10, yp08, xp11 - 1, yp09 - 1, frameColor); + osd->DrawRectangle(xp12, yp08, xp13 - 1, yp09 - 1, Theme.Color(clrDateBg)); + osd->DrawRectangle(xp14, yp08, xp14 + lineHeight / 2 - 1, yp09 - 1, frameColor); + osd->DrawRectangle(xp14 + lineHeight / 2, yp08 + lineHeight / 2, xp15 - 1, yp09 - 1, clrTransparent); + osd->DrawEllipse (xp14 + lineHeight / 2, yp08, xp15 - 1, yp09 - 1, frameColor, 5); + } +} + +cSkinLCARSDisplayReplay::~cSkinLCARSDisplayReplay() +{ + delete osd; +} + +void cSkinLCARSDisplayReplay::DrawDate(void) +{ + cString s = DayDateTime(); + if (!*lastDate || strcmp(s, lastDate)) { + osd->DrawText(xp12, yp08, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xp13 - xp12, lineHeight, taRight | taBorder); + lastDate = s; + } +} + +void cSkinLCARSDisplayReplay::DrawTrack(void) +{ + cDevice *Device = cDevice::PrimaryDevice(); + const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack()); + if (!Track && *lastTrackId.description || Track && strcmp(lastTrackId.description, Track->description)) { + osd->DrawText(xp03, yp04, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp07 - xp03); + strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description)); + } +} + +void cSkinLCARSDisplayReplay::SetRecording(const cRecording *Recording) +{ + const cRecordingInfo *RecordingInfo = Recording->Info(); + SetTitle(RecordingInfo->Title()); + osd->DrawText(xp03, yp01 - lineHeight, RecordingInfo->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xp13 - xp03); + osd->DrawText(xp00, yp00, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taTop | taRight | taBorder); + osd->DrawText(xp00, yp01 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taBottom | taRight | taBorder); +} + +void cSkinLCARSDisplayReplay::SetTitle(const char *Title) +{ + osd->DrawText(xp03, yp00, Title, Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp13 - xp03); +} + +static const char *const *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 cSkinLCARSDisplayReplay::SetMode(bool Play, bool Forward, int Speed) +{ + Speed = constrain(Speed, -1, 3); + cBitmap bm(ReplaySymbols[Play][Forward][Speed + 1]); + osd->DrawBitmap(xp01 - bm.Width() / 2, (yp02 + yp03 - bm.Height()) / 2, bm, Theme.Color(clrReplayFrameFg), frameColor); +} + +void cSkinLCARSDisplayReplay::SetProgress(int Current, int Total) +{ + cProgressBar pb(xp13 - xp03, lineHeight, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent)); + osd->DrawBitmap(xp03, yp02, pb); +} + +void cSkinLCARSDisplayReplay::SetCurrent(const char *Current) +{ + const cFont *font = cFont::GetFont(fontOsd); + int w = font->Width(Current) + 10; + osd->DrawText(xp03, yp03 - lineHeight, Current, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, w, 0, taLeft); +} + +void cSkinLCARSDisplayReplay::SetTotal(const char *Total) +{ + const cFont *font = cFont::GetFont(fontOsd); + int w = font->Width(Total) + 10; + osd->DrawText(xp13 - w, yp03 - lineHeight, Total, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, w, 0, taRight); +} + +void cSkinLCARSDisplayReplay::SetJump(const char *Jump) +{ + osd->DrawText(xp06, yp08, Jump, Theme.Color(clrReplayJumpFg), Jump ? Theme.Color(clrReplayJumpBg) : frameColor, cFont::GetFont(fontOsd), xp07 - xp06, 0, taCenter); +} + +void cSkinLCARSDisplayReplay::SetMessage(eMessageType Type, const char *Text) +{ + if (Text) { + osd->SaveRegion(xp06, yp08, xp13 - 1, yp09 - 1); + osd->DrawText(xp06, yp08, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xp13 - xp06, 0, taCenter); + } + else + osd->RestoreRegion(); +} + +void cSkinLCARSDisplayReplay::Flush(void) +{ + if (!modeOnly) { + DrawDate(); + DrawTrack(); + } + osd->Flush(); +} + +// --- cSkinLCARSDisplayVolume ----------------------------------------------- + +class cSkinLCARSDisplayVolume : public cSkinDisplayVolume { +private: + cOsd *osd; + int x0, x1, x2, x3, x4, x5, x6, x7; + int y0, y1; + tColor frameColor; + int mute; +public: + cSkinLCARSDisplayVolume(void); + virtual ~cSkinLCARSDisplayVolume(); + virtual void SetVolume(int Current, int Total, bool Mute); + virtual void Flush(void); + }; + +cSkinLCARSDisplayVolume::cSkinLCARSDisplayVolume(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 = cOsd::OsdWidth(); + x6 = x7 - lineHeight / 2; + x5 = x6 - lineHeight / 2; + x4 = x5 - Gap; + y0 = 0; + y1 = lineHeight; + osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1); + osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground)); + osd->DrawRectangle(x0, y0, x1 - 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->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent); + osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5); +} + +cSkinLCARSDisplayVolume::~cSkinLCARSDisplayVolume() +{ + delete osd; +} + +void cSkinLCARSDisplayVolume::SetVolume(int Current, int Total, bool Mute) +{ + int xl = x3 + TextSpacing; + int xr = x4 - TextSpacing; + int yt = y0 + TextFrame; + int yb = y1 - TextFrame; + 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() + TextSpacing; + int w = (y1 - y0) / 3; + int d = TextFrame; + 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 cSkinLCARSDisplayVolume::Flush(void) +{ + osd->Flush(); +} + +// --- cSkinLCARSDisplayTracks ----------------------------------------------- + +class cSkinLCARSDisplayTracks : public cSkinDisplayTracks { +private: + cOsd *osd; + int xt00, xt01, xt02, xt03, xt04, xt05, xt06, xt07, xt08, xt09, xt10, xt11, xt12; + int yt00, yt01, yt02, yt03, yt04, yt05, yt06, yt07; + int lineHeight; + tColor frameColor; + int currentIndex; + static cBitmap bmAudioLeft, bmAudioRight, bmAudioStereo; + void SetItem(const char *Text, int Index, bool Current); +public: + cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks); + virtual ~cSkinLCARSDisplayTracks(); + virtual void SetTrack(int Index, const char * const *Tracks); + virtual void SetAudioChannel(int AudioChannel); + virtual void Flush(void); + }; + +cBitmap cSkinLCARSDisplayTracks::bmAudioLeft(audioleft_xpm); +cBitmap cSkinLCARSDisplayTracks::bmAudioRight(audioright_xpm); +cBitmap cSkinLCARSDisplayTracks::bmAudioStereo(audiostereo_xpm); + +cSkinLCARSDisplayTracks::cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) +{ + const cFont *font = cFont::GetFont(fontOsd); + lineHeight = font->Height(); + frameColor = Theme.Color(clrTrackFrameBg); + currentIndex = -1; + xt00 = 0; + xt01 = xt00 + lineHeight / 2; + xt02 = xt01 + Gap; + xt03 = xt00 + 2 * lineHeight; + int ItemsWidth = font->Width(Title) + xt03 - xt02; + for (int i = 0; i < NumTracks; i++) + ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]) + 2 * TextFrame); + xt04 = xt02 + ItemsWidth; + xt05 = xt04 + Gap; + xt06 = xt04 + lineHeight; + xt07 = xt05 + lineHeight; + xt08 = xt07 + lineHeight; + xt09 = xt08 + Gap; + xt10 = xt09 + lineHeight / 2; + xt11 = xt10 + Gap; + xt12 = xt11 + lineHeight; + yt00 = 0; + yt01 = yt00 + lineHeight; + yt02 = yt01 + lineHeight; + yt03 = yt02 + Gap; + yt04 = yt03 + NumTracks * lineHeight + (NumTracks - 1) * Gap; + yt05 = yt04 + Gap; + yt06 = yt05 + lineHeight; + yt07 = yt06 + lineHeight; + while (yt07 > cOsd::OsdHeight()) { + yt04 -= lineHeight + Gap; + yt05 = yt04 + Gap; + yt06 = yt05 + lineHeight; + yt07 = yt06 + lineHeight; + } + osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - yt07, xt00, yt00, xt12 - 1, yt07 - 1); + // The upper elbow: + osd->DrawRectangle(xt00, yt00, xt12 - 1, yt07 - 1, Theme.Color(clrBackground)); + osd->DrawRectangle(xt00, yt00, xt03 - 1, yt02 - 1, clrTransparent); + osd->DrawEllipse (xt00, yt00, xt03 - 1, yt02 - 1, frameColor, 2); + osd->DrawRectangle(xt03, yt00, xt04 - 1, yt02 - 1, frameColor); + osd->DrawRectangle(xt04, yt00, xt08 - 1, yt01 - 1, frameColor); + osd->DrawEllipse (xt04, yt01, xt06 - 1, yt02 - 1, frameColor, -2); + osd->DrawRectangle(xt09, yt00, xt10 - 1, yt01 - 1, frameColor); + osd->DrawRectangle(xt11, yt00, xt11 + lineHeight / 2 - 1, yt01 - 1, frameColor); + osd->DrawRectangle(xt11 + lineHeight / 2, yt00, xt12 - 1, yt00 + lineHeight / 2 - 1, clrTransparent); + osd->DrawEllipse (xt11 + lineHeight / 2, yt00, xt12 - 1, yt01 - 1, frameColor, 5); + osd->DrawText(xt03, yt00, Title, Theme.Color(clrTrackFrameFg), frameColor, font, xt04 - xt03, 0, taTop | taRight); + // The items: + for (int i = 0; i < NumTracks; i++) + SetItem(Tracks[i], i, false); + // The lower elbow: + osd->DrawRectangle(xt00, yt05, xt03 - 1, yt07 - 1, clrTransparent); + osd->DrawEllipse (xt00, yt05, xt03 - 1, yt07 - 1, frameColor, 3); + osd->DrawRectangle(xt03, yt05, xt04 - 1, yt07 - 1, frameColor); + osd->DrawRectangle(xt04, yt06, xt08 - 1, yt07 - 1, frameColor); + osd->DrawEllipse (xt04, yt05, xt06 - 1, yt06 - 1, frameColor, -3); + osd->DrawRectangle(xt09, yt06, xt10 - 1, yt07 - 1, frameColor); + osd->DrawRectangle(xt11, yt06, xt11 + lineHeight / 2 - 1, yt07 - 1, frameColor); + osd->DrawRectangle(xt11 + lineHeight / 2, yt06 + lineHeight / 2, xt12 - 1, yt07 - 1, clrTransparent); + osd->DrawEllipse (xt11 + lineHeight / 2, yt06, xt12 - 1, yt07 - 1, frameColor, 5); +} + +cSkinLCARSDisplayTracks::~cSkinLCARSDisplayTracks() +{ + delete osd; +} + +void cSkinLCARSDisplayTracks::SetItem(const char *Text, int Index, bool Current) +{ + int y0 = yt03 + Index * (lineHeight + Gap); + int y1 = y0 + lineHeight; + if (y1 > yt04) + return; + tColor ColorFg, ColorBg; + if (Current) { + ColorFg = Theme.Color(clrTrackItemCurrentFg); + ColorBg = Theme.Color(clrTrackItemCurrentBg); + osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor); + osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg); + osd->DrawRectangle(xt05, y0, xt05 + lineHeight / 2 - 1, y1 - 1, ColorBg); + osd->DrawEllipse (xt05 + lineHeight / 2, y0, xt07 - 1, y1 - 1, ColorBg, 5); + currentIndex = Index; + } + else { + ColorFg = Theme.Color(clrTrackItemFg); + ColorBg = Theme.Color(clrTrackItemBg); + osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor); + osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg); + if (currentIndex == Index) + osd->DrawRectangle(xt05, y0, xt07 - 1, y1 - 1, Theme.Color(clrBackground)); + } + const cFont *font = cFont::GetFont(fontOsd); + osd->DrawText(xt02, y0, Text, ColorFg, ColorBg, font, xt04 - xt02, y1 - y0, taTop | taLeft | taBorder); +} + +void cSkinLCARSDisplayTracks::SetTrack(int Index, const char * const *Tracks) +{ + if (currentIndex >= 0) + SetItem(Tracks[currentIndex], currentIndex, false); + SetItem(Tracks[Index], Index, true); +} + +void cSkinLCARSDisplayTracks::SetAudioChannel(int AudioChannel) +{ + cBitmap *bm = NULL; + switch (AudioChannel) { + case 0: bm = &bmAudioStereo; break; + case 1: bm = &bmAudioLeft; break; + case 2: bm = &bmAudioRight; break; + default: ; + } + if (bm) + osd->DrawBitmap(xt04 - bm->Width(), (yt06 + yt07 - bm->Height()) / 2, *bm, Theme.Color(clrTrackFrameFg), frameColor); + else + osd->DrawRectangle(xt03, yt06, xt04 - 1, yt07 - 1, frameColor); +} + +void cSkinLCARSDisplayTracks::Flush(void) +{ + osd->Flush(); +} + +// --- cSkinLCARSDisplayMessage ---------------------------------------------- + +class cSkinLCARSDisplayMessage : public cSkinDisplayMessage { +private: + cOsd *osd; + int x0, x1, x2, x3, x4, x5, x6, x7; + int y0, y1; +public: + cSkinLCARSDisplayMessage(void); + virtual ~cSkinLCARSDisplayMessage(); + virtual void SetMessage(eMessageType Type, const char *Text); + virtual void Flush(void); + }; + +cSkinLCARSDisplayMessage::cSkinLCARSDisplayMessage(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + int lineHeight = font->Height(); + x0 = 0; + x1 = lineHeight / 2; + x2 = lineHeight; + x3 = x2 + Gap; + x7 = cOsd::OsdWidth(); + x6 = x7 - lineHeight / 2; + x5 = x6 - lineHeight / 2; + x4 = x5 - Gap; + y0 = 0; + y1 = lineHeight; + osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1); +} + +cSkinLCARSDisplayMessage::~cSkinLCARSDisplayMessage() +{ + delete osd; +} + +void cSkinLCARSDisplayMessage::SetMessage(eMessageType Type, const char *Text) +{ + tColor ColorFg = Theme.Color(clrMessageStatusFg + 2 * Type); + tColor ColorBg = Theme.Color(clrMessageStatusBg + 2 * Type); + osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground)); + osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent); + osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, ColorBg, 7); + osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, ColorBg); + osd->DrawText(x3, y0, Text, ColorFg, ColorBg, cFont::GetFont(fontOsd), x4 - x3, 0, taCenter); + osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, ColorBg); + osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent); + osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, ColorBg, 5); +} + +void cSkinLCARSDisplayMessage::Flush(void) +{ + osd->Flush(); +} + +// --- cSkinLCARS ------------------------------------------------------------ + +cSkinLCARS::cSkinLCARS(void) +:cSkin("lcars", &::Theme) +{ +} + +const char *cSkinLCARS::Description(void) +{ + return "LCARS"; +} + +cSkinDisplayChannel *cSkinLCARS::DisplayChannel(bool WithInfo) +{ + return new cSkinLCARSDisplayChannel(WithInfo); +} + +cSkinDisplayMenu *cSkinLCARS::DisplayMenu(void) +{ + return new cSkinLCARSDisplayMenu; +} + +cSkinDisplayReplay *cSkinLCARS::DisplayReplay(bool ModeOnly) +{ + return new cSkinLCARSDisplayReplay(ModeOnly); +} + +cSkinDisplayVolume *cSkinLCARS::DisplayVolume(void) +{ + return new cSkinLCARSDisplayVolume; +} + +cSkinDisplayTracks *cSkinLCARS::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) +{ + return new cSkinLCARSDisplayTracks(Title, NumTracks, Tracks); +} + +cSkinDisplayMessage *cSkinLCARS::DisplayMessage(void) +{ + return new cSkinLCARSDisplayMessage; +} diff --git a/skinlcars.h b/skinlcars.h new file mode 100644 index 0000000..7306d12 --- /dev/null +++ b/skinlcars.h @@ -0,0 +1,27 @@ +/* + * skinlcars.h: A VDR skin with Star Trek's "LCARS" layout + * + * See the main source file 'vdr.c' for copyright information and + * how to reach the author. + * + * $Id: skinlcars.h 1.1 2012/04/15 13:17:35 kls Exp $ + */ + +#ifndef __SKINLCARS_H +#define __SKINLCARS_H + +#include "skins.h" + +class cSkinLCARS : public cSkin { +public: + cSkinLCARS(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 cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks); + virtual cSkinDisplayMessage *DisplayMessage(void); + }; + +#endif //__SKINLCARS_H diff --git a/skins.c b/skins.c index b9c55ef..5fb85a7 100644 --- a/skins.c +++ b/skins.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: skins.c 2.5 2012/03/11 14:36:11 kls Exp $ + * $Id: skins.c 2.10 2012/06/02 11:44:14 kls Exp $ */ #include "skins.h" @@ -67,9 +67,15 @@ cSkinDisplay::~cSkinDisplay() cSkinDisplayMenu::cSkinDisplayMenu(void) { + menuCategory = mcUndefined; SetTabs(0); } +void cSkinDisplayMenu::SetMenuCategory(eMenuCategory MenuCategory) +{ + menuCategory = MenuCategory; +} + void cSkinDisplayMenu::SetTabs(int Tab1, int Tab2, int Tab3, int Tab4, int Tab5) { tabs[0] = 0; @@ -166,6 +172,11 @@ cSkinDisplayReplay::cSkinDisplayReplay(void) marks = NULL; } +void cSkinDisplayReplay::SetRecording(const cRecording *Recording) +{ + SetTitle(Recording->Title()); +} + void cSkinDisplayReplay::SetMarks(const cMarks *Marks) { marks = Marks; diff --git a/skins.h b/skins.h index 19bba51..f716448 100644 --- a/skins.h +++ b/skins.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: skins.h 2.2 2012/03/11 14:38:23 kls Exp $ + * $Id: skins.h 2.5 2012/05/12 11:10:30 kls Exp $ */ #ifndef __SKINS_H @@ -72,6 +72,8 @@ public: */ }; +enum eMenuCategory { mcUndefined = -1, mcUnknown = 0, mcMain, mcSchedule, mcChannel, mcTimer, mcRecording, mcPlugin, mcSetup, mcCommand, mcEvent, mcText, mcFolder, mcCam }; + class cSkinDisplayMenu : public cSkinDisplay { ///< This class implements the general purpose menu display, which is ///< used throughout the program to display information and let the @@ -92,6 +94,7 @@ class cSkinDisplayMenu : public cSkinDisplay { public: enum { MaxTabs = 6 }; private: + eMenuCategory menuCategory; int tabs[MaxTabs]; protected: cTextScroller textScroller; @@ -104,6 +107,16 @@ protected: ///< part can be found, NULL will be returned. public: cSkinDisplayMenu(void); + eMenuCategory MenuCategory(void) const { return menuCategory; } + ///< Returns the menu category, set by a previous call to SetMenuCategory(). + virtual void SetMenuCategory(eMenuCategory MenuCategory); + ///< Sets the current menu category. This allows skins to handle known + ///< types of menus in different ways, for instance by displaying icons + ///< or special decorations. + ///< A derived class can reimplement this function to be informed of any + ///< changes in the menu category. If it does, it shall call the base class + ///< function in order to set the members accordingly for later calls to the + ///< MenuCategory() function. 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. @@ -200,6 +213,11 @@ public: 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 SetRecording(const cRecording *Recording); + ///< Sets the recording that is currently being played. + ///< The default implementation calls SetTitle() with the title and short + ///< text of the Recording. A derived class can use any information provided + ///< by the given Recording and display it. virtual void SetTitle(const char *Title) = 0; ///< Sets the title of the recording. virtual void SetMode(bool Play, bool Forward, int Speed) = 0; diff --git a/skinsttng.c b/skinsttng.c index 4c3b6a4..d985538 100644 --- a/skinsttng.c +++ b/skinsttng.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: skinsttng.c 2.14 2012/03/11 14:06:05 kls Exp $ + * $Id: skinsttng.c 2.15 2012/04/23 08:39:11 kls Exp $ */ // "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures @@ -16,6 +16,7 @@ #include "osd.h" #include "menu.h" #include "themes.h" +#include "videodir.h" #include "symbols/arrowdown.xpm" #include "symbols/arrowup.xpm" @@ -401,8 +402,11 @@ private: int lineHeight; tColor frameColor; int currentIndex; + cString title; bool message; cString lastDate; + int lastDiskUsageState; + void DrawTitle(void); void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown); void SetTextScrollbar(void); public: @@ -429,6 +433,7 @@ cSkinSTTNGDisplayMenu::cSkinSTTNGDisplayMenu(void) const cFont *font = cFont::GetFont(fontOsd); lineHeight = font->Height(); frameColor = Theme.Color(clrMenuFrame); + lastDiskUsageState = -1; currentIndex = -1; message = false; x0 = 0; @@ -548,15 +553,22 @@ void cSkinSTTNGDisplayMenu::Clear(void) osd->DrawRectangle(x1, y3, x7 - 1, y4 - 1, Theme.Color(clrBackground)); } -void cSkinSTTNGDisplayMenu::SetTitle(const char *Title) +void cSkinSTTNGDisplayMenu::DrawTitle(void) { const cFont *font = cFont::GetFont(fontOsd); const char *VDR = " VDR"; + bool WithDisk = MenuCategory() == mcMain || MenuCategory() == mcRecording; int w = font->Width(VDR); - osd->DrawText(x3 + TextSpacing, y0, Title, Theme.Color(clrMenuTitle), frameColor, font, x4 - w - x3 - TextSpacing); + osd->DrawText(x3 + TextSpacing, y0, WithDisk ? cString::sprintf("%s - %s", *title, *cVideoDiskUsage::String()) : title, Theme.Color(clrMenuTitle), frameColor, font, x4 - w - x3 - TextSpacing); osd->DrawText(x4 - w, y0, VDR, frameColor, clrBlack, font, w, lineHeight); } +void cSkinSTTNGDisplayMenu::SetTitle(const char *Title) +{ + title = Title; + DrawTitle(); +} + void cSkinSTTNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) { cString date = DayDateTime(); @@ -749,6 +761,8 @@ const cFont *cSkinSTTNGDisplayMenu::GetTextAreaFont(bool FixedFont) const void cSkinSTTNGDisplayMenu::Flush(void) { + if (cVideoDiskUsage::HasChanged(lastDiskUsageState)) + DrawTitle(); if (!message) { cString date = DayDateTime(); if (!*lastDate || strcmp(date, lastDate)) { diff --git a/svdrp.c b/svdrp.c index 01366dd..f8db847 100644 --- a/svdrp.c +++ b/svdrp.c @@ -10,7 +10,7 @@ * and interact with the Video Disk Recorder - or write a full featured * graphical interface that sits on top of an SVDRP connection. * - * $Id: svdrp.c 2.16 2012/03/04 12:05:56 kls Exp $ + * $Id: svdrp.c 2.19 2012/05/12 11:55:18 kls Exp $ */ #include "svdrp.h" @@ -432,7 +432,7 @@ void cSVDRP::Reply(int Code, const char *fmt, ...) if (Code != 0) { va_list ap; va_start(ap, fmt); - cString buffer = cString::sprintf(fmt, ap); + cString buffer = cString::vsprintf(fmt, ap); va_end(ap); const char *s = buffer; while (s && *s) { @@ -662,14 +662,14 @@ void cSVDRP::CmdDELR(const char *Option) { if (*Option) { if (isnumber(Option)) { - cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1); + cRecording *recording = recordings.Get(strtol(Option, NULL, 10) - 1); if (recording) { cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName()); if (!rc) { if (!cCutter::Active(recording->FileName())) { if (recording->Delete()) { Reply(250, "Recording \"%s\" deleted", Option); - ::Recordings.DelByName(recording->FileName()); + Recordings.DelByName(recording->FileName()); } else Reply(554, "Error while deleting recording!"); @@ -681,7 +681,7 @@ void cSVDRP::CmdDELR(const char *Option) Reply(550, "Recording \"%s\" is in use by timer %d", Option, rc->Timer()->Index() + 1); } else - Reply(550, "Recording \"%s\" not found%s", Option, Recordings.Count() ? "" : " (use LSTR before deleting)"); + Reply(550, "Recording \"%s\" not found%s", Option, recordings.Count() ? "" : " (use LSTR before deleting)"); } else Reply(501, "Error in recording number \"%s\"", Option); @@ -723,7 +723,7 @@ void cSVDRP::CmdEDIT(const char *Option) { if (*Option) { if (isnumber(Option)) { - cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1); + cRecording *recording = recordings.Get(strtol(Option, NULL, 10) - 1); if (recording) { cMarks Marks; if (Marks.Load(recording->FileName(), recording->FramesPerSecond(), recording->IsPesRecording()) && Marks.Count()) { @@ -740,7 +740,7 @@ void cSVDRP::CmdEDIT(const char *Option) Reply(554, "No editing marks defined"); } else - Reply(550, "Recording \"%s\" not found%s", Option, Recordings.Count() ? "" : " (use LSTR before editing)"); + Reply(550, "Recording \"%s\" not found%s", Option, recordings.Count() ? "" : " (use LSTR before editing)"); } else Reply(501, "Error in recording number \"%s\"", Option); @@ -1076,10 +1076,10 @@ void cSVDRP::CmdLSTE(const char *Option) void cSVDRP::CmdLSTR(const char *Option) { - bool recordings = Recordings.Update(true); + recordings.Update(true); if (*Option) { if (isnumber(Option)) { - cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1); + cRecording *recording = recordings.Get(strtol(Option, NULL, 10) - 1); if (recording) { FILE *f = fdopen(file, "w"); if (f) { @@ -1097,11 +1097,11 @@ void cSVDRP::CmdLSTR(const char *Option) else Reply(501, "Error in recording number \"%s\"", Option); } - else if (recordings) { - cRecording *recording = Recordings.First(); + else if (recordings.Count()) { + cRecording *recording = recordings.First(); while (recording) { - Reply(recording == Recordings.Last() ? 250 : -250, "%d %s", recording->Index() + 1, recording->Title(' ', true)); - recording = Recordings.Next(recording); + Reply(recording == recordings.Last() ? 250 : -250, "%d %s", recording->Index() + 1, recording->Title(' ', true)); + recording = recordings.Next(recording); } } else @@ -1367,11 +1367,11 @@ void cSVDRP::CmdPLAY(const char *Option) char c = *option; *option = 0; if (isnumber(num)) { - cRecording *recording = Recordings.Get(strtol(num, NULL, 10) - 1); + cRecording *recording = recordings.Get(strtol(num, NULL, 10) - 1); if (recording) { if (c) option = skipspace(++option); - cReplayControl::SetRecording(NULL, NULL); + cReplayControl::SetRecording(NULL); cControl::Shutdown(); if (*option) { int pos = 0; @@ -1383,13 +1383,13 @@ void cSVDRP::CmdPLAY(const char *Option) else resume.Save(pos); } - cReplayControl::SetRecording(recording->FileName(), recording->Title()); + cReplayControl::SetRecording(recording->FileName()); cControl::Launch(new cReplayControl); cControl::Attach(); Reply(250, "Playing recording \"%s\" [%s]", num, recording->Title()); } else - Reply(550, "Recording \"%s\" not found%s", num, Recordings.Count() ? "" : " (use LSTR before playing)"); + Reply(550, "Recording \"%s\" not found%s", num, recordings.Count() ? "" : " (use LSTR before playing)"); } else Reply(501, "Error in recording number \"%s\"", num); diff --git a/svdrp.h b/svdrp.h index 8ba096c..5ec9bc7 100644 --- a/svdrp.h +++ b/svdrp.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: svdrp.h 2.2 2012/02/16 12:37:53 kls Exp $ + * $Id: svdrp.h 2.3 2012/04/26 10:30:06 kls Exp $ */ #ifndef __SVDRP_H @@ -43,7 +43,7 @@ class cSVDRP { private: cSocket socket; cFile file; - cRecordings Recordings; + cRecordings recordings; cPUTEhandler *PUTEhandler; int numChars; int length; diff --git a/thread.c b/thread.c index e6a8898..5bcc9a5 100644 --- a/thread.c +++ b/thread.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 2.3 2009/04/13 13:50:39 kls Exp $ + * $Id: thread.c 2.4 2012/05/08 11:15:57 kls Exp $ */ #include "thread.h" @@ -239,7 +239,7 @@ void cThread::SetDescription(const char *Description, ...) if (Description) { va_list ap; va_start(ap, Description); - description = strdup(cString::sprintf(Description, ap)); + description = strdup(cString::vsprintf(Description, ap)); va_end(ap); } } diff --git a/timers.c b/timers.c index a988011..4634c1c 100644 --- a/timers.c +++ b/timers.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 2.8 2012/02/27 09:38:41 kls Exp $ + * $Id: timers.c 2.9 2012/04/25 09:02:03 kls Exp $ */ #include "timers.h" @@ -142,7 +142,7 @@ cTimer& cTimer::operator= (const cTimer &Timer) int cTimer::Compare(const cListObject &ListObject) const { - cTimer *ti = (cTimer *)&ListObject; + const cTimer *ti = (const cTimer *)&ListObject; time_t t1 = StartTime(); time_t t2 = ti->StartTime(); int r = t1 - t2; @@ -820,3 +820,18 @@ void cTimers::DeleteExpired(void) } lastDeleteExpired = time(NULL); } + +// --- cSortedTimers --------------------------------------------------------- + +static int CompareTimers(const void *a, const void *b) +{ + return (*(const cTimer **)a)->Compare(**(const cTimer **)b); +} + +cSortedTimers::cSortedTimers(void) +:cVector(Timers.Count()) +{ + for (const cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) + Append(Timer); + Sort(CompareTimers); +} diff --git a/timers.h b/timers.h index aa746b1..e2734c6 100644 --- a/timers.h +++ b/timers.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.h 2.3 2012/02/20 15:52:57 kls Exp $ + * $Id: timers.h 2.4 2012/04/15 13:21:31 kls Exp $ */ #ifndef __TIMERS_H @@ -135,4 +135,9 @@ public: extern cTimers Timers; +class cSortedTimers : public cVector { +public: + cSortedTimers(void); + }; + #endif //__TIMERS_H diff --git a/tools.c b/tools.c index 3296b54..bc01a5f 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 2.22 2012/02/18 15:30:35 kls Exp $ + * $Id: tools.c 2.24 2012/05/12 13:29:20 kls Exp $ */ #include "tools.h" @@ -958,7 +958,7 @@ cString cString::sprintf(const char *fmt, ...) return cString(buffer, true); } -cString cString::sprintf(const char *fmt, va_list &ap) +cString cString::vsprintf(const char *fmt, va_list &ap) { char *buffer; if (!fmt || vasprintf(&buffer, fmt, ap) < 0) { @@ -1042,6 +1042,15 @@ cString DateString(time_t t) return buf; } +cString ShortDateString(time_t t) +{ + char buf[32]; + struct tm tm_r; + tm *tm = localtime_r(&t, &tm_r); + strftime(buf, sizeof(buf), "%d.%m.%y", tm); + return buf; +} + cString TimeString(time_t t) { char buf[25]; diff --git a/tools.h b/tools.h index 4998141..b73448d 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 2.16 2012/02/29 10:41:00 kls Exp $ + * $Id: tools.h 2.21 2012/05/20 13:58:06 kls Exp $ */ #ifndef __TOOLS_H @@ -177,7 +177,7 @@ public: cString &operator=(const char *String); cString &Truncate(int Index); ///< Truncate the string at the given Index (if Index is < 0 it is counted from the end of the string). static cString sprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); - static cString sprintf(const char *fmt, va_list &ap); + static cString vsprintf(const char *fmt, va_list &ap); }; ssize_t safe_read(int filedes, void *buffer, size_t size); @@ -228,13 +228,26 @@ void TouchFile(const char *FileName); time_t LastModifiedTime(const char *FileName); off_t FileSize(const char *FileName); ///< returns the size of the given file, or -1 in case of an error (e.g. if the file doesn't exist) cString WeekDayName(int WeekDay); + ///< Converts the given WeekDay (0=Sunday, 1=Monday, ...) to a three letter + ///< day name. cString WeekDayName(time_t t); + ///< Converts the week day of the given time to a three letter day name. cString WeekDayNameFull(int WeekDay); + ///< Converts the given WeekDay (0=Sunday, 1=Monday, ...) to a full + ///< day name. cString WeekDayNameFull(time_t t); + ///< Converts the week day of the given time to a full day name. cString DayDateTime(time_t t = 0); + ///< Converts the given time to a string of the form "www dd.mm. hh:mm". + ///< If no time is given, the current time is taken. cString TimeToString(time_t t); + ///< Converts the given time to a string of the form "www mmm dd hh:mm:ss yyyy". cString DateString(time_t t); + ///< Converts the given time to a string of the form "www dd.mm.yyyy". +cString ShortDateString(time_t t); + ///< Converts the given time to a string of the form "dd.mm.yy". cString TimeString(time_t t); + ///< Converts the given time to a string of the form "hh:mm". uchar *RgbToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality = 100); ///< Converts the given Memory to a JPEG image and returns a pointer ///< to the resulting image. Mem must point to a data block of exactly @@ -457,6 +470,7 @@ public: }; template class cVector { + ///< cVector may only be used for *simple* types, like int or pointers - not for class objects that allocate additional memory! private: mutable int allocated; mutable int size; @@ -515,7 +529,7 @@ public: virtual void Append(T Data) { if (size >= allocated) - Realloc(allocated * 4 / 2); // increase size by 50% + Realloc(allocated * 3 / 2); // increase size by 50% data[size++] = Data; } virtual void Remove(int Index) @@ -526,6 +540,8 @@ public: } virtual void Clear(void) { + for (int i = 0; i < size; i++) + data[i] = T(0); size = 0; } void Sort(__compar_fn_t Compare) diff --git a/vdr.c b/vdr.c index bafd4ef..3fcb675 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.tvdr.de * - * $Id: vdr.c 2.35 2012/03/14 09:09:19 kls Exp $ + * $Id: vdr.c 2.36 2012/04/26 09:23:41 kls Exp $ */ #include @@ -56,6 +56,7 @@ #include "recording.h" #include "shutdown.h" #include "skinclassic.h" +#include "skinlcars.h" #include "skinsttng.h" #include "sourceparams.h" #include "sources.h" @@ -677,6 +678,7 @@ int main(int argc, char *argv[]) // Default skins: + new cSkinLCARS; new cSkinSTTNG; new cSkinClassic; Skins.SetCurrent(Setup.OSDSkin); diff --git a/videodir.c b/videodir.c index 7331a85..870b4cb 100644 --- a/videodir.c +++ b/videodir.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: videodir.c 2.0 2008/02/16 13:00:03 kls Exp $ + * $Id: videodir.c 2.1 2012/04/22 15:03:10 kls Exp $ */ #include "videodir.h" @@ -241,3 +241,43 @@ bool IsOnVideoDirectoryFileSystem(const char *FileName) } while (Dir.Next()); return false; } + +// --- cVideoDiskUsage ------------------------------------------------------- + +#define DISKSPACECHEK 5 // seconds between disk space checks +#define MB_PER_MINUTE 25.75 // this is just an estimate! + +int cVideoDiskUsage::state = 0; +time_t cVideoDiskUsage::lastChecked = 0; +int cVideoDiskUsage::usedPercent = 0; +int cVideoDiskUsage::freeMB = 0; +int cVideoDiskUsage::freeMinutes = 0; + +bool cVideoDiskUsage::HasChanged(int &State) +{ + if (time(NULL) - lastChecked > DISKSPACECHEK) { + int FreeMB; + int UsedPercent = VideoDiskSpace(&FreeMB); + if (FreeMB != freeMB) { + usedPercent = UsedPercent; + freeMB = FreeMB; + int MBperMinute = Recordings.MBperMinute(); + if (MBperMinute <= 0) + MBperMinute = MB_PER_MINUTE; + freeMinutes = int(double(FreeMB) / MBperMinute); + state++; + } + lastChecked = time(NULL); + } + if (State != state) { + State = state; + return true; + } + return false; +} + +cString cVideoDiskUsage::String(void) +{ + HasChanged(state); + return cString::sprintf("%s %d%% - %2d:%02d %s", tr("Disk"), usedPercent, freeMinutes / 60, freeMinutes % 60, tr("free")); +} diff --git a/videodir.h b/videodir.h index 5e9aef5..0a0587a 100644 --- a/videodir.h +++ b/videodir.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: videodir.h 2.0 2008/02/16 12:53:11 kls Exp $ + * $Id: videodir.h 2.1 2012/04/22 15:07:56 kls Exp $ */ #ifndef __VIDEODIR_H @@ -25,4 +25,42 @@ cString PrefixVideoFileName(const char *FileName, char Prefix); void RemoveEmptyVideoDirectories(void); bool IsOnVideoDirectoryFileSystem(const char *FileName); +class cVideoDiskUsage { +private: + static int state; + static time_t lastChecked; + static int usedPercent; + static int freeMB; + static int freeMinutes; +public: + static bool HasChanged(int &State); + ///< Returns true if the usage of the video disk space has changed since the last + ///< call to this function with the given State variable. The caller should + ///< initialize State to -1, and it will be set to the current internal state + ///< value of the video disk usage checker upon return. Future calls with the same + ///< State variable can then quickly check for changes. + static void ForceCheck(void) { lastChecked = 0; } + ///< To avoid unnecessary load, the video disk usage is only actually checked + ///< every DISKSPACECHEK seconds. Calling ForceCheck() makes sure that the next call + ///< to HasChanged() will check the disk usage immediately. This is useful in case + ///< some files have been deleted and the result shall be displayed instantly. + static cString String(void); + ///< Returns a localized string of the form "Disk nn% - hh:mm free". + ///< This function is mainly for use in skins that want to retain the display of the + ///< free disk space in the menu title, as was the case until VDR version 1.7.27. + ///< An implicit call to HasChanged() is done in this function, to make sure the + ///< returned value is up to date. + static int UsedPercent(void) { return usedPercent; } + ///< Returns the used space of the video disk in percent. + ///< The caller should call HasChanged() first, to make sure the value is up to date. + static int FreeMB(void) { return freeMB; } + ///< Returns the amount of free space on the video disk in MB. + ///< The caller should call HasChanged() first, to make sure the value is up to date. + static int FreeMinutes(void) { return freeMinutes; } + ///< Returns the number of minutes that can still be recorded on the video disk. + ///< This is an estimate and depends on the data rate of the existing recordings. + ///< There is no guarantee that this value will actually be met. + ///< The caller should call HasChanged() first, to make sure the value is up to date. + }; + #endif //__VIDEODIR_H -- cgit v1.2.3