#include "symbols/audio.xpm" #include "symbols/dolbydigital.xpm" #include "symbols/encrypted.xpm" #include "symbols/radio.xpm" #include "symbols/recording.xpm" #include "symbols/teletext.xpm" #include "displaychannel.h" cNopacityDisplayChannel::cNopacityDisplayChannel(bool WithInfo) { config.setDynamicValues(); withInfo = WithInfo; groupSep = false; present = NULL; lastSeen = -1; lastSignalDisplay = 0; lastSignalStrength = 0; lastSignalQuality = 0; lastScreenWidth = 0; currentLast = 0; channelChange = false; isRadioChannel = false; radioIconDrawn = false; initial = true; FrameTime = config.channelFrameTime; FadeTime = config.channelFadeTime; lastDate = ""; SetGeometry(); CreatePixmaps(); CreateFonts(); DrawBackground(); DrawSignalMeter(); } cNopacityDisplayChannel::~cNopacityDisplayChannel() { Cancel(-1); while (Active()) cCondWait::SleepMs(10); osd->DestroyPixmap(pixmapBackgroundTop); osd->DestroyPixmap(pixmapBackgroundBottom); osd->DestroyPixmap(pixmapLogo); osd->DestroyPixmap(pixmapChannelInfo); osd->DestroyPixmap(pixmapDate); if (withInfo) { osd->DestroyPixmap(pixmapBackgroundMiddle); osd->DestroyPixmap(pixmapProgressBar); osd->DestroyPixmap(pixmapEPGInfo); } if (pixmapScreenResolution) osd->DestroyPixmap(pixmapScreenResolution); osd->DestroyPixmap(pixmapStreamInfo); if (config.displaySignalStrength && showSignal) { osd->DestroyPixmap(pixmapSignalStrength); osd->DestroyPixmap(pixmapSignalQuality); osd->DestroyPixmap(pixmapSignalMeter); osd->DestroyPixmap(pixmapSignalLabel); } if (config.displaySignalStrength && showSignal) { delete fontInfoline; } delete fontHeader; delete fontDate; delete fontEPG; delete fontEPGSmall; delete osd; } cBitmap cNopacityDisplayChannel::bmTeletext(teletext_xpm); cBitmap cNopacityDisplayChannel::bmRadio(radio_xpm); cBitmap cNopacityDisplayChannel::bmAudio(audio_xpm); cBitmap cNopacityDisplayChannel::bmDolbyDigital(dolbydigital_xpm); cBitmap cNopacityDisplayChannel::bmEncrypted(encrypted_xpm); cBitmap cNopacityDisplayChannel::bmRecording(recording_xpm); void cNopacityDisplayChannel::SetGeometry(void) { height = cOsd::OsdHeight() * config.channelHeight / 100; int top = cOsd::OsdTop() + cOsd::OsdHeight() - height - config.channelBorderBottom; osd = CreateOsd(cOsd::OsdLeft(), top, cOsd::OsdWidth(), height); infoWidth = osd->Width() - (config.logoWidth + 2 * config.channelBorderVertical + config.logoBorder); infoX = config.logoWidth + config.channelBorderVertical + config.logoBorder; channelInfoWidth = infoWidth * 0.7; dateWidth = infoWidth - channelInfoWidth; channelInfoHeight = height * 0.2; if (channelInfoHeight%2 != 0) channelInfoHeight++; progressBarHeight = height * 0.1; streamInfoHeight = height * 0.2; if (streamInfoHeight%2 != 0) streamInfoHeight++; epgInfoHeight = height - channelInfoHeight - streamInfoHeight - progressBarHeight; epgInfoLineHeight = epgInfoHeight / 4; streamInfoY = channelInfoHeight + progressBarHeight + epgInfoHeight; } void cNopacityDisplayChannel::CreatePixmaps(void) { int channelInfoY = 0; if (withInfo) { pixmapProgressBar = osd->CreatePixmap(2, cRect(infoX, channelInfoHeight, infoWidth, progressBarHeight)); pixmapEPGInfo = osd->CreatePixmap(2, cRect(infoX, channelInfoHeight + progressBarHeight, infoWidth, epgInfoHeight)); pixmapBackgroundMiddle = osd->CreatePixmap(1, cRect(infoX, channelInfoHeight, infoWidth, progressBarHeight + epgInfoHeight)); } else { channelInfoY = (height - channelInfoHeight) / 3; streamInfoY = (height - channelInfoHeight) / 3 + channelInfoHeight; } pixmapBackgroundTop = osd->CreatePixmap(1, cRect(infoX, channelInfoY, infoWidth, channelInfoHeight)); pixmapBackgroundBottom = osd->CreatePixmap(1, cRect(infoX, streamInfoY, infoWidth, streamInfoHeight)); pixmapChannelInfo = osd->CreatePixmap(2, cRect(infoX, channelInfoY, channelInfoWidth, channelInfoHeight)); pixmapDate = osd->CreatePixmap(2, cRect(infoX + channelInfoWidth, channelInfoY, dateWidth, channelInfoHeight)); pixmapStreamInfo = osd->CreatePixmap(2, cRect(infoX, streamInfoY, infoWidth, streamInfoHeight)); pixmapLogo = osd->CreatePixmap(1, cRect(0, 0, config.logoWidth + 2 * config.logoBorder, height)); if (config.channelFadeTime) { pixmapBackgroundTop->SetAlpha(0); pixmapBackgroundBottom->SetAlpha(0); pixmapChannelInfo->SetAlpha(0); pixmapDate->SetAlpha(0); pixmapLogo->SetAlpha(0); pixmapStreamInfo->SetAlpha(0); if (withInfo) { pixmapBackgroundMiddle->SetAlpha(0); pixmapProgressBar->SetAlpha(0); pixmapEPGInfo->SetAlpha(0); } } if (withInfo) { pixmapProgressBar->Fill(clrTransparent); pixmapEPGInfo->Fill(clrTransparent); } pixmapScreenResolution = NULL; } void cNopacityDisplayChannel::CreateFonts(void) { fontHeader = cFont::CreateFont(config.fontName, channelInfoHeight - 8 + config.fontChannelHeaderSize); fontDate = cFont::CreateFont(config.fontName, channelInfoHeight/2 + config.fontChannelDateSize); fontEPG = cFont::CreateFont(config.fontName, epgInfoLineHeight + config.fontEPGSize); fontEPGSmall = cFont::CreateFont(config.fontName, epgInfoLineHeight - 6 + config.fontEPGSmallSize); } void cNopacityDisplayChannel::DrawBackground(void){ DrawBlendedBackground(pixmapBackgroundTop, Theme.Color(clrChannelBackground), Theme.Color(clrChannelBackBlend), true); if (withInfo) pixmapBackgroundMiddle->Fill(Theme.Color(clrChannelBackground)); DrawBlendedBackground(pixmapBackgroundBottom, Theme.Color(clrChannelBackground), Theme.Color(clrChannelBackBlend), false); pixmapBackgroundTop->DrawEllipse(cRect(0, 0, channelInfoHeight/2, channelInfoHeight/2), clrTransparent, -2); pixmapBackgroundTop->DrawEllipse(cRect(infoWidth - channelInfoHeight/2, 0, channelInfoHeight/2, channelInfoHeight/2), clrTransparent, -1); pixmapBackgroundBottom->DrawEllipse(cRect(0, streamInfoHeight/2, streamInfoHeight/2, streamInfoHeight/2), clrTransparent, -3); pixmapBackgroundBottom->DrawEllipse(cRect(infoWidth - streamInfoHeight/2, streamInfoHeight/2, streamInfoHeight/2, streamInfoHeight/2), clrTransparent, -4); pixmapChannelInfo->Fill(clrTransparent); pixmapDate->Fill(clrTransparent); pixmapLogo->Fill(clrTransparent); pixmapStreamInfo->Fill(clrTransparent); } void cNopacityDisplayChannel::DrawDate(void) { cString curDate = DayDateTime(); if (initial || channelChange || strcmp(curDate, lastDate)) { int strDateWidth = fontDate->Width(curDate); int strDateHeight = fontDate->Height(); int x = dateWidth - strDateWidth - channelInfoHeight/2; int y = (channelInfoHeight - strDateHeight) / 2; pixmapDate->Fill(clrTransparent); pixmapDate->DrawText(cPoint(x, y), curDate, Theme.Color(clrChannelHead), clrTransparent, fontDate); lastDate = curDate; } } void cNopacityDisplayChannel::DrawIcons(const cChannel *Channel) { int spacing = 10; int x = infoWidth - config.resolutionIconSize - 3*spacing; int y = 0; isRadioChannel = ((!Channel->Vpid())&&(Channel->Apid(0)))?true:false; bool rec = cRecordControls::Active(); x -= bmRecording.Width() + spacing; y = (streamInfoHeight - bmRecording.Height()) / 2; pixmapStreamInfo->DrawBitmap(cPoint(x,y), bmRecording, Theme.Color(rec ? clrChannelRecActive : clrChannelSymbolOff), clrTransparent); x -= bmEncrypted.Width() + spacing; y = (streamInfoHeight - bmEncrypted.Height()) / 2; pixmapStreamInfo->DrawBitmap(cPoint(x,y), bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), clrTransparent); x -= bmDolbyDigital.Width() + spacing; y = (streamInfoHeight - bmDolbyDigital.Height()) / 2; pixmapStreamInfo->DrawBitmap(cPoint(x,y), bmDolbyDigital, Theme.Color(Channel->Dpid(0) ? clrChannelSymbolOn : clrChannelSymbolOff), clrTransparent); x -= bmAudio.Width() + spacing; y = (streamInfoHeight - bmAudio.Height()) / 2; pixmapStreamInfo->DrawBitmap(cPoint(x,y), bmAudio, Theme.Color(Channel->Apid(1) ? clrChannelSymbolOn : clrChannelSymbolOff), clrTransparent); if (Channel->Vpid()) { x -= bmTeletext.Width() + spacing; y = (streamInfoHeight - bmTeletext.Height()) / 2; pixmapStreamInfo->DrawBitmap(cPoint(x,y), bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), clrTransparent); } else if (Channel->Apid(0)) { x -= bmRadio.Width() + spacing; y = (streamInfoHeight - bmTeletext.Height()) / 2; pixmapStreamInfo->DrawBitmap(cPoint(x,y), bmRadio, Theme.Color(clrChannelSymbolOn), clrTransparent); } } void cNopacityDisplayChannel::DrawScreenResolution(void) { int spacing = 10; int screenWidth = 0; int screenHeight = 0; double aspect = 0; if (!pixmapScreenResolution) { int x = infoX + infoWidth - config.resolutionIconSize - 2*spacing; int y = streamInfoY + streamInfoHeight - config.resolutionIconSize - 3; pixmapScreenResolution = osd->CreatePixmap(3, cRect(x, y, config.resolutionIconSize, config.resolutionIconSize)); pixmapScreenResolution->Fill(clrTransparent); if ((initial)&&(config.channelFadeTime)) pixmapScreenResolution->SetAlpha(0); } cImageLoader imgLoader; if (isRadioChannel) { if (!radioIconDrawn) { if (imgLoader.LoadIcon("radio", config.resolutionIconSize)) { pixmapScreenResolution->DrawImage(cPoint(0,0), imgLoader.GetImage()); } lastScreenWidth = 0; radioIconDrawn = true; } } else { cDevice::PrimaryDevice()->GetVideoSize(screenWidth, screenHeight, aspect); if (screenWidth != lastScreenWidth) { cString iconName(""); switch (screenWidth) { case 1920: case 1440: iconName = "hd1080i"; break; case 1280: if (screenHeight == 720) iconName = "hd720p"; else iconName = "hd1080i"; break; case 720: iconName = "sd576i"; break; default: iconName = "sd576i"; break; } if (imgLoader.LoadIcon(*iconName, config.resolutionIconSize)) { pixmapScreenResolution->DrawImage(cPoint(0,0), imgLoader.GetImage()); } lastScreenWidth = screenWidth; radioIconDrawn = false; } } } void cNopacityDisplayChannel::DrawSignalMeter(void) { signalWidth = infoWidth * 0.15; signalHeight = signalWidth *15 / 200; showSignal = false; if (config.displaySignalStrength) { cImageLoader imgLoader; cString signalStrength = "STR"; cString signalQuality = "SNR"; if (imgLoader.LoadIcon("signal", signalWidth, signalHeight)) { cImage imgSignal = imgLoader.GetImage(); signalWidth = imgSignal.Width(); signalHeight = imgSignal.Height(); int signalMeterY = streamInfoY + (streamInfoHeight - 2*signalHeight - 5)/2; fontInfoline = cFont::CreateFont(config.fontName, signalHeight - 2); int labelWidth = max(fontInfoline->Width(*signalStrength), fontInfoline->Width(*signalQuality)) + 2; signalX = streamInfoHeight / 2 + labelWidth; showSignal = true; pixmapSignalStrength = osd->CreatePixmap(3, cRect(infoX + signalX, signalMeterY + 2, signalWidth + 2, signalHeight + 2)); pixmapSignalQuality = osd->CreatePixmap(3, cRect(infoX + signalX, signalMeterY + signalHeight + 5, signalWidth + 2, signalHeight + 2)); pixmapSignalMeter = osd->CreatePixmap(4, cRect(infoX + signalX + 1, signalMeterY + 3, signalWidth, 2*signalHeight + 3)); pixmapSignalLabel = osd->CreatePixmap(3, cRect(infoX + streamInfoHeight / 2, signalMeterY + 2, labelWidth, 2*signalHeight + 3)); pixmapSignalStrength->Fill(Theme.Color(clrProgressBarBack)); pixmapSignalQuality->Fill(Theme.Color(clrProgressBarBack)); pixmapSignalMeter->Fill(clrTransparent); pixmapSignalLabel->Fill(clrTransparent); if (config.channelFadeTime) { pixmapSignalStrength->SetAlpha(0); pixmapSignalQuality->SetAlpha(0); pixmapSignalMeter->SetAlpha(0); pixmapSignalLabel->SetAlpha(0); } pixmapSignalStrength->DrawImage(cPoint(1,1), imgSignal); pixmapSignalQuality->DrawImage(cPoint(1,1), imgSignal); pixmapSignalLabel->DrawText(cPoint(0, 2), *signalStrength, Theme.Color(clrChannelEPGInfo), clrTransparent, fontInfoline); pixmapSignalLabel->DrawText(cPoint(0, signalHeight + 4), *signalQuality, Theme.Color(clrChannelEPGInfo), clrTransparent, fontInfoline); } } } void cNopacityDisplayChannel::DrawSignal(void) { time_t Now = time(NULL); if (Now != lastSignalDisplay) { int SignalStrength = cDevice::ActualDevice()->SignalStrength(); int SignalQuality = cDevice::ActualDevice()->SignalQuality(); if ((SignalStrength == 0)&&(SignalQuality==0)) return; if ((lastSignalStrength != SignalStrength) || (lastSignalQuality != SignalQuality)) { pixmapSignalMeter->Fill(clrTransparent); pixmapSignalMeter->DrawRectangle(cRect(double(SignalStrength) /100 * signalWidth, 0, signalWidth - (double)SignalStrength /100 * signalWidth + 1, signalHeight), Theme.Color(clrChannelBackground)); pixmapSignalMeter->DrawRectangle(cRect(double(SignalQuality) /100 * signalWidth, signalHeight + 3, signalWidth - (double)SignalQuality / 100 * signalWidth + 1, signalHeight + 1), Theme.Color(clrChannelBackground)); } lastSignalStrength = SignalStrength; lastSignalQuality = SignalQuality; lastSignalDisplay = Now; } } void cNopacityDisplayChannel::SetChannel(const cChannel *Channel, int Number) { pixmapLogo->Fill(clrTransparent); pixmapChannelInfo->Fill(clrTransparent); if (withInfo) { pixmapProgressBar->Fill(clrTransparent); pixmapEPGInfo->Fill(clrTransparent); } channelChange = true; lastSignalStrength = 0; lastSignalQuality = 0; cString ChannelNumber(""); cString ChannelName(""); groupSep = false; if (Channel) { ChannelName = Channel->Name(); if (!Channel->GroupSep()) { DrawIcons(Channel); ChannelNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : ""); } else groupSep = true; } else if (Number) { ChannelNumber = cString::sprintf("%d-", Number); } else { ChannelName = ChannelString(NULL, 0); } cString channelString = cString::sprintf("%s %s", *ChannelNumber, *ChannelName); if (!groupSep) { pixmapChannelInfo->DrawText(cPoint(channelInfoHeight/2, (channelInfoHeight-fontHeader->Height())/2), channelString, Theme.Color(clrChannelHead), clrTransparent, fontHeader); cImageLoader imgLoader; if (imgLoader.LoadLogo(*ChannelName)) { pixmapLogo->DrawImage(cPoint(config.logoBorder, (height-config.logoHeight)/2), imgLoader.GetImage()); } } else { if (withInfo) { pixmapProgressBar->Fill(clrTransparent); pixmapEPGInfo->Fill(clrTransparent); pixmapEPGInfo->DrawText(cPoint(channelInfoHeight/2, (epgInfoHeight-fontHeader->Height())/2 - fontHeader->Height()/2), channelString, Theme.Color(clrChannelHead), clrTransparent, fontHeader); } else { pixmapChannelInfo->DrawText(cPoint(channelInfoHeight/2, (channelInfoHeight-fontHeader->Height())/2), channelString, Theme.Color(clrChannelHead), clrTransparent, fontHeader); } cImageLoader imgLoader; if (imgLoader.LoadIcon("Channelseparator", config.logoHeight)) { pixmapLogo->DrawImage(cPoint(config.logoBorder + (config.logoWidth - config.logoHeight)/2, (height-config.logoHeight)/2), imgLoader.GetImage()); } } } void cNopacityDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following) { if (!withInfo) return; if (present != Present) lastSeen = -1; present = Present; if (Present || Following) { pixmapProgressBar->Fill(clrTransparent); pixmapEPGInfo->Fill(clrTransparent); } int indent = 20; for (int i = 0; i < 2; i++) { const cEvent *e = !i ? Present : Following; int y = !i ? 0 : 2; if (e) { cString startTime = e->GetTimeString(); int startTimeWidth = fontEPG->Width(*startTime); int epgWidth = fontEPG->Width(e->Title()); int epgWidthShort = fontEPGSmall->Width(e->ShortText()); cString strSeen(""); if (i==0) { int seen = (int)(time(NULL) - e->StartTime())/60; strSeen = cString::sprintf("%d/%dmin", seen, e->Duration()/60); } else { strSeen = cString::sprintf("%dmin", e->Duration()/60); } int seenWidth = fontEPG->Width(*strSeen); int space = infoWidth - 9*indent - seenWidth - startTimeWidth - config.resolutionIconSize; cString strEPG; if (space < epgWidth) { cTextWrapper epgInfoWrapper(e->Title(), fontEPG, space); strEPG = epgInfoWrapper.GetLine(0); strEPG = cString::sprintf("%s...", *strEPG); } else { strEPG = e->Title(); } cString strEPGShort(""); int spaceShort = infoWidth - 6*indent - startTimeWidth - config.resolutionIconSize; if (spaceShort < epgWidthShort) { cTextWrapper epgInfoWrapper(e->ShortText(), fontEPGSmall, spaceShort); strEPGShort = epgInfoWrapper.GetLine(0); strEPGShort = cString::sprintf("%s...", *strEPGShort); } else { strEPGShort = e->ShortText(); } tColor fontColor = (i==0)?Theme.Color(clrChannelEPG):Theme.Color(clrChannelEPGInfo); pixmapEPGInfo->DrawText(cPoint(indent, y * epgInfoLineHeight), *startTime, fontColor, clrTransparent, fontEPG); pixmapEPGInfo->DrawText(cPoint(2 * indent + startTimeWidth, y * epgInfoLineHeight), *strEPG, fontColor, clrTransparent, fontEPG); pixmapEPGInfo->DrawText(cPoint(2 * indent + startTimeWidth, (y+1) * epgInfoLineHeight + 3), *strEPGShort, fontColor, clrTransparent, fontEPGSmall); int x = infoWidth - indent - seenWidth - config.resolutionIconSize - indent; pixmapEPGInfo->DrawText(cPoint(x, y * epgInfoLineHeight), *strSeen, fontColor, clrTransparent, fontEPG); } } } void cNopacityDisplayChannel::DrawProgressBar(int Current, int Total) { if ((Current < currentLast + 3) && !channelChange) return; currentLast = Current; if ((Current > 0) || (Total > 0)) { int barHeight = pixmapProgressBar->ViewPort().Height()-8; if (barHeight%2 != 0) barHeight++; int barFullWidth = pixmapProgressBar->ViewPort().Width() - 20 - barHeight; double percentSeen = ((double)Current) / (double)Total; pixmapProgressBar->DrawEllipse(cRect(9, 3, barHeight+2, barHeight+2), Theme.Color(clrProgressBarBack)); pixmapProgressBar->DrawEllipse(cRect(9 + barFullWidth, 3, barHeight+2, barHeight+2), Theme.Color(clrProgressBarBack)); pixmapProgressBar->DrawRectangle(cRect( 9 + barHeight/2, 3, barFullWidth, barHeight+1), Theme.Color(clrProgressBarBack)); pixmapProgressBar->DrawEllipse(cRect(10, 4, barHeight, barHeight), Theme.Color(clrProgressBarBlend)); if (Current > 0) { tColor colAct = DrawProgressbarBackground(10 + barHeight/2, 4, barFullWidth * percentSeen, barHeight-1); pixmapProgressBar->DrawEllipse(cRect(10 + barFullWidth * percentSeen, 4, barHeight, barHeight), colAct); //pixmapProgressBar->DrawRectangle(cRect( 10 + barHeight/2, 4, barFullWidth * percentSeen, barHeight-1), Theme.Color(clrProgressBar)); } } } tColor cNopacityDisplayChannel::DrawProgressbarBackground(int left, int top, int width, int height) { tColor clr1 = Theme.Color(clrProgressBar); tColor clr2 = Theme.Color(clrProgressBarBlend); tColor clr = 0x00000000; int step = width / 256; int alpha = 0x0; int alphaStep; int maximum = 0; if (step == 0) { //width < 256 step = 1; alphaStep = 256 / width; maximum = width; } else { //width > 256 alphaStep = 0x1; maximum = 256; } int x = 0; for (int i = 0; i < maximum; i++) { x = left + i*step; clr = AlphaBlend(clr1, clr2, alpha); pixmapProgressBar->DrawRectangle(cRect(x,top,step,height), clr); alpha += alphaStep; } if (step > 0) { int rest = width - step*256; pixmapProgressBar->DrawRectangle(cRect(left+step*256, top, rest, height), clr); } return clr; } void cNopacityDisplayChannel::SetMessage(eMessageType Type, const char *Text) { } void cNopacityDisplayChannel::Flush(void) { DrawDate(); if (!groupSep) DrawScreenResolution(); if (config.displaySignalStrength && showSignal) { DrawSignal(); } if (withInfo) { int Current = 0; int Total = 0; if (present) { time_t t = time(NULL); if (t > present->StartTime()) Current = t - present->StartTime(); Total = present->Duration(); DrawProgressBar(Current, Total); } } if (initial) { if (config.channelFadeTime) Start(); } initial = false; channelChange = false; osd->Flush(); } void cNopacityDisplayChannel::Action(void) { uint64_t Start = cTimeMs::Now(); while (Running()) { uint64_t Now = cTimeMs::Now(); cPixmap::Lock(); double t = min(double(Now - Start) / FadeTime, 1.0); int Alpha = t * ALPHA_OPAQUE; pixmapBackgroundTop->SetAlpha(Alpha); pixmapBackgroundBottom->SetAlpha(Alpha); pixmapLogo->SetAlpha(Alpha); pixmapChannelInfo->SetAlpha(Alpha); pixmapDate->SetAlpha(Alpha); if (withInfo) { pixmapBackgroundMiddle->SetAlpha(Alpha); pixmapProgressBar->SetAlpha(Alpha); pixmapEPGInfo->SetAlpha(Alpha); } pixmapStreamInfo->SetAlpha(Alpha); if (pixmapScreenResolution) pixmapScreenResolution->SetAlpha(Alpha); if (config.displaySignalStrength && showSignal) { pixmapSignalStrength->SetAlpha(Alpha); pixmapSignalQuality->SetAlpha(Alpha); pixmapSignalMeter->SetAlpha(Alpha); pixmapSignalLabel->SetAlpha(Alpha); } if (Running()) osd->Flush(); cPixmap::Unlock(); int Delta = cTimeMs::Now() - Now; if (Running() && (Delta < FrameTime)) cCondWait::SleepMs(FrameTime - Delta); if ((int)(Now - Start) > FadeTime) { break; } } }