diff options
Diffstat (limited to 'osdworker.c')
-rw-r--r-- | osdworker.c | 756 |
1 files changed, 756 insertions, 0 deletions
diff --git a/osdworker.c b/osdworker.c new file mode 100644 index 0000000..8147ddb --- /dev/null +++ b/osdworker.c @@ -0,0 +1,756 @@ +/* + * osdworker.c: osd worker thread + * + * See the README file for copyright information and how to reach the author. + * + */ + +#include <vdr/tools.h> +#include <sys/time.h> + +#include "tools/socket.h" +#include "tools/select.h" + +#include "osdworker.h" + + +#include "vncEncodeRRE.h" +#include "vncEncodeCoRRE.h" +#include "vncEncodeHexT.h" + +////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// + +cOSDWorker *cOSDWorker::m_Instance = NULL; + +cOSDWorker::cOSDWorker(void) + : cThread("[ffnetdev] OSD via VNC") +{ + m_Active = false; + m_OSDClient = NULL; + m_pSendBuffer = NULL; + m_SendBufferSize = 0; + state = NO_CLIENT; + close_OSDclient_request = false; + + UseAlpha = false; + + m_pEncoder = NULL; + + ServerFormat.trueColour = false; + ServerFormat.bitsPerPixel = 8; + ServerFormat.depth = 8; + ServerFormat.bigEndian = false; + ServerFormat.redShift = 16; + ServerFormat.redMax = 255; + ServerFormat.greenShift = 8; + ServerFormat.greenMax = 255; + ServerFormat.blueShift = 0; + ServerFormat.blueMax = 255; + + memset(&m_OSDBuffer, 0, sizeof(m_OSDBuffer)); + + numOSDColors = 0; + memset(&OSDColors, 0, sizeof(OSDColors)); + + m_notupdatedLeft = -1; + m_notupdatedTop = -1; + m_notupdatedRight = -1; + m_notupdatedBottom = -1; + memset(&m_lasttime, 0, sizeof(m_lasttime)); + memset(&m_lastupdate, 0, sizeof(m_lastupdate)); +} + +cOSDWorker::~cOSDWorker() { + if (m_Active) Stop(); + + if (m_pEncoder != NULL) + { + m_pEncoder->LogStats(); + delete m_pEncoder; + m_pEncoder = NULL; + } + + if (m_pSendBuffer != NULL) + delete [] m_pSendBuffer; +} + + + + + +void cOSDWorker::Init(int osdport, cPluginFFNetDev *pPlugin) { + if (m_Instance == NULL) + { + m_Instance = new cOSDWorker; + m_Instance->OSDPort = osdport; + m_Instance->Start(); + m_Instance->m_pPlugin = pPlugin; + } +} + + +void cOSDWorker::Exit(void) { + if (m_Instance != NULL) { + m_Instance->Stop(); + DELETENULL(m_Instance); + } +} + +void cOSDWorker::Stop(void) { + m_Active = false; + Cancel(3); +} + +void cOSDWorker::CloseOSDClient(void) { + if (m_Instance == NULL) + return; + + m_Instance->close_OSDclient_request = true; +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Closing of OSD client socket requested.\r\n"); +#endif +} + +bool cOSDWorker::SendPlayMode(ePlayMode PlayMode) { + + // not yet implemented + return true; +} + + +void cOSDWorker::CreateSendBuffer(int SendBufferSize) +{ + if (SendBufferSize != m_SendBufferSize) + { + if (m_pSendBuffer != NULL) + delete [] m_pSendBuffer; + + m_pSendBuffer = new BYTE[SendBufferSize]; + memset(m_pSendBuffer, 0, SendBufferSize); + + m_SendBufferSize = SendBufferSize; + } +} + +bool cOSDWorker::ClearScreen(void) +{ + if (m_Instance == NULL) + return false; + + // this should be improved; + // 1) maybe we should send a our very "special" pseudo encoding[CLEAR_SCREEN] to our "special" VNC client to get an empty screen really fast + bool bRetVal = false; + memset(&(m_Instance->m_OSDBuffer), 0, 720*576); + memset(&(m_Instance->m_lasttime), 0, sizeof(m_Instance->m_lasttime)); + bRetVal = SendScreen(720,0,0,720,576,&(m_Instance->m_OSDBuffer)); + + rfbBellMsg fu; + fu.type=rfbBell; + OSDWrite((unsigned char*)&fu, sz_rfbBellMsg); + + return bRetVal; +} + + +bool cOSDWorker::SendScreen(unsigned int stride, unsigned int x1, unsigned int y1, unsigned int w, unsigned int h, const void *data) +{ + if (m_Instance == NULL) + return false; + + rfbFramebufferUpdateMsg fu; + rfbFramebufferUpdateRectHeader furh; + + unsigned int x; + unsigned int y; + for (y=0; y<h; y++) + for (x=0; x<w; x++) + m_Instance->m_OSDBuffer[(720*(y+y1))+x+x1] = *((unsigned char *)data+(y*stride)+x); + + x = x1; + y = y1; + x1 = (m_Instance->m_notupdatedLeft != -1 && m_Instance->m_notupdatedLeft < (int)x1) + ? m_Instance->m_notupdatedLeft : x1; + y1 = (m_Instance->m_notupdatedTop != -1 && m_Instance->m_notupdatedTop < (int)y1) + ? m_Instance->m_notupdatedTop : y1; + + w = (m_Instance->m_notupdatedRight != -1 && m_Instance->m_notupdatedRight > (int)(x1 + w)) + ? m_Instance->m_notupdatedRight - x1 : w + (x - x1); + h = (m_Instance->m_notupdatedBottom != -1 && m_Instance->m_notupdatedBottom > (int)(y1 + h)) + ? m_Instance->m_notupdatedBottom - y1 : h + (y - y1); + + struct timeval curtime; + gettimeofday(&curtime, 0); + curtime.tv_sec = curtime.tv_sec - (((int)curtime.tv_sec / 1000000) * 1000000); + if ((curtime.tv_sec * 1000 + (curtime.tv_usec / 1000) < m_Instance->m_lasttime.tv_sec * 1000 + (m_Instance->m_lasttime.tv_usec / 1000) + 100) || + (m_Instance->m_pEncoder == NULL)) + { + m_Instance->m_notupdatedLeft = (int)x1; + m_Instance->m_notupdatedTop = (int)y1; + m_Instance->m_notupdatedRight = (int)(x1 + w); + m_Instance->m_notupdatedBottom = (int)(y1 + h); + m_Instance->m_lasttime = curtime; + + return false; + } + else + { + m_Instance->m_notupdatedLeft = -1; + m_Instance->m_notupdatedTop = -1; + m_Instance->m_notupdatedRight = -1; + m_Instance->m_notupdatedBottom = -1; + m_Instance->m_lasttime = curtime; + m_Instance->m_lastupdate = curtime; + } + + if ((m_Instance->state==HANDSHAKE_OK) && (m_Instance->m_pEncoder != NULL)) { + RECT rect = {x1, y1, x1 + w, y1 + h}; + fu.type=rfbFramebufferUpdate; + fu.nRects=Swap16IfLE(1); + OSDWrite((unsigned char*)&fu, sz_rfbFramebufferUpdateMsg); + + int BufferSize = m_Instance->m_pEncoder->RequiredBuffSize(w, h); + m_Instance->CreateSendBuffer(BufferSize); + BufferSize = m_Instance->m_pEncoder->EncodeRect( &(m_Instance->m_OSDBuffer[0]), m_Instance->m_pSendBuffer, rect); +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Send OSD Data %d Bytes\n", BufferSize); +#endif + dsyslog("[ffnetdev] VNC: Send OSD Data %d Bytes\n", BufferSize); + OSDWrite((unsigned char*)m_Instance->m_pSendBuffer, BufferSize); + + return true; + } + else { + return false; + } +} + + +bool cOSDWorker::SendCMAP(int NumColors, const tColor *Colors) +{ + if (m_Instance == NULL) + return false; + + rfbSetColourMapEntriesMsg scme; + CARD16 red; + CARD16 green; + CARD16 blue; + CARD16 alpha; + + int i; + + if ((m_Instance->state==HANDSHAKE_OK) && !(m_Instance->ClientFormat.trueColour)) { + scme.type=rfbSetColourMapEntries; + scme.firstColour = Swap16IfLE(0); + scme.nColours = Swap16IfLE((CARD16)NumColors); + + OSDWrite((unsigned char*)&scme, sz_rfbSetColourMapEntriesMsg); + + for(i=0; i<NumColors; i++) + { + red = ((Colors[i]&0x00FF0000) >> 16); + green = ((Colors[i]&0x0000FF00) >> 8); + blue = ((Colors[i]&0x000000FF) ); + + if (m_Instance->UseAlpha) { + alpha = ((Colors[i]&0xFF000000) >> 24); + OSDWrite( (unsigned char*) &alpha, 2); + } + + OSDWrite( (unsigned char*) &red, 2); + OSDWrite( (unsigned char*) &green, 2); + OSDWrite( (unsigned char*) &blue, 2); + + m_Instance->OSDColors[i] = Colors[i]; + } + m_Instance->numOSDColors = NumColors; + if (m_Instance->m_pEncoder != NULL) + m_Instance->m_pEncoder->SetLocalFormat(m_Instance->ServerFormat, 720, 576); + + return true; + } + else { + for (i=0; i<NumColors; i++) + m_Instance->OSDColors[i] = Colors[i]; + m_Instance->numOSDColors = NumColors; + if (m_Instance->m_pEncoder != NULL) + m_Instance->m_pEncoder->SetLocalFormat(m_Instance->ServerFormat, 720, 576); + + return false; + } + + +} + +bool cOSDWorker::OSDWrite(unsigned char *data, unsigned int data_length) +{ + if (m_Instance == NULL) + return false; + + if (m_Instance->m_OSDClient!=NULL) { + if (m_Instance->m_OSDClient->IsOpen()) + { + //fprintf(stderr, "[ffnetdev] VNC: Trying to send...\n"); + if (!m_Instance->m_OSDClient->SafeWrite(data, data_length)) + { + CloseOSDClient(); + return false; + } + } //else fprintf(stderr, "[ffnetdev] VNC: Cannot send...\n"); + //for (unsigned int i=0; i<data_length; i++) fprintf(stderr,"%02X ",*(data+i)); + //fprintf(stderr,"\n"); + + return true; + } + return false; +} + +bool cOSDWorker::RFBRead(char *buffer, int len) +{ + if (m_Instance == NULL) + return false; + + if ( m_OSDClient->Read(buffer, len)==0 ) { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Client closed connection.\n"); +#endif + isyslog("[ffnetdev] VNC: Connection closed: client %s:%d", + m_OSDClient->RemoteIp().c_str(), m_OSDClient->RemotePort()); + state = NO_CLIENT; + m_Instance->m_OSDClient->Close(); + delete m_pEncoder; + m_pEncoder = NULL; + + return false; + } + else + return true; +} + +void cOSDWorker::HandleClientRequests(cTBSelect *select) +{ + if ( select->CanRead(*m_OSDClient) ) { + rfbClientToServerMsg msg; + + if (!RFBRead((char*)&msg, 1)) + return; + + switch (msg.type) { + + case rfbSetPixelFormat: if (!RFBRead( ((char*)&msg.spf)+1, sz_rfbSetPixelFormatMsg-1)) + return; + dsyslog("[ffnetdev] VNC: SetPixelFormat\n"); + dsyslog("[ffnetdev] VNC: ->bitsPerPixel: %d\n",msg.spf.format.bitsPerPixel); + dsyslog("[ffnetdev] VNC: ->depth: %d\n",msg.spf.format.depth); + dsyslog("[ffnetdev] VNC: ->bigEndian: %d\n",msg.spf.format.bigEndian); + dsyslog("[ffnetdev] VNC: ->trueColour: %d\n",msg.spf.format.trueColour); + dsyslog("[ffnetdev] VNC: ->redMax: %d\n",Swap16IfLE(msg.spf.format.redMax)); + dsyslog("[ffnetdev] VNC: ->greenMax: %d\n",Swap16IfLE(msg.spf.format.greenMax)); + dsyslog("[ffnetdev] VNC: ->blueMax: %d\n",Swap16IfLE(msg.spf.format.blueMax)); + dsyslog("[ffnetdev] VNC: ->redShift: %d\n",msg.spf.format.redShift); + dsyslog("[ffnetdev] VNC: ->greenShift: %d\n",msg.spf.format.greenShift); + dsyslog("[ffnetdev] VNC: ->blueShift: %d\n",msg.spf.format.blueShift); + + if ( (msg.spf.format.bitsPerPixel!=8 ) + &&(msg.spf.format.bitsPerPixel!=16) + &&(msg.spf.format.bitsPerPixel!=32)) { + esyslog("[ffnetdev] SORRY!!! VNC client requested unsupported pixel format! Closing connection...\n"); + CloseOSDClient(); + return; + } + else + ClientFormat = msg.spf.format; + dsyslog("[ffnetdev] VNC: RGB %d %d %d %d %d %d\n", + ClientFormat.redShift, ClientFormat.redMax, ClientFormat.greenShift, ClientFormat.greenMax, ClientFormat.blueShift, ClientFormat.blueMax); + break; + case rfbFixColourMapEntries: if (!RFBRead( ((char*)&msg.fcme)+1, sz_rfbFixColourMapEntriesMsg-1)) + return; + isyslog("[ffnetdev] VNC: FixColourMapEntries (ignored).\n"); + break; + case rfbSetEncodings: if (!RFBRead( ((char*)&msg.se)+1, sz_rfbSetEncodingsMsg-1)) + return; + + dsyslog("[ffnetdev] VNC: SetEncodings: Client offers %d encodings:\n", Swap16IfLE(msg.se.nEncodings)); + + CARD32 encodings[16]; + if (!RFBRead( ((char*)&encodings), Swap16IfLE(msg.se.nEncodings)*sizeof(CARD32) )) + return; + + for (int i=0;i<Swap16IfLE(msg.se.nEncodings);i++) { + switch (Swap32IfLE(encodings[i])) { + case rfbEncodingRaw: + if (m_pEncoder == NULL) + { + dsyslog("[ffnetdev] VNC: ->RAW encoding.\n"); + m_pEncoder = new vncEncoder(); + } + break; + case rfbEncodingCopyRect: + isyslog("[ffnetdev] VNC: ->CopyRect encoding(not supported).\n"); + break; + case rfbEncodingRRE: + if (m_pEncoder == NULL) + { + dsyslog("[ffnetdev] VNC: ->RRE encoding.\n"); + m_pEncoder = new vncEncodeRRE(); + } + break; + case rfbEncodingCoRRE: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->CoRRE encoding(not supported).\n"); + m_pEncoder = new vncEncodeCoRRE(); + } + break; + case rfbEncodingHextile: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->Hextile encoding(not supported).\n"); + m_pEncoder = new vncEncodeHexT(); + } + break; + case rfbEncodingZlib: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->Zlib encoding(not supported).\n"); + //m_pEncoder = new vncEncodeZlib(); + } + break; + case rfbEncodingTight: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->Tight encoding(not supported).\n"); + //m_pEncoder = new vncEncodeTight(); + } + break; + case rfbEncodingZlibHex: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->ZlibHex encoding(not supported).\n"); + //m_pEncoder = new vncEncodeZlibHex(); + } + break; + case rfbEncodingZRLE: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->ZRLE encoding(not supported).\n"); + } + break; + case rfbEncSpecialUseAlpha: + if (m_pEncoder == NULL) + { + isyslog("[ffnetdev] VNC: ->Special FFnetDev Encoding: client wants alpha channel.\n"); + } + UseAlpha = true; + break; + default: + esyslog("[ffnetdev] VNC: ->Unknown encoding or unknown pseudo encoding.\n"); + } + + if (m_pEncoder != NULL) + { + m_pEncoder->Init(); + m_pEncoder->SetLocalFormat(ServerFormat, 720, 576); + m_pEncoder->SetCompressLevel(6); + m_pEncoder->SetQualityLevel(9); + m_pEncoder->SetRemoteFormat(ClientFormat); + } + } + break; + case rfbFramebufferUpdateRequest: + if (!RFBRead( ((char*)&msg.fur)+1, sz_rfbFramebufferUpdateRequestMsg-1)) + return; +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: FramebufferUpdateRequest: Client wants %s:\n", + msg.fur.incremental? "incremental update":"complete update"); + fprintf(stderr, "[ffnetdev] VNC: x: %d, y: %d, w: %d, h: %d\n", + Swap16IfLE(msg.fur.x), + Swap16IfLE(msg.fur.y), + Swap16IfLE(msg.fur.w), + Swap16IfLE(msg.fur.h) + ); +#endif + dsyslog("[ffnetdev] VNC: FramebufferUpdateRequest: Client wants %s:\n", + msg.fur.incremental? "incremental update":"complete update"); + dsyslog("[ffnetdev] VNC: x: %d, y: %d, w: %d, h: %d\n", + Swap16IfLE(msg.fur.x), + Swap16IfLE(msg.fur.y), + Swap16IfLE(msg.fur.w), + Swap16IfLE(msg.fur.h) + ); + if (FirstUpdateRequest) { + ClearScreen(); + FirstUpdateRequest = false; + } + else + { + SendCMAP(numOSDColors, OSDColors); + SendScreen(720, //stride + Swap16IfLE(msg.fur.x), Swap16IfLE(msg.fur.y), + Swap16IfLE(msg.fur.w), Swap16IfLE(msg.fur.h), + &m_OSDBuffer); + } + break; + case rfbKeyEvent: if (!RFBRead( ((char*)&msg.ke)+1, sz_rfbKeyEventMsg-1)) + return; +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: KeyEvent\n"); +#endif + dsyslog("[ffnetdev] VNC: KeyEvent\n"); + cMyRemote *pRemote; + if ((pRemote = m_pPlugin->GetRemote()) != NULL) { + if (msg.ke.down) + pRemote->Put(Swap32IfLE(msg.ke.key), false, false); + else + pRemote->Put(Swap32IfLE(msg.ke.key), false, true); + } +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Remote: %04X\n", msg.ke.key); +#endif + dsyslog("[ffnetdev] VNC: Remote: %04X\n", msg.ke.key); + break; + case rfbPointerEvent: if (!RFBRead( ((char*)&msg.pe)+1, sz_rfbPointerEventMsg-1)) + return; + //fprintf(stderr, "[ffnetdev] VNC: PointerEvent\n"); + break; + case rfbClientCutText: if (!RFBRead( ((char*)&msg.cct)+1, sz_rfbClientCutTextMsg-1)) + return; +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: ClientCutText\n"); +#endif + dsyslog("[ffnetdev] VNC: ClientCutText\n"); + break; + default: +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Unknown RFB message.\n"); +#endif + dsyslog("[ffnetdev] VNC: Unknown RFB message.\n"); + } + } +} + +void cOSDWorker::Action(void) { + cTBSelect select; + cTBSocket m_OSDListen; + + const char* m_ListenIp = "0.0.0.0"; + uint m_OSDListenPort = OSDPort; + + m_OSDClient = new cTBSocket; + + m_Active = true; + + if (!m_OSDListen.Listen(m_ListenIp, m_OSDListenPort, 1)) { + esyslog("[ffnetdev] VNC: Couldn't listen %s:%d: %s", m_ListenIp, m_OSDListenPort, strerror(errno)); + m_Active = false; + } + else + isyslog("[ffnetdev] VNC: Listening on port %d", m_OSDListenPort); + + + while (m_Active) { + select.Clear(); + + if (state==NO_CLIENT) + select.Add(m_OSDListen, false); + else + select.Add(*m_OSDClient, false); + + int numfd; + /* React on status change of any of the above file descriptor */ + if ((numfd=select.Select(1000)) < 0) { + if (!m_Active) // Exit was requested while polling + continue; + esyslog("FFNetDev: Fatal error, FFNetDev exiting: %s", strerror(errno)); + m_Active = false; + continue; + } + + //DEBUG + /* + fprintf(stderr, "Num_FD OSD: %d\n", numfd); + + if (select.CanRead(m_OSDListen) || select.CanWrite(m_OSDListen)) + fprintf (stderr, "m_OSDListen can act.\n"); + if (select.CanRead(*m_OSDClient) || select.CanWrite(*m_OSDClient)) + fprintf (stderr, "m_OSDClient can act.\n"); + */ + //fprintf(stderr, "State: %d\n",state); + + int res; + switch (state) { + + case NO_CLIENT: /* Accept connecting OSD clients */ + if (select.CanRead(m_OSDListen) ) { + if (m_OSDClient->Accept(m_OSDListen)) { + isyslog("[ffnetdev] VNC: Accepted client %s:%d", + m_OSDClient->RemoteIp().c_str(), m_OSDClient->RemotePort()); + state = CLIENT_CONNECTED; + /* Sending RFB protocol version */ + rfbProtocolVersionMsg msg; + sprintf(msg, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion); + if (!m_OSDClient->SafeWrite(&msg, sz_rfbProtocolVersionMsg)) + { + state = NO_CLIENT; + } + else + { +// m_pPlugin->SetPrimaryDevice(); + } + break; + + } + else { + esyslog("[ffnetdev] VNC: Couldn't accept : %s", strerror(errno)); + state = NO_CLIENT; + m_Active = false; + continue; + } + } + break; + + case CLIENT_CONNECTED: + rfbProtocolVersionMsg pvmsg; + res = m_OSDClient->Read(&pvmsg, sz_rfbProtocolVersionMsg); +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Client wants RFB protocol version %s\n", pvmsg); +#endif + dsyslog("[ffnetdev] VNC: Client wants RFB protocol version %s\n", pvmsg); + if (1) {//FIXME:protocol ok + state = PROTOCOL_OK; + /* Sending security type */ + CARD32 secmsg; + secmsg = Swap32IfLE(rfbNoAuth); + if (!m_OSDClient->SafeWrite(&secmsg, sizeof(secmsg))) + { + state = NO_CLIENT; + break; + } + } + else { + state = NO_CLIENT; +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Client wants unsupported protocol version.\n"); +#endif + dsyslog("[ffnetdev] VNC: Client wants unsupported protocol version.\n"); + if ( m_OSDClient->Close() ) { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Client socket closed successfully.\n"); +#endif + isyslog("[ffnetdev] VNC: Connection closed."); + } + else { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Error closing client socket.\n"); +#endif + esyslog("[ffnetdev] VNC: Error closing connection."); + m_Active=false; + continue; + } + } + break; + case PROTOCOL_OK: /* Since we do not need authentication challenge(rfbNoAuth), proceed to next state */ + state = AUTHENTICATED; + break; + case AUTHENTICATED: + rfbClientInitMsg cimsg; + res = m_OSDClient->Read(&cimsg, sz_rfbClientInitMsg); +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Client wants %s desktop(ignored).\n", + cimsg.shared ? "shared":"non-shared"); +#endif + dsyslog("[ffnetdev] VNC: Client wants %s desktop(ignored).\n", + cimsg.shared ? "shared":"non-shared"); + + rfbPixelFormat pxfmt; + pxfmt.bitsPerPixel = 8; + pxfmt.depth = 8; + pxfmt.bigEndian = 0; + pxfmt.trueColour = 0; + pxfmt.redMax = 0; + pxfmt.greenMax = 0; + pxfmt.blueMax = 0; + pxfmt.redShift = 0; + pxfmt.greenShift = 0; + pxfmt.blueShift = 0; + pxfmt.pad1 = 0; + pxfmt.pad2 = 0; + + rfbServerInitMsg simsg; + simsg.framebufferWidth = Swap16IfLE(720); + simsg.framebufferHeight = Swap16IfLE(576); + simsg.format = pxfmt; + simsg.nameLength = Swap32IfLE(7); + if (!m_OSDClient->SafeWrite(&simsg, sizeof(simsg))) + { + state = NO_CLIENT; + break; + } + + CARD8 name[7]; + strcpy((char*)&name, "VDR-OSD"); + if (!m_OSDClient->SafeWrite(&name, 7)) + { + state = NO_CLIENT; + break; + } + + state = HANDSHAKE_OK; + FirstUpdateRequest = true; + break; + + case HANDSHAKE_OK: + + /* Check for closed OSD connection */ + if (close_OSDclient_request==true) { + close_OSDclient_request = false; + state = NO_CLIENT; + UseAlpha = false; + + delete m_pEncoder; + m_pEncoder = NULL; + + m_pPlugin->RestorePrimaryDevice(); + + if ( m_OSDClient->Close() ) { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Client socket closed successfully.\n"); +#endif + isyslog("[ffnetdev] VNC: Connection closed."); + } + else { +#ifdef DEBUG + fprintf(stderr, "[ffnetdev] VNC: Error closing client socket.\n"); +#endif + esyslog("[ffnetdev] VNC: Error closing connection."); + m_Active=false; + continue; + } + } + HandleClientRequests(&select); + + break; + default: fprintf(stderr, "[ffnetdev] VNC: Undefined state! This is a bug! Please report.\n"); + esyslog("[ffnetdev] VNC: Fatal error, FFNetDev exiting: undefined state"); + m_Active = false; + continue; + } + + + + struct timeval curtime; + gettimeofday(&curtime, 0); + curtime.tv_sec = curtime.tv_sec - (((int)curtime.tv_sec / 1000000) * 1000000); + if ((curtime.tv_sec * 1000 + (curtime.tv_usec / 1000) > m_lastupdate.tv_sec * 1000 + (m_lastupdate.tv_usec / 1000) + 500) && + (m_notupdatedLeft != -1) && (m_notupdatedTop != -1) && (m_notupdatedRight != -1) && + (m_notupdatedBottom != -1)) + { + memset(&m_lasttime, 0, sizeof(m_lasttime)); + SendScreen(720, m_notupdatedLeft, m_notupdatedTop, + m_notupdatedRight - m_notupdatedLeft, + m_notupdatedBottom - m_notupdatedTop, + &(m_Instance->m_OSDBuffer[m_notupdatedTop * 720 + m_notupdatedLeft])); + } + } // while(m_Active) + +} |