From 4f3abbda0fbeb5a377d4043bfaf8c86955bb6087 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Wed, 21 Nov 2007 23:37:56 +0000 Subject: [PATCH] Start of new live tv --- boxx.cc | 33 ++- boxx.h | 54 ++-- colour.cc | 1 + command.cc | 7 +- eventdispatcher.cc | 2 +- objects.mk | 9 +- tcp.cc | 82 +++--- tcp.h | 12 +- vchannellist.cc | 57 ++-- vdr.cc | 156 +++++++---- vdr.h | 49 +++- vdrrequestpacket.cc | 26 +- vdrrequestpacket.h | 5 + vdrresponsepacket.cc | 58 ++-- vdrresponsepacket.h | 22 +- vepg.cc | 4 + vvideolive.cc | 6 +- vvideolivetv.cc | 637 +++++++++++++++++++++++++++++++++++++++++++ vvideolivetv.h | 114 ++++++++ 19 files changed, 1101 insertions(+), 233 deletions(-) create mode 100644 vvideolivetv.cc create mode 100644 vvideolivetv.h diff --git a/boxx.cc b/boxx.cc index c9fe60a..3b2596e 100644 --- a/boxx.cc +++ b/boxx.cc @@ -65,17 +65,6 @@ void Boxx::draw() } } -int Boxx::handleCommand(int x) -{ - // A similar comment for this? FIXME make a commandreceiver thingy - return 0; -} - -void Boxx::processMessage(Message* m) -{ - // And this? -} - void Boxx::setSize(UINT w, UINT h) { area.w = w; @@ -150,12 +139,7 @@ void Boxx::blt(Region& r) destination y on screen */ - if (parent) - { - printf("parent blt???\n"); - abort(); - return; - } + if (parent) abort(); // if (parent) then this is a child boxx. It can not blt. // this shouldn't be here r.x -= area.x; @@ -199,6 +183,16 @@ int Boxx::getY() return area.y; } +int Boxx::getX2() +{ + return area.x + area.w; +} + +int Boxx::getY2() +{ + return area.y + area.h; +} + UINT Boxx::getWidth() { return area.w; @@ -209,6 +203,11 @@ UINT Boxx::getHeight() return area.h; } +Region* Boxx::getRegion() +{ + return &area; +} + // Level 1 drawing functions void Boxx::fillColour(Colour& colour) diff --git a/boxx.h b/boxx.h index 1889519..2c741f7 100644 --- a/boxx.h +++ b/boxx.h @@ -42,24 +42,41 @@ class Boxx Boxx(); virtual ~Boxx(); - virtual void setSize(UINT w, UINT h); + virtual void setSize(UINT w, UINT h); // virtual? really? void setPosition(UINT x, UINT y); // Set position on parent. Even numbers only!!! void createBuffer(); // Make this a root view that goes in the BoxStack - - void setGap(UINT gap); - - // Not really for box.. see .cc virtual void draw(); - virtual int handleCommand(int); - virtual void processMessage(Message*); - virtual bool mouseMove(int x, int y) {return false;}; - virtual bool mouseLBDOWN(int x, int y) {return false;}; - + + + void setGap(UINT gap); void setBackgroundColour(Colour& colour); void setVisible(bool isVisible); - virtual void deactivateAllControls(){}; + // The following are supposed to be abstract functions + // However, it is useful to be able to make instances of Boxx + // Therefore the following stubs are provided. + virtual int handleCommand(int x) { return 0; } + virtual void processMessage(Message* m) {} + virtual bool mouseMove(int x, int y) { return false; } + virtual bool mouseLBDOWN(int x, int y) { return false; } + virtual void deactivateAllControls() {} + + + // Get functions + int getScreenX(); // where is it on screen + int getScreenY(); + int getRootBoxOffsetX(); // where is it relative to the top-parent in the boxstack + int getRootBoxOffsetY(); + int getX(); // where is it relative to its parent + int getX2(); // .. and the right edge + int getY(); + int getY2(); + UINT getWidth(); + UINT getHeight(); + bool getVisible(); + Region* getRegion(); // Not to be used for changing the region + // Drawing functions level 1 void fillColour(Colour& colour); @@ -80,19 +97,6 @@ class Boxx int charWidth(char c); - // Following 4 used by mouse stuff only, except 1 getWidth/getHeight? in orig. vtabsman - int getScreenX(); - int getScreenY(); - int getRootBoxOffsetX(); - int getRootBoxOffsetY(); - int getX(); - int getY(); - UINT getWidth(); - UINT getHeight(); - bool getVisible(); - - - void add(Boxx*); // a boxx has a set of child boxxs void remove(Boxx*); @@ -101,7 +105,7 @@ class Boxx It's a hack (that should be deprecated?) to allow things like WSymbol to be created, do some drawing on the surface and then be deleted again, leaving the drawing present. A better design would be to create many WSymbols - one per symbol and leave them created - then the - automatic draw code (not written yet) will be able to redraw the symbols without all that code needing + automatic draw code will be able to redraw the symbols without all that code needing to be in the derived boxx's draw method. */ void TEMPADD(Boxx* child) { child->setParent(this); } diff --git a/colour.cc b/colour.cc index 32719f1..ac803b8 100644 --- a/colour.cc +++ b/colour.cc @@ -26,6 +26,7 @@ Real colours Colour Colour::BLACK(0, 0, 0); Colour Colour::RED(255, 0, 0); Colour Colour::GREEN(0, 255, 0); +Colour Colour::BLUE(0, 0, 255); Colour Colour::YELLOW(255, 255, 0); Colour Colour::VIDEOBLUE(0, 0, 150); Colour Colour::VIEWBACKGROUND(0, 0, 100); diff --git a/command.cc b/command.cc index 343832d..528a937 100644 --- a/command.cc +++ b/command.cc @@ -371,7 +371,6 @@ void Command::processMessage(Message* m) VVideoLive::getInstance()->streamEnd(); break; } - // Also connection_lost comes from player - anywhere else? // FIXME OBSELETE >> @@ -879,14 +878,14 @@ void Command::doJustConnected(VConnect* vconnect) boxstack->update(vw); // Enter pre-keys here -// handleCommand(Remote::SIX); +// handleCommand(Remote::THREE); // handleCommand(Remote::UP); // handleCommand(Remote::PLAY); // handleCommand(Remote::DOWN); // handleCommand(Remote::DOWN); // handleCommand(Remote::DOWN); -// handleCommand(Remote::OK); -// handleCommand(Remote::OK); + handleCommand(Remote::OK); + handleCommand(Remote::OK); // handleCommand(Remote::RED); } } diff --git a/eventdispatcher.cc b/eventdispatcher.cc index 08efeb3..0a23f30 100644 --- a/eventdispatcher.cc +++ b/eventdispatcher.cc @@ -40,7 +40,7 @@ bool EventDispatcher::edFindAndCall(void* userTag) { edLock(); - EDReceiver* edr; + EDReceiver* edr = NULL; EDRL::iterator i; for(i = receivers.begin(); i != receivers.end(); i++) { diff --git a/objects.mk b/objects.mk index b854ba6..e5e33e0 100644 --- a/objects.mk +++ b/objects.mk @@ -5,9 +5,9 @@ OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \ player.o playerradio.o vfeed.o afeed.o \ demuxer.o demuxervdr.o demuxerts.o stream.o draintarget.o \ region.o colour.o boxstack.o boxx.o tbboxx.o \ - vinfo.o vquestion.o vrecordinglist.o vlivebanner.o \ + vinfo.o vquestion.o vrecordinglist.o \ vmute.o vvolume.o vtimerlist.o vtimeredit.o vrecordingmenu.o \ - vchannellist.o vwelcome.o vvideolive.o vvideorec.o vepgsettimer.o \ + vchannellist.o vwelcome.o vvideorec.o vepgsettimer.o \ vchannelselect.o vserverselect.o vconnect.o vepg.o vrecmove.o \ vradiorec.o vaudioselector.o vscreensaver.o vopts.o \ wselectlist.o wjpeg.o wsymbol.o wbutton.o wtextbox.o wwss.o \ @@ -16,5 +16,6 @@ OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o \ remote.o led.o mtd.o video.o audio.o osd.o surface.o \ vmedialist.o media.o vpicture.o vpicturebanner.o \ vaudioplayer.o audioplayer.o demuxeraudio.o abstractoption.o \ - eventdispatcher.o vdrrequestpacket.o vdrresponsepacket.o - + eventdispatcher.o vdrrequestpacket.o vdrresponsepacket.o \ + vvideolivetv.o \ + vvideolive.o vlivebanner.o diff --git a/tcp.cc b/tcp.cc index 70f53ee..512a50b 100644 --- a/tcp.cc +++ b/tcp.cc @@ -26,11 +26,25 @@ #include "log.h" +#ifndef WIN32 +#define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex) +#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex) +#else +#define MUTEX_LOCK(mutex) WaitForSingleObject(*(mutex), INFINITE ) +#define MUTEX_UNLOCK(mutex) ReleaseMutex(*(mutex)) +#endif + TCP::TCP() { sock = 0; connected = 0; timeoutEnabled = 1; + +#ifndef WIN32 + pthread_mutex_init(&mutex, NULL); +#else + mutex=CreateMutex(NULL,FALSE,NULL); +#endif } TCP::~TCP() @@ -40,6 +54,10 @@ TCP::~TCP() CLOSESOCKET(sock); Log::getInstance()->log("TCP", Log::DEBUG, "Have closed"); } + +#ifdef WIN32 + CloseHandle(mutex); +#endif } void TCP::disableTimeout() @@ -216,7 +234,7 @@ int TCP::isConnected() return connected; } -int TCP::sendPacket(void* bufR, size_t count) +int TCP::sendData(void* bufR, size_t count) { size_t bytes_sent = 0; int this_write; @@ -224,6 +242,8 @@ int TCP::sendPacket(void* bufR, size_t count) unsigned char* buf = (unsigned char*)bufR; + MUTEX_LOCK(&mutex); + while (bytes_sent < count) { do @@ -238,57 +258,18 @@ int TCP::sendPacket(void* bufR, size_t count) #endif if (this_write <= 0) { + MUTEX_UNLOCK(&mutex); return(this_write); } bytes_sent += this_write; buf += this_write; } + + MUTEX_UNLOCK(&mutex); + return(count); } -UCHAR* TCP::receivePacket() -{ - ULONG packetLength; - int success; - - success = readData((UCHAR*)&packetLength, sizeof(int)); - if (!success) return NULL; - - packetLength = ntohl(packetLength); - - if (packetLength > 500000) - { - Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000"); - return NULL; - } - if (packetLength == 0) - { - Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0"); - return NULL; - } - - UCHAR* buffer = (UCHAR*) malloc(packetLength); - - success = readData(buffer, packetLength); - - if (!success) - { - Log::getInstance()->log("TCP", Log::ERR, "readData failed"); - free(buffer); - CLOSESOCKET(sock); - connected = 0; - return NULL; - } - - dataLength = packetLength; - return buffer; -} - -int TCP::getDataLength() -{ - return dataLength; -} - int TCP::readData(UCHAR* buffer, int totalBytes) { @@ -307,31 +288,30 @@ int TCP::readData(UCHAR* buffer, int totalBytes) { FD_ZERO(&readSet); FD_SET(sock, &readSet); - timeout.tv_sec = 20; + timeout.tv_sec = 2; timeout.tv_usec = 0; success = select(sock + 1, &readSet, NULL, NULL, passToSelect); if (success < 1) { - Log::getInstance()->log("TCP", Log::ERR, "Error or timeout"); return 0; // error, or timeout } #ifndef WIN32 thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead); #else - thisRead = recv(sock,(char*) &buffer[bytesRead],totalBytes - bytesRead, 0); + thisRead = recv(sock, (char*)&buffer[bytesRead], totalBytes - bytesRead, 0); #endif -// printf("read %i\n", thisRead); + //Log::getInstance()->log("TCP", Log::DEBUG, "Read %i", thisRead); if (!thisRead) { // if read returns 0 then connection is closed // in non-blocking mode if read is called with no data available, it returns -1 // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway. Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed"); + CLOSESOCKET(sock); connected = 0; return 0; } bytesRead += thisRead; - if (bytesRead == totalBytes) { return 1; @@ -340,8 +320,8 @@ int TCP::readData(UCHAR* buffer, int totalBytes) { if (++readTries == 100) { -// Log::getInstance()->log("TCP", Log::ERR, "Too many reads"); -// return 0; + Log::getInstance()->log("TCP", Log::ERR, "Too many reads"); + // return 0; } } } diff --git a/tcp.h b/tcp.h index 9b2e6be..e666340 100644 --- a/tcp.h +++ b/tcp.h @@ -36,6 +36,7 @@ #include #include #include +#include #else #include #include @@ -56,11 +57,8 @@ class TCP int isConnected(); void disableTimeout(); - int sendPacket(void *, size_t size); - UCHAR* receivePacket(); - int getDataLength(); - int readData(UCHAR* buffer, int totalBytes); + int sendData(void *, size_t size); static void dump(unsigned char* data, ULONG size); @@ -73,6 +71,12 @@ class TCP int timeoutEnabled; int dataLength; +#ifndef WIN32 + pthread_mutex_t mutex; +#else + HANDLE mutex; +#endif + static UCHAR dcc(UCHAR c); }; diff --git a/vchannellist.cc b/vchannellist.cc index ae2dd10..f9191b7 100644 --- a/vchannellist.cc +++ b/vchannellist.cc @@ -1,5 +1,5 @@ /* - Copyright 2004-2005 Chris Tallon + Copyright 2004-2007 Chris Tallon This file is part of VOMP. @@ -23,6 +23,7 @@ #include "remote.h" #include "wsymbol.h" #include "vvideolive.h" +#include "vvideolivetv.h" #include "colour.h" #include "video.h" #include "i18n.h" @@ -218,14 +219,21 @@ int VChannelList::handleCommand(int command) Channel* chan = NULL; if (chanList) chan = (Channel*)sl.getCurrentOptionData(); if (chan == NULL) return 2; - - VVideoLive* v = new VVideoLive(chanList, chan->type, this); - - v->draw(); - boxstack->add(v); - boxstack->update(v); - - v->channelChange(VVideoLive::NUMBER, chan->number); + + if (chan->type == VDR::VIDEO) + { + VVideoLiveTV* v = new VVideoLiveTV(chanList, chan->number, this); + boxstack->add(v); + v->go(); + } + else + { + VVideoLive* v = new VVideoLive(chanList, chan->type, this); + v->draw(); + boxstack->add(v); + boxstack->update(v); + v->channelChange(VVideoLive::NUMBER, chan->number); + } return 2; } @@ -267,23 +275,34 @@ void VChannelList::processMessage(Message* m) } else if (m->message == Message::CHANNEL_CHANGE) { - bool isinlist = false; - + Channel* chan = NULL; for (UINT i = 0; i < chanList->size(); i++) { if ((*chanList)[i]->number == m->parameter) { - isinlist = true; + chan = (*chanList)[i]; break; } } - if (!isinlist) return; - - VVideoLive* v = new VVideoLive(chanList, VDR::VIDEO, this); // FIXME - what's wrong with it? + if (!chan) return; - v->draw(); - boxstack->add(v); - boxstack->update(v); - v->channelChange(VVideoLive::NUMBER, m->parameter); +/* + if (chan->type == VDR::VIDEO) + { + VVideoLiveTV* v = new VVideoLiveTV(chanList, this); + v->draw(); + boxstack->add(v); + boxstack->update(v); + v->channelChange(VVideoLive::NUMBER, chan->number); + } + else + { + VVideoLive* v = new VVideoLive(chanList, chan->type, this); + v->draw(); + boxstack->add(v); + boxstack->update(v); + v->channelChange(VVideoLive::NUMBER, chan->number); + } +*/ } } diff --git a/vdr.cc b/vdr.cc index bfb281d..cb9032b 100644 --- a/vdr.cc +++ b/vdr.cc @@ -33,15 +33,6 @@ VDR* VDR::instance = NULL; -#ifndef WIN32 -#define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex) -#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex) -#else -#define MUTEX_LOCK(mutex) WaitForSingleObject(*(mutex), INFINITE ) -#define MUTEX_UNLOCK(mutex) ReleaseMutex(*(mutex)) -#endif - - VDR::VDR() { if (instance) return; @@ -49,11 +40,6 @@ VDR::VDR() initted = 0; findingServer = 0; tcp = NULL; -#ifndef WIN32 - pthread_mutex_init(&mutex, NULL); -#else - mutex=CreateMutex(NULL,FALSE,NULL); -#endif connected = false; maxChannelNumber = 0; channelNumberWidth = 1; @@ -61,9 +47,6 @@ VDR::VDR() VDR::~VDR() { -#ifdef WIN32 - CloseHandle(mutex); -#endif instance = NULL; if (initted) shutdown(); } @@ -200,19 +183,70 @@ void VDR::threadMethod() { threadSetKillable(); - UCHAR* packet; - ULONG packetLength; + ULONG channelID; + + ULONG requestID; + ULONG userDataLength; + UCHAR* userData; + + ULONG streamID; + VDR_ResponsePacket* vresp; while(1) - { - packet = (UCHAR*)tcp->receivePacket(); // cancellation point - - vresp = new VDR_ResponsePacket(); - if (packet) + { + if (!tcp->readData((UCHAR*)&channelID, sizeof(ULONG))) + { + // Error or timeout. + Log::getInstance()->log("VDR", Log::DEBUG, "Net read timeout"); + + // Do timeouts + + continue; + } + + vresp = new VDR_ResponsePacket(); + + if (channelID == CHANNEL_REQUEST_RESPONSE) + { + if (!tcp->readData((UCHAR*)&requestID, sizeof(ULONG))) break; + if (!tcp->readData((UCHAR*)&userDataLength, sizeof(ULONG))) break; + if (userDataLength > 5000000) break; // how big can these packets get? + if (userDataLength > 0) + { + userData = (UCHAR*)malloc(userDataLength); + if (!userData) break; + if (!tcp->readData(userData, userDataLength)) break; + } + else + { + userData = NULL; + } + vresp->setResponse(requestID, userData, userDataLength); + Log::getInstance()->log("VDR", Log::DEBUG, "Rxd a response packet, requestID=%lu, len=%lu", requestID, userDataLength); + } + else if (channelID == CHANNEL_STREAM) + { + if (!tcp->readData((UCHAR*)&streamID, sizeof(ULONG))) break; + if (!tcp->readData((UCHAR*)&userDataLength, sizeof(ULONG))) break; + if (userDataLength > 0) + { + userData = (UCHAR*)malloc(userDataLength); + if (!userData) break; + if (!tcp->readData(userData, userDataLength)) break; + } + else + { + userData = NULL; + } + vresp->setStream(streamID, userData, userDataLength); + Log::getInstance()->log("VDR", Log::DEBUG, "Rxd a stream packet, streamID=%lu, len=%lu", streamID, userDataLength); + } + else { - packetLength = (ULONG)tcp->getDataLength(); - vresp->set(packet, packetLength); + Log::getInstance()->log("VDR", Log::ERR, "Rxd a response packet on channel %lu !!", channelID); + delete vresp; + break; } if (!edFindAndCall(vresp)) // makes ED lock, find receiver for vresp (using ed_cb_find() ) and then call (using ed_cb_call() ) @@ -238,16 +272,24 @@ bool VDR::ed_cb_find(EDReceiver* edr, void* userTag) // Is vresp for vdrpr ? - // Not written yet. will be true - if (vdrpr); - if (vresp); - - return true; + ULONG packetChannel = vresp->getChannelID(); + if (vdrpr->receiverChannel != packetChannel) return false; + + if (packetChannel == CHANNEL_REQUEST_RESPONSE) + { + if (vdrpr->requestSerialNumber == vresp->getRequestID()) return true; + } + else if (packetChannel == CHANNEL_STREAM) + { + if (vdrpr->streamID == vresp->getStreamID()) return true; + } + + return false; } VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp) { - logger->log("VDR", Log::DEBUG, "RR"); + logger->log("VDR", Log::DEBUG, "RR %lu", vrp->getOpcode()); if (!connected) { @@ -259,31 +301,29 @@ VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp) // make a VDR_PacketReceiver // - init with serial number of request packet - VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver(); - vdrpr->receiverChannel = VDR::CHANNEL_REQUEST_RESPONSE; - vdrpr->requestSerialNumber = vrp->getSerial(); - edRegister(vdrpr); + VDR_PacketReceiver vdrpr; + vdrpr.receiverChannel = VDR::CHANNEL_REQUEST_RESPONSE; + vdrpr.requestSerialNumber = vrp->getSerial(); + edRegister(&vdrpr); edLock(); - if ((ULONG)tcp->sendPacket(vrp->getPtr(), vrp->getLen()) != vrp->getLen()) + if ((ULONG)tcp->sendData(vrp->getPtr(), vrp->getLen()) != vrp->getLen()) { edUnlock(); + edUnregister(&vdrpr); VDR_ResponsePacket* vresp = new VDR_ResponsePacket(); return vresp; // "no-response" return } // Sleep and block this thread. The sleep unlocks the mutex logger->log("VDR", Log::DEBUG, "RR sleep"); - edSleepThisReceiver(vdrpr); + edSleepThisReceiver(&vdrpr); logger->log("VDR", Log::DEBUG, "RR unsleep"); // Woken because a response packet has arrived, mutex will be locked edUnlock(); - - VDR_ResponsePacket* toReturn = vdrpr->save_vresp; - delete vdrpr; - return toReturn; + return vdrpr.save_vresp; } ///////////////////////////////////////////////////////////////////////////// @@ -304,7 +344,7 @@ bool VDR_PacketReceiver::call(void* userTag) if (receiverChannel == VDR::CHANNEL_STREAM) { // It's a stream packet. - streamReceiver->receiveData(NULL, 0); + streamReceiver->streamReceive(NULL, 0); delete (VDR_ResponsePacket*)userTag; return false; } @@ -489,14 +529,34 @@ ChannelList* VDR::getChannelsList(ULONG type) return chanList; } + int VDR::streamChannel(ULONG number) +{ + // FIXME radio + return 0; +} + +int VDR::streamChannel(ULONG number, StreamReceiver* tstreamReceiver) { VDR_RequestPacket vrp; if (!vrp.init(VDR_STREAMCHANNEL, true, sizeof(ULONG))) return 0; if (!vrp.addULONG(number)) return 0; + + VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver(); // FIXME - leaked + vdrpr->receiverChannel = VDR::CHANNEL_STREAM; + vdrpr->streamID = vrp.getSerial(); + vdrpr->streamReceiver = tstreamReceiver; + edRegister(vdrpr); + VDR_ResponsePacket* vresp = RequestResponse(&vrp); - if (vresp->noResponse()) { delete vresp; return 0; } + if (vresp->noResponse()) + { + delete vresp; + edUnregister(vdrpr); + delete vdrpr; + return 0; + } int toReturn = (int)vresp->extractULONG(); delete vresp; @@ -546,8 +606,8 @@ UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived, ULON } // Special handling for getblock - UCHAR* toReturn = vresp->getBlock_getPacket(); - *amountReceived = vresp->getLength(); + UCHAR* toReturn = vresp->getBlock_getUserData(); + *amountReceived = vresp->getUserDataLength(); delete vresp; @@ -942,9 +1002,9 @@ MediaList* VDR::getMediaList(const char* parent,int mediaType) return NULL; } - if (vresp->getLength() < 12) + if (vresp->getUserDataLength() < 12) { - Log::getInstance()->log("VDR", Log::ERR, "receiveMediaList packet too short, expected 12, got %d", vresp->getLength()); + Log::getInstance()->log("VDR", Log::ERR, "receiveMediaList packet too short, expected 12, got %d", vresp->getUserDataLength()); delete vresp; return NULL; } diff --git a/vdr.h b/vdr.h index 68f53ed..44a8e86 100644 --- a/vdr.h +++ b/vdr.h @@ -79,7 +79,7 @@ class RecMan; class StreamReceiver { public: - void receiveData(void*, ULONG) {}; + virtual void streamReceive(void*, ULONG)=0; }; class VDR_PacketReceiver : public EDReceiver // implementation in vdr.cc @@ -87,6 +87,8 @@ class VDR_PacketReceiver : public EDReceiver // implementation in vdr.cc public: virtual bool call(void* userTag); + friend class VDR; + protected: ULONG receiverChannel; // If receiverChannel == 1: @@ -94,6 +96,7 @@ class VDR_PacketReceiver : public EDReceiver // implementation in vdr.cc VDR_ResponsePacket* save_vresp; // set by ed_cb_call, used in RequestResponse // If receiverChannel == 2: + ULONG streamID; StreamReceiver* streamReceiver; }; @@ -154,6 +157,7 @@ class VDR : public Thread_TYPE, public EventDispatcher MarkList* getMarks(char* fileName); int deleteTimer(RecTimer* delTimer); ChannelList* getChannelsList(ULONG type); + int streamChannel(ULONG number, StreamReceiver*); int streamChannel(ULONG number); void getChannelPids(Channel* channel); UCHAR* getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived); @@ -201,20 +205,6 @@ class VDR : public Thread_TYPE, public EventDispatcher ULONG maxChannelNumber; ULONG channelNumberWidth; -#ifndef WIN32 - pthread_mutex_t mutex; -#else - HANDLE mutex; -#endif - - -#ifndef WIN32 - // KIS for now - pthread_t waitingRequestThread; -#else - // FIXME - Marten -#endif - const static ULONG VDR_LOGIN = 1; const static ULONG VDR_GETRECORDINGLIST = 2; const static ULONG VDR_DELETERECORDING = 3; @@ -272,4 +262,33 @@ Picture types: #define P_FRAME 2 #define B_FRAME 3 + + +Packet formats + +Packet format for an RR channel request: + +4 bytes = channel ID = 1 (request/response channel) +4 bytes = request ID (from serialNumber) +4 bytes = opcode +4 bytes = length of the rest of the packet +? bytes = rest of packet. depends on packet + + +Packet format for an RR channel response: + +4 bytes = channel ID = 1 (request/response channel) +4 bytes = request ID (from serialNumber) +4 bytes = length of the rest of the packet +? bytes = rest of packet. depends on packet + + +Packet format for a stream packet: + +4 bytes = channel ID = 2 (stream channel) +4 bytes = stream ID (from requestID) +4 bytes = length of the stream data (rest of packet) +? bytes = stream data + */ + diff --git a/vdrrequestpacket.cc b/vdrrequestpacket.cc index 25ce2cb..851d9d8 100644 --- a/vdrrequestpacket.cc +++ b/vdrrequestpacket.cc @@ -19,20 +19,13 @@ */ #include +#include +#include #include "vdrrequestpacket.h" #include "vdr.h" -/* Packet format for an RR channel request: - -4 bytes = channel ID = 1 (request/response channel) -4 bytes = request ID (from serialNumber) -4 bytes = opcode -4 bytes = length of the rest of the packet -? bytes = rest of packet. depends on packet -*/ - ULONG VDR_RequestPacket::serialNumberCounter = 1; VDR_RequestPacket::VDR_RequestPacket() @@ -42,6 +35,8 @@ VDR_RequestPacket::VDR_RequestPacket() bufUsed = 0; lengthSet = false; serialNumber = 0; + + opcode = 0; } VDR_RequestPacket::~VDR_RequestPacket() @@ -49,7 +44,7 @@ VDR_RequestPacket::~VDR_RequestPacket() free(buffer); } -bool VDR_RequestPacket::init(ULONG opcode, bool setUserDataLength, ULONG userDataLength) +bool VDR_RequestPacket::init(ULONG topcode, bool setUserDataLength, ULONG userDataLength) { if (buffer) return false; @@ -69,11 +64,12 @@ bool VDR_RequestPacket::init(ULONG opcode, bool setUserDataLength, ULONG userDat channel = VDR::CHANNEL_REQUEST_RESPONSE; serialNumber = serialNumberCounter++; + opcode = topcode; *(ULONG*)&buffer[0] = htonl(channel); *(ULONG*)&buffer[4] = htonl(serialNumber); *(ULONG*)&buffer[8] = htonl(opcode); - *(ULONG*)&buffer[12] = htonl(userDataLength); + *(ULONG*)&buffer[userDataLenPos] = htonl(userDataLength); bufUsed = headerLength; return true; @@ -84,7 +80,7 @@ bool VDR_RequestPacket::copyin(const UCHAR* src, ULONG len) if (!checkExtend(len)) return false; memcpy(buffer + bufUsed, src, len); bufUsed += len; - if (!lengthSet) *(ULONG*)&buffer[12] = htonl(bufUsed - headerLength); + if (!lengthSet) *(ULONG*)&buffer[userDataLenPos] = htonl(bufUsed - headerLength); return true; } @@ -94,7 +90,7 @@ bool VDR_RequestPacket::addString(const char* string) if (!checkExtend(len)) return false; memcpy(buffer + bufUsed, string, len); bufUsed += len; - if (!lengthSet) *(ULONG*)&buffer[12] = htonl(bufUsed - headerLength); + if (!lengthSet) *(ULONG*)&buffer[userDataLenPos] = htonl(bufUsed - headerLength); return true; } @@ -103,7 +99,7 @@ bool VDR_RequestPacket::addULONG(ULONG ul) if (!checkExtend(sizeof(ULONG))) return false; *(ULONG*)&buffer[bufUsed] = htonl(ul); bufUsed += sizeof(ULONG); - if (!lengthSet) *(ULONG*)&buffer[12] = htonl(bufUsed - headerLength); + if (!lengthSet) *(ULONG*)&buffer[userDataLenPos] = htonl(bufUsed - headerLength); return true; } @@ -112,7 +108,7 @@ bool VDR_RequestPacket::addULLONG(ULLONG ull) if (!checkExtend(sizeof(ULLONG))) return false; *(ULLONG*)&buffer[bufUsed] = htonll(ull); bufUsed += sizeof(ULLONG); - if (!lengthSet) *(ULONG*)&buffer[12] = htonl(bufUsed - headerLength); + if (!lengthSet) *(ULONG*)&buffer[userDataLenPos] = htonl(bufUsed - headerLength); return true; } diff --git a/vdrrequestpacket.h b/vdrrequestpacket.h index 3642ba6..03ff75a 100644 --- a/vdrrequestpacket.h +++ b/vdrrequestpacket.h @@ -44,6 +44,8 @@ class VDR_RequestPacket ULONG getChannel() { return channel; } ULONG getSerial() { return serialNumber; } + ULONG getOpcode() { return opcode; } + private: static ULONG serialNumberCounter; @@ -55,9 +57,12 @@ class VDR_RequestPacket ULONG channel; ULONG serialNumber; + ULONG opcode; + bool checkExtend(ULONG by); const static ULONG headerLength = 16; + const static ULONG userDataLenPos = 12; }; #endif diff --git a/vdrresponsepacket.cc b/vdrresponsepacket.cc index 121a587..3f3810e 100644 --- a/vdrresponsepacket.cc +++ b/vdrresponsepacket.cc @@ -20,40 +20,52 @@ #include "vdrresponsepacket.h" +#include "vdr.h" + VDR_ResponsePacket::VDR_ResponsePacket() { - packetLength = 0; + userDataLength = 0; packetPos = 0; - packet = NULL; + userData = NULL; getBlockRelease = false; + + channelID = 0; + + requestID = 0; + streamID = 0; } VDR_ResponsePacket::~VDR_ResponsePacket() { if (getBlockRelease) return; // don't free if it's a getblock - if (packet) free(packet); + if (userData) free(userData); } -void VDR_ResponsePacket::set(UCHAR* tpacket, ULONG tpacketLength) +void VDR_ResponsePacket::setResponse(ULONG trequestID, UCHAR* tuserData, ULONG tuserDataLength) { - packet = tpacket; - packetLength = tpacketLength; + channelID = VDR::CHANNEL_REQUEST_RESPONSE; + requestID = trequestID; + userData = tuserData; + userDataLength = tuserDataLength; } -ULONG VDR_ResponsePacket::getLength() +void VDR_ResponsePacket::setStream(ULONG tstreamID, UCHAR* tuserData, ULONG tuserDataLength) { - return packetLength; + channelID = VDR::CHANNEL_STREAM; + streamID = tstreamID; + userData = tuserData; + userDataLength = tuserDataLength; } bool VDR_ResponsePacket::end() { - return (packetPos >= packetLength); + return (packetPos >= userDataLength); } int VDR_ResponsePacket::serverError() { - if ((packetPos == 0) && (packetLength == 4) && !ntohl(*(ULONG*)packet)) return 1; + if ((packetPos == 0) && (userDataLength == 4) && !ntohl(*(ULONG*)userData)) return 1; else return 0; } @@ -61,49 +73,49 @@ char* VDR_ResponsePacket::extractString() { if (serverError()) return NULL; - int length = strlen((char*)&packet[packetPos]); - if ((packetPos + length) > packetLength) return NULL; + int length = strlen((char*)&userData[packetPos]); + if ((packetPos + length) > userDataLength) return NULL; char* str = new char[length + 1]; - strcpy(str, (char*)&packet[packetPos]); + strcpy(str, (char*)&userData[packetPos]); packetPos += length + 1; return str; } UCHAR VDR_ResponsePacket::extractUCHAR() { - if ((packetPos + sizeof(UCHAR)) > packetLength) return 0; - UCHAR uc = packet[packetPos]; + if ((packetPos + sizeof(UCHAR)) > userDataLength) return 0; + UCHAR uc = userData[packetPos]; packetPos += sizeof(UCHAR); return uc; } ULONG VDR_ResponsePacket::extractULONG() { - if ((packetPos + sizeof(ULONG)) > packetLength) return 0; - ULONG ul = ntohl(*(ULONG*)&packet[packetPos]); + if ((packetPos + sizeof(ULONG)) > userDataLength) return 0; + ULONG ul = ntohl(*(ULONG*)&userData[packetPos]); packetPos += sizeof(ULONG); return ul; } ULLONG VDR_ResponsePacket::extractULLONG() { - if ((packetPos + sizeof(ULLONG)) > packetLength) return 0; - ULLONG ull = ntohll(*(ULLONG*)&packet[packetPos]); + if ((packetPos + sizeof(ULLONG)) > userDataLength) return 0; + ULLONG ull = ntohll(*(ULLONG*)&userData[packetPos]); packetPos += sizeof(ULLONG); return ull; } long VDR_ResponsePacket::extractLONG() { - if ((packetPos + sizeof(long)) > packetLength) return 0; - long l = ntohl(*(long*)&packet[packetPos]); + if ((packetPos + sizeof(long)) > userDataLength) return 0; + long l = ntohl(*(long*)&userData[packetPos]); packetPos += sizeof(long); return l; } -UCHAR* VDR_ResponsePacket::getBlock_getPacket() +UCHAR* VDR_ResponsePacket::getBlock_getUserData() { getBlockRelease = true; - return packet; + return userData; } diff --git a/vdrresponsepacket.h b/vdrresponsepacket.h index a750551..e37edd6 100644 --- a/vdrresponsepacket.h +++ b/vdrresponsepacket.h @@ -33,11 +33,16 @@ class VDR_ResponsePacket VDR_ResponsePacket(); ~VDR_ResponsePacket(); - void set(UCHAR* packet, ULONG packetLength); + void setResponse(ULONG requestID, UCHAR* packet, ULONG packetLength); + void setStream(ULONG streamID, UCHAR* packet, ULONG packetLength); - bool noResponse() { return (packet == NULL); }; + bool noResponse() { return (userData == NULL); }; int serverError(); - ULONG getLength(); + + ULONG getUserDataLength() { return userDataLength; } + ULONG getChannelID() { return channelID; } + ULONG getRequestID() { return requestID; } + ULONG getStreamID() { return streamID; } char* extractString(); UCHAR extractUCHAR(); @@ -48,13 +53,18 @@ class VDR_ResponsePacket bool end(); // Do this a better way? - UCHAR* getBlock_getPacket(); + UCHAR* getBlock_getUserData(); private: - UCHAR* packet; - ULONG packetLength; + UCHAR* userData; + ULONG userDataLength; ULONG packetPos; + ULONG channelID; + + ULONG requestID; + ULONG streamID; + bool getBlockRelease; }; diff --git a/vepg.cc b/vepg.cc index d18787e..4982be3 100644 --- a/vepg.cc +++ b/vepg.cc @@ -353,9 +353,13 @@ int VEpg::handleCommand(int command) case Remote::DF_DOWN: case Remote::DOWN: { // cursor down the channel list + Log::getInstance()->log("VEPG", Log::DEBUG, "Down start"); + chanListbox.down(); drawData(); boxstack->update(this); + Log::getInstance()->log("VEPG", Log::DEBUG, "Down end"); + return 2; } case Remote::DF_LEFT: diff --git a/vvideolive.cc b/vvideolive.cc index 06e1864..90945be 100644 --- a/vvideolive.cc +++ b/vvideolive.cc @@ -497,9 +497,13 @@ void VVideoLive::showEPG() VEpg* vepg = new VEpg(this, currentChannel, streamType); vepg->draw(); - + + Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG draw finished"); + boxstack->add(vepg); boxstack->update(vepg); + + Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG blttd to screen"); } void VVideoLive::toggleChopSides() diff --git a/vvideolivetv.cc b/vvideolivetv.cc new file mode 100644 index 0000000..e9a387d --- /dev/null +++ b/vvideolivetv.cc @@ -0,0 +1,637 @@ +/* + Copyright 2007 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "vvideolivetv.h" + +#include "vchannellist.h" +#include "video.h" +//#include "playerlivetv.h" +#include "channel.h" +#include "boxstack.h" +#include "colour.h" +#include "osd.h" +#include "command.h" +#include "i18n.h" +#include "wtextbox.h" +#include "remote.h" +#include "vaudioselector.h" +#include "colour.h" +#include "event.h" + +VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList) +{ + vdr = VDR::getInstance(); + boxstack = BoxStack::getInstance(); + video = Video::getInstance(); + + chanList = tchanList; + vchannelList = tvchannelList; + numberWidth = (int)VDR::getInstance()->getChannelNumberWidth(); + + currentChannelIndex = 0; + previousChannelIndex = 0; + osdChannelIndex = 0; + keying = 0; + + // Convert channel number to index + UINT i; + for(i = 0; i < chanList->size(); i++) + { + if ((*chanList)[i]->number == (UINT)initialChannelNumber) + { + currentChannelIndex = i; + osdChannelIndex = i; + break; + } + } + + eventList = NULL; + + videoMode = video->getMode(); +// player = new PlayerLiveTV(Command::getInstance(), this); +// player->init(chanList); + + setSize(video->getScreenWidth(), video->getScreenHeight()); + createBuffer(); + Colour transparent(0, 0, 0, 0); + setBackgroundColour(transparent); + + dowss = false; + char* optionWSS = vdr->configLoad("General", "WSS"); + if (optionWSS) + { + if (strstr(optionWSS, "Yes")) dowss = true; + delete[] optionWSS; + } + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss); + + if (dowss) + { + wss.setFormat(video->getFormat()); + wss.setWide(true); + add(&wss); + + wssRegion.x = 0; + wssRegion.y = 6; + wssRegion.w = video->getScreenWidth(); + wssRegion.h = 2; + } + + Colour osdBack = Colour(50, 50, 50); + + osd.setBackgroundColour(osdBack); + osd.setPosition(0, video->getScreenHeight() - 150); + osd.setSize(video->getScreenWidth(), 150); + osd.setVisible(false); + add(&osd); + + clock.setBackgroundColour(Colour::BLACK); + clock.setPosition(osd.getWidth() - 100, 4); + clock.setSize(90, 30); + clock.setText("00:00"); + osd.add(&clock); + + osdChanNum.setBackgroundColour(Colour::BLACK); + osdChanNum.setPosition(40, 4); + osdChanNum.setSize((numberWidth*10) + 22, 30); // 10 px = width of number chars in font + osd.add(&osdChanNum); + + osdChanName.setBackgroundColour(Colour::BLACK); + osdChanName.setPosition(osdChanNum.getX2() + 10, 4); + osdChanName.setSize(300, 30); + osd.add(&osdChanName); + + boxRed.setBackgroundColour(Colour::RED); + boxRed.setPosition(50, 104); + boxRed.setSize(18, 16); + osd.add(&boxRed); + + boxGreen.setBackgroundColour(Colour::GREEN); + boxGreen.setPosition(220, 104); + boxGreen.setSize(18, 16); + osd.add(&boxGreen); + + boxYellow.setBackgroundColour(Colour::YELLOW); + boxYellow.setPosition(390, 104); + boxYellow.setSize(18, 16); + osd.add(&boxYellow); + + boxBlue.setBackgroundColour(Colour::BLUE); + boxBlue.setPosition(560, 104); + boxBlue.setSize(18, 16); + osd.add(&boxBlue); + + textRed.setBackgroundColour(Colour::BLACK); + textRed.setPosition(boxRed.getX()+18, 98); + textRed.setSize(120, 30); + textRed.setText("Summary"); + osd.add(&textRed); + + textGreen.setBackgroundColour(Colour::BLACK); + textGreen.setPosition(boxGreen.getX()+18, 98); + textGreen.setSize(120, 30); + textGreen.setText("Audio"); + osd.add(&textGreen); + + textYellow.setBackgroundColour(Colour::BLACK); + textYellow.setPosition(boxYellow.getX()+18, 98); + textYellow.setSize(120, 30); + textYellow.setText(""); + osd.add(&textYellow); + + textBlue.setBackgroundColour(Colour::BLACK); + textBlue.setPosition(boxBlue.getX()+18, 98); + textBlue.setSize(90, 30); + textBlue.setText("EPG"); + osd.add(&textBlue); + + sl.setPosition(70, 36); + sl.setSize(500, 58); + sl.setNoLoop(); + osd.add(&sl); +} + +VVideoLiveTV::~VVideoLiveTV() +{ +// delete player; + video->setDefaultAspect(); +} + +int VVideoLiveTV::handleCommand(int command) +{ + switch(command) + { + case Remote::STOP: + case Remote::BACK: + case Remote::MENU: + { + stop(); + vchannelList->highlightChannel((*chanList)[currentChannelIndex]); + return 4; + } + case Remote::UP: + { + // New remote only + // epg data up + sl.up(); + sl.draw(); + boxstack->update(this, osd.getRegion()); + return 2; + } + case Remote::DOWN: + { + // New remote only + // epg data down + sl.down(); + sl.draw(); + boxstack->update(this, osd.getRegion()); + return 2; + } + case Remote::LEFT: + { + // New remote only + // epg data ch down + doLeft(); + return 2; + } + case Remote::RIGHT: + { + // New remote only + // epg data ch up + doRight(); + return 2; + } + case Remote::DF_UP: + case Remote::CHANNELUP: + { + doChanUp(); + return 2; + } + case Remote::DF_DOWN: + case Remote::CHANNELDOWN: + { + doChanDown(); + return 2; + } + case Remote::PREVCHANNEL: + { + channelChange(PREVIOUS, 0); + return 2; + } + case Remote::OK: + { + doOK(); + return 2; + } + case Remote::GUIDE: + case Remote::RED: + { + return 2; + } + case Remote::FULL: + case Remote::TV: + { + toggleChopSides(); + return 2; + } + + case Remote::ZERO: + case Remote::ONE: + case Remote::TWO: + case Remote::THREE: + case Remote::FOUR: + case Remote::FIVE: + case Remote::SIX: + case Remote::SEVEN: + case Remote::EIGHT: + case Remote::NINE: + { + // key in channel number + doKey(command); + return 2; + } + + case Remote::GREEN: + { + /* + VAudioSelector* vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((Player*)player)->getCurrentAudioChannel()); + vas->setBackgroundColour(Colour::VIEWBACKGROUND); + vas->setPosition(0, getHeight()-200); + vas->draw(); + BoxStack::getInstance()->add(vas); + BoxStack::getInstance()->update(vas); + */ + } +#ifdef DEV + case Remote::YELLOW: + { + } + case Remote::BLUE: + { + } +#endif + } + + return 1; +} + +void VVideoLiveTV::go() +{ + doNowNext(); + osd.setVisible(true); + draw(); + boxstack->update(this); + // set a timer for osd deletion + + // start player +} + +void VVideoLiveTV::stop() +{ +} + +void VVideoLiveTV::doNowNext() +{ + delData(); + keying = 0; + + Channel* currentChannel = (*chanList)[osdChannelIndex]; + + char formatChanNum[20]; + SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number); + osdChanNum.setText(formatChanNum); + osdChanName.setText(currentChannel->name); + + eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number); + + if (!eventList) + { + sl.addOption(tr("No channel data available"), 0, 1); + } + else + { + sort(eventList->begin(), eventList->end(), EventSorter()); + + char tempString[300]; + char tempString2[300]; + struct tm* btime; + Event* event; + int eventListSize = eventList->size(); + for(int i = 0; i < eventListSize; i++) + { + event = (*eventList)[i]; + + //btime = localtime((time_t*)&event->time); + time_t etime = event->time; + btime = localtime(&etime); +#ifndef _MSC_VER + strftime(tempString2, 299, "%0H:%0M ", btime); +#else + strftime(tempString2, 299, "%H:%M ", btime); +#endif + SNPRINTF(tempString, 299, "%s %s", tempString2, event->title); + sl.addOption(tempString, (ULONG)event, (i==0)); + } + } +} + +void VVideoLiveTV::delData() +{ + if (eventList) + { + int eventListSize = eventList->size(); + for(int i = 0; i < eventListSize; i++) + { + delete (*eventList)[i]; + } + eventList->clear(); + delete eventList; + + } + sl.clear(); +} + +void VVideoLiveTV::doOK() +{ + if (osd.getVisible()) + { + if (osdChannelIndex == currentChannelIndex) + { + osd.setVisible(false); + draw(); + boxstack->update(this, osd.getRegion()); + } + else + { + channelChange(INDEX, osdChannelIndex); + doNowNext(); + draw(); + boxstack->update(this, osd.getRegion()); + } + } + else + { + osdChannelIndex = currentChannelIndex; + doNowNext(); + osd.setVisible(true); + draw(); + boxstack->update(this, osd.getRegion()); + // set a timer for deletion of osd + } +} + +void VVideoLiveTV::doLeft() +{ + if (osd.getVisible()) + { + osdChannelIndex = downChannel(osdChannelIndex); + } + else + { + osdChannelIndex = currentChannelIndex; + osd.setVisible(true); + } + + doNowNext(); + draw(); + boxstack->update(this, osd.getRegion()); +} + +void VVideoLiveTV::doRight() +{ + if (osd.getVisible()) + { + osdChannelIndex = upChannel(osdChannelIndex); + } + else + { + osdChannelIndex = currentChannelIndex; + osd.setVisible(true); + } + + doNowNext(); + draw(); + boxstack->update(this, osd.getRegion()); +} + +void VVideoLiveTV::doChanUp() +{ + channelChange(OFFSET, UP); + osdChannelIndex = currentChannelIndex; + doNowNext(); + draw(); + boxstack->update(this, osd.getRegion()); +} + +void VVideoLiveTV::doChanDown() +{ + channelChange(OFFSET, DOWN); + osdChannelIndex = currentChannelIndex; + doNowNext(); + draw(); + boxstack->update(this, osd.getRegion()); +} + +void VVideoLiveTV::doKey(int command) +{ + int i; + + for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i]; + keyingInput[0] = command; + keying++; + + char keyingString[numberWidth+1]; + for (i = 0; i < numberWidth; i++) keyingString[i] = '_'; + keyingString[numberWidth] = '\0'; + + for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48; + + if (keying == numberWidth) + { + UINT newChannel = 0; + for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10, i); + + channelChange(NUMBER, newChannel); + osdChannelIndex = currentChannelIndex; + doNowNext(); + draw(); + boxstack->update(this, osd.getRegion()); + } + else + { + osdChanNum.setText(keyingString); + osdChanNum.draw(); + boxstack->update(this, osd.getRegion()); + } +} + +bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData) +{ + UINT newChannel = 0; + + if (changeType == INDEX) + { + newChannel = newData; + } + else if (changeType == NUMBER) + { + UINT i; + for(i = 0; i < chanList->size(); i++) + { + if ((*chanList)[i]->number == (UINT)newData) + { + newChannel = i; + break; + } + } + + if (i == chanList->size()) + { + // no such channel + return false; + } + } + else if (changeType == OFFSET) + { + if (newData == UP) newChannel = upChannel(currentChannelIndex); + else newChannel = downChannel(currentChannelIndex); + } + else if (changeType == PREVIOUS) + { + newChannel = previousChannelIndex; + } + else + { + return false; // bad input + } + + if (newChannel == currentChannelIndex) return true; + + previousChannelIndex = currentChannelIndex; + currentChannelIndex = newChannel; + + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex); + + return true; +// player->setChannel(currentChannelIndex); +} + +void VVideoLiveTV::processMessage(Message* m) +{ + if (m->message == Message::MOUSE_LBDOWN) + { + BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press + } + else if (m->message == Message::CHANNEL_CHANGE) + { + channelChange(NUMBER, m->parameter); + } + else if (m->message == Message::EPG_CLOSE) + { + video->setMode(videoMode); + } + else if (m->message == Message::AUDIO_CHANGE_CHANNEL) + { + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %i", m->parameter); +// ((Player*)player)->setAudioChannel(m->parameter); + } + else if (m->message == Message::PLAYER_EVENT) + { +/* + switch(m->parameter) + { + case Player::CONNECTION_LOST: // connection lost detected + { + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player"); + // I can't handle this, send it to command + Message* m2 = new Message(); + m2->to = Command::getInstance(); + m2->message = Message::CONNECTION_LOST; + Command::getInstance()->postMessageNoLock(m2); + break; + } + case Player::STREAM_END: + { + // I can't handle this, send it to command - improve this + Message* m2 = new Message(); // Must be done after this thread finishes, and must break into master mutex + m2->to = Command::getInstance(); + m2->message = Message::STREAM_END; + Command::getInstance()->postMessageNoLock(m2); + break; + } + case Player::ASPECT43: + { + if (dowss) + { + Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43"); + wss.setWide(false); + wss.draw(); + BoxStack::getInstance()->update(this, &wssRegion); + } + break; + } + case Player::ASPECT169: + { + if (dowss) + { + Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169"); + wss.setWide(true); + wss.draw(); + BoxStack::getInstance()->update(this, &wssRegion); + } + break; + } + } + */ + } +} + +UINT VVideoLiveTV::upChannel(UINT index) +{ + if (index == (chanList->size() - 1)) // at the end + return 0; // so go to start + else + return index + 1; +} + +UINT VVideoLiveTV::downChannel(UINT index) +{ + if (index == 0) // at the start + return chanList->size() - 1; // so go to end + else + return index - 1; +} + +void VVideoLiveTV::toggleChopSides() +{ + if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs + + if (videoMode == Video::NORMAL) + { + videoMode = Video::LETTERBOX; + video->setMode(Video::LETTERBOX); + } + else + { + videoMode = Video::NORMAL; + video->setMode(Video::NORMAL); + } +} + diff --git a/vvideolivetv.h b/vvideolivetv.h new file mode 100644 index 0000000..26a2a79 --- /dev/null +++ b/vvideolivetv.h @@ -0,0 +1,114 @@ +/* + Copyright 2007 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef VVIDEOLIVETV_H +#define VVIDEOLIVETV_H + +#include +#include +#include + +#include "boxx.h" +#include "region.h" +#include "wwss.h" +#include "vdr.h" +#include "wtextbox.h" +#include "wselectlist.h" + +class VEpg; +class VChannelList; +class Video; +class VChannelList; +class BoxStack; +class WTextbox; +//class PlayerLiveTV; + +class VVideoLiveTV : public Boxx +{ + public: + VVideoLiveTV(ChannelList* chanList, ULONG initialChannelNumber, VChannelList* vchannelList); + ~VVideoLiveTV(); + int handleCommand(int command); + void processMessage(Message* m); + + void go(); + + bool channelChange(UCHAR changeType, UINT newData); + // changeType = INDEX = (newData is a channel index in the list) + // = NUMBER = (newData is a real channel number) + // = OFFSET = (newData is UP or DOWN) + + const static UCHAR INDEX = 1; + const static UCHAR NUMBER = 2; + const static UCHAR OFFSET = 3; + const static UCHAR PREVIOUS = 4; + const static UCHAR UP = 1; + const static UCHAR DOWN = 2; + + private: + BoxStack* boxstack; + VDR* vdr; + Video* video; +// PlayerLiveTV* player; + ChannelList* chanList; + VChannelList* vchannelList; + EventList* eventList; + int numberWidth; + int videoMode; + + UINT currentChannelIndex; + UINT previousChannelIndex; + UINT osdChannelIndex; + int keying; + int keyingInput[10]; + + void stop(); + UINT upChannel(UINT index); + UINT downChannel(UINT index); + void toggleChopSides(); + void delData(); + void doNowNext(); + void doOK(); + void doLeft(); + void doRight(); + void doChanUp(); + void doChanDown(); + void doKey(int command); + + Wwss wss; + Region wssRegion; + bool dowss; + + Boxx osd; + WTextbox clock; + WTextbox osdChanNum; + WTextbox osdChanName; + WSelectList sl; + Boxx boxRed; + Boxx boxGreen; + Boxx boxYellow; + Boxx boxBlue; + WTextbox textRed; + WTextbox textGreen; + WTextbox textYellow; + WTextbox textBlue; +}; + +#endif -- 2.39.2