From c8d5cfdcea850b02f540ca3b5b858c5bf3fd9239 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Tue, 4 Dec 2007 22:24:18 +0000 Subject: [PATCH] Live TV updates --- boxx.cc | 11 +++++++ boxx.h | 2 +- command.cc | 4 +-- playerlivetv.cc | 43 +++++++++++++++++++------- playerlivetv.h | 17 +++++----- vchannellist.cc | 10 +++--- vchannelselect.cc | 5 +++ vepg.cc | 79 ++++++++++++++++++++++++++++++++++++++--------- vepg.h | 7 +++-- vvideolive.cc | 4 +-- vvideolivetv.cc | 25 ++++++++------- 11 files changed, 146 insertions(+), 61 deletions(-) diff --git a/boxx.cc b/boxx.cc index 3b2596e..17e6dd1 100644 --- a/boxx.cc +++ b/boxx.cc @@ -208,6 +208,17 @@ Region* Boxx::getRegion() return &area; } +void Boxx::getRootBoxRegion(Region* r) +{ + // Returns a region that describes the position of this box on the box with the surface + // To be used for boxstack->update calls + + r->x = getRootBoxOffsetX(); + r->y = getRootBoxOffsetY(); + r->w = area.w; + r->h = area.h; +} + // Level 1 drawing functions void Boxx::fillColour(Colour& colour) diff --git a/boxx.h b/boxx.h index 2c741f7..929e654 100644 --- a/boxx.h +++ b/boxx.h @@ -76,7 +76,7 @@ class Boxx UINT getHeight(); bool getVisible(); Region* getRegion(); // Not to be used for changing the region - + void getRootBoxRegion(Region*); // Drawing functions level 1 void fillColour(Colour& colour); diff --git a/command.cc b/command.cc index 8edb347..e126a9f 100644 --- a/command.cc +++ b/command.cc @@ -892,8 +892,8 @@ void Command::doJustConnected(VConnect* vconnect) // 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/playerlivetv.cc b/playerlivetv.cc index f6dad3c..6616cf7 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -48,7 +48,7 @@ PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, videoStartup = false; stopNow = false; - state = 1; + state = S_STOP; video->turnVideoOn(); } @@ -123,7 +123,7 @@ void PlayerLiveTV::setAudioChannel(int newChannel) void PlayerLiveTV::go(ULONG index) { struct PLTVInstruction i; - i.instruction = 1; + i.instruction = I_SETCHANNEL; i.channelIndex = index; instructions.push(i); threadStart(); @@ -133,7 +133,7 @@ void PlayerLiveTV::setChannel(ULONG index) { logger->log("PlayerLiveTV", Log::DEBUG, "setChannel"); struct PLTVInstruction i; - i.instruction = 1; + i.instruction = I_SETCHANNEL; i.channelIndex = index; instructions.push(i); threadSignalNoLock(); @@ -143,7 +143,7 @@ void PlayerLiveTV::stop() { logger->log("PlayerLiveTV", Log::DEBUG, "stop"); struct PLTVInstruction i; - i.instruction = 2; + i.instruction = I_STOP; instructions.push(i); threadSignal(); threadStop(); @@ -478,6 +478,27 @@ void PlayerLiveTV::switchState(UCHAR newState) } } +void PlayerLiveTV::optimizeInstructionQueue() +{ + // Walk the list + + // Currently there are only 2 instruction types, so this is a bit overkill... + + struct PLTVInstruction i; + while(instructions.size() > 1) + { + i = instructions.front(); + if (i.instruction == I_SETCHANNEL) + { + instructions.pop(); // if this is the first of more than 1 command, currently it cannot possibly be relevant + } + else if (i.instruction == I_STOP) + { + return; // return here and ensure the next instruction will be stop + } + } +} + void PlayerLiveTV::threadMethod() { while(1) @@ -486,18 +507,17 @@ void PlayerLiveTV::threadMethod() { switchState(S_PREBUFFERING); videoStartup = false; - videoStartup2Counter = 0; + preBufferCount = 0; } while(!instructions.empty()) { + if (instructions.size() > 1) optimizeInstructionQueue(); + struct PLTVInstruction i = instructions.front(); instructions.pop(); - logger->log("PlayerLiveTV", Log::DEBUG, "%u %lu", i.instruction, i.channelIndex); - - - if (i.instruction == 1) + if (i.instruction == I_SETCHANNEL) { logger->log("PlayerLiveTV", Log::DEBUG, "start new stream"); @@ -511,7 +531,7 @@ void PlayerLiveTV::threadMethod() vdr->streamChannel(chan->number, this); } - else if (i.instruction == 2) + else if (i.instruction == I_STOP) { logger->log("PlayerLiveTV", Log::DEBUG, "Stopping"); switchState(S_STOP); @@ -529,7 +549,7 @@ void PlayerLiveTV::threadMethod() if (state == S_PREBUFFERING) { - if (++videoStartup2Counter == 3) + if (++preBufferCount == preBufferAmount) { switchState(S_PLAY); } @@ -538,7 +558,6 @@ void PlayerLiveTV::threadMethod() threadLock(); threadWaitForSignal(); // unlocks and waits for signal - threadUnlock(); } diff --git a/playerlivetv.h b/playerlivetv.h index 3ee74d8..3f20030 100644 --- a/playerlivetv.h +++ b/playerlivetv.h @@ -18,8 +18,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PLAYER_H -#define PLAYER_H +#ifndef PLAYERLIVETV_H +#define PLAYERLIVETV_H #include #include @@ -50,7 +50,7 @@ class DemuxerTS; struct PLTVInstruction { - UCHAR instruction; // 1 = setChannel, 2 = stop + UCHAR instruction; ULONG channelIndex; }; @@ -97,7 +97,6 @@ class PlayerLiveTV : public Thread_TYPE, public Callback, public StreamReceiver void threadPostStopCleanup() {}; private: - MessageQueue* messageQueue; void* messageReceiver; Log* logger; @@ -110,6 +109,9 @@ class PlayerLiveTV : public Thread_TYPE, public Callback, public StreamReceiver ChannelList* chanList; queue instructions; + const static UCHAR I_SETCHANNEL = 1; + const static UCHAR I_STOP = 2; + queue streamChunks; bool initted; @@ -123,13 +125,12 @@ class PlayerLiveTV : public Thread_TYPE, public Callback, public StreamReceiver bool videoStartup; bool stopNow; + int preBufferCount; + const static int preBufferAmount = 3; - int videoStartup2Counter; - - void clearStreamChunks(); void chunkToDemuxer(); - + void optimizeInstructionQueue(); }; #endif diff --git a/vchannellist.cc b/vchannellist.cc index f9191b7..054f7ea 100644 --- a/vchannellist.cc +++ b/vchannellist.cc @@ -286,23 +286,21 @@ void VChannelList::processMessage(Message* m) } if (!chan) return; -/* if (chan->type == VDR::VIDEO) { - VVideoLiveTV* v = new VVideoLiveTV(chanList, this); - v->draw(); + VVideoLiveTV* v = new VVideoLiveTV(chanList, chan->number, this); boxstack->add(v); - boxstack->update(v); - v->channelChange(VVideoLive::NUMBER, chan->number); + 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); + */ } -*/ } } diff --git a/vchannelselect.cc b/vchannelselect.cc index 8264ccb..a7e1e08 100644 --- a/vchannelselect.cc +++ b/vchannelselect.cc @@ -155,6 +155,11 @@ int VChannelSelect::handleCommand(int command) else Timers::getInstance()->setTimerD(this, 1, 3); return 2; } + case Remote::OK: + { + changeChannel(true); + return 2; + } } // allow command to drop through to other views diff --git a/vepg.cc b/vepg.cc index a12cf85..b1aaa50 100644 --- a/vepg.cc +++ b/vepg.cc @@ -49,9 +49,10 @@ VEpg* VEpg::instance = NULL; -VEpg::VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType) +VEpg::VEpg(void* tparent, UINT tcurrentChannelIndex, ULONG streamType) { instance = this; + currentChannelIndex = tcurrentChannelIndex; // PAL / NTSC sizes ----------------------- @@ -68,7 +69,7 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType) xpos = 60; ypos = 16; summaryLines = 8; - summaryLowerPadding = 16; + summaryLowerPadding = 18; chanNameYpos = 244; gridRows = 7; } @@ -79,14 +80,14 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType) xpos = 50; ypos = 10; summaryLines = 6; - summaryLowerPadding = 26; + summaryLowerPadding = 28; chanNameYpos = 206; gridRows = 5; } // initialise variables and pointers boxstack = BoxStack::getInstance(); - videoLive = v; + parent = tparent; eventList = NULL; chanList = VDR::getInstance()->getChannelsList(streamType); //TODO want to be able to display video and radio together e = 0; @@ -118,7 +119,7 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType) // progInfo.setSurface(surface); progInfo.setBackgroundColour(Colour::VIEWBACKGROUND); - progInfo.setPosition(0, progTitle.getY() + progTitle.getHeight()); + progInfo.setPosition(0, progTitle.getY2()); progInfo.setSize(300,((Surface::getFontHeight() + 4) * summaryLines) + summaryLowerPadding); progInfo.setGap(4); add(&progInfo); @@ -132,7 +133,7 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType) // create area to display list of channels // chanListbox.setSurface(surface); // add channel list - chanListbox.setPosition(0, progInfo.getY() + progInfo.getHeight() + Surface::getFontHeight() + 8); // position channel list + chanListbox.setPosition(0, progInfo.getY2() + Surface::getFontHeight() + 8); // position channel list chanListbox.setSize(150, ((Surface::getFontHeight() + 2) * gridRows) + 5); //listbox line seperation is 2 pixels chanListbox.setGap(2); add(&chanListbox); @@ -145,7 +146,7 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType) for (UINT i = 0; i < chanList->size(); i++) { chan = (*chanList)[i]; - if (i == currentChannel) + if (i == currentChannelIndex) first = 1; chan->index = chanListbox.addOption(chan->name, 0, first); first = 0; @@ -428,7 +429,20 @@ int VEpg::handleCommand(int command) if (!chanList) return 2; // select programme and display menu TODO currently just changes to selected channel - if (videoLive) videoLive->channelChange(VVideoLive::NUMBER, (*chanList)[chanListbox.getCurrentOption()]->number); + + currentChannelIndex = chanListbox.getCurrentOption(); + + if (parent) + { + Message* m = new Message(); // Must be done after this view deleted + m->from = this; + m->to = parent; + m->message = Message::CHANNEL_CHANGE; + m->parameter = (*chanList)[currentChannelIndex]->number; + Command::getInstance()->postMessageNoLock(m); + } + + setCurrentChannel(); if(command == Remote::GO) return 2; @@ -438,11 +452,11 @@ int VEpg::handleCommand(int command) case Remote::GUIDE: { // return to normal TV mode - if (videoLive) // ptr check done in case being tested from videorec + if (parent) // ptr check done in case being tested from videorec { Message* m = new Message(); // Must be done after this view deleted m->from = this; - m->to = videoLive; + m->to = parent; m->message = Message::EPG_CLOSE; Command::getInstance()->postMessageNoLock(m); } @@ -450,12 +464,44 @@ int VEpg::handleCommand(int command) } case Remote::CHANNELUP: { - if (videoLive) videoLive->channelChange(VVideoLive::OFFSET, VVideoLive::UP); + if (currentChannelIndex == (chanList->size() - 1)) // at the end + currentChannelIndex = 0; + else + ++currentChannelIndex; + + if (parent) + { + Message* m = new Message(); // Must be done after this view deleted + m->from = this; + m->to = parent; + m->message = Message::CHANNEL_CHANGE; + m->parameter = (*chanList)[currentChannelIndex]->number; + Command::getInstance()->postMessageNoLock(m); + } + + setCurrentChannel(); + return 2; } case Remote::CHANNELDOWN: { - if (videoLive) videoLive->channelChange(VVideoLive::OFFSET, VVideoLive::DOWN); + if (currentChannelIndex == 0) // at the start + currentChannelIndex = chanList->size() - 1; // so go to end + else + --currentChannelIndex; + + if (parent) + { + Message* m = new Message(); // Must be done after this view deleted + m->from = this; + m->to = parent; + m->message = Message::CHANNEL_CHANGE; + m->parameter = (*chanList)[currentChannelIndex]->number; + Command::getInstance()->postMessageNoLock(m); + } + + setCurrentChannel(); + return 2; } } @@ -627,11 +673,13 @@ void VEpg::updateEventList() } } -void VEpg::setCurrentChannel(char* chname) +void VEpg::setCurrentChannel() { - chanName.setText(chname); + chanName.setText((*chanList)[currentChannelIndex]->name); chanName.draw(); - boxstack->update(this); + Region r; + chanName.getRootBoxRegion(&r); + boxstack->update(this, &r); } void VEpg::paintCell(Event* event, int yOffset, Colour bg, Colour fg) @@ -775,3 +823,4 @@ void VEpg::processMessage(Message* m) } } } + diff --git a/vepg.h b/vepg.h index c633b49..a03eed1 100644 --- a/vepg.h +++ b/vepg.h @@ -44,13 +44,12 @@ class VVideoLive; class VEpg : public Boxx, public TimerReceiver { public: - VEpg(VVideoLive* v, UINT currentChannel, ULONG streamType); + VEpg(void* parent, UINT currentChannel, ULONG streamType); ~VEpg(); static VEpg* getInstance(); int handleCommand(int command); // deal with commands (from remote control) void draw(); // draw epg view - void setCurrentChannel(char* chname); void processMessage(Message* m); void timercall(int clientReference); @@ -60,6 +59,7 @@ class VEpg : public Boxx, public TimerReceiver void setInfo(Event* event); // display details of selected programme void drawgrid(); // redraws grid and select programme void drawData(); + void setCurrentChannel(); WSelectList chanListbox; // listbox to display available channels WTextbox progTitle; // area to display time and title of selected programme @@ -81,9 +81,10 @@ class VEpg : public Boxx, public TimerReceiver void updateEventList(); void paintCell(Event* event, int yOffset, Colour bg, Colour fg); time_t prevHour(time_t* t); - VVideoLive* videoLive; + void* parent; BoxStack* boxstack; UINT gridRows; + UINT currentChannelIndex; }; #endif diff --git a/vvideolive.cc b/vvideolive.cc index 90945be..18d580c 100644 --- a/vvideolive.cc +++ b/vvideolive.cc @@ -268,8 +268,8 @@ void VVideoLive::channelChange(UCHAR changeType, UINT newData) if (unavailable) showUnavailable(0); else stop(1); - VEpg* vepg = VEpg::getInstance(); - if(vepg) vepg->setCurrentChannel((*chanList)[currentChannel]->name); +// VEpg* vepg = VEpg::getInstance(); +// if(vepg) vepg->setCurrentChannel((*chanList)[currentChannel]->name); VLiveBanner* vlb = VLiveBanner::getInstance(); if (vlb) diff --git a/vvideolivetv.cc b/vvideolivetv.cc index 2840c0d..897cca4 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -98,7 +98,7 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V wssRegion.h = 2; } - Colour osdBack = Colour(50, 50, 50); + Colour osdBack = Colour(0, 0, 0, 128); osd.setBackgroundColour(osdBack); osd.setPosition(0, video->getScreenHeight() - 150); @@ -106,17 +106,17 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V osd.setVisible(false); add(&osd); - clock.setBackgroundColour(Colour::BLACK); + clock.setBackgroundColour(osdBack); clock.setPosition(osd.getWidth() - 100, 4); clock.setSize(90, 30); osd.add(&clock); - osdChanNum.setBackgroundColour(Colour::BLACK); + osdChanNum.setBackgroundColour(osdBack); 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.setBackgroundColour(osdBack); osdChanName.setPosition(osdChanNum.getX2() + 10, 4); osdChanName.setSize(300, 30); osd.add(&osdChanName); @@ -141,30 +141,31 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V boxBlue.setSize(18, 16); osd.add(&boxBlue); - textRed.setBackgroundColour(Colour::BLACK); + textRed.setBackgroundColour(osdBack); textRed.setPosition(boxRed.getX()+18, 98); textRed.setSize(120, 30); textRed.setText("Summary"); osd.add(&textRed); - textGreen.setBackgroundColour(Colour::BLACK); + textGreen.setBackgroundColour(osdBack); textGreen.setPosition(boxGreen.getX()+18, 98); textGreen.setSize(120, 30); textGreen.setText("Audio"); osd.add(&textGreen); - textYellow.setBackgroundColour(Colour::BLACK); + textYellow.setBackgroundColour(osdBack); textYellow.setPosition(boxYellow.getX()+18, 98); textYellow.setSize(120, 30); textYellow.setText(""); osd.add(&textYellow); - textBlue.setBackgroundColour(Colour::BLACK); + textBlue.setBackgroundColour(osdBack); textBlue.setPosition(boxBlue.getX()+18, 98); textBlue.setSize(90, 30); textBlue.setText("EPG"); osd.add(&textBlue); + sl.setBackgroundColour(osdBack); sl.setPosition(70, 36); sl.setSize(500, 58); sl.setNoLoop(); @@ -311,7 +312,7 @@ void VVideoLiveTV::go() setClock(); displayOSD(); - player->go(0); + player->go(currentChannelIndex); } void VVideoLiveTV::stop() @@ -566,7 +567,7 @@ void VVideoLiveTV::doEPG() video->setMode(Video::QUARTER); video->setPosition(170, 5); //TODO need to deal with 4:3 switching - VEpg* vepg = new VEpg(NULL, currentChannelIndex, VDR::VIDEO); + VEpg* vepg = new VEpg(this, currentChannelIndex, VDR::VIDEO); vepg->draw(); boxstack->add(vepg); boxstack->update(vepg); @@ -663,8 +664,9 @@ bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData) currentChannelIndex = newChannel; Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex); - player->setChannel(currentChannelIndex); + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex); + return true; } @@ -678,7 +680,6 @@ void VVideoLiveTV::processMessage(Message* m) { channelChange(NUMBER, m->parameter); osdChannelIndex = currentChannelIndex; - displayOSD(); } else if (m->message == Message::EPG_CLOSE) { -- 2.39.5