- eConnections holds reference to object
[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(): ref(0)
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 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, int adapter, int frontend, int demux): eDVBDemux(adapter, demux), m_state(state_idle), m_mgr(mgr)
94 {
95         if (frontend >= 0)
96         {
97                 int ok;
98                 m_frontend = new eDVBFrontend(adapter, frontend, ok);
99                 if (!ok)
100                 {
101                         eDebug("warning, frontend failed");
102                         m_frontend = 0;
103                         return;
104                 }
105                 m_frontend->connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
106         }
107 }
108
109 eDVBChannel::~eDVBChannel()
110 {
111         if (m_channel_id)
112                 m_mgr->removeChannel(m_channel_id, this);
113 }
114
115 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
116 {
117         eDebug("fe state changed!");
118         int state, ourstate = 0;
119         if (fe->getState(state))
120                 return;
121         
122         if (state == iDVBFrontend::stateLock)
123         {
124                 eDebug("OURSTATE: ok");
125                 ourstate = state_ok;
126         } else if (state == iDVBFrontend::stateTuning)
127         {
128                 eDebug("OURSTATE: tuning");
129                 ourstate = state_tuning;
130         } else if (state == iDVBFrontend::stateFailed)
131         {
132                 eDebug("OURSTATE: failed/unavailable");
133                 ourstate = state_unavailable;
134         } else
135                 eFatal("state unknown");
136         
137         if (ourstate != m_state)
138         {
139                 m_state = ourstate;
140                 m_stateChanged(this);
141         }
142 }
143
144 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
145 {
146         ePtr<iDVBChannelList> list;
147         
148         if (m_mgr->getChannelList(list))
149         {
150                 eDebug("no channel list set!");
151                 return -ENOENT;
152         }
153         
154         eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
155                 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
156                 
157
158         ePtr<iDVBFrontendParameters> feparm;
159         if (list->getChannelFrontendData(channelid, feparm))
160         {
161                 eDebug("channel not found!");
162                 return -ENOENT;
163         }
164         eDebug("allocateChannel: channel found..");
165         
166         if (!m_frontend)
167         {
168                 eDebug("no frontend to tune!");
169                 return -ENODEV;
170         }
171         
172         if (m_channel_id)
173                 m_mgr->removeChannel(m_channel_id, this);
174         m_channel_id = channelid;
175         m_mgr->addChannel(m_channel_id, this);
176         m_state = state_tuning;
177         eDebug("%p", &*feparm);
178         return m_frontend->tune(*feparm);
179 }
180
181 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
182 {
183         connection = new eConnection(this, m_stateChanged.connect(stateChange));
184         return 0;
185 }
186
187 RESULT eDVBChannel::getState(int &state)
188 {
189         state = m_state;
190         return 0;
191 }
192
193 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
194 {
195         return -1;
196 }
197
198 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux)
199 {
200         demux = this;
201         return 0;
202 }
203
204 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
205 {
206         frontend = m_frontend;
207         if (frontend)
208                 return 0;
209         else
210                 return -ENODEV;
211 }