4.5.0r6
[enigma2.git] / usr / include / enigma2 / lib / dvb / esection.h
1 #ifndef __esection_h
2 #define __esection_h
3
4 #include <lib/dvb/idemux.h>
5 #include <set>
6
7 #define TABLE_eDebug(x...) do { if (m_debug) eDebug(x); } while(0)
8 #define TABLE_eDebugNoNewLine(x...) do { if (m_debug) eDebugNoNewLine(x); } while(0)
9
10 class eGTable: public iObject, public sigc::trackable
11 {
12         DECLARE_REF(eGTable);
13         ePtr<iDVBSectionReader> m_reader;
14         eDVBTableSpec m_table;
15         
16         unsigned int m_tries;
17         
18         ePtr<eTimer> m_timeout;
19
20         void sectionRead(const __u8 *data, int len);
21         void timeout();
22         ePtr<eConnection> m_sectionRead_conn;
23 protected:
24         bool m_debug;
25         virtual int createTable(unsigned int nr, const __u8 *data, int len, unsigned int max)=0;
26 public:
27         sigc::signal1<void, int> tableReady;
28         eGTable(bool debug=true);
29         RESULT start(iDVBSectionReader *reader, const eDVBTableSpec &table);
30         RESULT start(iDVBDemux *reader, const eDVBTableSpec &table);
31         RESULT getSpec(eDVBTableSpec &spec) { spec = m_table; return 0; }
32         virtual ~eGTable();
33         int error;
34         int ready;
35 };
36
37 template <class Section>
38 class eTable: public eGTable
39 {
40 private:
41         std::vector<Section*> sections;
42         std::set<int> avail;
43 protected:
44         int createTable(unsigned int nr, const __u8 *data, int len, unsigned int max)
45         {
46                 E_UNUSED(len);
47
48                 unsigned int ssize = sections.size();
49                 if (max < ssize || nr >= max)
50                 {
51                         TABLE_eDebug("kaputt max(%d) < ssize(%d) || nr(%d) >= max(%d)",
52                                 max, ssize, nr, max);
53                         return 0;
54                 }
55                 if (avail.find(nr) != avail.end())
56                         delete sections[nr];
57
58                 sections.resize(max);
59                 sections[nr] = new Section(data);
60                 avail.insert(nr);
61
62                 for (unsigned int i = 0; i < max; ++i)
63                         if (avail.find(i) != avail.end())
64                                 TABLE_eDebugNoNewLine("+");
65                         else
66                                 TABLE_eDebugNoNewLine("-");
67                                 
68                 TABLE_eDebug(" %zd/%d TID %02x", avail.size(), max, data[0]);
69
70                 if (avail.size() == max)
71                 {
72                         TABLE_eDebug("done!");
73                         return 1;
74                 } else
75                         return 0;
76         }
77 public:
78         std::vector<Section*> &getSections() { return sections; }
79         eTable(bool debug=true): eGTable(debug)
80         {
81         }
82         ~eTable()
83         {
84                 for (std::set<int>::iterator i(avail.begin()); i != avail.end(); ++i)
85                         delete sections[*i];
86         }
87 };
88
89 class eAUGTable: public iObject, public sigc::trackable
90 {
91         DECLARE_REF(eAUGTable);
92 protected:
93         void slotTableReady(int);
94 public:
95         sigc::signal1<void, int> tableReady;
96         virtual void getNext(int err)=0;
97 };
98
99 template <class Table>
100 class eAUTable: public eAUGTable
101 {
102         ePtr<Table> current, next;              // current is READY AND ERRORFREE, next is not yet ready
103         int first;
104         ePtr<iDVBDemux> m_demux;
105         eMainloop *ml;
106
107         /* needed to detect broken table version handling (seen on some m2ts files) */
108         struct timespec m_prev_table_update;
109         int m_table_cnt;
110 public:
111
112         eAUTable()
113         {
114         }
115
116         ~eAUTable()
117         {
118                 stop();
119         }
120         
121         void stop()
122         {
123                 current = next = 0;
124                 m_demux = 0;
125         }
126         
127         int begin(eMainloop *m, const eDVBTableSpec &spec, ePtr<iDVBDemux> demux)
128         {
129                 m_table_cnt = 0;
130                 ml = m;
131                 m_demux = demux;
132                 first= 1;
133                 current = 0;
134                 next = new Table();
135                 CONNECT(next->tableReady, eAUTable::slotTableReady);
136                 next->start(demux, spec);
137                 return 0;
138         }
139         
140         int get()
141         {
142                 if (current)
143                 {
144                         /*emit*/ tableReady(0);
145                         return 0;
146                 } else if (!next)
147                 {
148                         /*emit*/ tableReady(-1);
149                         return 0;
150                 } else
151                         return 1;
152         }
153         
154         RESULT getCurrent(ePtr<Table> &ptr)
155         {
156                 if (!current)
157                         return -1;
158                 ptr = current;
159                 return 0;
160         }
161
162 #if 0   
163         void abort()
164         {
165                 eDebug("eAUTable: aborted!");
166                 if (next)
167                         next->abort();
168                 delete next;
169                 next=0;
170         }
171 #endif
172
173         int ready()
174         {
175                 return !!current;
176         }
177         
178         void inject(Table *t)
179         {
180                 next=t;
181                 getNext(0);
182         }
183
184         void getNext(int error)
185         {
186                 current = 0;
187                 if (error)
188                 {
189                         next=0;
190                         if (first)
191                                 /*emit*/ tableReady(error);
192                         first=0;
193                         return;
194                 } else
195                         current=next;
196
197                 next=0;
198                 first=0;
199                 
200                 ASSERT(current->ready);
201                         
202                 /*emit*/ tableReady(0);
203                 
204                 eDVBTableSpec spec;
205
206                 if (current && (!current->getSpec(spec)))
207                 {
208                         /* detect broken table version handling (seen on some m2ts files) */
209                         if (m_table_cnt)
210                         {
211                                 if (llabs(timeout_msec(m_prev_table_update)) > 500)
212                                         m_table_cnt = -1;
213                                 else if (m_table_cnt > 1) // two pmt update within one second
214                                 {
215                                         eDebug("Seen two consecutive table version changes within 500ms. "
216                                             "This seems broken, so auto update for pid %04x, table %02x is now disabled!!",
217                                             spec.pid, spec.tid);
218                                         m_table_cnt = 0;
219                                         return;
220                                 }
221                         }
222
223                         ++m_table_cnt;
224                         clock_gettime(CLOCK_MONOTONIC, &m_prev_table_update);
225
226                         next = new Table();
227                         CONNECT(next->tableReady, eAUTable::slotTableReady);
228                         spec.flags &= ~(eDVBTableSpec::tfAnyVersion|eDVBTableSpec::tfThisVersion|eDVBTableSpec::tfHaveTimeout);
229                         next->eGTable::start(m_demux, spec);
230                 }
231         }
232 };
233
234 #endif