diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2008-01-13 18:00:00 +0100 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2008-01-13 18:00:00 +0100 |
commit | fc4c8740a72e6c7cea5a001e19fdacb63c3cc538 (patch) | |
tree | 6ab0ae16b8d588e34d86f8a1a69c101ce8ba2809 /PLUGINS/src/pictures/player.c | |
parent | 29b2d48bb53df75f1cb978e72bc709a6658d6e5c (diff) | |
download | vdr-patch-lnbsharing-fc4c8740a72e6c7cea5a001e19fdacb63c3cc538.tar.gz vdr-patch-lnbsharing-fc4c8740a72e6c7cea5a001e19fdacb63c3cc538.tar.bz2 |
Version 1.5.13vdr-1.5.13
- Fixed the declaration of cSubtitleObject::Decode8BppCodeString() (thanks to
Gregoire Favre).
- The new setup option "Miscellaneous/Emergency exit" can be used to turn off
the automatic restart of VDR in case a recording fails for some reason.
- The kInfo key is now propagated to any open menu, so that it can react to it
in a context sensitive manner (suggested by Andreas Brugger). If there is
no menu open it will show the info of the current broadcast or replay.
- cTimeMs now uses the monotonic clock, if available (thanks to Petri Hintukainen).
- Fixed cVector::Clear() and cStringList::Clear().
- Added cString::Truncate().
- Fixed the "i18n:" target in the "newplugin" script, so that it can create the
initial *.pot file.
- Fixed handling the '-l' option.
- Fixed error handling in cCuttingThread::Action() (thanks to Udo Richter).
- Fixed a loss of the date display in the "classic" skin's main menu (reported by
Andreas Brugger).
- Added a missing setting of lastFreeMB in cMenuMain::Update() (reported by
Andreas Brugger).
- Added '-Wno-parentheses' to the compiler options in order to avoid silly compiler
warnings for expressions like 'a || b && c', where GCC 4.3 wants to force the
programmer to write 'a || (b && c)', while everybody knows that '&&' links
stronger than '||' (reported by Tobias Grimm).
- Updated the Hungarian language texts (thanks to István Füley).
- Fixed displaying weekday names in the Schedule menu if the system uses UTF-8
(reported by Jiri Dobry).
- The new plugin "pictures" implements a simple picture viewer.
See PLUGINS/src/pictures/README for details.
- The automatic shutdown is now suppressed if the remote control is currently
disabled (suggested by Helmut Auer, implemented by Udo Richter).
- Added a section about "Logging" to PLUGINS.html (suggested by Torsten Kunkel).
- Enhanced the SVDRP command CLRE to allow clearing the EPG data of a particular
channel (thanks to Benjamin Hess).
Diffstat (limited to 'PLUGINS/src/pictures/player.c')
-rw-r--r-- | PLUGINS/src/pictures/player.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/PLUGINS/src/pictures/player.c b/PLUGINS/src/pictures/player.c new file mode 100644 index 0000000..9e07fc5 --- /dev/null +++ b/PLUGINS/src/pictures/player.c @@ -0,0 +1,249 @@ +/* + * player.c: A player for still pictures + * + * See the README file for copyright information and how to reach the author. + * + * $Id: player.c 1.1 2008/01/13 11:29:27 kls Exp $ + */ + +#include "player.h" +#include <vdr/remote.h> +#include <vdr/tools.h> + +int SlideShowDelay = 3; // seconds + +cString HandleUnderscores(const char *s) +{ + // Skip anything before and including the first '_' and replace + // any remaining '_' with blanks: + const char *p = strchr(s, '_'); + if (p) { + p++; + char buf[strlen(p) + 1]; + strcpy(buf, p); + return strreplace(buf, '_', ' '); + } + return s; +} + +// --- cPicturePlayer -------------------------------------------------------- + +class cPicturePlayer : public cPlayer { +private: + int size; + int length; + uchar *buffer; + virtual void Activate(bool On); +public: + cPicturePlayer(void); + ~cPicturePlayer(); + void SetPicture(const char *FileName); + }; + +cPicturePlayer::cPicturePlayer(void) +{ + size = KILOBYTE(100); // will be adjusted automatically if files are larger + length = 0; + buffer = MALLOC(uchar, size); +} + +cPicturePlayer::~cPicturePlayer() +{ + free(buffer); +} + +void cPicturePlayer::Activate(bool On) +{ + if (length > 0) + DeviceStillPicture(buffer, length); +} + +void cPicturePlayer::SetPicture(const char *FileName) +{ + int f = open(FileName, O_RDONLY); + if (f >= 0) { + for (;;) { + length = read(f, buffer, size); + if (length > 0) { + if (length >= size) { + size = size * 3 / 2; + buffer = (uchar *)realloc(buffer, size); + lseek(f, 0, SEEK_SET); + continue; + } + DeviceStillPicture(buffer, length); + } + else + LOG_ERROR_STR(FileName); + break; + } + close(f); + } + else + LOG_ERROR_STR(FileName); +} + +// --- cPictureControl ------------------------------------------------------- + +int cPictureControl::active = 0; +cString cPictureControl::lastDisplayed; + +cPictureControl::cPictureControl(cPictureEntry *Pictures, const cPictureEntry *PictureEntry, bool SlideShow) +:cControl(player = new cPicturePlayer) +{ + pictures = Pictures; + pictureEntry = PictureEntry; + osd = NULL; + lastPath = "/"; + slideShow = SlideShow; + alwaysDisplayCaption = false; + NextPicture(slideShow && pictureEntry->IsDirectory() ? 1 : 0); + active++; +} + +cPictureControl::~cPictureControl() +{ + active--; + delete osd; + delete player; + delete pictures; +} + +void cPictureControl::NextPicture(int Direction) +{ + if (Direction) { + const cPictureEntry *pe = Direction > 0 ? pictureEntry->NextPicture() : pictureEntry->PrevPicture(); + if (pe) + pictureEntry = pe; + } + if (pictureEntry) { + player->SetPicture(pictureEntry->Path()); + DisplayCaption(); + } +} + +void cPictureControl::NextDirectory(int Direction) +{ + // This only works reliable if a directory contains only subdirectories or pictures, not both! + if (Direction) { + const cPictureEntry *pe = Direction > 0 ? pictureEntry->Parent()->Entries()->Last()->NextPicture() : pictureEntry->Parent()->Entries()->First()->PrevPicture(); + if (pe && Direction < 0) + pe = pe->Parent()->Entries()->First(); + if (pe && pe != pictureEntry) { + pictureEntry = pe; + player->SetPicture(pictureEntry->Path()); + DisplayCaption(); + } + } +} + +static void DrawTextOutlined(cOsd *Osd, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font) +{ + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + if (dx || dy) + Osd->DrawText(x + dx, y + dy, s, ColorBg, clrTransparent, Font); + } + } + Osd->DrawText(x, y, s, ColorFg, clrTransparent, Font); +} + +void cPictureControl::DisplayCaption(void) +{ + bool Force = false; + cString Path = pictureEntry->Path(); + lastDisplayed = Path + strlen(pictures->Name()) + 1; + const char *p = strrchr(Path, '/'); + const char *q = strrchr(lastPath, '/'); + if (p && q) { + int lp = p - Path; + int lq = q - lastPath; + if (lp != lq || strncmp(lastPath, Path, lp)) { + lastPath = Path; + Force = true; + } + } + if (!alwaysDisplayCaption && !Force) { + DELETENULL(osd); + return; + } + const cFont *Font = cFont::GetFont(fontOsd); + int w = cOsd::OsdWidth(); + int h = 2 * Font->Height(); + if (!osd) { + osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - h, OSD_LEVEL_SUBTITLES); + tArea Areas[] = { { 0, 0, w, h, 8 } }; + if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) + osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); + else { + tArea Areas[] = { { 0, 0, w, h, 4 } }; + osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); + } + } + const char *Year = pictureEntry->Parent()->Parent() ? pictureEntry->Parent()->Parent()->Name() : ""; + cString Description = HandleUnderscores(pictureEntry->Parent()->Name()); + osd->DrawRectangle(0, 0, w - 1, h - 1, clrTransparent); + DrawTextOutlined(osd, 0, 0, Description, clrWhite, clrBlack, Font); + DrawTextOutlined(osd, 0, h / 2, Year, clrWhite, clrBlack, Font); + struct stat sb; + if (stat(Path, &sb) == 0) { + cString Time = DayDateTime(sb.st_mtime); + DrawTextOutlined(osd, w - Font->Width(Time), h / 2, Time, clrWhite, clrBlack, Font); + } + p++; + Path.Truncate(-4); // don't display the ".mpg" extension + DrawTextOutlined(osd, w - Font->Width(p), 0, p, clrWhite, clrBlack, Font); + osd->Flush(); +} + +eOSState cPictureControl::ProcessKey(eKeys Key) +{ + switch (Key) { + case kUp: + case kPlay: slideShowDelay.Set(); + slideShow = true; + break; + case kDown: + case kPause: slideShow = false; + break; + case kLeft|k_Repeat: + case kLeft: NextPicture(-1); + slideShow = false; + break; + case kRight|k_Repeat: + case kRight: NextPicture(+1); + slideShow = false; + break; + case kOk: if (osd && !alwaysDisplayCaption) + DELETENULL(osd); + else { + alwaysDisplayCaption = !alwaysDisplayCaption; + DisplayCaption(); + } + break; + case kGreen: + case kPrev: NextDirectory(-1); + slideShow = false; + break; + case kYellow: + case kNext: NextDirectory(+1); + slideShow = false; + break; + case kBlue: + case kStop: return osEnd; + case kBack: slideShow = false; + cRemote::CallPlugin(PLUGIN_NAME_I18N); + break; + default: break; + } + if (slideShow && slideShowDelay.TimedOut()) { + NextPicture(+1); + slideShowDelay.Set(SlideShowDelay * 1000); + } + return osContinue; +} + +const char *cPictureControl::LastDisplayed(void) +{ + return lastDisplayed; +} |