installdir = $(DATADIR)/enigma2
install_DATA = \
- *.xml *.png encoding.conf
+ *.xml *.png encoding.conf radio.mvi
<key id="KEY_TEXT" mapto="startTeletext" flags="m" />
</map>
+ <map context="InfobarRdsActions">
+ <key id="KEY_TEXT" mapto="startRassInteractive" flags="m" />
+ </map>
+
+ <map context="RassInteractiveActions">
+ <key id="KEY_LEFT" mapto="prevSubPage" flags="mr" />
+ <key id="KEY_RIGHT" mapto="nextSubPage" flags="mr" />
+ <key id="KEY_UP" mapto="prevPage" flags="mr" />
+ <key id="KEY_DOWN" mapto="nextPage" flags="mr" />
+ <key id="KEY_EXIT" mapto="exit" flags="m" />
+ </map>
+
<map context="ChannelSelectBaseActions">
<key id="KEY_RED" mapto="showAllServices" flags="m" />
<key id="KEY_GREEN" mapto="showSatellites" flags="m" />
<font filename="ae_AlMateen.ttf" name="Replacement" scale="90" replacement="1" />
</fonts>
- <screen name="InfoBar" flags="wfNoBorder" position="0,330" size="720,198" title="InfoBar" backgroundColor="transparent" >
-
- <widget source="RadioText" render="Label" position="50,0" size="620,50" font="LCD;25" backgroundColor="transparent">
- <convert type="RadioText">RadioText</convert>
- </widget>
-
- <ePixmap position="0,50" zPosition="-1" size="720,148" pixmap="info-bg.png" />
+ <screen name="InfoBar" flags="wfNoBorder" position="0,380" size="720,148" title="InfoBar" backgroundColor="transparent" >
+ <ePixmap position="0,0" zPosition="-1" size="720,148" pixmap="info-bg.png" />
<!-- not used in this skin yet -->
- <widget name="NimA" position="0,50" size="0,0" />
- <widget name="NimB" position="0,50" size="0,0" />
- <widget name="NimA_Active" position="0,50" size="0,0" />
- <widget name="NimB_Active" position="0,50" size="0,0" />
+ <widget name="NimA" position="0,0" size="0,0" />
+ <widget name="NimB" position="0,0" size="0,0" />
+ <widget name="NimA_Active" position="0,0" size="0,0" />
+ <widget name="NimB_Active" position="0,0" size="0,0" />
<!-- 'teletext available'
<widget source="CurrentService" render="Pixmap" pixmap="format.png" position="613,40" size="28,15">
-->
<!-- ............................................................................. -->
- <eLabel text="SNR:" position="195,50" size="40,22" font="Regular;15" transparent="1" />
- <eLabel text="AGC:" position="275,50" size="40,22" font="Regular;15" transparent="1" />
- <eLabel text="BER:" position="355,50" size="40,22" font="Regular;15" transparent="1" />
+ <eLabel text="SNR:" position="195,0" size="40,22" font="Regular;15" transparent="1" />
+ <eLabel text="AGC:" position="275,0" size="40,22" font="Regular;15" transparent="1" />
+ <eLabel text="BER:" position="355,0" size="40,22" font="Regular;15" transparent="1" />
- <widget source="FrontendStatus" render="Label" position="232,50" size="40,22" font="Regular;15" transparent="1" >
+ <widget source="FrontendStatus" render="Label" position="232,0" size="40,22" font="Regular;15" transparent="1" >
<convert type="FrontendInfo">SNR</convert>
</widget>
- <widget source="FrontendStatus" render="Label" position="314,50" size="40,22" font="Regular;15" transparent="1" >
+ <widget source="FrontendStatus" render="Label" position="314,0" size="40,22" font="Regular;15" transparent="1" >
<convert type="FrontendInfo">AGC</convert>
</widget>
- <widget source="FrontendStatus" render="Label" position="392,50" size="53,22" font="Regular;15" transparent="1" >
+ <widget source="FrontendStatus" render="Label" position="392,0" size="53,22" font="Regular;15" transparent="1" >
<convert type="FrontendInfo">BER</convert>
</widget>
- <widget source="FrontendStatus" render="Progress" position="447,51" size="88,6" pixmap="rtgbar.png" >
+ <widget source="FrontendStatus" render="Progress" position="447,1" size="88,6" pixmap="rtgbar.png" >
<convert type="FrontendInfo">SNR</convert>
</widget>
- <widget source="FrontendStatus" render="Progress" position="447,58" size="88,6" pixmap="rtgbar.png" >
+ <widget source="FrontendStatus" render="Progress" position="447,8" size="88,6" pixmap="rtgbar.png" >
<convert type="FrontendInfo">AGC</convert>
</widget>
- <widget source="FrontendStatus" render="Progress" position="447,65" size="88,6" >
+ <widget source="FrontendStatus" render="Progress" position="447,15" size="88,6" >
<convert type="FrontendInfo">BER</convert>
</widget>
- <widget name="BlinkingPoint" pixmap="record.png" position="430,81" zPosition="2" size="58,25" alphatest="on" />
+ <widget name="BlinkingPoint" pixmap="record.png" position="430,31" zPosition="2" size="58,25" alphatest="on" />
<!-- show 'is crypted' icon when service is crypted. -->
- <widget source="CurrentService" render="Pixmap" pixmap="crypt.png" position="570,90" size="12,15" >
+ <widget source="CurrentService" render="Pixmap" pixmap="crypt.png" position="570,40" size="12,15" >
<convert type="ServiceInfo">IsCrypted</convert>
<convert type="ConditionalShowHide" />
</widget>
<!-- show 'multichannel' icon when service has multichannel
audio. -->
- <widget source="CurrentService" render="Pixmap" pixmap="dolby.png" position="585,90" size="25,15">
+ <widget source="CurrentService" render="Pixmap" pixmap="dolby.png" position="585,40" size="25,15">
<convert type="ServiceInfo">IsMultichannel</convert>
<convert type="ConditionalShowHide" />
</widget>
- <widget source="CurrentService" render="Pixmap" pixmap="format.png" position="613,90" size="28,15">
+ <widget source="CurrentService" render="Pixmap" pixmap="format.png" position="613,40" size="28,15">
<convert type="ServiceInfo">IsWidescreen</convert>
<convert type="ConditionalShowHide" />
</widget>
- <widget source="CurrentService" render="Label" position="69,76" size="427,34" font="Regular;22" backgroundColor="#101258" >
+ <widget source="CurrentService" render="Label" position="69,26" size="427,34" font="Regular;22" backgroundColor="#101258" >
<convert type="ServiceName">Name</convert>
<!-- <convert type="ServiceName">Provider</convert> -->
</widget>
- <widget source="CurrentTime" render="Label" position="575,60" size="90,30" backgroundColor="dark" font="Regular;19" >
+ <widget source="CurrentTime" render="Label" position="575,10" size="90,30" backgroundColor="dark" font="Regular;19" >
<convert type="ClockToText">WithSeconds</convert>
</widget>
- <widget source="Event_Now" render="Label" position="210,118" size="60,22" font="Regular;20" backgroundColor="dark">
+ <widget source="Event_Now" render="Label" position="210,68" size="60,22" font="Regular;20" backgroundColor="dark">
<convert type="EventTime">StartTime</convert>
<convert type="ClockToText">Default</convert>
</widget>
- <widget source="Event_Next" render="Label" position="210,148" size="60,22" font="Regular;20" backgroundColor="dark">
+ <widget source="Event_Next" render="Label" position="210,98" size="60,22" font="Regular;20" backgroundColor="dark">
<convert type="EventTime">StartTime</convert>
<convert type="ClockToText">Default</convert>
</widget>
- <widget source="Event_Now" render="Label" position="273,118" size="282,22" font="Regular;20" backgroundColor="dark">
+ <widget source="Event_Now" render="Label" position="273,68" size="282,22" font="Regular;20" backgroundColor="dark">
<convert type="EventName">Name</convert>
</widget>
- <widget source="Event_Next" render="Label" position="273,148" size="282,22" font="Regular;20" backgroundColor="dark">
+ <widget source="Event_Next" render="Label" position="273,98" size="282,22" font="Regular;20" backgroundColor="dark">
<convert type="EventName">Name</convert>
</widget>
- <widget source="Event_Now" render="Label" position="555,118" size="100,26" font="Regular;22" backgroundColor="dark" halign="right">
+ <widget source="Event_Now" render="Label" position="555,68" size="100,26" font="Regular;22" backgroundColor="dark" halign="right">
<convert type="EventTime">Remaining</convert>
<convert type="RemainingToText">InMinutes</convert>
</widget>
- <widget source="Event_Next" render="Label" position="555,148" size="100,26" font="Regular;22" backgroundColor="dark" halign="right">
+ <widget source="Event_Next" render="Label" position="555,98" size="100,26" font="Regular;22" backgroundColor="dark" halign="right">
<convert type="EventTime">Duration</convert>
<convert type="ClockToText">InMinutes</convert>
</widget>
- <widget source="Event_Now" render="Progress" position="304,110" size="121,8" zPosition="1">
+ <widget source="Event_Now" render="Progress" position="304,60" size="121,8" zPosition="1">
<convert type="EventTime">Progress</convert>
</widget>
<!-- red button: is recording possible? -->
- <widget source="RecordingPossible" render="Pixmap" pixmap="button_red.png" position="210,182" size="27,12" >
+ <widget source="RecordingPossible" render="Pixmap" pixmap="button_red.png" position="210,132" size="27,12" >
<convert type="ConditionalShowHide" />
</widget>
- <widget source="RecordingPossible" render="FixedLabel" text="Record" position="240,180" size="85,22" font="Regular;14" backgroundColor="blue" transparent="1">
+ <widget source="RecordingPossible" render="FixedLabel" text="Record" position="240,130" size="85,22" font="Regular;14" backgroundColor="blue" transparent="1">
<convert type="ConditionalShowHide" />
</widget>
- <widget source="CurrentService" render="Pixmap" pixmap="button_green.png" position="320,182" size="27,12" >
+ <widget source="CurrentService" render="Pixmap" pixmap="button_green.png" position="320,132" size="27,12" >
<convert type="ServiceInfo">SubservicesAvailable</convert>
<convert type="ConditionalShowHide" />
</widget>
- <widget source="CurrentService" render="FixedLabel" text="Subservices" position="350,180" size="85,22" font="Regular;14" backgroundColor="blue" transparent="1" >
+ <widget source="CurrentService" render="FixedLabel" text="Subservices" position="350,130" size="85,22" font="Regular;14" backgroundColor="blue" transparent="1" >
<convert type="ServiceInfo">SubservicesAvailable</convert>
<convert type="ConditionalShowHide" />
</widget>
- <widget source="TimeshiftPossible" render="Pixmap" pixmap="button_yellow.png" position="430,182" size="27,12" >
+ <widget source="TimeshiftPossible" render="Pixmap" pixmap="button_yellow.png" position="430,132" size="27,12" >
<convert type="ConditionalShowHide" />
</widget>
- <widget source="TimeshiftPossible" render="FixedLabel" text="Timeshift" position="460,180" size="85,22" font="Regular;14" backgroundColor="blue" transparent="1" >
+ <widget source="TimeshiftPossible" render="FixedLabel" text="Timeshift" position="460,130" size="85,22" font="Regular;14" backgroundColor="blue" transparent="1" >
<convert type="ConditionalShowHide" />
</widget>
- <widget source="ExtensionsAvailable" render="Pixmap" pixmap="button_blue.png" position="540,182" size="27,12" >
+ <widget source="ExtensionsAvailable" render="Pixmap" pixmap="button_blue.png" position="540,132" size="27,12" >
<convert type="ConditionalShowHide" />
</widget>
- <widget source="ExtensionsAvailable" render="FixedLabel" text="Extensions" position="570,180" size="95,22" font="Regular;14" backgroundColor="blue" transparent="1" >
+ <widget source="ExtensionsAvailable" render="FixedLabel" text="Extensions" position="570,130" size="95,22" font="Regular;14" backgroundColor="blue" transparent="1" >
<convert type="ConditionalShowHide" />
</widget>
</screen>
<font filename="lcd.ttf" name="LCD" scale="100" />
</fonts>
- <screen name="Standby" flags="wfNoBorder" position="0,0" size="720,576" title="Standby">
- </screen>
+ <screen name="Standby" flags="wfNoBorder" position="0,0" size="720,576" title="Standby" />
<screen name="Menu" position="210,150" size="300,285" title="Main menu">
<widget name="title" position="10,10" size="280,35" font="Regular;23" />
<!--<widget name="menu" position="10,55" size="280,150" font="Regular;23" />-->
<screen name="ChannelContextMenu" position="210,150" size="300,250" title="Channellist menu">
<widget name="menu" position="10,10" size="300,230" scrollbarMode="showOnDemand" />
</screen>
- <screen name="Scart" position="0,0" size="720,576">
- </screen>
+ <screen name="Scart" position="0,0" size="720,576" />
<screen name="MediaPlayer" position="104,83" size="512,442" title="MediaPlayer">
<eLabel position="11,9" zPosition="1" size="359,78" backgroundColor="#182C40" />
<widget name="artisttext" position="13,11" zPosition="3" size="65,17" font="Regular;16" valign="top" foregroundColor="#cccccc" backgroundColor="#33294a6b" shadowColor="#000000" shadowOffset="-2,-2"/>
<widget name="model" position="20,10" size="380,25" font="Regular;23" />
<widget name="capacity" position="20,40" size="380,25" font="Regular;23" />
<widget name="bus" position="20,70" size="380,25" font="Regular;23" />
- <widget name="initialize" position="150,120" zPosition="1" size="120,30" pixmap="init.png" transparent="1" alphatest="on" />
+ <widget name="initialize" position="150,120" zPosition="1" size="120,30" pixmap="init.png" transparent="1" alphatest="on" />
<widget name="initializetext" position="150,120" size="120,30" valign="center" halign="center" zPosition="2" font="Regular;20" transparent="1" />
</screen>
<screen name="Setup" position="90,148" size="540,280" title="Setup">
<widget name="key_yellow" position="280,0" size="140,40" backgroundColor="yellow" font="Regular;21" />
<widget name="key_blue" position="420,0" size="140,40" backgroundColor="blue" font="Regular;21" />
<widget name="list" position="0,45" size="560,196" scrollbarMode="showOnDemand" />
- <widget source="RadioText" render="Label" position="0,241" size="560,66" font="LCD;25" >
- <convert type="RadioText">RadioText</convert>
+ <widget source="RdsDecoder" render="Label" position="0,241" size="560,66" font="LCD;25" >
+ <convert type="RdsInfo">RadioText</convert>
</widget>
</screen>
<screen name="RadioInfoBar" position="90,420" size="560,105" zPosition="-1">
<widget source="CurrentService" render="Label" position="0,0" size="390,26" font="Regular;22" backgroundColor="dark" >
<convert type="ServiceName">Name</convert>
</widget>
- <widget name="BlinkingPoint" pixmap="record.png" position="400,0" zPosition="2" size="58,25" />
<widget source="CurrentTime" render="Label" position="465,0" size="95,28" font="Regular;22" backgroundColor="dark" >
<convert type="ClockToText">WithSeconds</convert>
</widget>
<widget source="Event_Now" render="Progress" position="465,27" size="90,9" zPosition="1" borderWidth="2" >
<convert type="EventTime">Progress</convert>
</widget>
- <widget source="Event_Now" render="Label" position="0,44" size="60,22" font="Regular;20" backgroundColor="dark" >
- <convert type="EventTime">StartTime</convert>
- <convert type="ClockToText">Default</convert>
+ <widget source="RdsDecoder" render="Pixmap" pixmap="rass_logo.png" position="0,27" size="50,21" >
+ <convert type="RdsInfo">RasInteractiveAvailable</convert>
+ <convert type="ConditionalShowHide" />
</widget>
- <widget source="Event_Next" render="Label" position="0,74" size="60,22" font="Regular;20" backgroundColor="dark" >
+ <widget source="Event_Now" render="Label" position="0,49" size="60,22" font="Regular;20" backgroundColor="dark" >
<convert type="EventTime">StartTime</convert>
<convert type="ClockToText">Default</convert>
</widget>
- <widget source="Event_Now" render="Label" position="80,44" size="380,22" font="Regular;20" backgroundColor="dark" >
- <convert type="EventName">Name</convert>
- </widget>
- <widget source="Event_Next" render="Label" position="80,74" size="380,22" font="Regular;20" backgroundColor="dark" >
+ <widget source="Event_Now" render="Label" position="80,49" size="380,22" font="Regular;20" backgroundColor="dark" >
<convert type="EventName">Name</convert>
</widget>
-
- <widget source="Event_Now" render="Label" position="470,44" size="150,22" font="Regular;20" backgroundColor="dark" >
+ <widget source="Event_Now" render="Label" position="470,49" size="150,22" font="Regular;20" backgroundColor="dark" >
<convert type="EventTime">Remaining</convert>
<convert type="RemainingToText">InMinutes</convert>
</widget>
- <widget source="Event_Next" render="Label" position="470,74" size="150,22" font="Regular;20" backgroundColor="dark" >
+ <widget source="Event_Next" render="Label" position="80,79" size="380,22" font="Regular;20" backgroundColor="dark" >
+ <convert type="EventName">Name</convert>
+ </widget>
+ <widget source="Event_Next" render="Label" position="0,79" size="60,22" font="Regular;20" backgroundColor="dark" >
+ <convert type="EventTime">StartTime</convert>
+ <convert type="ClockToText">Default</convert>
+ </widget>
+ <widget source="Event_Next" render="Label" position="470,79" size="150,22" font="Regular;20" backgroundColor="dark" >
<convert type="EventTime">Duration</convert>
<convert type="ClockToText">InMinutes</convert>
</widget>
<screen name="PictureInPicture" position="400,60" size="240,192" zPosition="-1" flags="wfNoBorder" >
<widget name="video" position="0,0" size="240,192" />
</screen>
- <screen name="SubtitleDisplay" position="0,0" size="720,568" zPosition="-1" flags="wfNoBorder" >
+
+ <screen name="SubtitleDisplay" position="0,0" size="720,568" zPosition="-1" flags="wfNoBorder" />
+
+ <colors>
+ <color name="rds_bg" value="#77ffffff" />
+ <color name="rds_fg" value="#000000" />
+ <color name="rds_text_bg" value="#003258" />
+ </colors>
+
+ <screen name="RdsInfoDisplay" backgroundColor="transparent" position="0,0" size="720,568" zPosition="-2" flags="wfNoBorder" >
+ <widget name="RadioText" backgroundColor="rds_text_bg" position="50,481" size="620,29" font="Regular;21" noWrap="1" shadowOffset="-2,-2" shadowColor="transpBlack" />
+ <widget name="RtpText" backgroundColor="rds_text_bg" position="50,510" size="620,29" font="Regular;21" halign="right" noWrap="1" shadowOffset="-2,-2" shadowColor="transpBlack" />
+ <widget name="RassLogo" pixmap="rass_logo.png" position="50,445" size="50,21" />
</screen>
+
+ <screen name="RassInteractive" backgroundColor="rds_bg" position="50,180" size="100,275" flags="wfNoBorder" >
+ <ePixmap pixmap="rass_logo.png" position="0,0" size="100,21" />
+ <eLabel text="Index" position="36,25" size="60,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <eLabel text="0" position="5,25" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="Marker" position="21,25" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <eLabel text="1" position="5,50" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_1" position="35,50" size="36,20" alphatest="on" />
+ <eLabel text="2" position="5,75" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_2" position="35,75" size="36,20" alphatest="on" />
+ <eLabel text="3" position="5,100" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_3" position="35,100" size="36,20" alphatest="on" />
+ <eLabel text="4" position="5,125" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_4" position="35,125" size="36,20" alphatest="on" />
+ <eLabel text="5" position="5,150" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_5" position="35,150" size="36,20" alphatest="on" />
+ <eLabel text="6" position="5,175" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_6" position="35,175" size="36,20" alphatest="on" />
+ <eLabel text="7" position="5,200" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_7" position="35,200" size="36,20" alphatest="on" />
+ <eLabel text="8" position="5,225" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_8" position="35,225" size="36,20" alphatest="on" />
+ <eLabel text="9" position="5,250" size="16,25" font="Regular;21" foregroundColor="rds_fg" backgroundColor="rds_bg" />
+ <widget name="subpages_9" position="35,250" size="36,20" alphatest="on" />
+ </screen>
+
<screen name="PiPSetup" backgroundColor="transparent" position="70,400" size="600,150" title="PiPSetup" flags="wfNoBorder">
<widget name="text" position="0,0" size="600,150" font="Regular;23" />
</screen>
+
<screen name="MovieSelection" position="90,78" size="560,455" title="Select a movie">
<widget name="key_red" position="0,0" size="140,40" backgroundColor="red" font="Regular;21" />
<widget name="key_green" position="140,0" size="140,40" backgroundColor="green" font="Regular;21" />
#include <lib/dvb/idemux.h>
#include <lib/gdi/gpixmap.h>
-DEFINE_REF(eDVBRadioTextParser);
+DEFINE_REF(eDVBRdsDecoder);
-eDVBRadioTextParser::eDVBRadioTextParser(iDVBDemux *demux)
- :bytesread(0), ptr(0), p1(-1), p2(-1), msgPtr(0), state(0)
+eDVBRdsDecoder::eDVBRdsDecoder(iDVBDemux *demux)
+ :msgPtr(0), bsflag(0), qdar_pos(0), t_ptr(0), qdarmvi_show(0), state(0)
,m_abortTimer(eApp)
{
setStreamID(0xC0, 0xC0);
+ memset(rass_picture_mask, 0, sizeof(rass_picture_mask));
+
if (demux->createPESReader(eApp, m_pes_reader))
eDebug("failed to create PES reader!");
else
- m_pes_reader->connectRead(slot(*this, &eDVBRadioTextParser::processData), m_read_connection);
- CONNECT(m_abortTimer.timeout, eDVBRadioTextParser::abortNonAvail);
+ m_pes_reader->connectRead(slot(*this, &eDVBRdsDecoder::processData), m_read_connection);
+ CONNECT(m_abortTimer.timeout, eDVBRdsDecoder::abortNonAvail);
+}
+
+eDVBRdsDecoder::~eDVBRdsDecoder()
+{
+ // delete cached rass slides
+ for (int page=0; page < 10; ++page)
+ {
+ unsigned char mask = rass_picture_mask[(page*4)/8];
+ if (page % 2)
+ mask >>= 4;
+ int subpage=0;
+ while(mask)
+ {
+ if (mask & 1)
+ {
+ std::string filename = getRassPicture(page, subpage);
+ if (filename.length())
+ remove(filename.c_str());
+ }
+ mask >>= 1;
+ ++subpage;
+ }
+ }
+ remove("/tmp/RassLast.mvi");
}
#define SWAP(x) ((x<<8)|(x>>8))
{ 11025,12000,8000,0 }
};
-void eDVBRadioTextParser::connectUpdatedRadiotext(const Slot0<void> &slot, ePtr<eConnection> &connection)
+void eDVBRdsDecoder::connectEvent(const Slot1<void, int> &slot, ePtr<eConnection> &connection)
{
- connection = new eConnection(this, m_updated_radiotext.connect(slot));
+ connection = new eConnection(this, m_event.connect(slot));
}
-void eDVBRadioTextParser::processPESPacket(__u8 *data, int len)
+void eDVBRdsDecoder::addToPictureMask(int id)
+{
+ int page = id / 1000;
+ int tmp = page > 0 ? id / page : id;
+ int subpage = 0;
+ while(tmp > 1000)
+ {
+ ++subpage;
+ tmp -= 1000;
+ tmp *= 10;
+ }
+ int index = (page*4+subpage)/8;
+ int val = (page%2) ? 16 * (1 << subpage) : (1 << subpage);
+ if (rass_picture_mask[index] & val) // already have this picture
+ return;
+ rass_picture_mask[index] |= val;
+ /* emit */ m_event(RassInteractivePicMaskChanged);
+}
+
+void eDVBRdsDecoder::removeFromPictureMask(int id)
+{
+ int page = id / 1000;
+ int tmp = page > 0 ? id / page : id;
+ int subpage = 0;
+ while(tmp > 1000)
+ {
+ ++subpage;
+ tmp -= 1000;
+ tmp *= 10;
+ }
+ int index = (page*4)/8;
+ int val = (page%2) ? 16 * (1 << subpage) : (1 << subpage);
+ if (rass_picture_mask[index] & val) // have this picture
+ {
+ rass_picture_mask[index] &= ~val;
+ /* emit */ m_event(RassInteractivePicMaskChanged);
+ }
+}
+
+void eDVBRdsDecoder::processPESPacket(__u8 *data, int len)
{
int pos=9+data[8];// skip pes header
+ int cnt=0;
while (pos < len)
{
m_abortTimer.stop();
int ancillary_len = 1 + data[offs - 1];
offs -= ancillary_len;
- while(offs < pos)
- gotAncillaryByte(data[offs++]);
+ gotAncillaryData(data+offs, ancillary_len);
}
}
}
-inline void eDVBRadioTextParser::gotAncillaryByte(__u8 data)
+void eDVBRdsDecoder::process_qdar(unsigned char *buf)
{
- buf[bytesread]=data;
- bytesread+=1;
- if ( bytesread == 128 )
+ if (buf[0] == 0x40 && buf[1] == 0xDA)
{
- while(ptr<128)
+ unsigned int item,cnt,ctrl,item_type;
+ unsigned long item_length,id,item_no,ptr,tmp;
+ unsigned short crc_qdar,crc_read;
+ char fname[50];
+ ptr=4;cnt=0;
+ item=buf[2]<<8; // Number of Items
+ item|=buf[3];
+
+ while ( cnt++ < item ) //read in items
{
- if ( buf[ptr] == 0xFD )
- {
- if (p1 == -1)
- p1 = ptr;
- else
- p2 = ptr;
- }
- if ( p1 != -1 && p2 != -1 )
+ id=buf[ptr++]<<8; //QDarID
+ id|=buf[ptr++];
+
+ item_no=buf[ptr++]<<8; // Item Number
+ item_no|=buf[ptr++];
+
+ ctrl=buf[ptr++]; //controlbyte
+ item_type=buf[ptr++]; //item type
+
+ item_length=buf[ptr++]<<24; // Item length
+ item_length|=buf[ptr++]<<16;
+ item_length|=buf[ptr++]<<8;
+ item_length|=buf[ptr++];
+
+ ptr=ptr+4; // rfu Bytes ... not used
+ tmp=ptr; // calc crc
+ crc_qdar=0xFFFF;
+ while (tmp < ptr+item_length)
+ crc_qdar = crc_ccitt_byte(crc_qdar, buf[tmp++]);
+
+ crc_read=buf[ptr+item_length]<<8;
+ crc_read|=buf[ptr+item_length+1];
+ //eDebug("[RDS/Rass] CRC read: %04X calculated: %04X",crc_read,crc_qdar^0xFFFF);
+
+ if (crc_read == (crc_qdar^0xFFFF)) // process item
{
- int cnt=buf[--p2];
- while ( cnt-- > 0 )
+ switch(item_type)
{
- unsigned char c = buf[--p2];
- if ( state == 1 )
- crc=0xFFFF;
- if ( state >= 1 && state < 11 )
- crc = crc_ccitt_byte(crc, c);
-
- switch (state)
- {
- case 0:
- if ( c==0xFE ) // Startkennung
- state=1;
- break;
- case 1: // 10bit Site Address + 6bit Encoder Address
- case 2:
- case 3: // Sequence Counter
- ++state;
- break;
- case 4:
- leninfo=c;
- ++state;
- break;
- case 5:
- if ( c==0x0A ) // message element code 0x0A Radio Text
- ++state;
- else
- state=0;
- break;
- case 6: // Data Set Number ... ignore
- case 7: // Program Service Number ... ignore
- ++state;
- break;
- case 8: // Message Element Length
- todo=c;
- if ( !todo || todo > 65 || todo > leninfo-4)
- state=0;
+ case 0x01: //Stillframe
+ if (ctrl&0x01) // display slide
+ {
+ sprintf(fname,"/tmp/RassLast.mvi");
+ FILE *fh=fopen(fname,"wb");
+ fwrite(buf+ptr,1,item_length-2,fh);
+ fclose(fh);
+ /*emit*/ m_event(RecvRassSlidePic);
+ qdarmvi_show=1;
+ }
+ if (ctrl&0x02) // save slide for interactive mode
+ {
+ if (id == 0 || id >= 1000)
+ {
+ sprintf(fname,"/tmp/Rass%04d.mvi",(int)id);
+ FILE *fh=fopen(fname,"wb");
+ fwrite(buf+ptr,1,item_length-2,fh);
+ fclose(fh);
+ addToPictureMask(id);
+ }
else
+ eDebug("ignore recv interactive picture id %lu", id);
+ }
+ if (ctrl&0x04) // display slide if nothing had been displayed yet
+ {
+ if (qdarmvi_show != 1)
{
- ++state;
- todo-=2;
- msgPtr=0;
+ sprintf(fname,"/tmp/RassLast.mvi");
+ FILE *fh=fopen(fname,"wb");
+ fwrite(buf+ptr,1,item_length-2,fh);
+ fclose(fh);
+ /*emit*/ m_event(RecvRassSlidePic);
+ qdarmvi_show=1;
}
- break;
- case 9: // Radio Text Status bit:
- // 0 = AB-flagcontrol
- // 1-4 = Transmission-Number
- // 5-6 = Buffer-Config
- ++state; // ignore ...
- break;
- case 10:
- // TODO build a complete radiotext charcode to UTF8 conversion table for all character > 0x80
- switch (c)
+ }
+ if (ctrl&0x08) // delete slide
+ {
+ eDebug("delete slide id %lu, item_no %lu", id, item_no);
+ if (id == 0 || id >= 1000)
{
- case 0 ... 0x7f: break;
- case 0x8d: c='ß'; break;
- case 0x91: c='ä'; break;
- case 0xd1: c='Ä'; break;
- case 0x97: c='ö'; break;
- case 0xd7: c='Ö'; break;
- case 0x99: c='ü'; break;
- case 0xd9: c='Ü'; break;
- default: c=' '; break; // convert all unknown to space
+ eDebug("delete %lu", id);
+ removeFromPictureMask(id);
+ sprintf(fname,"/tmp/Rass%04d.mvi",(int)id); // was item_no ? ! ?
+ remove(fname);
}
- message[msgPtr++]=c;
- if(todo)
- --todo;
else
- ++state;
- break;
- case 11:
- crc16=c<<8;
+ eDebug("ignore del interactive picture id %lu", id);
+ }
+ break;
+ default: //nothing more yet defined
+ break;
+ }
+ }
+ else
+ {
+ eDebug("[RDS/Rass] CRC error, skip Rass-Qdar-Item");
+ }
+
+ ptr=+item_length;
+ }
+ }
+ else
+ {
+ eDebug("[RDS/Rass] No Rass-QDAR archive (%02X %02X) so skipping !\n",buf[0],buf[1]);
+ }
+}
+
+inline void eDVBRdsDecoder::gotAncillaryData(__u8 *buf, int len)
+{
+ int cnt=buf[--len];
+ while ( cnt-- > 0 )
+ {
+ unsigned char c = buf[--len];
+
+ if (bsflag == 1) // byte stuffing
+ {
+ bsflag=2;
+ switch (c)
+ {
+ case 0x00: c=0xFD; break;
+ case 0x01: c=0xFE; break;
+ case 0x02: c=0xFF; break;
+ }
+ }
+
+ if (c == 0xFD && bsflag ==0)
+ bsflag=1;
+ else
+ bsflag=0;
+
+ if (bsflag == 0)
+ {
+ if ( state == 1 )
+ crc=0xFFFF;
+ if (( state >= 1 && state < 11 ) || ( state >=26 && state < 36 ))
+ crc = crc_ccitt_byte(crc, c);
+
+ switch (state)
+ {
+ case 0:
+ if ( c==0xFE ) // Startkennung
+ state=1;
+ break;
+ case 1: // 10bit Site Address + 6bit Encoder Address
+ case 2:
+ case 3: // Sequence Counter
+ ++state;
+ break;
+ case 4:
+ leninfo=c;
+ ++state;
+ break;
+ case 5:
+ switch (c)
+ {
+ case 0x0A: // Radiotext
++state;
break;
- case 12:
- crc16|=c;
- message[msgPtr--]=0;
- while(message[msgPtr] == ' ' && msgPtr > 0)
- message[msgPtr--] = 0;
- if ( crc16 == (crc^0xFFFF) )
+ case 0x46: // Radiotext Plus tags
+ state=38;
+ break;
+ case 0xDA: // Rass
+ state=26;
+ break;
+ default: // reset to state 0
+ state=0;
+ }
+ break;
+
+ // process Radiotext
+ case 6: // Data Set Number ... ignore
+ case 7: // Program Service Number ... ignore
+ ++state;
+ break;
+ case 8: // Message Element Length
+ text_len=c;
+ if ( !text_len || text_len > 65 || text_len > leninfo-4)
+ state=0;
+ else
+ {
+ ++state;
+ text_len-=2;
+ msgPtr=0;
+ }
+ break;
+ case 9: // Radio Text Status bit:
+ // 0 = AB-flagcontrol
+ // 1-4 = Transmission-Number
+ // 5-6 = Buffer-Config
+ ++state; // ignore ...
+ break;
+ case 10:
+ // TODO build a complete radiotext charcode to UTF8 conversion table for all character > 0x80
+ switch (c)
+ {
+ case 0 ... 0x7f: break;
+ case 0x8d: c='ß'; break;
+ case 0x91: c='ä'; break;
+ case 0xd1: c='Ä'; break;
+ case 0x97: c='ö'; break;
+ case 0xd7: c='Ö'; break;
+ case 0x99: c='ü'; break;
+ case 0xd9: c='Ü'; break;
+ default: c=' '; break; // convert all unknown to space
+ }
+ message[msgPtr++]=c;
+ if(text_len)
+ --text_len;
+ else
+ ++state;
+ break;
+ case 11:
+ crc16=c<<8;
+ ++state;
+ break;
+ case 12:
+ crc16|=c;
+ message[msgPtr--]=0;
+ while(message[msgPtr] == ' ' && msgPtr > 0)
+ message[msgPtr--] = 0;
+ if ( crc16 == (crc^0xFFFF) )
+ {
+ eDebug("radiotext: (%s)", message);
+ /*emit*/ m_event(RadioTextChanged);
+ memcpy(lastmessage,message,66);
+ }
+ else
+ eDebug("invalid radiotext crc (%s)", message);
+ state=0;
+ break;
+
+ // process Rass
+ case 26: //MEL
+ text_len = c;
+ text_len2 = c;
+ ++state;
+ text_len-=9;
+ text_len2-=9;
+ t_ptr=0;
+ break;
+ case 27: // SID not used atm
+ ++state;
+ break;
+ case 28: // SID not used atm
+ ++state;
+ break;
+ case 29: // PNR packet number
+ part=c<<16;
+ ++state;
+ break;
+ case 30: // PNR packet number
+ part|=c<<8;
+ ++state;
+ break;
+ case 31: // PNR packet number
+ part|=c;
+ ++state;
+ break;
+ case 32: // NOP number of packets
+ parts=c<<16;
+ ++state;
+ break;
+ case 33: // NOP number of packets
+ parts|=c<<8;
+ ++state;
+ break;
+ case 34: // NOP number of packets
+ parts|=c;
+ ++state;
+ break;
+ case 35:
+ datamessage[t_ptr++]=c;
+ if(text_len)
+ --text_len;
+ else
+ ++state;
+ break;
+ case 36:
+ crc16=c<<8;
+ ++state;
+ break;
+ case 37:
+ crc16|=c;
+ //eDebug("[RDS/Rass] CRC read: %04X CRC calculated: %04X",crc16,crc^0xFFFF);
+ state=0;
+ if ( crc16 == (crc^0xFFFF) )
+ {
+ if (partcnt == -1)
+ partcnt=1;
+ if (partcnt == part)
+ {
+ memcpy(qdar+qdar_pos,datamessage,text_len2+1);
+ qdar_pos=qdar_pos+text_len2+1;
+ if (partcnt == parts)
{
- eDebug("radiotext: (%s)", message);
- /*emit*/ m_updated_radiotext();
+ process_qdar(qdar); // decode qdar archive
+ qdar_pos=0;
+ partcnt=-1;
}
else
- eDebug("invalid radiotext crc (%s)", message);
- state=0;
- break;
+ ++partcnt;
+ }
+ else
+ {
+ qdar_pos=0;
+ partcnt=-1;
+ }
}
- }
- p1=ptr;
- p2=-1;
+ else
+ {
+ eDebug("[RDS/Rass] CRC error, skip Rass-Qdar-Packet");
+ eDebug("[RDS/Rass] CRC read: %04X CRC calculated: %04X",crc16,crc^0xFFFF);
+ partcnt=-1;
+ }
+ state=0;
+ break;
+
+ // process RT plus tags ...
+ case 38: // Message Element Length
+ text_len=c;
+ ++state;
+ break;
+ case 39: // Application ID
+ case 40: // always 0x4BD7 so we ignore it ;)
+ case 41: // Applicationgroup Typecode/PTY ... ignore
+ ++state;
+ break;
+ case 42:
+ rtp_buf[0]=c;
+ ++state;
+ break;
+ case 43:
+ rtp_buf[1]=c;
+ ++state;
+ break;
+ case 44:
+ rtp_buf[2]=c;
+ ++state;
+ break;
+ case 45:
+ rtp_buf[3]=c;
+ ++state;
+ break;
+ case 46: // bit 10#4 = Item Togglebit
+ // bit 10#3 = Item Runningbit
+ // Tag1: bit 10#2..11#5 = Contenttype, 11#4..12#7 = Startmarker, 12#6..12#1 = Length
+ rtp_buf[4]=c;
+ if (lastmessage[0] == 0) // no rds message till now ? quit ...
+ break;
+ int rtp_typ[2],rtp_start[2],rtp_len[2];
+ rtp_typ[0] = (0x38 & rtp_buf[0]<<3) | rtp_buf[1]>>5;
+ rtp_start[0] = (0x3e & rtp_buf[1]<<1) | rtp_buf[2]>>7;
+ rtp_len[0] = 0x3f & rtp_buf[2]>>1;
+ // Tag2: bit 12#0..13#3 = Contenttype, 13#2..14#5 = Startmarker, 14#4..14#0 = Length(5bit)
+ rtp_typ[1] = (0x20 & rtp_buf[2]<<5) | rtp_buf[3]>>3;
+ rtp_start[1] = (0x38 & rtp_buf[3]<<3) | rtp_buf[4]>>5;
+ rtp_len[1] = 0x1f & rtp_buf[4];
+
+ unsigned char rtplus_osd_tmp[64];
+
+ memcpy(rtp_item[rtp_typ[0]],lastmessage+rtp_start[0],rtp_len[0]+1);
+ rtp_item[rtp_typ[0]][rtp_len[0]+1]=0;
+
+ if (rtp_typ[0] != rtp_typ[1])
+ {
+ memcpy(rtp_item[rtp_typ[1]],lastmessage+rtp_start[1],rtp_len[1]+1);
+ rtp_item[rtp_typ[1]][rtp_len[1]+1]=0;
+ }
+
+ // main RTPlus item_types used by the radio stations:
+ // 1 title
+ // 4 artist
+ // 24 info.date_time
+ // 31 stationname
+ // 32 program.now
+ // 39 homepage
+ // 41 phone.hotline
+ // 46 email.hotline
+ // todo: make a window to display all saved items ...
+
+ //create RTPlus OSD for title/artist
+ rtplus_osd[0]=0;
+
+ if ( rtp_item[4][0] != 0 )//artist
+ sprintf((char*)rtplus_osd_tmp," (%s)",rtp_item[4]);
+
+ if ( rtp_item[1][0] != 0 )//title
+ sprintf((char*)rtplus_osd,"%s%s",rtp_item[1],rtplus_osd_tmp);
+
+ if ( rtplus_osd[0] != 0 )
+ {
+ /*emit*/ m_event(RtpTextChanged);
+ eDebug("RTPlus: %s",rtplus_osd);
+ }
+
+ state=0;
+ break;
}
- ++ptr;
}
- if (p1 != -1 && (128-p1) != 128)
- {
- bytesread=ptr=128-p1;
- memcpy(buf, buf+p1, ptr);
- p1=0;
- }
- else
- bytesread=ptr=0;
}
}
-int eDVBRadioTextParser::start(int pid)
+std::string eDVBRdsDecoder::getRassPicture(int page, int subpage)
+{
+ int val=0;
+
+ switch(subpage)
+ {
+ case 0:
+ val=page*1000;
+ break;
+ case 1:
+ val=page*1100;
+ break;
+ case 2:
+ val=page*1110;
+ break;
+ case 3:
+ val=page*1111;
+ break;
+ }
+ char fname[50];
+ sprintf(fname,"/tmp/Rass%04d.mvi",val);
+ return fname;
+}
+
+int eDVBRdsDecoder::start(int pid)
{
int ret = -1;
if (m_pes_reader && !(ret = m_pes_reader->start(pid)))
return ret;
}
-void eDVBRadioTextParser::abortNonAvail()
+void eDVBRdsDecoder::abortNonAvail()
{
eDebug("no ancillary data in audio stream... abort radiotext pes parser");
if (m_pes_reader)
m_pes_reader->stop();
}
+
+ePyObject eDVBRdsDecoder::getRassPictureMask()
+{
+ ePyObject ret = PyTuple_New(5);
+ PyTuple_SET_ITEM(ret, 0, PyInt_FromLong(rass_picture_mask[0]));
+ PyTuple_SET_ITEM(ret, 1, PyInt_FromLong(rass_picture_mask[1]));
+ PyTuple_SET_ITEM(ret, 2, PyInt_FromLong(rass_picture_mask[2]));
+ PyTuple_SET_ITEM(ret, 3, PyInt_FromLong(rass_picture_mask[3]));
+ PyTuple_SET_ITEM(ret, 4, PyInt_FromLong(rass_picture_mask[4]));
+ return ret;
+}
#include <lib/dvb/pesparse.h>
#include <lib/gdi/gpixmap.h>
-class eDVBRadioTextParser: public iObject, public ePESParser, public Object
+class eDVBRdsDecoder: public iObject, public ePESParser, public Object
{
- DECLARE_REF(eDVBRadioTextParser);
- int bytesread, ptr, p1, p2, msgPtr;
- unsigned char buf[128], message[66], leninfo, todo, state;
+ DECLARE_REF(eDVBRdsDecoder);
+ int msgPtr, bsflag, qdar_pos, t_ptr, qdarmvi_show;
+ unsigned char message[66], lastmessage[66], datamessage[256], rtp_buf[5], leninfo, text_len, text_len2, state;
+ unsigned char rtp_item[64][64], rtplus_osd[64]; //rtp
+ unsigned char qdar[60*1024]; //60 kB for holding Rass qdar archive
unsigned short crc16, crc;
+ long part, parts, partcnt;
+ enum { RadioTextChanged, RtpTextChanged, RassInteractivePicMaskChanged, RecvRassSlidePic };
+ unsigned char rass_picture_mask[5]; // 40 bits... (10 * 4 pictures)
+ void addToPictureMask(int id);
+ void removeFromPictureMask(int id);
public:
- eDVBRadioTextParser(iDVBDemux *demux);
+ eDVBRdsDecoder(iDVBDemux *demux);
+ ~eDVBRdsDecoder();
int start(int pid);
- void connectUpdatedRadiotext(const Slot0<void> &slot, ePtr<eConnection> &connection);
- const char *getCurrentText() { return msgPtr ? (const char*)message : ""; }
+ void connectEvent(const Slot1<void, int> &slot, ePtr<eConnection> &connection);
+ const char *getRadioText() { return (const char*)message; }
+ const char *getRtpText() { return (const char*)rtplus_osd; }
+ ePyObject getRassPictureMask();
+ std::string getRassPicture(int page, int subpage);
+ std::string getRassSlideshowPicture() { return "/tmp/RassLast.mvi"; }
private:
void abortNonAvail();
void processPESPacket(__u8 *pkt, int len);
- inline void gotAncillaryByte(__u8 data);
+ inline void gotAncillaryData(__u8 *data, int len);
+ void process_qdar(unsigned char*);
ePtr<iDVBPESReader> m_pes_reader;
ePtr<eConnection> m_read_connection;
- Signal0<void> m_updated_radiotext;
+ Signal1<void, int> m_event;
eTimer m_abortTimer;
};
install_PYTHON = \
__init__.py ClockToText.py Converter.py EventName.py StaticText.py EventTime.py \
Poll.py RemainingToText.py StringList.py ServiceName.py FrontendInfo.py ServiceInfo.py \
- ConditionalShowHide.py ServicePosition.py ValueRange.py RadioText.py Streaming.py
+ ConditionalShowHide.py ServicePosition.py ValueRange.py RdsInfo.py Streaming.py
--- /dev/null
+from enigma import iRdsDecoder, iPlayableService
+from Components.Converter.Converter import Converter
+from Components.Element import cached
+
+class RdsInfo(Converter, object):
+ RASS_INTERACTIVE_AVAILABLE = 0
+ RTP_TEXT_CHANGED = 1
+ RADIO_TEXT_CHANGED = 2
+
+ def __init__(self, type):
+ Converter.__init__(self, type)
+ self.type = {
+ "RadioText": self.RADIO_TEXT_CHANGED,
+ "RtpText": self.RTP_TEXT_CHANGED,
+ "RasInteractiveAvailable": self.RASS_INTERACTIVE_AVAILABLE
+ }[type]
+
+ self.interesting_events = {
+ self.RADIO_TEXT_CHANGED: [iPlayableService.evUpdatedRadioText],
+ self.RTP_TEXT_CHANGED: [iPlayableService.evUpdatedRtpText],
+ self.RASS_INTERACTIVE_AVAILABLE: [iPlayableService.evUpdatedRassInteractivePicMask]
+ }[self.type]
+
+ @cached
+ def getText(self):
+ decoder = self.source.decoder
+ text = ""
+ if decoder:
+ if self.type == self.RADIO_TEXT_CHANGED:
+ text = decoder.getText(iRdsDecoder.RadioText)
+ elif self.type == self.RTP_TEXT_CHANGED:
+ text = decoder.getText(iRdsDecoder.RtpText)
+ else:
+ print "unknown RdsInfo Converter type", self.type
+ return text
+
+ text = property(getText)
+
+ @cached
+ def getBoolean(self):
+ decoder = self.source.decoder
+ if self.type == self.RASS_INTERACTIVE_AVAILABLE:
+ mask = decoder and decoder.getRassInteractiveMask()
+ return (mask and mask[0] & 1 and True) or False
+ elif self.type == self.RADIO_TEXT_CHANGED:
+ return (len(decoder.getText(iRdsDecoder.RadioText)) and True) or False
+ elif self.type == self.RTP_TEXT_CHANGED:
+ return (len(decoder.getText(iRdsDecoder.RtpText)) and True) or False
+ boolean = property(getBoolean)
+
+ def changed(self, what):
+ if what[0] != self.CHANGED_SPECIFIC or what[1] in self.interesting_events:
+ Converter.changed(self, what)
install_PYTHON = \
__init__.py Clock.py EventInfo.py Source.py MenuList.py CurrentService.py \
- FrontendStatus.py Boolean.py Config.py ServiceList.py RadioText.py StreamService.py \
+ FrontendStatus.py Boolean.py Config.py ServiceList.py RdsDecoder.py StreamService.py \
StaticText.py
--- /dev/null
+from Components.PerServiceDisplay import PerServiceBase
+from Components.Element import cached
+from enigma import iPlayableService
+from Source import Source
+
+class RdsDecoder(PerServiceBase, Source, object):
+ def __init__(self, navcore):
+ Source.__init__(self)
+ PerServiceBase.__init__(self, navcore,
+ {
+ iPlayableService.evStart: self.gotEvent,
+ iPlayableService.evUpdatedRadioText: self.gotEvent,
+ iPlayableService.evUpdatedRtpText: self.gotEvent,
+ iPlayableService.evUpdatedRassInteractivePicMask: self.gotEvent,
+ iPlayableService.evEnd: self.gotEvent
+ }, with_event=True)
+
+ @cached
+ def getDecoder(self):
+ service = self.navcore.getCurrentService()
+ return service and service.rdsDecoder()
+
+ decoder = property(getDecoder)
+
+ def gotEvent(self, what):
+ if what in [iPlayableService.evStart, iPlayableService.evEnd]:
+ self.changed((self.CHANGED_CLEAR,))
+ else:
+ self.changed((self.CHANGED_SPECIFIC, what))
from Screen import Screen
from Components.Button import Button
from Components.ServiceList import ServiceList
-from Components.ActionMap import NumberActionMap, ActionMap
+from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
from Components.MenuList import MenuList
from Components.ServiceEventTracker import ServiceEventTracker
from EpgSelection import EPGSelection
from Tools.NumericalTextInput import NumericalTextInput
from Components.NimManager import nimmanager
from Components.Sources.Clock import Clock
+from Components.Sources.RdsDecoder import RdsDecoder
from Components.Input import Input
from Components.ParentalControl import parentalControl
from Screens.InputBox import InputBox, PinInput
from Screens.MessageBox import MessageBox
from Screens.ServiceInfo import ServiceInfo
+from Screens.RdsDisplay import RassInteractive
from ServiceReference import ServiceReference
from Tools.BoundFunction import boundFunction
from re import *
self.revertMode = None
self.close(None)
-from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarRadioText
+from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
-class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
+class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
def __init__(self, session):
Screen.__init__(self, session)
InfoBarEvent.__init__(self)
InfoBarServiceName.__init__(self)
- InfoBarInstantRecord.__init__(self)
self["CurrentTime"] = Clock()
+ self["RdsDecoder"] = RdsDecoder(self.session.nav)
-class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarRadioText):
-
+class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
ALLOW_SUSPEND = True
- def __init__(self, session):
+ def __init__(self, session, infobar):
ChannelSelectionBase.__init__(self, session)
ChannelSelectionEdit.__init__(self)
ChannelSelectionEPG.__init__(self)
- InfoBarRadioText.__init__(self)
-
+ self.infobar = infobar
config.radio = ConfigSubsection();
config.radio.lastservice = ConfigText()
config.radio.lastroot = ConfigText()
self.onLayoutFinish.append(self.onCreate)
- self.info = session.instantiateDialog(RadioInfoBar)
+ self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
{
iPlayableService.evEnd: self.__evServiceEnd
})
+########## RDS Radiotext / Rass Support BEGIN
+ self.infobar = infobar # reference to real infobar (the one and only)
+ self["RdsDecoder"] = self.info["RdsDecoder"]
+ self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
+ {
+ "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
+ },-1)
+ self["RdsActions"].setEnabled(False)
+ infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
+
+ def startRassInteractive(self):
+ self.info.hide();
+ self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
+
+ def RassInteractiveClosed(self):
+ self.info.show()
+ self.infobar.rass_interactive = None
+ self.infobar.RassSlidePicChanged()
+
+ def RassInteractivePossibilityChanged(self, state):
+ self["RdsActions"].setEnabled(state)
+########## RDS Radiotext / Rass Support END
+
+ def closeRadio(self):
+ self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
+ self.info.hide()
+ #set previous tv service
+ lastservice=eServiceReference(config.tv.lastservice.value)
+ self.session.nav.playService(lastservice)
+ self.close(None)
+
def __evServiceStart(self):
service = self.session.nav.getCurrentService()
if service:
config.radio.lastservice.save()
self.saveRoot()
- def closeRadio(self):
- self.info.hide()
- #set previous tv service
- lastservice=eServiceReference(config.tv.lastservice.value)
- self.session.nav.playService(lastservice)
- self.close(None)
-
class SimpleChannelSelection(ChannelSelectionBase):
def __init__(self, session, title):
ChannelSelectionBase.__init__(self, session)
from Tools.Notifications import AddNotificationWithCallback
from Screens.InfoBarGenerics import InfoBarShowHide, \
- InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarRadioText, \
+ InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarRdsDecoder, \
InfoBarEPG, InfoBarEvent, InfoBarServiceName, InfoBarSeek, InfoBarInstantRecord, \
InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, \
InfoBarSubserviceSelection, InfoBarTuner, InfoBarShowMovies, InfoBarTimeshift, \
from Screens.HelpMenu import HelpableScreen, HelpMenu
class InfoBar(InfoBarShowHide,
- InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRadioText,
+ InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRdsDecoder,
InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarAudioSelection,
HelpableScreen, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish,
InfoBarSubserviceSelection, InfoBarTuner, InfoBarTimeshift, InfoBarSeek,
for x in HelpableScreen, \
InfoBarShowHide, \
- InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRadioText, \
+ InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRdsDecoder, \
InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarAudioSelection, \
InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarSubserviceSelection, \
InfoBarTuner, InfoBarTimeshift, InfoBarSeek, InfoBarSummarySupport, InfoBarTimeshiftState, \
if config.usage.e1like_radio_mode.value:
self.showRadioChannelList(True)
else:
- self.session.open(ChannelSelectionRadio)
+ self.rds_display.hide() # in InfoBarRdsDecoder
+ self.session.openWithCallback(self.ChannelSelectionRadioClosed, ChannelSelectionRadio, self)
+
+ def ChannelSelectionRadioClosed(self, *arg):
+ self.rds_display.show() # in InfoBarRdsDecoder
def showMovies(self):
self.session.openWithCallback(self.movieSelected, MovieSelection)
from Components.ServiceEventTracker import ServiceEventTracker
from Components.Sources.CurrentService import CurrentService
from Components.Sources.EventInfo import EventInfo
-from Components.Sources.RadioText import RadioText
from Components.Sources.FrontendStatus import FrontendStatus
from Components.Sources.Boolean import Boolean
from Components.Sources.Clock import Clock
from Screens.TimerSelection import TimerSelection
from Screens.PictureInPicture import PictureInPicture
from Screens.SubtitleDisplay import SubtitleDisplay
+from Screens.RdsDisplay import RdsInfoDisplay, RassInteractive
from Screens.SleepTimerEdit import SleepTimerEdit
from ServiceReference import ServiceReference
self["Event_Now"] = EventInfo(self.session.nav, EventInfo.NOW)
self["Event_Next"] = EventInfo(self.session.nav, EventInfo.NEXT)
-class InfoBarRadioText:
- """provides radio (RDS) text info display"""
+class InfoBarRdsDecoder:
+ """provides RDS and Rass support/display"""
def __init__(self):
- self["RadioText"] = RadioText(self.session.nav)
+ self.rds_display = self.session.instantiateDialog(RdsInfoDisplay)
+ self.rass_interactive = None
+
+ self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+ {
+ iPlayableService.evEnd: self.__serviceStopped,
+ iPlayableService.evUpdatedRassSlidePic: self.RassSlidePicChanged
+ })
+
+ self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
+ {
+ "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
+ },-1)
+
+ self["RdsActions"].setEnabled(False)
+
+ self.onLayoutFinish.append(self.rds_display.show)
+ self.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
+
+ def RassInteractivePossibilityChanged(self, state):
+ self["RdsActions"].setEnabled(state)
+
+ def RassSlidePicChanged(self):
+ if not self.rass_interactive:
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ if decoder:
+ decoder.showRassSlidePicture()
+
+ def __serviceStopped(self):
+ if self.rass_interactive is not None:
+ rass_interactive = self.rass_interactive
+ self.rass_interactive = None
+ rass_interactive.close()
+
+ def startRassInteractive(self):
+ self.rds_display.hide()
+ self.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
+
+ def RassInteractiveClosed(self, *val):
+ if self.rass_interactive is not None:
+ self.rass_interactive = None
+ self.RassSlidePicChanged()
+ self.rds_display.show()
class InfoBarServiceName:
def __init__(self):
Console.py InputBox.py ChoiceBox.py SimpleSummary.py ImageWizard.py \
MediaPlayer.py TimerSelection.py PictureInPicture.py TimeDateInput.py \
SubtitleDisplay.py SubservicesQuickzap.py ParentalControlSetup.py NumericalTextInputHelpDialog.py \
- SleepTimerEdit.py Ipkg.py
+ SleepTimerEdit.py Ipkg.py RdsDisplay.py
--- /dev/null
+from enigma import iPlayableService, loadPNG, iRdsDecoder, ePoint, gRGB
+from Screens.Screen import Screen
+from Components.Sources.RdsDecoder import RdsDecoder
+from Components.ActionMap import NumberActionMap
+from Components.ServiceEventTracker import ServiceEventTracker
+from Components.Pixmap import Pixmap
+from Components.Label import Label
+from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE
+
+class RdsInfoDisplay(Screen):
+ ALLOW_SUSPEND = True
+
+ def __init__(self, session):
+ Screen.__init__(self, session)
+
+ self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+ {
+ iPlayableService.evEnd: self.__serviceStopped,
+ iPlayableService.evUpdatedRadioText: self.RadioTextChanged,
+ iPlayableService.evUpdatedRtpText: self.RtpTextChanged,
+ iPlayableService.evUpdatedRassInteractivePicMask: self.RassInteractivePicMaskChanged,
+ })
+
+ self["RadioText"] = Label()
+ self["RtpText"] = Label()
+ self["RassLogo"] = Pixmap()
+
+ self.onLayoutFinish.append(self.hideWidgets)
+ self.rassInteractivePossible=False
+ self.onRassInteractivePossibilityChanged = [ ]
+
+ def hideWidgets(self):
+ for x in (self["RadioText"],self["RtpText"],self["RassLogo"]):
+ x.hide()
+
+ def RadioTextChanged(self):
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ rdsText = decoder and decoder.getText(iRdsDecoder.RadioText)
+ if rdsText and len(rdsText):
+ self["RadioText"].setText(rdsText)
+ self["RadioText"].show()
+ else:
+ self["RadioText"].hide()
+
+ def RtpTextChanged(self):
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ rtpText = decoder and decoder.getText(iRdsDecoder.RtpText)
+ if rtpText and len(rtpText):
+ self["RtpText"].setText(rtpText)
+ self["RtpText"].show()
+ else:
+ self["RtpText"].hide()
+
+ def RassInteractivePicMaskChanged(self):
+ if not self.rassInteractivePossible:
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ mask = decoder and decoder.getRassInteractiveMask()
+ if mask[0] & 1: #rass interactive index page available
+ self["RassLogo"].show()
+ self.rassInteractivePossible = True
+ for x in self.onRassInteractivePossibilityChanged:
+ x(True)
+
+ def __serviceStopped(self):
+ self.hideWidgets()
+ if self.rassInteractivePossible:
+ self.rassInteractivePossible = False
+ for x in self.onRassInteractivePossibilityChanged:
+ x(False)
+
+class RassInteractive(Screen):
+ def __init__(self, session):
+ Screen.__init__(self, session)
+
+ self["actions"] = NumberActionMap( [ "NumberActions", "RassInteractiveActions" ],
+ {
+ "exit": self.close,
+ "0": lambda x : self.numPressed(0),
+ "1": lambda x : self.numPressed(1),
+ "2": lambda x : self.numPressed(2),
+ "3": lambda x : self.numPressed(3),
+ "4": lambda x : self.numPressed(4),
+ "5": lambda x : self.numPressed(5),
+ "6": lambda x : self.numPressed(6),
+ "7": lambda x : self.numPressed(7),
+ "8": lambda x : self.numPressed(8),
+ "9": lambda x : self.numPressed(9),
+ "nextPage": self.nextPage,
+ "prevPage": self.prevPage,
+ "nextSubPage": self.nextSubPage,
+ "prevSubPage": self.prevSubPage
+ })
+
+ self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+ {
+ iPlayableService.evUpdatedRassInteractivePicMask: self.recvRassInteractivePicMaskChanged
+ })
+
+ self["subpages_1"] = Pixmap()
+ self["subpages_2"] = Pixmap()
+ self["subpages_3"] = Pixmap()
+ self["subpages_4"] = Pixmap()
+ self["subpages_5"] = Pixmap()
+ self["subpages_6"] = Pixmap()
+ self["subpages_7"] = Pixmap()
+ self["subpages_8"] = Pixmap()
+ self["subpages_9"] = Pixmap()
+ self["Marker"] = Label(">")
+
+ self.subpage = {
+ 1 : self["subpages_1"],
+ 2 : self["subpages_2"],
+ 3 : self["subpages_3"],
+ 4 : self["subpages_4"],
+ 5 : self["subpages_5"],
+ 6 : self["subpages_6"],
+ 7 : self["subpages_7"],
+ 8 : self["subpages_8"],
+ 9 : self["subpages_9"] }
+
+ self.subpage_png = {
+ 1 : loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "rass_page1.png")),
+ 2 : loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "rass_page2.png")),
+ 3 : loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "rass_page3.png")),
+ 4 : loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "rass_page4.png")) }
+
+ self.current_page=0;
+ self.current_subpage=0;
+ self.showRassPage(0,0)
+ self.onLayoutFinish.append(self.updateSubPagePixmaps)
+
+ def updateSubPagePixmaps(self):
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ if not decoder: # this should never happen
+ print "NO RDS DECODER in showRassPage"
+ else:
+ mask = decoder.getRassInteractiveMask()
+ page = 1
+ while page < 10:
+ subpage_cnt = self.countAvailSubpages(page, mask)
+ subpage = self.subpage[page]
+ if subpage_cnt > 0:
+ if subpage.instance:
+ png = self.subpage_png[subpage_cnt]
+ if png:
+ subpage.instance.setPixmap(png)
+ subpage.show()
+ else:
+ print "rass png missing"
+ else:
+ subpage.hide()
+ page += 1
+
+ def recvRassInteractivePicMaskChanged(self):
+ self.updateSubPagePixmaps()
+
+ def showRassPage(self, page, subpage):
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ if not decoder: # this should never happen
+ print "NO RDS DECODER in showRassPage"
+ else:
+ decoder.showRassInteractivePic(page, subpage)
+ page_diff = page - self.current_page
+ self.current_page = page
+ if page_diff:
+ current_pos = self["Marker"].getPosition()
+ y = current_pos[1]
+ y += page_diff * 25
+ self["Marker"].setPosition(current_pos[0],y)
+
+ def getMaskForPage(self, page, masks=None):
+ if not masks:
+ service = self.session.nav.getCurrentService()
+ decoder = service and service.rdsDecoder()
+ if not decoder: # this should never happen
+ print "NO RDS DECODER in getMaskForPage"
+ masks = decoder.getRassInteractiveMask()
+ if masks:
+ mask = masks[(page*4)/8]
+ if page % 2:
+ mask >>= 4
+ else:
+ mask &= 0xF
+ return mask
+
+ def countAvailSubpages(self, page, masks):
+ mask = self.getMaskForPage(page, masks)
+ cnt = 0
+ while mask:
+ if mask & 1:
+ cnt += 1
+ mask >>= 1
+ return cnt
+
+ def nextPage(self):
+ mask = 0
+ page = self.current_page
+ while mask == 0:
+ page += 1
+ if page > 9:
+ page = 0
+ mask = self.getMaskForPage(page)
+ self.numPressed(page)
+
+ def prevPage(self):
+ mask = 0
+ page = self.current_page
+ while mask == 0:
+ if page > 0:
+ page -= 1
+ else:
+ page = 9
+ mask = self.getMaskForPage(page)
+ self.numPressed(page)
+
+ def nextSubPage(self):
+ self.numPressed(self.current_page)
+
+ def prevSubPage(self):
+ num = self.current_page
+ mask = self.getMaskForPage(num)
+ cur_bit = 1 << self.current_subpage
+ tmp = cur_bit
+ while True:
+ if tmp == 1:
+ tmp = 8
+ else:
+ tmp >>= 1
+ if tmp == cur_bit: # no other subpage avail
+ return
+ if mask & tmp: # next subpage found
+ subpage = 0
+ while tmp > 1: # convert bit to subpage
+ subpage += 1
+ tmp >>= 1
+ self.current_subpage = subpage
+ self.showRassPage(num, subpage)
+ return
+
+ def numPressed(self, num):
+ mask = self.getMaskForPage(num)
+ if self.current_page == num:
+ self.skip = 0
+ cur_bit = 1 << self.current_subpage
+ tmp = cur_bit
+ else:
+ self.skip = 1
+ cur_bit = 16
+ tmp = 1
+ while True:
+ if not self.skip:
+ if tmp == 8 and cur_bit < 16:
+ tmp = 1
+ else:
+ tmp <<= 1
+ else:
+ self.skip = 0
+ if tmp == cur_bit: # no other subpage avail
+ return
+ if mask & tmp: # next subpage found
+ subpage = 0
+ while tmp > 1: # convert bit to subpage
+ subpage += 1
+ tmp >>= 1
+ self.current_subpage = subpage
+ self.showRassPage(num, subpage)
+ return
};
SWIG_TEMPLATE_TYPEDEF(ePtr<iAudioDelay>, iAudioDelayPtr);
-SWIG_IGNORE(iRadioText);
-class iRadioText: public iObject
+class iRdsDecoder_ENUMS
{
#ifdef SWIG
- iRadioText();
- ~iRadioText();
+ iRdsDecoder_ENUMS();
+ ~iRdsDecoder_ENUMS();
#endif
public:
- virtual std::string getRadioText(int x=0)=0;
+ enum { RadioText, RtpText };
};
-SWIG_TEMPLATE_TYPEDEF(ePtr<iRadioText>, iRadioTextPtr);
+
+SWIG_IGNORE(iRdsDecoder);
+class iRdsDecoder: public iObject, public iRdsDecoder_ENUMS
+{
+#ifdef SWIG
+ iRdsDecoder();
+ ~iRdsDecoder();
+#endif
+public:
+ virtual std::string getText(int x=RadioText)=0;
+ virtual void showRassSlidePicture()=0;
+ virtual void showRassInteractivePic(int page, int subpage)=0;
+ virtual SWIG_PYOBJECT(ePyObject) getRassInteractiveMask()=0;
+};
+SWIG_TEMPLATE_TYPEDEF(ePtr<iRdsDecoder>, iRdsDecoderPtr);
SWIG_IGNORE(iSubserviceList);
class iSubserviceList: public iObject
/* when cueSheet is implemented */
evCuesheetChanged,
- /* when radioText is implemented */
+ /* when rdsDecoder is implemented */
evUpdatedRadioText,
+ evUpdatedRtpText,
+
+ /* Radio Screenshow Support */
+ evUpdatedRassSlidePic,
+ evUpdatedRassInteractivePicMask,
evVideoSizeChanged,
virtual SWIG_VOID(RESULT) cueSheet(ePtr<iCueSheet> &SWIG_OUTPUT)=0;
virtual SWIG_VOID(RESULT) subtitle(ePtr<iSubtitleOutput> &SWIG_OUTPUT)=0;
virtual SWIG_VOID(RESULT) audioDelay(ePtr<iAudioDelay> &SWIG_OUTPUT)=0;
- virtual SWIG_VOID(RESULT) radioText(ePtr<iRadioText> &SWIG_OUTPUT)=0;
+ virtual SWIG_VOID(RESULT) rdsDecoder(ePtr<iRdsDecoder> &SWIG_OUTPUT)=0;
};
SWIG_TEMPLATE_TYPEDEF(ePtr<iPlayableService>, iPlayableServicePtr);
return 0;
}
-RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
+RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
{
ptr = this;
return 0;
if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
return -4;
- if (m_radiotext_parser)
- m_radiotext_parser->start(program.audioStreams[i].pid);
+ if (m_rds_decoder)
+ m_rds_decoder->start(program.audioStreams[i].pid);
if (m_dvb_service && !m_is_pvr)
{
return 0;
}
-std::string eDVBServicePlay::getRadioText(int x)
+std::string eDVBServicePlay::getText(int x)
{
- if (m_radiotext_parser)
+ if (m_rds_decoder)
switch(x)
{
- case 0:
- return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
+ case RadioText:
+ return convertLatin1UTF8(m_rds_decoder->getRadioText());
+ case RtpText:
+ return convertLatin1UTF8(m_rds_decoder->getRtpText());
}
return "";
}
-void eDVBServicePlay::radioTextUpdated()
+void eDVBServicePlay::rdsDecoderEvent(int what)
{
- m_event((iPlayableService*)this, evUpdatedRadioText);
+ switch(what)
+ {
+ case eDVBRdsDecoder::RadioTextChanged:
+ m_event((iPlayableService*)this, evUpdatedRadioText);
+ break;
+ case eDVBRdsDecoder::RtpTextChanged:
+ m_event((iPlayableService*)this, evUpdatedRtpText);
+ break;
+ case eDVBRdsDecoder::RassInteractivePicMaskChanged:
+ m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
+ break;
+ case eDVBRdsDecoder::RecvRassSlidePic:
+ m_event((iPlayableService*)this, evUpdatedRassSlidePic);
+ break;
+ }
+}
+
+void eDVBServicePlay::showRassSlidePicture()
+{
+ if (m_rds_decoder)
+ {
+ if (m_decoder)
+ {
+ std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
+ if (rass_slide_pic.length())
+ m_decoder->showSinglePic(rass_slide_pic.c_str());
+ else
+ eDebug("empty filename for rass slide picture received!!");
+ }
+ else
+ eDebug("no MPEG Decoder to show iframes avail");
+ }
+ else
+ eDebug("showRassSlidePicture called.. but not decoder");
+}
+
+void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
+{
+ if (m_rds_decoder)
+ {
+ if (m_decoder)
+ {
+ std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
+ if (rass_interactive_pic.length())
+ m_decoder->showSinglePic(rass_interactive_pic.c_str());
+ else
+ eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
+ }
+ else
+ eDebug("no MPEG Decoder to show iframes avail");
+ }
+ else
+ eDebug("showRassInteractivePic called.. but not decoder");
+}
+
+ePyObject eDVBServicePlay::getRassInteractiveMask()
+{
+ if (m_rds_decoder)
+ return m_rds_decoder->getRassPictureMask();
+ Py_RETURN_NONE;
}
int eDVBServiceBase::getFrontendInfo(int w)
m_decoder = 0;
m_decode_demux = 0;
m_teletext_parser = 0;
- m_radiotext_parser = 0;
+ m_rds_decoder = 0;
m_subtitle_parser = 0;
m_new_dvb_subtitle_page_connection = 0;
m_new_subtitle_page_connection = 0;
- m_radiotext_updated_connection = 0;
+ m_rds_decoder_event_connection = 0;
m_video_event_connection = 0;
/* free the timeshift service handler, we need the resources */
m_decode_demux = 0;
m_decoder = 0;
m_teletext_parser = 0;
- m_radiotext_parser = 0;
+ m_rds_decoder = 0;
m_subtitle_parser = 0;
m_new_subtitle_page_connection = 0;
m_new_dvb_subtitle_page_connection = 0;
- m_radiotext_updated_connection = 0;
+ m_rds_decoder_event_connection = 0;
m_video_event_connection = 0;
m_timeshift_active = 1;
ePtr<iDVBDemux> data_demux;
if (!h.getDataDemux(data_demux))
{
- m_radiotext_parser = new eDVBRadioTextParser(data_demux);
- m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
- m_radiotext_parser->start(apid);
+ m_rds_decoder = new eDVBRdsDecoder(data_demux);
+ m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
+ m_rds_decoder->start(apid);
}
}
}
public iAudioTrackSelection, public iAudioChannelSelection,
public iSubserviceList, public iTimeshiftService,
public iCueSheet, public iSubtitleOutput, public iAudioDelay,
- public iRadioText
+ public iRdsDecoder
{
DECLARE_REF(eDVBServicePlay);
public:
RESULT cueSheet(ePtr<iCueSheet> &ptr);
RESULT subtitle(ePtr<iSubtitleOutput> &ptr);
RESULT audioDelay(ePtr<iAudioDelay> &ptr);
- RESULT radioText(ePtr<iRadioText> &ptr);
+ RESULT rdsDecoder(ePtr<iRdsDecoder> &ptr);
// iPauseableService
RESULT pause();
int getCurrentChannel();
RESULT selectChannel(int i);
- // iRadioText
- std::string getRadioText(int i=0);
+ // iRdsDecoder
+ std::string getText(int i=0);
+ void showRassSlidePicture();
+ void showRassInteractivePic(int page, int subpage);
+ ePyObject getRassInteractiveMask();
// iSubserviceList
int getNumberOfSubservices();
void checkSubtitleTiming();
/* radiotext */
- ePtr<eDVBRadioTextParser> m_radiotext_parser;
- ePtr<eConnection> m_radiotext_updated_connection;
- void radioTextUpdated();
+ ePtr<eDVBRdsDecoder> m_rds_decoder;
+ ePtr<eConnection> m_rds_decoder_event_connection;
+ void rdsDecoderEvent(int);
ePtr<eConnection> m_video_event_connection;
void video_event(struct iTSMPEGDecoder::videoEvent);
RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; }
RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; }
RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; }
- RESULT radioText(ePtr<iRadioText> &ptr) { ptr = 0; return -1; }
+ RESULT rdsDecoder(ePtr<iRdsDecoder> &ptr) { ptr = 0; return -1; }
// iPausableService
RESULT pause();
RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; }
RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; }
RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; }
- RESULT radioText(ePtr<iRadioText> &ptr) { ptr = 0; return -1; }
+ RESULT rdsDecoder(ePtr<iRdsDecoder> &ptr) { ptr = 0; return -1; }
// iPausableService
RESULT pause();