#include #include #include #include #include #include #include #include #include "lcd.h" #include "sockets.h" #include "lcdkeyconf.h" #include "i18n.h" // character mapping for output, see cLcd::Write #ifdef LCD_hd44780 #include "lcdtranstbl-hd44780.h" // hd44780 output #endif #ifdef LCD_CFontz #include "lcdtranstbl-CFontz.h" // CFontz output thanks to Stephan Schreiber. #endif #ifdef LCD_nomap #include "lcdtranstbl-nomap.h" // unmapped output (usable for curses output) #endif #define LCDMENU 0 #define LCDTITLE 1 #define LCDREPLAY 2 #define LCDMISC 3 #define LCDVOL 4 // public: cLcd::cLcd() { int i,j; connected=false; ThreadStateData.showvolume=false; ThreadStateData.newscroll=false; sock=wid=hgt=cellwid=cellhgt=0; replayDvbApi=NULL; primaryDvbApi=NULL; for (i=0;i31) ) { connected = true; wid=wid/2; LineMode=0; } // 2x40 if (!connected) { cLcd::Close(); return connected; } sock_send_string(sock,"screen_add VDR\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"screen_set VDR -heartbeat off\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"widget_add VDR line1 string\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"widget_add VDR line2 string\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"widget_add VDR line3 string\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"widget_add VDR line4 string\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"widget_add VDR prbar hbar\n"); sock_recv(sock, istring, 1024); sock_send_string(sock,"widget_set VDR prbar 1 1 0\n"); sock_recv(sock, istring, 1024); for (i=0; i (wid-1)) { snprintf( title, wid+1,"%s",string); } else { memset(title,' ',wid/2+1); snprintf(title + ( (wid-strlen(string))/2 ),wid-( (wid-strlen(string))/2 ),"%s",string); // center title for (i=0;i (wid-empty-3)) { longest1=( strlen(red) > strlen(green) ) ? red : green; longest2=( strlen(yellow) > strlen(blue) ) ? yellow : blue; longest =( strlen(longest1) > strlen(longest2) ) ? longest1: longest2; longest[strlen(longest)-1]='\0'; allchars--; } if (empty>0) { spacewid=(wid-allchars-3)/empty; if (spacewid<1) spacewid=1; char spacer[spacewid+1]; memset(spacer,'-',spacewid); spacer[spacewid]='\0'; if ( Red==NULL || Red[0]=='\0' ) strncpy(red,spacer,spacewid+1); if ( Green==NULL || Green[0]=='\0' ) strncpy(green,spacer,spacewid+1); if ( Yellow==NULL || Yellow[0]=='\0' ) strncpy(yellow,spacer,spacewid+1); if ( Blue==NULL || Blue[0]=='\0' ) strncpy(blue,spacer,spacewid+1); } #define MANYBLANKS "%s " snprintf(help,wid,MANYBLANKS,red); snprintf(help+strlen(red)+1,wid,MANYBLANKS,green); snprintf(help+wid-strlen(blue)-strlen(yellow)-1,wid,MANYBLANKS,yellow); snprintf(help+wid-strlen(blue),strlen(blue)+1,"%s",blue); for (i=0;i100) percent=100; if (percent<0) percent=0; if (begin==NULL) { BeginMutualExclusion(); ThreadStateData.barx=1; ThreadStateData.bary=1; ThreadStateData.barl=0; EndMutualExclusion(); } else { time_t t = time(NULL); if (t != LastProgress) { // output only once a second int beginw=strlen(begin); int endw=strlen(end); sprintf(workstring,"%s", begin); memset(workstring+beginw,' ',wid-beginw-endw); sprintf(workstring+wid-endw,"%s", end); cLcd::SetLine(LCDREPLAY,3,workstring); BeginMutualExclusion(); ThreadStateData.barx=beginw+1+((hgt==2)?wid:0); ThreadStateData.bary=((hgt==2)?1:4); ThreadStateData.barl=(percent*cellwid*(wid-beginw-endw))/100; EndMutualExclusion(); LastProgress = t; } } } void cLcd::SetLine(unsigned int n, unsigned int l, const char *string) { if (!connected) return; BeginMutualExclusion(); if (string != NULL) strncpy(ThreadStateData.lcdbuffer[n][l],string,wid+1); ThreadStateData.lcddirty[n][l]=true; EndMutualExclusion(); } void cLcd::SetLineC(unsigned int n, unsigned int l, const char *string) { if (!connected) return; BeginMutualExclusion(); if (string != NULL) cLcd::Copy(ThreadStateData.lcdbuffer[n][l],string,wid); ThreadStateData.lcddirty[n][l]=true; EndMutualExclusion(); } void cLcd::SetBuffer(unsigned int n, const char *l1,const char *l2,const char *l3,const char *l4) { if (!connected) return; BeginMutualExclusion(); if (l1 != NULL) strncpy(ThreadStateData.lcdbuffer[n][0],l1,wid+1); ThreadStateData.lcddirty[n][0]=true; if (l2 != NULL) strncpy(ThreadStateData.lcdbuffer[n][1],l2,wid+1); ThreadStateData.lcddirty[n][1]=true; if (l3 != NULL) strncpy(ThreadStateData.lcdbuffer[n][2],l3,wid+1); ThreadStateData.lcddirty[n][2]=true; if (l4 != NULL) strncpy(ThreadStateData.lcdbuffer[n][3],l4,wid+1); ThreadStateData.lcddirty[n][3]=true; EndMutualExclusion(); } void cLcd::SetRunning( bool nownext, const char *string1, const char *string2, const char *string3) { if (!connected) return; char line[256]; char line1[256]; snprintf(line,256,"%s %s%s%s", (string1==NULL || string1[0]=='\0')?" ":string1, (string2==NULL || string2[0]=='\0')?" ":string2, (string3==NULL || string3[0]=='\0')?"":"|", (string3==NULL || string3[0]=='\0')?" ":string3); cLcd::Copy(line1,line,2*wid); if (nownext) { cLcd::Split(line1,ThreadStateData.lcdbuffer[LCDMISC][2],ThreadStateData.lcdbuffer[LCDMISC][3]); ThreadStateData.lcddirty[LCDMISC][2]=true; ThreadStateData.lcddirty[LCDMISC][3]=true; } else { BeginMutualExclusion(); cLcd::Split(line1,ThreadStateData.lcdbuffer[LCDTITLE][2],ThreadStateData.lcdbuffer[LCDTITLE][3]); ThreadStateData.lcddirty[LCDTITLE][2]=true; ThreadStateData.lcddirty[LCDTITLE][3]=true; EndMutualExclusion(); cLcd::SetBuffer(LCDMISC,ThreadStateData.lcdbuffer[LCDTITLE][2],ThreadStateData.lcdbuffer[LCDTITLE][3],NULL,NULL); cLcd::Copy(ThreadStateData.lcdfullbuffer[LCDTITLE],line,LCDMAXFULLSTRING-3); int i = strlen(ThreadStateData.lcdfullbuffer[LCDTITLE]); ThreadStateData.lcdfullbuffer[LCDTITLE][i++]=' '; ThreadStateData.lcdfullbuffer[LCDTITLE][i++]='*'; ThreadStateData.lcdfullbuffer[LCDTITLE][i++]=' '; ThreadStateData.lcdfullbuffer[LCDTITLE][i]='\0'; ThreadStateData.newscroll=true; } } void cLcd::SummaryInit(char *string) { SummaryText = string; SummaryTextL = strlen(string); SummaryCurrent=0; } void cLcd::SummaryDown() { if (!connected) return; SummaryCurrent=( (SummaryCurrent+4*wid) < SummaryTextL )?SummaryCurrent+4*wid:SummaryCurrent; } void cLcd::SummaryUp() { if (!connected) return; SummaryCurrent=( SummaryCurrent > 4*wid )?SummaryCurrent-4*wid:0; } void cLcd::SummaryDisplay() { if ( (!connected) || (SummaryTextL < 1) ) return; char workstring[256]; unsigned int i, offset=0; for (i=0;i<4;i++) { if (SummaryCurrent+offset < SummaryTextL) { strncpy(workstring,SummaryText+SummaryCurrent+offset,wid+1); workstring[wid]='\0'; cLcd::SetLine(LCDMENU,i,workstring); offset+=wid; } else cLcd::SetLine(LCDMENU,i," "); } } void cLcd::SetCardStat(unsigned int card, unsigned int stat) { if (!connected) return; BeginMutualExclusion(); ThreadStateData.CardStat[card]=stat; EndMutualExclusion(); } void cLcd::Clear( unsigned int n) { if (!connected) return; cLcd::SetBuffer(n," "," "," "," "); } void cLcd::SetThreadState( ThreadStates newstate ) { if (!connected) return; BeginMutualExclusion(); if (ThreadStateData.State != newstate) { cLcd::LastState[(++LastStateP)%LCDMAXSTATEBUF]=newstate; ThreadStateData.State=newstate; ThreadStateData.barx=1, ThreadStateData.bary=1, ThreadStateData.barl=0; } EndMutualExclusion(); } void cLcd::PopThreadState() { BeginMutualExclusion(); LastStateP=(LastStateP+LCDMAXSTATEBUF-1)%LCDMAXSTATEBUF; ThreadStateData.State=cLcd::LastState[LastStateP]; ThreadStateData.barx=1, ThreadStateData.bary=1, ThreadStateData.barl=0; EndMutualExclusion(); } void cLcd::SetReplayDevice(cControl *DvbApi) { replayDvbApi=DvbApi; } void cLcd::SetPrimaryDevice(cDevice *DvbApi) { primaryDvbApi=DvbApi; } // private: // everything between BeginMutualExclusion(); and EndMutualExclusion(); // should have exclusive access to ThreadStateData void cLcd::BeginMutualExclusion() { CriticalArea.Lock(); } void cLcd::EndMutualExclusion() { cLcd::CriticalArea.Unlock(); } void cLcd::Copy(char *to, const char *from, unsigned int max) { // eliminates tabs, double blanks ... unsigned int i=0 , out=0; if (from != NULL) { while ((out < max) && (from[i] != '\0') ) { to[out]=(isspace(from[i]))?' ':from[i]; if ( (out>0) && (to[out-1]==' ') && ispunct(to[out]) ) {to[out-1]=to[out]; to[out]=' '; } if (!(( (out==0) && (to[out]==' ') ) || ( (out>0) && (to[out-1]==' ') && (to[out]==' ') ) || ( (out>0) && ispunct(to[out-1]) && (to[out]==' ') ) )) out++; i++; } if (out==0) to[out++]=' '; to[out]='\0'; } else { to[0]=' '; to[1]='\0'; } } void cLcd::Split(const char *string, char *string1, char *string2) { strncpy(string1,string,wid+1); if ( strlen(string) >wid ) { strncpy(string2,string+wid,wid+1); } else { string2[0]=' '; string2[1]='\0'; } } void cLcd::Write(int line, const char *string) { // used for any text output to LCDd char workstring[256]; unsigned int i,out; if (hgt > 2) { sprintf(workstring,"widget_set VDR line%d 1 %d \"",line,line); } else if (LineMode==0) { sprintf(workstring,"widget_set VDR line%d %d %d \"",line,(line==2||line==4)?wid+1:1,(line<3)?1:2 ); } else { sprintf(workstring,"widget_set VDR line%d %d %d \"",line,(line==3||line==4)?wid+1:1,(line==1||line==4)?1:2); } out=strlen(workstring); for (i=0;(i' ... replaying bool ShowStates=false; unsigned int offset; offset=(wid>36)?20:0; for (i=0; i1); t = time(NULL); now = localtime(&t); if ( offset || !( ShowStates && ((t%FullCycle) >= TimeCycle) )) { if (wid > 19) snprintf(string,wid+1,"<%s %02d.%02d %02d:%02d:%02d>", WeekDayName(now->tm_wday), now->tm_mday, now->tm_mon+1, now->tm_hour, now->tm_min,now->tm_sec); else snprintf(string,wid+1,"<%02d.%02d %02d:%02d:%02d>", now->tm_mday, now->tm_mon+1, now->tm_hour, now->tm_min,now->tm_sec); } if ( offset || ( ShowStates && ((t%FullCycle) >= TimeCycle) )) { for (i=0; iNumDevices() ; k++) SetCardStat(k,1); voltime.tv_sec=0; for (i=0;i nextLcdUpdate ) { const cEventInfo *Present = NULL; cMutexLock MutexLock; const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock); if (Schedules) { const cSchedule *Schedule = Schedules->GetSchedule(); if (Schedule) { const char *PresentTitle, *PresentSubtitle; PresentTitle = NULL; PresentSubtitle = NULL; if ((Present = Schedule->GetPresentEvent()) != NULL) { nextLcdUpdate=Present->GetTime()+Present->GetDuration(); PresentTitle = Present->GetTitle(); PresentSubtitle = Present->GetSubtitle(); if ( (!isempty(PresentTitle)) && (!isempty(PresentSubtitle)) ) SetRunning(false,Present->GetTimeString(),PresentTitle,PresentSubtitle); else if (!isempty(PresentTitle)) SetRunning(false,Present->GetTimeString(),PresentTitle); } else SetRunning(false,tr("No EPG info available."), NULL); if ((Present = Schedule->GetFollowingEvent()) != NULL) nextLcdUpdate=(Present->GetTime()GetTime():nextLcdUpdate; } } if ( nextLcdUpdate <= time(NULL) ) nextLcdUpdate=(time(NULL)/60)*60+60; else if ( nextLcdUpdate > time(NULL)+60 ) nextLcdUpdate=(time(NULL)/60)*60+60; } // replaying if ( (now.tv_usec < WakeUpCycle) && (replayDvbApi) ) { char tempbuffer[16]; replayDvbApi->GetIndex(Current, Total, false); sprintf(tempbuffer,IndexToHMSF(Total)); SetProgress(IndexToHMSF(Current),tempbuffer, (100 * Current) / Total); } // copy BeginMutualExclusion(); // all data needed for output are copied here memcpy(&OutStateData,&ThreadStateData, sizeof (cLcd::StateData)); ThreadStateData.showvolume=false; if (ThreadStateData.newscroll) { scrollpos=0; scrollwaitcnt=scrollwait; ThreadStateData.newscroll=false; } for (i=0;i (2*wid+3) ) && !(scrollcnt=(scrollcnt+1)%scrollspeed) ) { if ( (scrollpos) || (scrollwaitcnt-- < 1) ) { scrollpos=(scrollpos+1)%strlen(OutStateData.lcdfullbuffer[ScrollState]); if ( scrollpos==1 ) scrollwaitcnt=scrollwait; for (i=0; i 1500000 ) { voltime.tv_sec=0; OutStateData.barx=1; OutStateData.bary=1; OutStateData.barl=0; volume=false; } else { volume=true; OutStateData.barx=1; OutStateData.bary=((hgt==2)?2:3); OutStateData.barl=(cellwid*((hgt==2)?2:1)*wid*OutStateData.volume)/255; } } if (volume) OutStateData.State = Vol; // modes switch (OutStateData.State) { case Menu: // display menu = 0 LineMode=1; if (!volume) { OutStateData.barx=1; OutStateData.bary=1; OutStateData.barl=0; } if (PrevState != Menu) for (i=0;i<4;i++) Lcddirty[LCDMENU][i]=true; for (i=0;i<4;i++) if (Lcddirty[LCDMENU][i]) { cLcd::Write(i+1,OutStateData.lcdbuffer[LCDMENU][i]); Lcddirty[LCDMENU][i]=false; } PrevState=Menu; break; case Title: // Display 'titlescsreen' = 1 LineMode=0; if ( (now.tv_usec < WakeUpCycle) || (PrevState != Title) ) { cLcd::GetTimeDateStat(workstring,OutStateData.CardStat); cLcd::Write(1,workstring); } if (PrevState != Title) for (i=1;i<4;i++) Lcddirty[LCDTITLE][i]=true; for (i=1;i<4;i++) if (Lcddirty[LCDTITLE][i]) { cLcd::Write(i+1,OutStateData.lcdbuffer[LCDTITLE][i]); Lcddirty[LCDTITLE][i]=false; } PrevState = Title; break; case Replay: // Display date/time during replaying = 2 LineMode=1; if ( (now.tv_usec < WakeUpCycle) || (PrevState != Replay) ) { cLcd::GetTimeDateStat(workstring,OutStateData.CardStat); cLcd::Write(1,workstring); } if (PrevState != Replay) { scrollpos=0; for (i=1;i<4;i++) Lcddirty[LCDREPLAY][i]=true; } for (i=1;i<4;i++) if (Lcddirty[LCDREPLAY][i]) { cLcd::Write(i+1,OutStateData.lcdbuffer[LCDREPLAY][i]); Lcddirty[LCDREPLAY][i]=false; } PrevState = Replay; break; case Misc: // Display messages = 3 LineMode=0; if (PrevState != Misc) for (i=0;i<4;i++) Lcddirty[LCDMISC][i]=true; for (i=0;i<4;i++) if (Lcddirty[LCDMISC][i]) { cLcd::Write(i+1,OutStateData.lcdbuffer[LCDMISC][i]); Lcddirty[LCDMISC][i]=false; } PrevState = Misc; break; case Vol: // Display Volume = 4 LineMode=0; if (PrevState != Vol) for (i=0;i<4;i++) Lcddirty[LCDVOL][i]=true; for (i=0;i<4;i++) if (Lcddirty[LCDVOL][i]) { cLcd::Write(i+1,OutStateData.lcdbuffer[LCDVOL][i]); Lcddirty[LCDVOL][i]=false; } PrevState = Vol; break; default: // quite impossible :) break; } // bargraph if ( (OutStateData.barx != barx) || (OutStateData.bary != bary) || (OutStateData.barl != barl) ) { sprintf(workstring,"widget_set VDR prbar %d %d %d\n",OutStateData.barx,OutStateData.bary,OutStateData.barl); sock_send_string(sock,workstring); barx=OutStateData.barx; bary=OutStateData.bary; barl=OutStateData.barl; } // keys workstring[0]='\0'; sock_recv(sock, workstring, 256); if ( strlen(workstring) > 4 ) { for (i=0; i < (strlen(workstring)-4); i++ ) { if (workstring[i]=='k' && workstring[i+1]=='e' && workstring[i+2]=='y' && workstring[i+3]==' ') { if (workstring[i+4] == LcdShiftKey) { LcdShiftkeyPressed = ! LcdShiftkeyPressed; if (LcdShiftkeyPressed) sock_send_string(sock,"screen_set VDR -heartbeat on\n"); else sock_send_string(sock,"screen_set VDR -heartbeat off\n"); } if ( (workstring[i+4] != LcdShiftKey) ) { if (LcdShiftkeyPressed) { syslog(LOG_INFO, "shiftkey pressed: %c", workstring[i+4] ); LcdShiftkeyPressed=false; sock_send_string(sock,"screen_set VDR -heartbeat off\n"); } else { syslog(LOG_INFO, "normalkey pressed: %c", workstring[i+4] ); } } } } } usleep(WakeUpCycle-(now.tv_usec%WakeUpCycle)); // sync to systemtime for nicer time output } }