- add prelim. pvr playback.
[enigma2.git] / lib / dvb / pmt.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/dvb/pmt.h>
3 #include <lib/dvb/specs.h>
4 #include <lib/dvb/dvb.h>
5
6 eDVBServicePMTHandler::eDVBServicePMTHandler()
7 {
8         ePtr<eDVBResourceManager> mgr;
9         eDVBResourceManager::getInstance(mgr);
10         m_resourceManager = mgr;
11         CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready);
12         CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready);
13 }
14
15 void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel)
16 {
17         int state;
18         channel->getState(state);
19         
20         if ((m_last_channel_state != iDVBChannel::state_ok)
21                 && (state == iDVBChannel::state_ok) && (!m_demux))
22         {
23                 if (m_channel)
24                         if (m_channel->getDemux(m_demux))
25                                 eDebug("shit it failed.. again.");
26                 
27                 serviceEvent(eventTuned);
28                 
29                 if (m_demux)
30                 {
31                         eDebug("ok ... now we start!!");
32
33                         /* emit */ m_resourceManager->m_channelRunning(channel);
34
35                         m_PAT.begin(eApp, eDVBPATSpec(), m_demux);
36                 }
37         }
38 }
39
40 void eDVBServicePMTHandler::PMTready(int error)
41 {
42         if (error)
43                 serviceEvent(eventNoPMT);
44         else
45                 serviceEvent(eventNewProgramInfo);
46 }
47
48 void eDVBServicePMTHandler::PATready(int)
49 {
50         eDebug("got PAT");
51         ePtr<eTable<ProgramAssociationTable> > ptr;
52         if (!m_PAT.getCurrent(ptr))
53         {
54                 int pmtpid = -1;
55                 ProgramAssociationTableConstIterator i;
56                 for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
57                 {
58                         const ProgramAssociationTable &pat = **i;
59                         ProgramAssociationConstIterator program;
60                         for (program = pat.getPrograms()->begin(); program != pat.getPrograms()->end(); ++program)
61                                 if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID())
62                                         pmtpid = (*program)->getProgramMapPid();
63                 }
64                 if (pmtpid == -1)
65                         serviceEvent(eventNoPATEntry);
66                 else
67                         m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux);
68         } else
69                 serviceEvent(eventNoPAT);
70 }
71
72 int eDVBServicePMTHandler::getProgramInfo(struct program &program)
73 {
74         eDebug("got PMT");
75         ePtr<eTable<ProgramMapTable> > ptr;
76         
77         program.videoStreams.clear();
78         program.audioStreams.clear();
79         program.pcrPid = -1;
80         
81         if (!m_PMT.getCurrent(ptr))
82         {
83                 ProgramMapTableConstIterator i;
84                 for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
85                 {
86                         const ProgramMapTable &pmt = **i;
87                         program.pcrPid = pmt.getPcrPid();
88                         
89                         ElementaryStreamInfoConstIterator es;
90                         for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
91                         {
92                                 int isaudio = 0, isvideo = 0;
93                                 videoStream video;
94                                 audioStream audio;
95                                 
96                                 video.pid = (*es)->getPid();
97                                 audio.pid = (*es)->getPid();
98                                 
99                                 switch ((*es)->getType())
100                                 {
101                                 case 0x01: // MPEG 1 video
102                                 case 0x02: // MPEG 2 video
103                                         isvideo = 1;
104                                         break;
105                                 case 0x03: // MPEG 1 audio
106                                 case 0x04: // MPEG 2 audio:
107                                         isaudio = 1;
108                                         audio.type = audioStream::atMPEG;
109                                         break;
110                                 }
111                                 if (isaudio)
112                                         program.audioStreams.push_back(audio);
113                                 if (isvideo)
114                                         program.videoStreams.push_back(video);
115                         }
116                 }
117                 return 0;
118         } else
119                 return -1;
120 }
121
122 int eDVBServicePMTHandler::getDemux(ePtr<iDVBDemux> &demux)
123 {
124         demux = m_demux;
125         if (demux)
126                 return 0;
127         else
128                 return -1;
129 }
130
131 int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref)
132 {
133         RESULT res;
134         m_reference = ref;
135         
136 //      ref.path = "/viva.ts"; // hrhr.
137         
138                 /* is this a normal (non PVR) channel? */
139         if (ref.path.empty())
140         {
141                 eDVBChannelID chid;
142                 ref.getChannelID(chid);
143                 res = m_resourceManager->allocateChannel(chid, m_channel);
144         } else
145         {
146                 eDebug("alloc PVR");
147                         /* allocate PVR */
148                 res = m_resourceManager->allocatePVRChannel(m_pvr_channel);
149                 if (res)
150                         eDebug("allocatePVRChannel failed!\n");
151                 m_channel = m_pvr_channel;
152         }
153         
154         if (m_channel)
155         {
156                 m_channel->connectStateChange(
157                         slot(*this, &eDVBServicePMTHandler::channelStateChanged), 
158                         m_channelStateChanged_connection);
159                 m_last_channel_state = -1;
160                 channelStateChanged(m_channel);
161         }
162         
163         if (m_pvr_channel)
164                 m_pvr_channel->playFile(ref.path.c_str());
165         
166         return res;
167 }