From fc4c8740a72e6c7cea5a001e19fdacb63c3cc538 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 13 Jan 2008 18:00:00 +0100 Subject: =?UTF-8?q?Version=201.5.13=20-=20Fixed=20the=20declaration=20of?= =?UTF-8?q?=20cSubtitleObject::Decode8BppCodeString()=20(thanks=20to=20=20?= =?UTF-8?q?=20Gregoire=20Favre).=20-=20The=20new=20setup=20option=20"Misce?= =?UTF-8?q?llaneous/Emergency=20exit"=20can=20be=20used=20to=20turn=20off?= =?UTF-8?q?=20=20=20the=20automatic=20restart=20of=20VDR=20in=20case=20a?= =?UTF-8?q?=20recording=20fails=20for=20some=20reason.=20-=20The=20kInfo?= =?UTF-8?q?=20key=20is=20now=20propagated=20to=20any=20open=20menu,=20so?= =?UTF-8?q?=20that=20it=20can=20react=20to=20it=20=20=20in=20a=20context?= =?UTF-8?q?=20sensitive=20manner=20(suggested=20by=20Andreas=20Brugger).?= =?UTF-8?q?=20If=20there=20is=20=20=20no=20menu=20open=20it=20will=20show?= =?UTF-8?q?=20the=20info=20of=20the=20current=20broadcast=20or=20replay.?= =?UTF-8?q?=20-=20cTimeMs=20now=20uses=20the=20monotonic=20clock,=20if=20a?= =?UTF-8?q?vailable=20(thanks=20to=20Petri=20Hintukainen).=20-=20Fixed=20c?= =?UTF-8?q?Vector::Clear()=20and=20cStringList::Clear().=20-=20Added=20cSt?= =?UTF-8?q?ring::Truncate().=20-=20Fixed=20the=20"i18n:"=20target=20in=20t?= =?UTF-8?q?he=20"newplugin"=20script,=20so=20that=20it=20can=20create=20th?= =?UTF-8?q?e=20=20=20initial=20*.pot=20file.=20-=20Fixed=20handling=20the?= =?UTF-8?q?=20'-l'=20option.=20-=20Fixed=20error=20handling=20in=20cCuttin?= =?UTF-8?q?gThread::Action()=20(thanks=20to=20Udo=20Richter).=20-=20Fixed?= =?UTF-8?q?=20a=20loss=20of=20the=20date=20display=20in=20the=20"classic"?= =?UTF-8?q?=20skin's=20main=20menu=20(reported=20by=20=20=20Andreas=20Brug?= =?UTF-8?q?ger).=20-=20Added=20a=20missing=20setting=20of=20lastFreeMB=20i?= =?UTF-8?q?n=20cMenuMain::Update()=20(reported=20by=20=20=20Andreas=20Brug?= =?UTF-8?q?ger).=20-=20Added=20'-Wno-parentheses'=20to=20the=20compiler=20?= =?UTF-8?q?options=20in=20order=20to=20avoid=20silly=20compiler=20=20=20wa?= =?UTF-8?q?rnings=20for=20expressions=20like=20'a=20||=20b=20&&=20c',=20wh?= =?UTF-8?q?ere=20GCC=204.3=20wants=20to=20force=20the=20=20=20programmer?= =?UTF-8?q?=20to=20write=20'a=20||=20(b=20&&=20c)',=20while=20everybody=20?= =?UTF-8?q?knows=20that=20'&&'=20links=20=20=20stronger=20than=20'||'=20(r?= =?UTF-8?q?eported=20by=20Tobias=20Grimm).=20-=20Updated=20the=20Hungarian?= =?UTF-8?q?=20language=20texts=20(thanks=20to=20Istv=C3=A1n=20F=C3=BCley).?= =?UTF-8?q?=20-=20Fixed=20displaying=20weekday=20names=20in=20the=20Schedu?= =?UTF-8?q?le=20menu=20if=20the=20system=20uses=20UTF-8=20=20=20(reported?= =?UTF-8?q?=20by=20Jiri=20Dobry).=20-=20The=20new=20plugin=20"pictures"=20?= =?UTF-8?q?implements=20a=20simple=20picture=20viewer.=20=20=20See=20PLUGI?= =?UTF-8?q?NS/src/pictures/README=20for=20details.=20-=20The=20automatic?= =?UTF-8?q?=20shutdown=20is=20now=20suppressed=20if=20the=20remote=20contr?= =?UTF-8?q?ol=20is=20currently=20=20=20disabled=20(suggested=20by=20Helmut?= =?UTF-8?q?=20Auer,=20implemented=20by=20Udo=20Richter).=20-=20Added=20a?= =?UTF-8?q?=20section=20about=20"Logging"=20to=20PLUGINS.html=20(suggested?= =?UTF-8?q?=20by=20Torsten=20Kunkel).=20-=20Enhanced=20the=20SVDRP=20comma?= =?UTF-8?q?nd=20CLRE=20to=20allow=20clearing=20the=20EPG=20data=20of=20a?= =?UTF-8?q?=20particular=20=20=20channel=20(thanks=20to=20Benjamin=20Hess)?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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 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 +#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