/* * advchctrlosd.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id$ */ #include #include #include "advchctrli18n.h" #include "advchctrlcommon.h" #include "advchctrlconfig.h" #include "advchctrlsetup.h" #include "advchctrlchannel.h" #include "advchctrlosd.h" #define CHANNELINPUT_TIMEOUT 1000 #define OSDHEIGHT advchctrlConfig.osdheight // in pixels #define OSDWIDTH advchctrlConfig.osdwidth // in pixels #define OSDROWHEIGHT m_Font->Height() // in pixels #define OSDSTATUSHEIGHT (OSDROWHEIGHT * 6) // in pixels (6 rows) #define OSDSPACING 5 #define OSDCORNERING 10 #define OSDSTATUSWIN_Y(offset) (advchctrlConfig.osdposition ? offset : (OSDHEIGHT - OSDSTATUSHEIGHT + offset)) #define OSDSTATUSWIN_X(col) ((col == 7) ? 475 : (col == 6) ? 410 : (col == 5) ? 275 : (col == 4) ? 220 : (col == 3) ? 125 : (col == 2) ? 70 : 15) #define OSDSTATUSWIN_XSYMBOL(c,w) (c * ((OSDWIDTH - (5 * w)) / 6) + ((c - 1) * w)) #define OSDBARX2(offset, val, max)((int)(((double)(val) / (max)) * (OSDWIDTH - (offset)))+(offset)) // --- cAdvChCtrlOsd ------------------------------------------------------------- cAdvChCtrlOsd::cAdvChCtrlOsd(void) :cOsdObject(true), cThread("advchctrl osd") { DEBUGOSD("%s()\n", __PRETTY_FUNCTION__); m_Osd = NULL; m_Active = false; m_Number = 0; m_Mutex = new cMutex(); if (Setup.UseSmallFont == 0) { // Dirty hack to force the small fonts... Setup.UseSmallFont = 1; m_Font = cFont::GetFont(fontSml); Setup.UseSmallFont = 0; } else m_Font = cFont::GetFont(fontSml); } cAdvChCtrlOsd::~cAdvChCtrlOsd(void) { DEBUGOSD("%s()\n", __PRETTY_FUNCTION__); if (m_Active) { m_Active = false; Cancel(3); } //if (m_Receiver) // delete m_Receiver; if (m_Osd) delete m_Osd; } void cAdvChCtrlOsd::DrawStatusWindow(void) { cMutexLock lock(m_Mutex); char buf1[128]; char buf2[128]; //int signal = 140; double barlength[2]; int TextLength[2]; int offset = 0; int TxtCol; cChannel *channel = Channels.GetByNumber(cDevice::PrimaryDevice()->CurrentChannel()); int ChVolume = AdvChCtrlChannelsList.GetVolume(Channels.GetByNumber(cDevice::PrimaryDevice()->CurrentChannel())->GetChannelID()); if (ChVolume < 0) ChVolume = advchctrlConfig.defaultvolume; if (m_Osd) { m_Osd->DrawRectangle(0, OSDSTATUSWIN_Y(0), OSDWIDTH, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), advchctrlTheme[advchctrlConfig.theme].clrBackground); snprintf(buf1, sizeof(buf1), "%d%s %s", m_Number ? m_Number : channel->Number(), m_Number ? "-" : "", channel->ShortName(true)); m_Osd->DrawRectangle(0, OSDSTATUSWIN_Y(offset), OSDWIDTH, OSDSTATUSWIN_Y(offset+OSDROWHEIGHT-1), advchctrlTheme[advchctrlConfig.theme].clrTitleBackground); m_Osd->DrawText(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), buf1, advchctrlTheme[advchctrlConfig.theme].clrTitleText, advchctrlTheme[advchctrlConfig.theme].clrTitleBackground, m_Font); // if (advchctrlConfig.theme == eThemeSTTNG) // { // m_Osd->DrawEllipse(0, OSDSTATUSWIN_Y(0), OSDCORNERING, OSDSTATUSWIN_Y(OSDCORNERING), clrTransparent, -2); // m_Osd->DrawEllipse((OSDWIDTH-OSDCORNERING), OSDSTATUSWIN_Y(0), OSDWIDTH, OSDSTATUSWIN_Y(OSDCORNERING), clrTransparent, -1); // m_Osd->DrawEllipse((OSDWIDTH-OSDCORNERING), OSDSTATUSWIN_Y(0), OSDWIDTH, OSDSTATUSWIN_Y(OSDCORNERING), advchctrlTheme[advchctrlConfig.theme].clrTitleBackground, 1); // m_Osd->DrawEllipse((OSDWIDTH-OSDCORNERING), OSDSTATUSWIN_Y(0)+ OSDCORNERING+1, OSDWIDTH, OSDSTATUSWIN_Y((2*OSDCORNERING)), advchctrlTheme[advchctrlConfig.theme].clrTitleBackground, 4); // m_Osd->DrawRectangle((OSDWIDTH-OSDCORNERING - 15), OSDSTATUSWIN_Y(0),(OSDWIDTH-OSDCORNERING-12), OSDSTATUSWIN_Y(offset+OSDROWHEIGHT-1), advchctrlTheme[advchctrlConfig.theme].clrTitleBackground); // } offset += OSDROWHEIGHT + 15; snprintf(buf1, sizeof(buf1), "%s", tr("Default volume")); snprintf(buf2, sizeof(buf2), "%s", tr("Channel volume")); TextLength[0] = m_Font->Width(buf1); TextLength[1] = m_Font->Width(buf2); // TxtCol = (advchctrlConfig.theme == eThemeSTTNG ? advchctrlTheme[advchctrlConfig.theme].clrTitleText: advchctrlTheme[advchctrlConfig.theme].clrInactiveText); TxtCol = advchctrlTheme[advchctrlConfig.theme].clrInactiveText; m_Osd->DrawRectangle(0, OSDSTATUSWIN_Y(offset),OSDSTATUSWIN_X(1)+max(TextLength[0],TextLength[1]) ,OSDSTATUSWIN_Y(offset)+(2*OSDROWHEIGHT), advchctrlTheme[advchctrlConfig.theme].clrMenuBackground); m_Osd->DrawText(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), buf1, TxtCol, advchctrlTheme[advchctrlConfig.theme].clrMenuBackground, m_Font); m_Osd->DrawText(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset)+OSDROWHEIGHT, buf2, TxtCol, advchctrlTheme[advchctrlConfig.theme].clrMenuBackground, m_Font); barlength[0] = OSDBARX2(2*OSDSTATUSWIN_X(1) + max(TextLength[0],TextLength[1]), (advchctrlConfig.defaultvolume), 255); // DEBUGOSD("signal:%d offset:%d barx2:%f Y(%d):%d", signal, OSDSTATUSWIN_X(1) + m_Font->Width(buf), barlength[0], offset, OSDSTATUSWIN_Y(offset)); m_Osd->DrawRectangle(2*OSDSTATUSWIN_X(1) + max(TextLength[0],TextLength[1]), OSDSTATUSWIN_Y(offset)+3, (int)barlength[0], OSDSTATUSWIN_Y(offset)+OSDROWHEIGHT-3, advchctrlTheme[advchctrlConfig.theme].clrGreen); offset += OSDROWHEIGHT; barlength[1] = OSDBARX2(2*OSDSTATUSWIN_X(1) + max(TextLength[0],TextLength[1]), ChVolume, 255); //barlength = OSDBARX2(300, 85, 255); // m_Osd->DrawRectangle(OSDSTATUSWIN_X(1) + m_Font->Width(buf), OSDSTATUSWIN_Y(offset+3),(int) barlength , OSDSTATUSWIN_Y(offset+OSDROWHEIGHT-3), advchctrlTheme[advchctrlConfig.theme].clrRed); m_Osd->DrawRectangle(2*OSDSTATUSWIN_X(1) + max(TextLength[0],TextLength[1]), OSDSTATUSWIN_Y(offset)+3,(int) barlength[1] , OSDSTATUSWIN_Y(offset)+OSDROWHEIGHT-3, advchctrlTheme[advchctrlConfig.theme].clrRed); //DEBUGOSD("signal:%d offset:%d barx2:%f ChVolume:%d", signal, OSDSTATUSWIN_X(1) + max(TextLength[0],TextLength[1]), barlength[1], ChVolume); offset += OSDROWHEIGHT; m_Osd->DrawRectangle(0, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT)-OSDROWHEIGHT, OSDWIDTH, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), advchctrlTheme[advchctrlConfig.theme].clrMenuBackground); // m_Osd->DrawRectangle(OSDSTATUSWIN_X(0), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT)-OSDROWHEIGHT, OSDSTATUSWIN_X(0), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), advchctrlTheme[advchctrlConfig.theme].clrRed); m_Osd->DrawRectangle(OSDSTATUSWIN_X(0) + OSDWIDTH/4, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT)-OSDROWHEIGHT, OSDSTATUSWIN_X(0) + (2 * OSDWIDTH/4), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), advchctrlTheme[advchctrlConfig.theme].clrGreen); snprintf(buf1, sizeof(buf1), "%s", tr("Reset")); TextLength[0] = m_Font->Width(buf1); m_Osd->DrawText(OSDSTATUSWIN_X(0) + int(1.5 *OSDWIDTH/4)-TextLength[0]/2, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT)-OSDROWHEIGHT, buf1, advchctrlTheme[advchctrlConfig.theme].clrTitleText, advchctrlTheme[advchctrlConfig.theme].clrGreen, m_Font); // m_Osd->DrawRectangle(OSDSTATUSWIN_X(4), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT)-OSDROWHEIGHT, OSDSTATUSWIN_X(5), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), advchctrlTheme[advchctrlConfig.theme].clrBlue); m_Osd->DrawEllipse(0, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT-OSDCORNERING), OSDCORNERING, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), clrTransparent, -3); m_Osd->DrawEllipse((OSDWIDTH-OSDCORNERING), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT-OSDCORNERING), OSDWIDTH, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), clrTransparent, -4); m_Osd->Flush(); } } void cAdvChCtrlOsd::Action(void) { DEBUGOSD("%s()\n", __PRETTY_FUNCTION__); cTimeMs t; m_Active = true; while (m_Active) { t.Set(0); DrawStatusWindow(); cCondWait::SleepMs(100 * advchctrlConfig.updateinterval - t.Elapsed()); } } void cAdvChCtrlOsd::Show(void) { DEBUGOSD("%s()\n", __PRETTY_FUNCTION__); m_Osd = cOsdProvider::NewOsd(((Setup.OSDWidth - OSDWIDTH) / 2) + Setup.OSDLeft + advchctrlConfig.osdoffset, ((Setup.OSDHeight - OSDHEIGHT) / 2) + Setup.OSDTop); if (m_Osd) { tArea Areas1[] = { { 0, 0, OSDWIDTH, OSDHEIGHT, 4 } }; if (m_Osd->CanHandleAreas(Areas1, sizeof(Areas1) / sizeof(tArea)) == oeOk) { m_Osd->SetAreas(Areas1, sizeof(Areas1) / sizeof(tArea)); } else { tArea Areas2[] = { { 0, OSDSTATUSWIN_Y(0), (OSDWIDTH-1), OSDSTATUSWIN_Y(OSDSTATUSHEIGHT-1), 4 } };//, // { 0, OSDINFOWIN_Y(0), (OSDWIDTH-1), OSDINFOWIN_Y(OSDROWHEIGHT-1), 4 }, // { 0, OSDINFOWIN_Y(OSDROWHEIGHT), (OSDWIDTH-1), OSDINFOWIN_Y(OSDINFOHEIGHT-1), 2 } }; m_Osd->SetAreas(Areas2, sizeof(Areas2) / sizeof(tArea)); } m_Osd->Flush(); Start(); } } void cAdvChCtrlOsd::ChannelSwitch(const cDevice * device, int channelNumber, bool LiveView) { DEBUGOSD("%s(%d,%d)\n", __PRETTY_FUNCTION__, device->DeviceNumber(), channelNumber); if (!device->IsPrimaryDevice() || !channelNumber || cDevice::PrimaryDevice()->CurrentChannel() != channelNumber) return; } eOSState cAdvChCtrlOsd::ProcessKey(eKeys Key) { eOSState state = cOsdObject::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case k0: if ((m_Number == 0) && (m_OldNumber != 0)) { m_Number = m_OldNumber; m_OldNumber = cDevice::CurrentChannel(); Channels.SwitchTo(m_Number); m_Number = 0; return osContinue; } case k1 ... k9: if (m_Number >= 0) { m_Number = m_Number * 10 + Key - k0; if (m_Number > 0) { DrawStatusWindow(); cChannel *ch = Channels.GetByNumber(m_Number); m_InputTime.Set(0); // Lets see if there can be any useful further input: int n = ch ? m_Number * 10 : 0; while (ch && (ch = Channels.Next(ch)) != NULL) { if (!ch->GroupSep()) { if (n <= ch->Number() && ch->Number() <= n + 9) { n = 0; break; } if (ch->Number() > n) n *= 10; } } if (n > 0) { // This channel is the only one that fits the input, so let's take it right away: m_OldNumber = cDevice::CurrentChannel(); Channels.SwitchTo(m_Number); m_Number = 0; } } } break; case kBack: return osEnd; case kGreen: { if (!(cDevice::PrimaryDevice()->IsMute())) cDevice::PrimaryDevice()->SetVolume(advchctrlConfig.defaultvolume, 1); } break; case kYellow: break; case kRight: case kLeft: break; case kUp|k_Repeat: case kUp: case kDown|k_Repeat: case kDown: m_OldNumber = cDevice::CurrentChannel(); cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1); m_Number = 0; break; case kNone: if (m_Number && (m_InputTime.Elapsed() > CHANNELINPUT_TIMEOUT)) { if (Channels.GetByNumber(m_Number)) { m_OldNumber = cDevice::CurrentChannel(); Channels.SwitchTo(m_Number); m_Number = 0; } else { m_InputTime.Set(0); m_Number = 0; } } break; case kOk: // toggle between display modes //if (++m_DisplayMode == eFemonModeAC3 && !Channels.GetByNumber(cDevice::CurrentChannel())->Dpid(0)) m_DisplayMode++; //if (m_DisplayMode >= eFemonModeMaxNumber) m_DisplayMode = 0; //DrawInfoWindow(); break; default: break; } state = osContinue; } return state; }