From bb375963684f2ac0fa80016ffd12f976f60a9596 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 28 Sep 2014 18:48:22 +0200 Subject: [PATCH] Channel logo support, PNG hardware support, bugfixes and channel logos in all menus --- imageomx.cc | 37 +++++++++++++++++++++++++++++----- imageomx.h | 8 ++++++++ osdopenvg.cc | 46 +++++++++++++++++++++++++------------------ osdopenvg.h | 4 ++-- osdvector.cc | 15 +++++++++++++- vchannellist.cc | 10 +++++++++- vdr.cc | 31 ++++++++++++++++++++++++++--- vdr.h | 1 + vdrcommand.h | 1 + vepglistadvanced.cc | 32 ++++++++++++++++++++++++++---- vvideolivetv.cc | 48 +++++++++++++++++++++++++++++++++++++++------ vvideolivetv.h | 2 ++ 12 files changed, 194 insertions(+), 41 deletions(-) diff --git a/imageomx.cc b/imageomx.cc index 5668cf3..8c288fe 100644 --- a/imageomx.cc +++ b/imageomx.cc @@ -37,6 +37,7 @@ ImageOMX::ImageOMX(OsdVector::PictureReader * treader):OsdVector::PictureDecoder omx_egl_render/*dec*/=NULL; buf_head_egl=NULL; + curformat = Unsupported; } ImageOMX::~ImageOMX() @@ -168,7 +169,14 @@ int ImageOMX::AllocateCodecsOMX(unsigned char * buffer, unsigned int length) ft_type.nPortIndex=omx_image_input_port; - ft_type.eCompressionFormat=OMX_IMAGE_CodingJPEG; + switch (curformat) + { + case Jpeg: ft_type.eCompressionFormat=OMX_IMAGE_CodingJPEG; + break; + case PNG: ft_type.eCompressionFormat=OMX_IMAGE_CodingPNG; + break; + } + error=OMX_SetParameter(omx_imag_decode,OMX_IndexParamImagePortFormat,&ft_type); if (error!=OMX_ErrorNone){ @@ -244,7 +252,11 @@ unsigned char* ImageOMX::decodePicture(LoadIndex index, unsigned char * buffer, // Log::getInstance()->log("Image", Log::DEBUG, // "decodePicture 1"); EGLPictureCreator * pictcreat =dynamic_cast(Osd::getInstance()); - if (buffer[0]!= 0xff || buffer[1] !=0xd8) return false; // Jpeg magic numbers + curformat=Unsupported; + if (buffer[0]== 0xff && buffer[1] ==0xd8) curformat=Jpeg; + if (buffer[0]== 0x89 && buffer[1] ==0x50 && buffer[2] ==0x4e) curformat=PNG; + + if (curformat == Unsupported) return buffer; // Jpeg magic numbers // Log::getInstance()->log("Image", Log::DEBUG, // "decodePicture 2"); VideoOMX *video=(VideoOMX*)Video::getInstance(); @@ -356,11 +368,26 @@ bool ImageOMX::intDecodePicture(LoadIndex index, unsigned char * buffer, unsigne return false; }*/ + switch (curformat) + { + case Jpeg: + port_def_type.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; + port_def_type.format.image.nSliceHeight = 16; + port_def_type.format.image.nStride = 0; + break; + case PNG: + //port_def_type.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; + //port_def_type.format.image.nSliceHeight = 32; + //port_def_type.format.image.nStride = 0; + port_def_type.format.image.nFrameHeight+=-(port_def_type.format.image.nFrameHeight%32); // The OpenMax png part is broken for the last slice + // so we cut the broken part, not nice but works + break; + } + + + - port_def_type.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; - port_def_type.format.image.nSliceHeight = 16; - port_def_type.format.image.nStride = 0; error = OMX_SetParameter(omx_imag_decode, OMX_IndexParamPortDefinition, &port_def_type); if (error != OMX_ErrorNone) { diff --git a/imageomx.h b/imageomx.h index 25021fa..1b48ede 100644 --- a/imageomx.h +++ b/imageomx.h @@ -84,6 +84,14 @@ class ImageOMX : public OsdVector::PictureDecoder int DestroyInputBufsOMX(); int DestroyInputBufsOMXwhilePlaying(); + enum ImageFormats { + Unsupported, + Jpeg, + PNG + }; + + enum ImageFormats curformat; + vector input_bufs_omx_all; diff --git a/osdopenvg.cc b/osdopenvg.cc index 6c85934..cd869f2 100644 --- a/osdopenvg.cc +++ b/osdopenvg.cc @@ -176,13 +176,22 @@ int OsdOpenVG::init(void* device) Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height); VC_RECT_T dst_rect ={0,0,display_width,display_height}; VC_RECT_T src_rect={0,0,BACKBUFFER_WIDTH <<16,BACKBUFFER_HEIGHT<<16}; - // VC_RECT_T src_rect_bg={0,0,1<<16,1<<16}; - // VC_RECT_T src_rect_im={0,0,1,1}; - - /* uint32_t back_image_ptr; - bcm_backres=vc_dispmanx_resource_create(VC_IMAGE_RGB888,1,1,&back_image_ptr); - unsigned int color=0x00FF0000; - vc_dispmanx_resource_write_data(bcm_backres,VC_IMAGE_RGB888,4,&color,&src_rect_im);*/ + VC_RECT_T src_rect_bg={0,0,16<<16,16<<16}; + VC_RECT_T src_rect_im={0,0,16,16}; + + uint32_t back_image_ptr; + bcm_backres=vc_dispmanx_resource_create(VC_IMAGE_RGBX32,16,16,&back_image_ptr); + unsigned int color[16*16]; + //memset(color,0xFF,sizeof(unsigned int)*4*8); + for (int j=0;j<16;j++) { + int help=j; + //unsigned int cur_col=help | (help<< 8) | (help<< 16) | (0xFF<< 24); + unsigned int cur_col=help *3 | (help<< (8+2)) | (help<< (16+2)) | (0xFF<< (24)); + for (int i=0;i<16;i++) { + color[i+16*j]=cur_col; + } + } + vc_dispmanx_resource_write_data(bcm_backres,VC_IMAGE_RGBX32,16*4,color,&src_rect_im); DISPMANX_UPDATE_HANDLE_T bcm_update; bcm_display=vc_dispmanx_display_open(0); @@ -192,9 +201,9 @@ int OsdOpenVG::init(void* device) &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0); - /* bcm_background=vc_dispmanx_element_add(bcm_update,bcm_display, + bcm_background=vc_dispmanx_element_add(bcm_update,bcm_display, 0,&dst_rect,bcm_backres , - &src_rect_bg,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);*/ + &src_rect_bg,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0); vc_dispmanx_update_submit_sync(bcm_update); @@ -292,8 +301,6 @@ int OsdOpenVG::init(void* device) /*if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init stuff return 0; }*/ - // InitializeMagick(""); - threadStart(); @@ -462,9 +469,9 @@ int OsdOpenVG::shutdown() bcm_update=vc_dispmanx_update_start(0); vc_dispmanx_element_remove(bcm_update,bcm_element); -// vc_dispmanx_element_remove(bcm_update,bcm_background); + vc_dispmanx_element_remove(bcm_update,bcm_background); vc_dispmanx_update_submit_sync(bcm_update); -// vc_dispmanx_resource_delete(bcm_backres); + vc_dispmanx_resource_delete(bcm_backres); vc_dispmanx_display_close(bcm_display); @@ -905,8 +912,9 @@ void OsdOpenVG::executeDrawCommand(SVGCommand & command) vgTranslate(tx,ty); //vgScale(command.w/imagewidth,command.h/imageheight); vgScale(scalex,scaley); + vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL); - //Log::getInstance()->log("OSD", Log::DEBUG, "Draw Image Scale %g %g %g %g %g %g",command.w,imagewidth,command.h,imageheight,scalex,scaley); + //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia Draw Image Scale %g %g %g %g %g %g",command.w,imagewidth,command.h,imageheight,scalex,scaley); } @@ -919,10 +927,10 @@ void OsdOpenVG::executeDrawCommand(SVGCommand & command) // vgGetError()); if (command.reference) { vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL); - vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); vgLoadMatrix(save_matrix2); } + vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); vgLoadMatrix(save_matrix); @@ -1109,9 +1117,9 @@ unsigned int OsdOpenVG::handleTask(OpenVGCommand& command) PictureInfo *info = (PictureInfo*) command.data; VGImage handle; //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia OVGcreateImageMemory"); - handle=vgCreateImage(VG_sXBGR_8888,info->width,info->height,VG_IMAGE_QUALITY_BETTER); + handle=vgCreateImage(VG_sABGR_8888,info->width,info->height,VG_IMAGE_QUALITY_BETTER); vgImageSubData(handle,info->image,info->width*4, - VG_sXBGR_8888,0,0,info->width,info->height); + VG_sABGR_8888,0,0,info->width,info->height); info->decoder->freeReference(info->reference); bool static_image=true; @@ -1138,8 +1146,8 @@ unsigned int OsdOpenVG::handleTask(OpenVGCommand& command) case OVGcreateEGLImage: { PictureInfo *info = (PictureInfo*) command.data; VGImage handle; - //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia OVGcreateImageMemory"); - handle=vgCreateImage(VG_sXBGR_8888,info->width,info->height,VG_IMAGE_QUALITY_BETTER); + //Log::getInstance()->log("OSD", Log::DEBUG, "TVMedia OVGcreateImageMemory %d %d",info->width,info->height); + handle=vgCreateImage(VG_sABGR_8888,info->width,info->height,VG_IMAGE_QUALITY_BETTER); info->handle = handle; info->reference = eglCreateImageKHR(egl_display, egl_context, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)handle, NULL); diff --git a/osdopenvg.h b/osdopenvg.h index 0eb31fb..49fdfe6 100644 --- a/osdopenvg.h +++ b/osdopenvg.h @@ -169,8 +169,8 @@ protected: uint32_t display_width; DISPMANX_DISPLAY_HANDLE_T bcm_display; DISPMANX_ELEMENT_HANDLE_T bcm_element; -// DISPMANX_ELEMENT_HANDLE_T bcm_background; -// DISPMANX_RESOURCE_HANDLE_T bcm_backres; + DISPMANX_ELEMENT_HANDLE_T bcm_background; + DISPMANX_RESOURCE_HANDLE_T bcm_backres; uint32_t mode; diff --git a/osdvector.cc b/osdvector.cc index 28e1d21..da4212c 100644 --- a/osdvector.cc +++ b/osdvector.cc @@ -569,6 +569,9 @@ LoadIndex OsdVector::loadTVMedia(TVMediaInfo& tvmedia) case 5: index=VDR::getInstance()->loadTVMediaEventThumb(tvmedia); break; + case 6: + index=VDR::getInstance()->loadChannelLogo(tvmedia); + break; default: index=VDR::getInstance()->loadTVMedia(tvmedia); break; @@ -748,8 +751,15 @@ void OsdVector::PictureReader::threadMethod() } //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Sleep Picture Reader"); + struct timespec target_time; + clock_gettime(CLOCK_REALTIME,&target_time); + target_time.tv_nsec+=1000000LL*10; + if (target_time.tv_nsec>999999999) { + target_time.tv_nsec-=1000000000L; + target_time.tv_sec+=1; + } threadLock(); - threadWaitForSignal(); + threadWaitForSignalTimed(&target_time); threadUnlock(); //Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Sleep end Picture Reader"); } @@ -803,6 +813,8 @@ bool OsdVector::PictureReader::processReceivedPictures() delete vresp; return true; } + // Log::getInstance()->log("OsdVector", Log::DEBUG, "TVMedia Pictures arrived VDR %x %d %d", + // vresp->getStreamID(),vresp->getUserDataLength(),vresp->getFlag()); if (vresp->getFlag() != 2) { UCHAR *userdata=vresp->getUserData(); ULONG length=vresp->getUserDataLength(); @@ -852,5 +864,6 @@ bool OsdVector::PictureReader::processReceivedPictures() } + if (pict_incoming.size() || pict_incoming_static.size()) return true; return decoded; } diff --git a/vchannellist.cc b/vchannellist.cc index 69d5fb0..9233a9e 100644 --- a/vchannellist.cc +++ b/vchannellist.cc @@ -80,8 +80,10 @@ VChannelList::~VChannelList() void VChannelList::setList(ChannelList* tlist) { char str[500]; + OsdVector *osdv=dynamic_cast(Osd::getInstance()); sl.addColumn(0); + if (osdv) sl.addColumn(20); sl.addColumn(60); chanList = tlist; @@ -90,11 +92,17 @@ void VChannelList::setList(ChannelList* tlist) int first = 1; if (chanList) { + for (UINT i = 0; i < chanList->size(); i++) { chan = (*chanList)[i]; sprintf(str, "%lu\t%s", chan->number, chan->name); - chan->index = sl.addOption(str, (ULONG)chan, first); + TVMediaInfo *info=NULL; + if (osdv) { + info= new TVMediaInfo(); + info->setChannelLogo((*chanList)[i]->number); + } + chan->index = sl.addOption(str, (ULONG)chan, first, info); first = 0; } } diff --git a/vdr.cc b/vdr.cc index 46fecfb..83e6403 100644 --- a/vdr.cc +++ b/vdr.cc @@ -616,7 +616,7 @@ bool VDR_PacketReceiver::call(void* userTag, bool & deleteme) { // It's TVMedia VDR_ResponsePacket* vresp = (VDR_ResponsePacket*)userTag; - Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia Pictures arrived VDR"); + Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia Pictures arrived VDR %x",vresp->getStreamID()); OsdVector *osd=dynamic_cast(Osd::getInstance()); if (osd) osd->getPictReader()->receivePicture(vresp); else delete vresp; //nonsense @@ -1806,9 +1806,9 @@ ULONG VDR::loadTVMedia(TVMediaInfo& tvmedia) if (!vrp.addULONG(tvmedia.type_pict)) return -1; if (!vrp.addULONG(tvmedia.container)) return -1; if (!vrp.addULONG(tvmedia.container_member)) return -1; - Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia with ID %d %d; %d %d %d %d;%d", +/* Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia with ID %d %d; %d %d %d %d;%d", tvmedia.primary_id,tvmedia.secondary_id,tvmedia.type,tvmedia.type_pict, - tvmedia.container,tvmedia.container_member,vrp.getSerial()); + tvmedia.container,tvmedia.container_member,vrp.getSerial());*/ VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver(); @@ -1869,3 +1869,28 @@ ULONG VDR::loadTVMediaEventThumb(TVMediaInfo & media) return vrp.getSerial(); } + +ULONG VDR::loadChannelLogo(TVMediaInfo & media) +{ + + VDR_RequestPacket vrp; + + if (!vrp.init(VDR_LOADCHANNELLOGO, false, 0)) return -1; + if (!vrp.addULONG(media.primary_id)) return NULL; + + VDR_PacketReceiver* vdrpr = new VDR_PacketReceiver(); + vdrpr->receiverChannel = VDR::CHANNEL_TVMEDIA; + vdrpr->streamID = vrp.getSerial(); + vdrpr->streamReceiver = NULL; + edRegister(vdrpr); + + + VDR_ResponsePacket* vresp = RequestResponse(&vrp); + //if (vresp->noResponse()) { delete vresp; return -1; } + delete vresp; + +// Log::getInstance()->log("VDR", Log::DEBUG, "TVMedia Channel Logo %d %x", +// media.primary_id,vrp.getSerial()); + + return vrp.getSerial(); +} diff --git a/vdr.h b/vdr.h index f850a72..b028288 100644 --- a/vdr.h +++ b/vdr.h @@ -212,6 +212,7 @@ class VDR : public Thread_TYPE, public EventDispatcher, public MediaProvider, pu ULONG loadTVMedia(TVMediaInfo& tvmedia); ULONG loadTVMediaRecThumb(TVMediaInfo& tvmedia); ULONG loadTVMediaEventThumb(TVMediaInfo& tvmedia); + ULONG loadChannelLogo(TVMediaInfo& tvmedia); void invalidateTVMedia(ULONG loadindex); diff --git a/vdrcommand.h b/vdrcommand.h index 21bd2be..df347e3 100644 --- a/vdrcommand.h +++ b/vdrcommand.h @@ -76,6 +76,7 @@ const static ULONG VDR_LOADTVMEDIA = 41; const static ULONG VDR_LOADTVMEDIARECTHUMB = 42; const static ULONG VDR_GETEVENTSCRAPEREVENTTYPE = 43; const static ULONG VDR_LOADTVMEDIAEVENTTHUMB = 44; +const static ULONG VDR_LOADCHANNELLOGO = 45; const static ULONG VDR_SHUTDOWN = 666; class VDR_Command : public SerializableList { diff --git a/vepglistadvanced.cc b/vepglistadvanced.cc index a15f283..f10f17d 100644 --- a/vepglistadvanced.cc +++ b/vepglistadvanced.cc @@ -480,7 +480,7 @@ void VEpgListAdvanced::drawDataNowNext(bool next, bool doIndexPop) int saveTop = sl.getTopOption(); sl.clear(); sl.addColumn(0); - sl.addColumn(25 ); + sl.addColumn(42 ); sl.addColumn(160); int first = 1; @@ -579,13 +579,23 @@ void VEpgListAdvanced::draw(bool doIndexPop) TBBoxx::draw(); + TVMediaInfo info; + info.setChannelLogo(channelNumber); + + + char freeSpace[50]; struct tm* btime; time_t now; time(&now); btime = localtime(&now); strftime(freeSpace, 299, "%d/%m/%y", btime); - drawTextRJ(freeSpace, 560+70, 5, DrawStyle::LIGHTTEXT); + if (mode == OneChannel) { + drawTVMedia(info,getWidth(),0.f,0,30.f,TopRight); + drawTextRJ(freeSpace, getWidth()-30, 5, DrawStyle::LIGHTTEXT); + } else { + drawTextRJ(freeSpace, getWidth(), 5, DrawStyle::LIGHTTEXT); + } // Symbols WSymbol w; @@ -693,13 +703,27 @@ void VEpgListAdvanced::updateSelection() epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal); epgTVmedia.setVisible(true); } else { - epgTVmedia.setVisible(false); + if (mode!=OneChannel) { + TVMediaInfo info; + info.setChannelLogo(channel); + epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal); + epgTVmedia.setVisible(true); + } else { + epgTVmedia.setVisible(false); + } } epg.setText(description.str().c_str()); } else { epg.setText(""); - epgTVmedia.setVisible(false); + if (mode!=OneChannel) { + TVMediaInfo info; + info.setChannelLogo(channel); + epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal); + epgTVmedia.setVisible(true); + } else { + epgTVmedia.setVisible(false); + } } } diff --git a/vvideolivetv.cc b/vvideolivetv.cc index 4718449..5d84cac 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -124,6 +124,18 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling okTriggeredOSD = false; + TVMediaInfo info; + info.setChannelLogo(initialChannelNumber); + OsdVector *osdv=dynamic_cast(Osd::getInstance()); + + if (osdv && streamType == VDR::RADIO) { + radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4); + radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2); + radioChannelLogo.setVisible(true); + radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical); + add(&radioChannelLogo); + } + osdposterbanner.setPosition(20,20); osdposterbanner.setBackgroundColour(osdBack); osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10); @@ -131,12 +143,22 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V add(&osdposterbanner); + osd.setBackgroundColour(osdBack); osd.setPosition(0, video->getScreenHeight() - 150); osd.setSize(video->getScreenWidth(), 150); osd.setVisible(false); add(&osd); + int channellogomove=0; + if (osdv) { + osdChannelLogo.setBackgroundColour(osdBack); + osdChannelLogo.setPosition(30,5); + osdChannelLogo.setSize(60,60); + osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical); + osd.add(&osdChannelLogo); + channellogomove=30-5; + } clock.setBackgroundColour(osdBack); clock.setPosition(osd.getWidth() - 100, 4); @@ -144,8 +166,8 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V osd.add(&clock); osdChanNum.setBackgroundColour(osdBack); - osdChanNum.setPosition(50, 4); - osdChanNum.setSize((numberWidth*10) + 22, 30); // 10 px = width of number chars in font + osdChanNum.setPosition(60+channellogomove, 4); + osdChanNum.setSize((numberWidth*10) + 22, getFontHeight()+5); // 10 px = width of number chars in font osd.add(&osdChanNum); osdChanName.setBackgroundColour(osdBack); @@ -201,8 +223,8 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V osd.add(&textBlue); sl.setBackgroundColour(osdBack); - sl.setPosition(70, 36); - sl.setSize(500, 58); + sl.setPosition(90, 36); + sl.setSize(480, 58); sl.setNoLoop(); osd.add(&sl); @@ -998,9 +1020,23 @@ bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData) textUnavailable.setVisible(false); } + OsdVector *osdv=dynamic_cast(Osd::getInstance()); + if (osdv) { + TVMediaInfo info; + Channel* currentChannel = (*chanList)[currentChannelIndex]; + if (currentChannel) { + info.setChannelLogo(currentChannel->number); + if (streamType == VDR::RADIO) { + radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical); + radioChannelLogo.setVisible(true); + } + osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical); + + } + } - draw(); - BoxStack::getInstance()->update(this); + draw(); + BoxStack::getInstance()->update(this); return true; } diff --git a/vvideolivetv.h b/vvideolivetv.h index a84cf89..0d3f3ce 100644 --- a/vvideolivetv.h +++ b/vvideolivetv.h @@ -148,6 +148,8 @@ class VVideoLiveTV : public Boxx, public TimerReceiver, public OSDReceiver WSymbol sAudioChannels; WTextbox textUnavailable; WTVMedia osdposterbanner; + WTVMedia radioChannelLogo; + WTVMedia osdChannelLogo; Boxx summary; WTextbox textSummary; -- 2.39.5