#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <sys/time.h> #include <vdr/config.h> #include <vdr/i18n.h> #include <vdr/tools.h> #include "lcd.h" #include "sockets.h" #include "lcdkeyconf.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;i<LCDMAXSTATES;i++) for (j=0;j<4;j++) { ThreadStateData.lcdbuffer[i][j][0]=' '; ThreadStateData.lcdbuffer[i][j][1]='\0'; ThreadStateData.lcddirty[i][j]=true; } ThreadStateData.State=Menu; for (i=0;i<LCDMAXSTATEBUF;i++) LastState[i]=Title; LastStateP=0; ThreadStateData.barx=1, ThreadStateData.bary=1, ThreadStateData.barl=0; for (i=0;i<LCDMAXCARDS;i++) ThreadStateData.CardStat[i]=0; } cLcd::~cLcd() { if (connected) { /*cLcd::Stop();*/ cLcd::Close(); } //YYYY } bool cLcd::Connect( char *host, unsigned int port ) { char istring[1024]; unsigned int i=0; if ( ( sock = sock_connect(host,port) ) < 1) { return connected=false; } sock_send_string(sock, "hello\n"); usleep(500000); // wait for a connect message sock_recv(sock, istring, 1024); if ( strncmp("connect LCDproc",istring,15) != 0 ) { cLcd::Close(); return connected=false; } while ( (strncmp("lcd",istring+i,3) != 0 ) && (i<(strlen(istring)-5)) ) i++; if (sscanf( istring+i,"lcd wid %d hgt %d cellwid %d cellhgt %d" , &wid, &hgt, &cellwid, &cellhgt) ) connected=true; if ((hgt < 4 ) || (wid < 16)) connected = false; // 4 lines are needed, may work with more than 4 though if ( (hgt==2) && (wid>31) ) { 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<LcdMaxKeys;i++) { sprintf(istring,"client_add_key %c\n",LcdUsedKeys[i]); sock_send_string(sock,istring); sock_recv(sock, istring, 1024); } cLcd::Start(); SetThreadState(Title); // Start thread return connected; } void cLcd::Close() { sock_close(sock); connected=false; sock=wid=hgt=cellwid=cellhgt=0; } void cLcd::Info() { // just for testing ... if (connected) printf("sock %d, wid %d, hgt %d, cellwid %d, cellhgt %d\n",sock, wid, hgt, cellwid, cellhgt); else printf("not connected\n"); } void cLcd::SetTitle( const char *string) { if (!connected) return; unsigned int i; char title[wid+1]; const char *trstring=tr("Schedule - %s"); int trstringlength=strlen(trstring)-3; if (strncmp(trstring,string,trstringlength)==0) { title[0]='>'; snprintf( title+1, wid,"%s",string+trstringlength); } else if (strlen(string) > (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<strlen(title);i++) title[i]=toupper(title[i]); // toupper } cLcd::SetLine(LCDMENU,0,title); } void cLcd::SetMain( unsigned int n, const char *string) { if (!connected) return; char line2[wid+1]; char line3[wid+1]; if (string != NULL) { cLcd::Copy(ThreadStateData.lcdfullbuffer[n],string,LCDMAXFULLSTRING-3); int i = strlen(ThreadStateData.lcdfullbuffer[n]); ThreadStateData.lcdfullbuffer[n][i++]=' '; ThreadStateData.lcdfullbuffer[n][i++]='*'; ThreadStateData.lcdfullbuffer[n][i++]=' '; ThreadStateData.lcdfullbuffer[n][i]='\0'; ThreadStateData.newscroll=true; cLcd::Copy(StringBuffer,string,2*wid); cLcd::Split(StringBuffer,line2,line3); } cLcd::SetBuffer(n,NULL,line2,line3,NULL); } void cLcd::SetHelp( unsigned int n, const char *Red, const char *Green, const char *Yellow, const char *Blue) { if (!connected) return; char help[2*wid], red[wid+1], green[wid+1], yellow[wid+1], blue[wid+1]; unsigned int allchars=0, i, empty=0, spacewid=1; char *longest, *longest1, *longest2; if ( Red==NULL || Red[0]=='\0' ) { empty++; red[0]=' '; red[1]='\0'; } else { strncpy(red,Red,wid); allchars+=strlen(red); } if ( Green==NULL || Green[0]=='\0' ) { empty++; green[0]=' '; green[1]='\0'; } else { strncpy(green,Green,wid); allchars+=strlen(green); } if ( Yellow==NULL || Yellow[0]=='\0' ) { empty++; yellow[0]=' '; yellow[1]='\0'; } else { strncpy(yellow,Yellow,wid); allchars+=strlen(yellow); } if ( Blue==NULL || Blue[0]=='\0' ) { empty++; blue[0]=' '; blue[1]='\0'; } else { strncpy(blue,Blue,wid); allchars+=strlen(blue); } while (allchars > (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;i<strlen(help);i++) help[i]=toupper(help[i]); cLcd::SetLine(n,3,help); } void cLcd::SetStatus( const char *string) { if (!connected) return; char statstring[2*wid+1]; if (string == NULL) { cLcd::SetMain(LCDMENU,StringBuffer); } else { cLcd::Copy(statstring,string,2*wid); cLcd::SetMain(LCDMENU,statstring); } } void cLcd::SetWarning( const char *string) { if (!connected) return; char statstring[2*wid+1]; if (string != NULL) { cLcd::Copy(statstring,string,2*wid); cLcd::Clear(LCDMISC); cLcd::SetMain(LCDMISC,statstring); cLcd::SetThreadState(Misc); } } void cLcd::ShowVolume(unsigned int vol, bool muted ) { if (!connected) return; BeginMutualExclusion(); ThreadStateData.volume=vol; ThreadStateData.muted=muted; ThreadStateData.showvolume=true; EndMutualExclusion(); if (ThreadStateData.muted) { cLcd::SetLine(Vol,0," "); cLcd::SetLine(Vol,1,tr("Mute")); cLcd::SetLine(Vol,2," "); cLcd::SetLine(Vol,3," "); } else { if (hgt==2) { cLcd::SetLine(Vol,0,"|---|---|---|---|---|---|---|---|---|---"); cLcd::SetLine(Vol,3," "); } else { cLcd::SetLine(Vol,0,tr("Volume ")); cLcd::SetLine(Vol,3,"|---|---|---|---|---|---|---|---|---|---"); } cLcd::SetLine(Vol,1,"|---|---|---|---|---|---|---|---|---|---"); cLcd::SetLine(Vol,2," "); } } void cLcd::SetProgress(const char *begin, const char *end, int percent) { if (!connected) return; char workstring[256]; if (percent>100) 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<strlen(string)) && (i<wid);i++) workstring[out++] = LcdTransTbl[ (unsigned char) string[i] ]; // char mapping see lcdtranstbl.h workstring[out++] = '"'; workstring[out++] = '\n'; workstring[out] = '\0'; sock_send_string(sock,workstring); } #define FullCycle 10 // seconds #define TimeCycle 7 // seconds void cLcd::GetTimeDateStat( char *string, unsigned int OutStateData[] ) { time_t t; struct tm *now; unsigned int i; const char States[] = ".-*>"; // '.' ... not present, '-' ... present, '*' ... recording, '>' ... replaying bool ShowStates=false; unsigned int offset; offset=(wid>36)?20:0; for (i=0; i<LCDMAXCARDS && (!ShowStates) ; i++) ShowStates = ShowStates || (OutStateData[i]>1); 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; i<LCDMAXCARDS; i++) { snprintf(string+offset,5," %d:%c", i,States[ OutStateData[i] ] ); offset+=4; } } } #define WakeUpCycle 125000 // us #define VolumeKeep 1500000 // us void cLcd::Action(void) { // LCD output thread unsigned int i,j, barx=1, bary=1, barl=0, ScrollState=0, ScrollLine=1; int Current=0, Total=1, scrollpos=0,scrollspeed=3,scrollcnt=0, scrollwait=10, scrollwaitcnt=10; struct timeval now, voltime; char workstring[256]; cLcd::ThreadStates PrevState=Menu; struct cLcd::StateData OutStateData; bool Lcddirty[LCDMAXSTATES][4]; bool LcdShiftkeyPressed=false; syslog(LOG_INFO, "LCD output thread started (pid=%d), display size: %dx%d", getpid(),hgt,wid); cLcd::Write(1," Welcome to V D R\0"); cLcd::Write(2,"--------------------\0"); cLcd::Write(3,"Video Disk Recorder\0"); cLcd::Write(4,"Version: "VDRVERSION"\0"); sleep(5); bool volume=false; OutStateData.showvolume=false; ThreadStateData.showvolume=false; if (primaryDvbApi) for (int k=0; k<primaryDvbApi->NumDevices() ; k++) SetCardStat(k,1); voltime.tv_sec=0; for (i=0;i<LCDMAXSTATES;i++) for (j=0;j<4;j++) Lcddirty[i][j]=true; time_t nextLcdUpdate = (time(NULL)/60)*60+60; while (true) { // main loop, wakes up every WakeUpCycle, any output to LCDd is done here gettimeofday(&now,NULL); // epg update if ( time(NULL) > 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,"No EPG info available.\0", NULL); // XXX tr !!! if ((Present = Schedule->GetFollowingEvent()) != NULL) nextLcdUpdate=(Present->GetTime()<nextLcdUpdate)?Present->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<LCDMAXSTATES;i++) for (j=0;j<4;j++) { ThreadStateData.lcddirty[i][j]=false; Lcddirty[i][j]= Lcddirty[i][j] || OutStateData.lcddirty[i][j]; } EndMutualExclusion(); // scroller if ( (OutStateData.State==PrevState) && ( PrevState == Replay || PrevState == Menu || PrevState == Title ) ) { switch (PrevState) { case Replay: ScrollState=LCDREPLAY; ScrollLine=1; break; case Menu: ScrollState=LCDMENU; ScrollLine=1; break; case Title: ScrollState=LCDTITLE; ScrollLine=2; break; default: break; } if ( ( strlen(OutStateData.lcdfullbuffer[ScrollState]) > (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<wid; i++) { OutStateData.lcdbuffer[ScrollState][ScrollLine][i]= OutStateData.lcdfullbuffer[ScrollState][(scrollpos+i)%strlen(OutStateData.lcdfullbuffer[ScrollState])]; } OutStateData.lcdbuffer[ScrollState][ScrollLine][wid]='\0'; for (i=0; i<wid; i++) { OutStateData.lcdbuffer[ScrollState][ScrollLine+1][i]= OutStateData.lcdfullbuffer[ScrollState][(scrollpos+wid+i)%strlen(OutStateData.lcdfullbuffer[ScrollState])]; } OutStateData.lcdbuffer[ScrollState][ScrollLine+1][wid]='\0'; Lcddirty[ScrollState][ScrollLine]=Lcddirty[ScrollState][ScrollLine+1]=true; } } } // volume if (OutStateData.showvolume) gettimeofday(&voltime,NULL); if ( voltime.tv_sec != 0) { // volume if ( ((now.tv_sec - voltime.tv_sec)*1000000+now.tv_usec-voltime.tv_usec ) > 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 } }