//*************************************************************************** // Group VDR/GraphTFT // File comthread.c // Date 28.10.06 // This code is distributed under the terms and conditions of the // GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. // (c) 2006-2013 Jörg Wendel //-------------------------------------------------------------------------- // Class ComThread //*************************************************************************** #include "common.h" #include "comthread.h" #include "display.h" //*************************************************************************** // Object //*************************************************************************** ComThread::ComThread(void* aDisplay, int width, int height) : cRemote("graphtft-fe") { listener = new TcpChannel(); display = aDisplay; themeWidth = width; themeHeight = height; bufferSize = maxBuf; buffer = new char[bufferSize+TB]; header = new TcpChannel::Header; running = false; timeout = 5; port = na; *host = 0; pid = 0; jpgQuality = 60; width = 720; height = 576; clientCount = 0; memset(clients, 0, sizeof(clients)); lastCheck = time(0); } ComThread::~ComThread() { if (display) ((cGraphTFTDisplay*)display)->clearComThread(); Stop(); listener->close(); delete listener; delete header; delete[] buffer; } //*************************************************************************** // Init //*************************************************************************** int ComThread::init(Renderer* aRenderer, unsigned int aPort, const char* aHost) { renderer = aRenderer; if (aHost) setHost(aHost); if (aPort) setPort(aPort); if (listener->open(port) != 0) { tell(0, "Error: Can't establish listener"); return fail; } tell(0, "Listener established!"); return success; } //*************************************************************************** // Stop //*************************************************************************** void ComThread::Stop() { if (running) { isyslog("GraphTFT plugin try to stop communication thread"); running = false; Cancel(3); } } //*************************************************************************** // Run //*************************************************************************** void ComThread::Action() { int status; TcpChannel* aClient; pid = getpid(); isyslog("GraphTFT plugin tcp communication thread started (pid=%d)", pid); running = true; while (running) { if (!(time(0) % 120)) tell(0, "still running, tcp is %sconnected", listener->isConnected() ? "" : "not "); if (!listener->isConnected()) { if (listener->listen(aClient, 1) == success) { lastCheck = time(0); listener->write(cGraphTftComService::cmdWelcome); clients[clientCount] = aClient; clientCount++; tell(0, "Client connection accepted, now " "%d clients connected", clientCount); refresh(); } } else { if ((status = listener->look(1)) != success) { if (status != TcpChannel::wrnNoEventPending) { tell(0, "Error: Communication problems, look failed, closing line!"); listener->close(); } } else if (read() != success) { listener->close(); tell(0, "Error: Communication problems, read failed, closing line!"); } else if (lastCheck+timeout < time(0)) { tell(0, "Missing check command on tcp connection, closing line!"); listener->close(); } } } isyslog("GraphTFT plugin tcp communication thread ended (pid=%d)", pid); } //*************************************************************************** // Read //*************************************************************************** int ComThread::read() { int status; TcpChannel::Header tmp; // es stehen Daten an, erst einmal den Header abholen .. if ((status = listener->read((char*)&tmp, sizeof(TcpChannel::Header))) == 0) { header->command = ntohl(tmp.command); header->size = ntohl(tmp.size); switch (header->command) { case cGraphTftComService::cmdWelcome: { tell(1, "Got welcome"); break; } case cGraphTftComService::cmdLogout: { tell(1, "Got logout from client, closing line"); listener->close(); break; } case cGraphTftComService::cmdData: { tell(7, "Got data"); status = listener->read(buffer, header->size); break; } case cGraphTftComService::cmdMouseEvent: { GraphTftTouchEvent ev; status = listener->read((char*)&ev, header->size); tell(7, "Got mouse event, button (%d) at (%d/%d)", ev.button, ev.x, ev.y); if (ev.flag & ComThread::efKeyboard) Put(ev.button); else ((cGraphTFTDisplay*)display)->mouseEvent(ev.x, ev.y, ev.button, ev.flag, ev.data); break; } case cGraphTftComService::cmdStartCalibration: { ((cGraphTFTDisplay*)display)->setCalibrate(true); break; } case cGraphTftComService::cmdStopCalibration: { ((cGraphTFTDisplay*)display)->setCalibrate(false); break; } case cGraphTftComService::cmdCheck: { lastCheck = time(0); break; } default: { tell(0, "Got unexpected protocol (%d), aborting", header->command); status = fail; break; } } } return status; } //*************************************************************************** // Put Key Code //*************************************************************************** bool ComThread::Put(uint64_t Code, bool Repeat, bool Release) { tell(5, "Put key action (%d)", Code); return cRemote::Put(Code, Repeat, Release); } //*************************************************************************** // Refresh //*************************************************************************** int ComThread::refresh() { long size; unsigned char* jpeg = 0; if (listener->isConnected()) { LogDuration ld("ComThread::refresh()", 2); // if ((size = renderer->getImageBuffer((const void*&)p, jpgQuality)) > 0) if ((size = renderer->toJpeg(jpeg, jpgQuality)) > 0) { tell(7, "Info: %ld kb to write", size/1024); if (listener->write(cGraphTftComService::cmdData, (char*)jpeg, size) != 0) { tell(0, "Error: Communication problems, closing client connection."); listener->close(); } } } return success; }