add support for Linkage services ( Premiere Subservices )
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Mon, 5 Dec 2005 19:24:42 +0000 (19:24 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Mon, 5 Dec 2005 19:24:42 +0000 (19:24 +0000)
TODO: show/hide green point depending on avail subservices

21 files changed:
data/keymap.xml
data/skin.xml
lib/base/estring.h
lib/dvb/eit.cpp
lib/dvb/eit.h
lib/dvb/idvb.h
lib/dvb/specs.h
lib/python/Components/Label.py
lib/python/Components/ServiceName.py
lib/python/Screens/InfoBar.py
lib/python/Screens/InfoBarGenerics.py
lib/python/Screens/Makefile.am
lib/python/Screens/SubserviceSelection.py [new file with mode: 0644]
lib/python/Screens/__init__.py
lib/service/event.cpp
lib/service/event.h
lib/service/iservice.h
lib/service/servicedvb.cpp
lib/service/servicedvb.h
lib/service/servicemp3.cpp
lib/service/servicemp3.h

index e10fe20..91f8262 100644 (file)
                <key id="KEY_AUDIO" mapto="audioSelection" flags="m" />
        </map>
 
+       <map context="InfobarSubserviceSelectionActions">
+               <key id="KEY_GREEN" mapto="subserviceSelection" flags="m" />
+       </map>
+
        <map context="InfobarVolumeActions">
                <key id="KEY_VOLUMEUP" mapto="volumeUp" flags="mr" />
                <key id="KEY_VOLUMEDOWN" mapto="volumeDown" flags="mr" />
index a2ffe18..44c4988 100644 (file)
@@ -49,6 +49,9 @@
                <screen name="AudioSelection" position="210,150" size="300,170" title="Audio">
                        <widget name="tracks" position="20,10" size="260,150" />
                </screen>
+               <screen name="SubserviceSelection" position="210,150" size="300,320" title="Subservices">
+                       <widget name="subservices" position="20,10" size="260,300" />
+               </screen>
                <screen name="HarddiskWait" position="140,165" size="360,60">
                        <widget name="wait" position="20,10" size="320,25" font="Arial;23"/>
                </screen>
                        <widget name="Event_Next_Duration" position="555,98" size="150,26" font="Arial;22" backgroundColor="dark" />
 
                        <widget name="ButtonRed" pixmap="/usr/share/enigma2/button_red.png" position="210,132" size="27,12" />
-                       <widget name="ButtonRedText" position="240,130" size="75,22" font="Arial;14" backgroundColor="blue" transparent="1" />
+                       <widget name="ButtonRedText" position="240,130" size="85,22" font="Arial;14" backgroundColor="blue" transparent="1" />
                        <widget name="ButtonGreen" pixmap="/usr/share/enigma2/button_green.png" position="320,132" size="27,12" />
-                       <widget name="ButtonYellow" pixmap="/usr/share/enigma2/button_yellow.png" position="430,132" size="27,12" />
-                       <widget name="ButtonBlue" pixmap="/usr/share/enigma2/button_blue.png" position="540,132" size="27,12" />
+                       <widget name="ButtonGreenText" position="350,130" size="85,22" font="Arial;14" backgroundColor="blue" transparent="1" />
+                       <!--widget name="ButtonYellow" pixmap="/usr/share/enigma2/button_yellow.png" position="430,132" size="27,12" />
+                       <widget name="ButtonBlue" pixmap="/usr/share/enigma2/button_blue.png" position="540,132" size="27,12" /-->
                        
                </screen>
 
index b997911..3402228 100644 (file)
@@ -11,7 +11,6 @@ int strnicmp(const char*, const char*, int);
 std::string getNum(int num, int base=10);
 
 std::string convertDVBUTF8(const unsigned char *data, int len, int table=0, int tsidonid=0); // with default ISO8859-1/Latin1
-std::string convertUTF8DVB(const std::string &string, int table=0); // with default ISO8859-1/Latin1
 std::string convertLatin1UTF8(const std::string &string);
 int isUTF8(const std::string &string);
 
index cc2c29b..9f3169f 100644 (file)
@@ -42,6 +42,11 @@ void eDVBServiceEITHandler::start(iDVBDemux *demux, int sid)
        m_EIT.begin(eApp, eDVBEITSpec(sid), demux);
 }
 
+void eDVBServiceEITHandler::startOther(iDVBDemux *demux, int sid)
+{
+       m_EIT.begin(eApp, eDVBEITSpecOther(sid), demux);
+}
+
 RESULT eDVBServiceEITHandler::getEvent(ePtr<eServiceEvent> &event, int nownext)
 {
        event = nownext ? m_event_next : m_event_now;
index 43bdb6b..bc52e14 100644 (file)
@@ -19,6 +19,7 @@ public:
        eDVBServiceEITHandler();
        
        void start(iDVBDemux *demux, int sid);
+       void startOther(iDVBDemux *demux, int sid);
        
        RESULT getEvent(ePtr<eServiceEvent> &event, int nownext);
        
index 22eccbd..742a3a3 100644 (file)
@@ -153,6 +153,12 @@ struct eServiceReferenceDVB: public eServiceReference
        eDVBNamespace getDVBNamespace() const { return eDVBNamespace(data[4]); }
        void setDVBNamespace(eDVBNamespace dvbnamespace) { data[4]=dvbnamespace.get(); }
 
+       eServiceID getParentServiceID() const { return eServiceID(data[5]); }
+       void setParentServiceID( eServiceID sid ) { data[5]=sid.get(); }
+
+       eTransportStreamID getParentTransportStreamID() const { return eTransportStreamID(data[6]); }
+       void setParentTransportStreamID( eTransportStreamID tsid ) { data[6]=tsid.get(); }
+
        eServiceReferenceDVB(eDVBNamespace dvbnamespace, eTransportStreamID transport_stream_id, eOriginalNetworkID original_network_id, eServiceID service_id, int service_type)
                :eServiceReference(eServiceReference::idDVB, 0)
        {
index 23ef2ce..afd5cef 100644 (file)
@@ -127,4 +127,25 @@ public:
        }
 };
 
+class eDVBEITSpecOther
+{
+       eDVBTableSpec m_spec;
+public:
+               /* this is for now&next on actual transponder. */
+       eDVBEITSpecOther(int sid)
+       {
+               m_spec.pid     = EventInformationSection::PID;
+               m_spec.tid     = TID_EIT_OTHER;
+               m_spec.tidext  = sid;
+               m_spec.timeout = EventInformationSection::TIMEOUT;
+               m_spec.flags   = eDVBTableSpec::tfAnyVersion |
+                       eDVBTableSpec::tfHaveTID | eDVBTableSpec::tfHaveTIDExt |
+                       eDVBTableSpec::tfCheckCRC | eDVBTableSpec::tfHaveTimeout;
+       }
+       operator eDVBTableSpec &()
+       {
+               return m_spec;
+       }
+};
+
 #endif
index 7402d72..c2d5774 100644 (file)
@@ -22,3 +22,8 @@ class Label(HTMLComponent, GUIComponent, VariableText):
                s = self.instance.calculateSize()
                return (s.width(), s.height())
 
+       def show(self):
+               self.instance.show()
+
+       def hide(self):
+               self.instance.hide()
index 2e794d6..a9c0930 100644 (file)
@@ -17,8 +17,9 @@ class ServiceName(PerServiceDisplay):
                if service is not None:
                        info = service.info()
                        if info is not None:
-                               self.setText(info.getName())
-                               setLCD(info.getName())
+                               name = info.getName()
+                               self.setText(name)
+                               setLCD(name)
        
        def stopEvent(self):
                        self.setText("");
index 45a0538..cee385c 100644 (file)
@@ -12,7 +12,8 @@ from Tools.Notifications import AddNotificationWithCallback
 from Screens.InfoBarGenerics import InfoBarVolumeControl, InfoBarShowHide, \
        InfoBarPowerKey, InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, \
        InfoBarEPG, InfoBarEvent, InfoBarServiceName, InfoBarPVR, InfoBarInstantRecord, \
-       InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish
+       InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, \
+       InfoBarSubserviceSelection
 
 from Screens.HelpMenu import HelpableScreen, HelpMenu
 
@@ -23,7 +24,8 @@ import time
 class InfoBar(Screen, InfoBarVolumeControl, InfoBarShowHide, InfoBarPowerKey,
        InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG,
        InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarAudioSelection, 
-       HelpableScreen, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish):
+       HelpableScreen, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish,
+       InfoBarSubserviceSelection):
 
        def __init__(self, session):
                Screen.__init__(self, session)
@@ -37,7 +39,7 @@ class InfoBar(Screen, InfoBarVolumeControl, InfoBarShowHide, InfoBarPowerKey,
                                InfoBarVolumeControl, InfoBarShowHide, InfoBarPowerKey, \
                                InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, \
                                InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarAudioSelection, \
-                               InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish:
+                               InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarSubserviceSelection:
                        x.__init__(self)
 
                self.helpList.append((self["actions"], "InfobarActions", [("showMovies", "Watch a Movie...")]))
index ddfac4a..f27cf40 100644 (file)
@@ -512,6 +512,26 @@ class InfoBarAudioSelection:
                if n > 0:
                        self.session.open(AudioSelection, audio)
 
+from Screens.SubserviceSelection import SubserviceSelection
+
+class InfoBarSubserviceSelection:
+       def __init__(self):
+               self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
+                       {
+                               "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
+                       })
+
+       def subserviceSelection(self):
+               service = self.session.nav.getCurrentService()
+               subservices = service.subServices()
+               n = subservices.getNumberOfSubservices()
+               if n > 0:
+                       self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
+
+       def subserviceSelected(self, service):
+               if not service is None:
+                       self.session.nav.playService(service)
+
 class InfoBarAdditionalInfo:
        def __init__(self):
                self["DolbyActive"] = PixmapConditional()
@@ -529,8 +549,11 @@ class InfoBarAdditionalInfo:
                self["ButtonRed"] = Pixmap()
                self["ButtonRedText"] = Label(_("Record"))
                self["ButtonGreen"] = Pixmap()
-               self["ButtonYellow"] = Pixmap()
-               self["ButtonBlue"] = Pixmap()
+               self["ButtonGreenText"] = Label(_("Subservices"))
+#              self["ButtonGreenText"].hide()
+#              self["ButtonGreen"].hidePixmap()
+#              self["ButtonYellow"] = Pixmap()
+#              self["ButtonBlue"] = Pixmap()
 
 class InfoBarNotifications:
        def __init__(self):
index 20e0961..71ee04f 100644 (file)
@@ -7,4 +7,4 @@ install_PYTHON = \
        Satconfig.py ScanSetup.py NetworkSetup.py Ci.py TimerEntry.py Volume.py \
        EpgSelection.py EventView.py Mute.py Standby.py ServiceInfo.py \
        AudioSelection.py InfoBarGenerics.py HelpMenu.py Wizard.py __init__.py \
-       Dish.py
+       Dish.py SubserviceSelection.py
diff --git a/lib/python/Screens/SubserviceSelection.py b/lib/python/Screens/SubserviceSelection.py
new file mode 100644 (file)
index 0000000..a73cf0e
--- /dev/null
@@ -0,0 +1,30 @@
+from Screen import Screen
+from Components.ActionMap import ActionMap
+from Components.MenuList import MenuList
+from Components.Label import Label
+from enigma import eServiceReferencePtr, eServiceReference
+
+class SubserviceSelection(Screen):
+       def KeyOk(self):
+               selection = self["subservices"].getCurrent()
+               self.close(selection[1])
+       def Cancel(self):
+               self.close(None)
+       def __init__(self, session, subservices):
+               Screen.__init__(self, session)
+
+               self["actions"] = ActionMap(["OkCancelActions"], 
+                       {
+                               "cancel": self.Cancel,
+                               "ok": self.KeyOk,
+                       })
+
+               self.subservices = subservices
+
+               tlist = []
+               n = subservices.getNumberOfSubservices()
+               for x in range(n):
+                       i = subservices.getSubservice(x)
+                       tlist.append((i.getName(), i))
+
+               self["subservices"] = MenuList(tlist)
index 0c6f171..bb1428f 100644 (file)
@@ -4,4 +4,4 @@ __all__ = ["ChannelSelection", "ClockDisplay", "ConfigMenu",
        "TimerEdit", "Setup", "HarddiskSetup", "FixedMenu",
        "Satconfig", "Scanconfig", "Ci.py", "Volume.py", "Mute.py",
        "EpgSelection", "EventView", "Standby", "ServiceInfo",
-       "AudioSelection", "InfoBarGenerics", "HelpMenu", "Wizard"]
+       "AudioSelection", "SubserviceSelection", "InfoBarGenerics", "HelpMenu", "Wizard"]
index 81a8d4b..40bc9b5 100644 (file)
@@ -2,6 +2,7 @@
 #include <lib/base/estring.h>
 #include <lib/base/encoding.h>
 #include <lib/dvb/dvbtime.h>
+#include <lib/dvb/idvb.h>
 #include <dvbsi++/event_information_section.h>
 #include <dvbsi++/short_event_descriptor.h>
 #include <dvbsi++/extended_event_descriptor.h>
@@ -119,7 +120,8 @@ bool eServiceEvent::loadLanguage(Event *evt, std::string lang, int tsidonid)
                                        data.m_componentType = cp->getComponentType();
                                        data.m_componentTag = cp->getComponentTag();
                                        data.m_iso639LanguageCode = cp->getIso639LanguageCode();
-                                       data.m_text = convertDVBUTF8(cp->getText());
+                                       int table=encodingHandler.getCountryCodeDefaultMapping(data.m_iso639LanguageCode);
+                                       data.m_text = convertDVBUTF8(cp->getText(),table,tsidonid);
                                        m_component_data.push_back(data);
                                        break;
                                }
@@ -128,14 +130,16 @@ bool eServiceEvent::loadLanguage(Event *evt, std::string lang, int tsidonid)
                                        const LinkageDescriptor  *ld = (LinkageDescriptor*)*desc;
                                        if ( ld->getLinkageType() == 0xB0 )
                                        {
-                                               linkage_service s;
-                                               s.m_onid = ld->getOriginalNetworkId();
-                                               s.m_tsid = ld->getTransportStreamId();
-                                               s.m_sid = ld->getServiceId();
-                                               const PrivateDataByteVector *privateData =
-                                                       ld->getPrivateDataBytes();
-                                               s.m_description.assign((const char*)&((*privateData)[0]), privateData->size());
-                                               m_linkage_services.push_back(s);
+                                               eServiceReference ref;
+                                               ref.type = eServiceReference::idDVB;
+                                               eServiceReferenceDVB &dvb_ref = (eServiceReferenceDVB&) ref;
+                                               dvb_ref.setServiceType(1);
+                                               dvb_ref.setTransportStreamID(ld->getTransportStreamId());
+                                               dvb_ref.setOriginalNetworkID(ld->getOriginalNetworkId());
+                                               dvb_ref.setServiceID(ld->getServiceId());
+                                               const PrivateDataByteVector *privateData = ld->getPrivateDataBytes();
+                                               dvb_ref.name = convertDVBUTF8((const char*)&((*privateData)[0]), privateData->size(), 0, tsidonid);
+                                               m_linkage_services.push_back(ref);
                                        }
                                        break;
                                }
@@ -199,4 +203,19 @@ RESULT eServiceEvent::getComponentData(ePtr<eComponentData> &dest, int tagnum) c
        return -1;
 }
 
+RESULT eServiceEvent::getLinkageService(eServiceReference &service, int num) const
+{
+       std::list<eServiceReference>::const_iterator it =
+               m_linkage_services.begin();
+       while( it != m_linkage_services.end() && num-- )
+               ++it;
+       if ( it != m_linkage_services.end() )
+       {
+               service = *it;
+               return 0;
+       }
+       service.type = eServiceReference::idInvalid;
+       return -1;
+}
+
 DEFINE_REF(eDebugClass);
index d224c18..550d9a8 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef SWIG
 #include <time.h>
 #include <lib/base/object.h>
+#include <lib/service/iservice.h>
 #include <list>
 #include <string>
 class Event;
@@ -28,28 +29,18 @@ DECLARE_REF(eComponentData);
 
 TEMPLATE_TYPEDEF(ePtr<eComponentData>, eComponentDataPtr);
 
-struct linkage_service
-{
-       uint16_t m_sid;
-       uint16_t m_onid;
-       uint16_t m_tsid;
-       std::string m_description;
-};
-
 class eServiceEvent: public iObject
 {
-DECLARE_REF(eServiceEvent);
-#ifndef SWIG
+       DECLARE_REF(eServiceEvent);
        bool loadLanguage(Event *event, std::string lang, int tsidonid);
        std::list<eComponentData> m_component_data;
-#endif
-public:
-#ifndef SWIG
-       std::list<linkage_service> m_linkage_services;
+       std::list<eServiceReference> m_linkage_services;
        time_t m_begin;
        int m_duration;
        std::string m_event_name, m_short_description, m_extended_description;
        // .. additional info
+public:
+#ifndef SWIG
        RESULT parseFrom(Event *evt, int tsidonid=0);
 #endif
        time_t getBeginTime() const { return m_begin; }
@@ -59,6 +50,8 @@ public:
        std::string getExtendedDescription() const { return m_extended_description; }
        std::string getBeginTimeString() const;
        SWIG_VOID(RESULT) getComponentData(ePtr<eComponentData> &SWIG_OUTPUT, int tagnum) const;
+       int getNumOfLinkageServices() const { return m_linkage_services.size(); }
+       SWIG_VOID(RESULT) getLinkageService(eServiceReference &SWIG_OUTPUT, int num) const;
 };
 
 TEMPLATE_TYPEDEF(ePtr<eServiceEvent>, eServiceEventPtr);
index dfd0669..4ec1215 100644 (file)
@@ -3,11 +3,12 @@
 
 #include <lib/python/swig.h>
 #include <lib/base/object.h>
-#include <lib/service/event.h>
 #include <string>
 #include <connection.h>
 #include <list>
 
+class eServiceEvent;
+
 class eServiceReference
 {
 public:
@@ -54,8 +55,8 @@ public:
        eServiceReference()
                : type(idInvalid), flags(0)
        {
+               memset(data, 0, sizeof(data));
        }
-
        eServiceReference(int type, int flags)
                : type(type), flags(flags)
        {
@@ -181,8 +182,6 @@ public:
 
 TEMPLATE_TYPEDEF(ePtr<iStaticServiceInformation>, iStaticServiceInformationPtr);
 
-class eServiceEvent;
-
 TEMPLATE_TYPEDEF(ePtr<eServiceEvent>, eServiceEventPtr);
 
 class iServiceInformation: public iObject
@@ -279,6 +278,15 @@ public:
 
 TEMPLATE_TYPEDEF(ePtr<iAudioTrackSelection>, iAudioTrackSelectionPtr);
 
+class iSubserviceList: public iObject
+{
+public:
+       virtual int getNumberOfSubservices()=0;
+       virtual SWIG_VOID(RESULT) getSubservice(eServiceReference &SWIG_OUTPUT, unsigned int n)=0;
+};
+
+TEMPLATE_TYPEDEF(ePtr<iSubserviceList>, iSubserviceListPtr);
+
 class iPlayableService: public iObject
 {
        friend class iServiceHandler;
@@ -300,6 +308,7 @@ public:
        virtual SWIG_VOID(RESULT) pause(ePtr<iPauseableService> &SWIG_OUTPUT)=0;
        virtual SWIG_VOID(RESULT) info(ePtr<iServiceInformation> &SWIG_OUTPUT)=0;
        virtual SWIG_VOID(RESULT) audioTracks(ePtr<iAudioTrackSelection> &SWIG_OUTPUT)=0;
+       virtual SWIG_VOID(RESULT) subServices(ePtr<iSubserviceList> &SWIG_OUTPUT)=0;
        virtual SWIG_VOID(RESULT) frontendStatusInfo(ePtr<iFrontendStatusInformation> &SWIG_OUTPUT)=0;
 };
 
index 3cb5387..307fb9f 100644 (file)
@@ -25,9 +25,40 @@ DEFINE_REF(eStaticServiceDVBInformation);
 
 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
 {
+       eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
        if ( !ref.name.empty() )
        {
-               name = ref.name;
+               if (service.getParentTransportStreamID().get()) // linkage subservice
+               {
+                       ePtr<iServiceHandler> service_center;
+                       if (!eServiceCenter::getInstance(service_center))
+                       {
+                               eServiceReferenceDVB parent = service;
+                               parent.setTransportStreamID( service.getParentTransportStreamID() );
+                               parent.setServiceID( service.getParentServiceID() );
+                               parent.setParentTransportStreamID(eTransportStreamID(0));
+                               parent.setParentServiceID(eServiceID(0));
+                               parent.name="";
+                               ePtr<iStaticServiceInformation> service_info;
+                               if (!service_center->info(parent, service_info))
+                               {
+                                       if (!service_info->getName(parent, name))
+                                       {
+                                               // just show short name
+                                               unsigned int pos = name.find("\xc2\x86");
+                                               if ( pos != std::string::npos )
+                                                       name.erase(0, pos+2);
+                                               pos = name.find("\xc2\x87");
+                                               if ( pos != std::string::npos )
+                                                       name.erase(pos);
+                                               name+=" - ";
+                                       }
+                               }
+                       }
+               }
+               else
+                       name="";
+               name += ref.name;
                return 0;
        }
        else
@@ -365,24 +396,19 @@ RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServic
                        ptr = new eStaticServiceDVBInformation;
                else // a dvb bouquet
                        ptr = new eStaticServiceDVBBouquetInformation;
-               return 0;
        }
        else if (!ref.path.empty()) /* do we have a PVR service? */
-       {
                ptr = new eStaticServiceDVBPVRInformation(ref);
-               return 0;
-       }
        else // normal dvb service
        {
                ePtr<eDVBService> service;
-               int r = lookupService(service, ref);
-               if (r) // no eDVBService avail for this reference ( Linkage Services... )
+               if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
                        ptr = new eStaticServiceDVBInformation;
                else
                        /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
                        ptr = service;
-               return 0;
        }
+       return 0;
 }
 
 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
@@ -467,10 +493,16 @@ void eDVBServicePlay::serviceEvent(int event)
                ePtr<iDVBDemux> m_demux;
                if (!m_service_handler.getDemux(m_demux))
                {
-//                     eventStartedEventAcquisition
-                       m_event_handler.start(m_demux, ((eServiceReferenceDVB&)m_reference).getServiceID().get());
+                       eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
+                       int sid = ref.getParentServiceID().get();
+                       if (!sid)
+                               sid = ref.getServiceID().get();
+                       if ( ref.getParentTransportStreamID().get() &&
+                               ref.getParentTransportStreamID() != ref.getTransportStreamID() )
+                               m_event_handler.startOther(m_demux, sid);
+                       else
+                               m_event_handler.start(m_demux, sid);
                }
-//                     eventNoEvent
                break;
        }
        case eDVBServicePMTHandler::eventTuneFailed:
@@ -699,6 +731,12 @@ RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
        return 0;
 }
 
+RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
+{
+       ptr = this;
+       return 0;
+}
+
 RESULT eDVBServicePlay::getName(std::string &name)
 {
        if (m_dvb_service)
@@ -706,7 +744,10 @@ RESULT eDVBServicePlay::getName(std::string &name)
                m_dvb_service->getName(m_reference, name);
                if (name.empty())
                        name = "(...)";
-       } else
+       }
+       else if (!m_reference.name.empty())
+               eStaticServiceDVBInformation().getName(m_reference, name);
+       else
                name = "DVB service";
        return 0;
 }
@@ -841,6 +882,47 @@ int eDVBServicePlay::getFrontendInfo(int w)
        return fe->readFrontendData(w);
 }
 
+int eDVBServicePlay::getNumberOfSubservices()
+{
+       ePtr<eServiceEvent> evt;
+       if (!m_event_handler.getEvent(evt, 0))
+               return evt->getNumOfLinkageServices();
+       return 0;
+}
+
+RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
+{
+       ePtr<eServiceEvent> evt;
+       if (!m_event_handler.getEvent(evt, 0))
+       {
+               if (!evt->getLinkageService(sub, n))
+               {
+                       eServiceReferenceDVB &subservice = (eServiceReferenceDVB&) sub;
+                       eServiceReferenceDVB &current = (eServiceReferenceDVB&) m_reference;
+                       subservice.setDVBNamespace(current.getDVBNamespace());
+                       if ( current.getParentTransportStreamID().get() )
+                       {
+                               subservice.setParentTransportStreamID( current.getParentTransportStreamID() );
+                               subservice.setParentServiceID( current.getParentServiceID() );
+                       }
+                       else
+                       {
+                               subservice.setParentTransportStreamID( current.getTransportStreamID() );
+                               subservice.setParentServiceID( current.getServiceID() );
+                       }
+                       if ( subservice.getParentTransportStreamID() == subservice.getTransportStreamID() &&
+                               subservice.getParentServiceID() == subservice.getServiceID() )
+                       {
+                               subservice.setParentTransportStreamID( eTransportStreamID(0) );
+                               subservice.setParentServiceID( eServiceID(0) );
+                       }
+                       return 0;
+               }
+       }
+       sub.type=eServiceReference::idInvalid;
+       return -1;
+}
+
 DEFINE_REF(eDVBServicePlay)
 
 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");
index 4b6ef3e..5f85135 100644 (file)
@@ -54,7 +54,8 @@ private:
 
 class eDVBServicePlay: public iPlayableService, public iPauseableService, 
                public iSeekableService, public Object, public iServiceInformation, 
-               public iAudioTrackSelection, public iFrontendStatusInformation
+               public iAudioTrackSelection, public iFrontendStatusInformation,
+               public iSubserviceList
 {
 DECLARE_REF(eDVBServicePlay);
 public:
@@ -69,7 +70,8 @@ public:
        RESULT info(ePtr<iServiceInformation> &ptr);
        RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr);
        RESULT frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr);
-       
+       RESULT subServices(ePtr<iSubserviceList> &ptr);
+
                // iPauseableService
        RESULT pause();
        RESULT unpause();
@@ -94,6 +96,10 @@ public:
                // iFrontendStatusInformation
        int getFrontendInfo(int w);
 
+               // iSubserviceList
+       int getNumberOfSubservices();
+       RESULT getSubservice(eServiceReference &subservice, unsigned int n);
+
 private:
        friend class eServiceFactoryDVB;
        eServiceReference m_reference;
index 8f99947..7bd4244 100644 (file)
@@ -146,17 +146,30 @@ RESULT eServiceMP3::stop()
        return 0;
 }
 
-RESULT eServiceMP3::pause(ePtr<iPauseableService> &ptr) { ptr=this; return 0; }
-RESULT eServiceMP3::seek(ePtr<iSeekableService> &ptr) { ptr = 0; return -1; }
-
-RESULT eServiceMP3::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr) { ptr = 0; return -1; }
-RESULT eServiceMP3::audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return -1; };
+RESULT eServiceMP3::pause(ePtr<iPauseableService> &ptr)
+{
+       ptr=this;
+       return 0;
+}
 
                // iPausableService
-RESULT eServiceMP3::pause() { printf("mp3 pauses!\n"); return 0; }
-RESULT eServiceMP3::unpause() { printf("mp3 unpauses!\n"); return 0; }
+RESULT eServiceMP3::pause()
+{
+       printf("mp3 pauses!\n");
+       return 0;
+}
 
-RESULT eServiceMP3::info(ePtr<iServiceInformation>&i) { i = this; return 0; }
+RESULT eServiceMP3::unpause()
+{
+       printf("mp3 unpauses!\n");
+       return 0;
+}
+
+RESULT eServiceMP3::info(ePtr<iServiceInformation>&i)
+{
+       i = this;
+       return 0;
+}
 
 RESULT eServiceMP3::getName(std::string &name)
 {
index 9f1a8e9..dfdaa44 100644 (file)
@@ -56,9 +56,11 @@ public:
        RESULT start();
        RESULT stop();
        RESULT pause(ePtr<iPauseableService> &ptr);
-       RESULT seek(ePtr<iSeekableService> &ptr);
-       RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr);
-       RESULT frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr);
+               // not implemented (yet)
+       RESULT seek(ePtr<iSeekableService> &ptr) { ptr = 0; return -1; }
+       RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return -1; }
+       RESULT frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr) { ptr = 0; return -1; }
+       RESULT subServices(ePtr<iSubserviceList> &ptr) { ptr = 0; return -1; }
 
                // iPausableService
        RESULT pause();