- added iStaticServiceInformation
[enigma2.git] / lib / dvb / dvb.cpp
1 #include <lib/dvb/idvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/dvb/dvb.h>
4 #include <lib/dvb/sec.h>
5 #include <errno.h>
6
7 DEFINE_REF(eDVBResourceManager);
8
9 eDVBResourceManager *eDVBResourceManager::instance;
10
11 eDVBResourceManager::eDVBResourceManager()
12 {
13         avail = 1;
14         busy = 0;
15         m_sec = new eDVBSatelliteEquipmentControl;
16         if (!instance)
17                 instance = this;
18 }
19
20 eDVBResourceManager::~eDVBResourceManager()
21 {
22         if (instance == this)
23                 instance = 0;
24 }
25
26 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
27 {
28         m_list = list;
29         return 0;
30 }
31
32 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
33 {
34         list = m_list;
35         if (list)
36                 return 0;
37         else
38                 return -ENOENT;
39 }
40
41
42 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, ePtr<iDVBChannel> &channel)
43 {
44         RESULT res;
45         eDVBChannel *ch;
46         channel = ch = new eDVBChannel(this, 0, 0, 0);
47
48         ePtr<iDVBFrontend> fe;
49         if (!channel->getFrontend(fe))
50                 fe->setSEC(m_sec);
51
52         res = ch->setChannel(channelid);
53         if (res)
54         {
55                 channel = 0;
56                 return res;
57         }
58         return 0;
59 }
60
61 RESULT eDVBResourceManager::allocateRawChannel(ePtr<iDVBChannel> &channel)
62 {
63         channel = new eDVBChannel(this, 0, 0, 0);
64         ePtr<iDVBFrontend> fe;
65         if (!channel->getFrontend(fe))
66                 fe->setSEC(m_sec);
67         
68         return 0;
69 }
70
71 RESULT eDVBResourceManager::allocatePVRChannel(int caps)
72 {
73         return -1; // will nicht, mag nicht, und das interface ist auch kaputt
74 }
75
76 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
77 {
78         eDebug("add channel %p", ch);
79         m_active_channels.insert(std::pair<eDVBChannelID,eDVBChannel*>(chid, ch));
80         return 0;
81 }
82
83 RESULT eDVBResourceManager::removeChannel(const eDVBChannelID &chid, eDVBChannel *)
84 {
85         int cnt = m_active_channels.erase(chid);
86         eDebug("remove channel: removed %d channels", cnt);
87         ASSERT(cnt <= 1);
88         if (cnt == 1)
89                 return 0;
90         return -ENOENT;
91 }
92
93 DEFINE_REF(eDVBChannel);
94
95 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, int adapter, int frontend, int demux): eDVBDemux(adapter, demux), m_state(state_idle), m_mgr(mgr)
96 {
97         if (frontend >= 0)
98         {
99                 int ok;
100                 m_frontend = new eDVBFrontend(adapter, frontend, ok);
101                 if (!ok)
102                 {
103                         eDebug("warning, frontend failed");
104                         m_frontend = 0;
105                         return;
106                 }
107                 m_frontend->connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
108         }
109 }
110
111 eDVBChannel::~eDVBChannel()
112 {
113         if (m_channel_id)
114                 m_mgr->removeChannel(m_channel_id, this);
115 }
116
117 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
118 {
119         eDebug("fe state changed!");
120         int state, ourstate = 0;
121         if (fe->getState(state))
122                 return;
123         
124         if (state == iDVBFrontend::stateLock)
125         {
126                 eDebug("OURSTATE: ok");
127                 ourstate = state_ok;
128         } else if (state == iDVBFrontend::stateTuning)
129         {
130                 eDebug("OURSTATE: tuning");
131                 ourstate = state_tuning;
132         } else if (state == iDVBFrontend::stateFailed)
133         {
134                 eDebug("OURSTATE: failed/unavailable");
135                 ourstate = state_unavailable;
136         } else
137                 eFatal("state unknown");
138         
139         if (ourstate != m_state)
140         {
141                 m_state = ourstate;
142                 m_stateChanged(this);
143         }
144 }
145
146 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
147 {
148         ePtr<iDVBChannelList> list;
149         
150         if (m_mgr->getChannelList(list))
151         {
152                 eDebug("no channel list set!");
153                 return -ENOENT;
154         }
155         
156         eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
157                 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
158                 
159
160         ePtr<iDVBFrontendParameters> feparm;
161         if (list->getChannelFrontendData(channelid, feparm))
162         {
163                 eDebug("channel not found!");
164                 return -ENOENT;
165         }
166         eDebug("allocateChannel: channel found..");
167         
168         if (!m_frontend)
169         {
170                 eDebug("no frontend to tune!");
171                 return -ENODEV;
172         }
173         
174         if (m_channel_id)
175                 m_mgr->removeChannel(m_channel_id, this);
176         m_channel_id = channelid;
177         m_mgr->addChannel(m_channel_id, this);
178         m_state = state_tuning;
179         eDebug("%p", &*feparm);
180         return m_frontend->tune(*feparm);
181 }
182
183 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
184 {
185         connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
186         return 0;
187 }
188
189 RESULT eDVBChannel::getState(int &state)
190 {
191         state = m_state;
192         return 0;
193 }
194
195 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
196 {
197         return -1;
198 }
199
200 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux)
201 {
202         demux = this;
203         return 0;
204 }
205
206 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
207 {
208         frontend = m_frontend;
209         if (frontend)
210                 return 0;
211         else
212                 return -ENODEV;
213 }