From d607265f695510e357c67d78e43d0c8138f8c588 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 13 Jan 2008 11:44:38 +0100 Subject: Added the 'pictures' plugin --- PLUGINS/src/pictures/player.c | 249 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 PLUGINS/src/pictures/player.c (limited to 'PLUGINS/src/pictures/player.c') diff --git a/PLUGINS/src/pictures/player.c b/PLUGINS/src/pictures/player.c new file mode 100644 index 00000000..9e07fc53 --- /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 +#include + +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; +} -- cgit v1.2.3