add a radiomode background picture (mvi file.. changable in
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 24 Mar 2007 00:49:20 +0000 (00:49 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 24 Mar 2007 00:49:20 +0000 (00:49 +0000)
/etc/enigma2/config ... config.misc.radiopic = /bla/blubber.mvi
add support for radio text plus,
add rass (radio screen show) support (yes used by SWR3, cont.ra and DASDING)
thanks to seddi for some piece of code
for better single iframe support its recommend to update in
dreambox-dvb-modules.bb CVSDATE for dm7025 to 20070323

26 files changed:
data/Makefile.am
data/keymap.xml
data/radio.mvi [new file with mode: 0755]
data/rass_logo.png [moved from lib/python/Components/Converter/RadioText.py with 100% similarity]
data/rass_page1.png [moved from lib/python/Components/Sources/RadioText.py with 100% similarity]
data/rass_page2.png [new file with mode: 0644]
data/rass_page3.png [new file with mode: 0644]
data/rass_page4.png [new file with mode: 0644]
data/skin.xml
data/skin_default.xml
lib/dvb/radiotext.cpp
lib/dvb/radiotext.h
lib/python/Components/Converter/Makefile.am
lib/python/Components/Converter/RdsInfo.py [new file with mode: 0644]
lib/python/Components/Sources/Makefile.am
lib/python/Components/Sources/RdsDecoder.py [new file with mode: 0644]
lib/python/Screens/ChannelSelection.py
lib/python/Screens/InfoBar.py
lib/python/Screens/InfoBarGenerics.py
lib/python/Screens/Makefile.am
lib/python/Screens/RdsDisplay.py [new file with mode: 0644]
lib/service/iservice.h
lib/service/servicedvb.cpp
lib/service/servicedvb.h
lib/service/servicemp3.h
lib/service/servicexine.h

index c866eac..ed26ec5 100644 (file)
@@ -5,4 +5,4 @@ SUBDIRS = countries fonts defaults extensions
 installdir = $(DATADIR)/enigma2
 
 install_DATA = \
-       *.xml *.png encoding.conf
+       *.xml *.png encoding.conf radio.mvi
index 835c521..5c0cb54 100644 (file)
                <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" />
diff --git a/data/radio.mvi b/data/radio.mvi
new file mode 100755 (executable)
index 0000000..bbd8016
Binary files /dev/null and b/data/radio.mvi differ
diff --git a/data/rass_page2.png b/data/rass_page2.png
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/data/rass_page3.png b/data/rass_page3.png
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/data/rass_page4.png b/data/rass_page4.png
new file mode 100644 (file)
index 0000000..e69de29
index 36f7325..cf2d2c7 100644 (file)
                <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>
index 4bdc5c1..65e810d 100644 (file)
@@ -3,8 +3,7 @@
                <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" />-->
@@ -18,8 +17,7 @@
        <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"/>
@@ -75,7 +73,7 @@
                <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" />
index 87498da..eff40e9 100644 (file)
@@ -3,19 +3,45 @@
 #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))
@@ -65,14 +91,54 @@ static int frequency[3][4] = {
        { 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)
        {
@@ -130,137 +196,440 @@ void eDVBRadioTextParser::processPESPacket(__u8 *data, int 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)))
@@ -268,9 +637,20 @@ int eDVBRadioTextParser::start(int 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;
+}
index b4ae0e2..8c354ff 100644 (file)
@@ -6,24 +6,37 @@
 #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;
 };
 
index b25a32d..a5d95f5 100644 (file)
@@ -3,5 +3,5 @@ installdir = $(LIBDIR)/enigma2/python/Components/Converter
 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
 
diff --git a/lib/python/Components/Converter/RdsInfo.py b/lib/python/Components/Converter/RdsInfo.py
new file mode 100644 (file)
index 0000000..3a7b2be
--- /dev/null
@@ -0,0 +1,53 @@
+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)
index 5e6a30a..b5e16d9 100644 (file)
@@ -2,5 +2,5 @@ installdir = $(LIBDIR)/enigma2/python/Components/Sources
 
 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
diff --git a/lib/python/Components/Sources/RdsDecoder.py b/lib/python/Components/Sources/RdsDecoder.py
new file mode 100644 (file)
index 0000000..886f81f
--- /dev/null
@@ -0,0 +1,29 @@
+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))
index 5a0f117..7f9f797 100644 (file)
@@ -1,7 +1,7 @@
 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
@@ -11,11 +11,13 @@ from Screens.FixedMenu import FixedMenu
 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 *
@@ -1256,32 +1258,30 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                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"],
                        {
@@ -1297,6 +1297,37 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                                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:
@@ -1371,13 +1402,6 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                                        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)
index 24c2b40..ab40838 100644 (file)
@@ -12,7 +12,7 @@ from Components.config import config
 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,  \
@@ -23,7 +23,7 @@ from Screens.InfoBarGenerics import InfoBarShowHide, \
 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,
@@ -47,7 +47,7 @@ class InfoBar(InfoBarShowHide,
                
                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, \
@@ -67,7 +67,11 @@ class InfoBar(InfoBarShowHide,
                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)
index 2ccd52d..78a67b7 100644 (file)
@@ -12,7 +12,6 @@ from Components.ProgressBar import *
 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
@@ -32,6 +31,7 @@ from Screens.MinuteInput import MinuteInput
 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
 
@@ -538,10 +538,53 @@ class InfoBarEvent:
                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):
index d5512e7..920a97f 100644 (file)
@@ -12,4 +12,4 @@ install_PYTHON = \
        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
diff --git a/lib/python/Screens/RdsDisplay.py b/lib/python/Screens/RdsDisplay.py
new file mode 100644 (file)
index 0000000..4190b94
--- /dev/null
@@ -0,0 +1,272 @@
+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
index feaa771..df4e302 100644 (file)
@@ -483,17 +483,30 @@ public:
 };
 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
@@ -676,8 +689,13 @@ public:
                        /* when cueSheet is implemented */
                evCuesheetChanged,
 
-                       /* when radioText is implemented */
+                       /* when rdsDecoder is implemented */
                evUpdatedRadioText,
+               evUpdatedRtpText,
+
+                       /* Radio Screenshow Support */
+               evUpdatedRassSlidePic,
+               evUpdatedRassInteractivePicMask,
 
                evVideoSizeChanged,
 
@@ -712,7 +730,7 @@ public:
        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);
 
index 9d9f2d1..e47ae52 100644 (file)
@@ -1475,7 +1475,7 @@ RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
        return 0;
 }
 
-RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
+RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
 {
        ptr = this;
        return 0;
@@ -1705,8 +1705,8 @@ int eDVBServicePlay::selectAudioStream(int i)
        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)
        {
@@ -1743,20 +1743,81 @@ RESULT eDVBServicePlay::selectChannel(int i)
        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)
@@ -2089,11 +2150,11 @@ void eDVBServicePlay::switchToLive()
        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 */
@@ -2113,11 +2174,11 @@ void eDVBServicePlay::switchToTimeshift()
        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;
@@ -2259,9 +2320,9 @@ void eDVBServicePlay::updateDecoder()
                                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);
                                }
                        }
                }
index 34ed972..7c785c4 100644 (file)
@@ -89,7 +89,7 @@ class eDVBServicePlay: public eDVBServiceBase,
                public iAudioTrackSelection, public iAudioChannelSelection,
                public iSubserviceList, public iTimeshiftService,
                public iCueSheet, public iSubtitleOutput, public iAudioDelay,
-               public iRadioText
+               public iRdsDecoder
 {
 DECLARE_REF(eDVBServicePlay);
 public:
@@ -112,7 +112,7 @@ 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();
@@ -144,8 +144,11 @@ public:
        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();
@@ -267,9 +270,9 @@ private:
        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);
index 4245c81..4996488 100644 (file)
@@ -66,7 +66,7 @@ public:
        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();
index 4a50b11..b56a485 100644 (file)
@@ -69,7 +69,7 @@ public:
        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();