Merge branch 'bug_124_m2ts_support' into experimental
[vuplus_dvbapp] / lib / mmi / mmi_ui.cpp
1 #include <lib/mmi/mmi_ui.h>
2 #include <lib/dvb_ci/dvbci_session.h> // for parseLengthField
3
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/ioctl.h>
7
8 #include <lib/base/init.h>
9 #include <lib/base/init_num.h>
10 #include <lib/base/eerror.h>
11 #include <lib/base/estring.h>
12
13 eMMI_UI::eMMI_UI(int max_slots)
14         :m_max_slots(max_slots)
15 {
16         slotdata = new slot_ui_data[m_max_slots];
17         for(int i=0;i<m_max_slots;++i)
18         {
19                 slotdata[i].mmiScreenReady=0;
20                 slotdata[i].mmiTuplePos=0;
21                 slotdata[i].state=-1;
22         }
23 }
24
25 eMMI_UI::~eMMI_UI()
26 {
27         for(int i=0;i<m_max_slots;++i)
28         {
29                 if (slotdata[i].mmiScreen)
30                         Py_DECREF(slotdata[i].mmiScreen);
31         }
32         delete [] slotdata;
33 }
34
35 int eMMI_UI::processMMIData(int slot_id, const unsigned char *tag, const void *data, int len)
36 {
37         switch (tag[2])
38         {
39         case 0x00:              //Tmmi_close
40         {
41                 unsigned char *d=(unsigned char*)data;
42                 int timeout=0;
43                 if (d[0] == 1)
44                 {
45                         if (len > 1)
46                                 timeout = d[1];
47                         else
48                         {
49                                 eDebug("mmi close tag incorrect.. no timeout given.. assume 5 seconds");
50                                 timeout = 5;
51                         }
52                 }
53                 else if (d[0] > 1)
54                         eDebug("mmi close tag incorrect.. byte 4 should be 0 or 1");
55                 mmiScreenClose(slot_id, timeout);
56                 break;
57         }
58         case 0x01:
59                 eDebug("MMI display control");
60                 if (((unsigned char*)data)[0] != 1)
61                         eDebug("kann ich nicht. aber das sag ich dem modul nicht.");
62                 return 1;
63         case 0x07:              //Tmenu_enq
64         {
65                 unsigned char *d=(unsigned char*)data;
66                 unsigned char *max=((unsigned char*)d) + len;
67                 int textlen = len - 2;
68                 eDebug("in enq");
69                 if ((d+2) > max)
70                         break;
71                 int blind = *d++ & 1;
72                 int alen = *d++;
73                         eDebug("%d bytes text", textlen);
74                 if ((d+textlen) > max)
75                         break;
76                 char str[textlen + 1];
77                 memcpy(str, ((char*)d), textlen);
78                 str[textlen] = '\0';
79                 eDebug("enq-text: %s",str);
80                 mmiScreenEnq(slot_id, blind, alen, (char*)convertDVBUTF8(str).c_str());
81                 break;
82         }
83         case 0x09:              //Tmenu_last
84         case 0x0c:              //Tlist_last
85         {
86                 unsigned char *d=(unsigned char*)data;
87                 unsigned char *max=((unsigned char*)d) + len;
88                 int pos = 0;
89                 eDebug("Tmenu_last");
90                 if (d > max)
91                         break;
92                 int n=*d++;
93                 if(tag[2] == 0x09)      //menu
94                         mmiScreenBegin(slot_id, 0);
95                 else                                                            //list
96                         mmiScreenBegin(slot_id, 1);
97                 if (n == 0xFF)
98                         n=0;
99                 else
100                         n++;
101                 eDebug("%d texts", n);
102                 for (int i=0; i < (n+3); ++i)
103                 {
104                         int textlen;
105                         if ((d+3) > max)
106                                 break;
107                         eDebug("text tag: %02x %02x %02x", d[0], d[1], d[2]);
108                         d+=3;
109                         d+=eDVBCISession::parseLengthField(d, textlen);
110                         eDebug("%d bytes text", textlen);
111                         if ((d+textlen) > max)
112                                 break;
113                         char str[textlen + 1];
114                         memcpy(str, ((char*)d), textlen);
115                         str[textlen] = '\0';
116                         mmiScreenAddText(slot_id, pos++, (char*)convertDVBUTF8(str).c_str());
117                         while (textlen--)
118                                 eDebugNoNewLine("%c", *d++);
119                         eDebug("");
120                 }
121                 mmiScreenFinish(slot_id);
122                 break;
123         }
124         default:
125                 eDebug("unknown APDU tag 9F 88 %02x", tag[2]);
126                 break;
127         }
128         return 0;
129 }
130
131 int eMMI_UI::getState(int slot)
132 {
133         if (slot < m_max_slots)
134                 return slotdata[slot].state;
135         return 0;
136 }
137
138 void eMMI_UI::setState(int slot, int newState)
139 {
140         if (slot < m_max_slots)
141         {
142                 slotdata[slot].state = newState;
143                 stateChanged(slot);
144         }
145 }
146
147 std::string eMMI_UI::getAppName(int slot)
148 {
149         if (slot < m_max_slots)
150                 return slotdata[slot].appName;
151         return "";
152 }
153
154 void eMMI_UI::setAppName(int slot, const char *name)
155 {
156         if (slot < m_max_slots)
157                 slotdata[slot].appName = name;
158 }
159
160 int eMMI_UI::availableMMI(int slot)
161 {
162         if (slot < m_max_slots)
163                 return slotdata[slot].mmiScreenReady;
164         return false;
165 }
166
167 int eMMI_UI::mmiScreenClose(int slot, int timeout)
168 {
169         if (slot >= m_max_slots)
170                 return 0;
171
172         slot_ui_data &data = slotdata[slot];
173
174         data.mmiScreenReady = 0;
175
176         if (data.mmiScreen)
177                 Py_DECREF(data.mmiScreen);
178         data.mmiScreen = PyList_New(1);
179
180         ePyObject tuple = PyTuple_New(2);
181         PyTuple_SET_ITEM(tuple, 0, PyString_FromString("CLOSE"));
182         PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(timeout));
183         PyList_SET_ITEM(data.mmiScreen, 0, tuple);
184         data.mmiScreenReady = 1;
185         stateChanged(slot);
186         return 0;
187 }
188
189 int eMMI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text)
190 {
191         if (slot >= m_max_slots)
192                 return 0;
193
194         slot_ui_data &data = slotdata[slot];
195
196         data.mmiScreenReady = 0;
197
198         if (data.mmiScreen)
199                 Py_DECREF(data.mmiScreen);
200         data.mmiScreen = PyList_New(2);
201
202         ePyObject tuple = PyTuple_New(1);
203         PyTuple_SET_ITEM(tuple, 0, PyString_FromString("ENQ"));
204         PyList_SET_ITEM(data.mmiScreen, 0, tuple);
205
206         tuple = PyTuple_New(4);
207         PyTuple_SET_ITEM(tuple, 0, PyString_FromString("PIN"));
208         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(answerLen));
209         PyTuple_SET_ITEM(tuple, 2, PyString_FromString(text));
210         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(blind));
211
212         PyList_SET_ITEM(data.mmiScreen, 1, tuple);
213
214         data.mmiScreenReady = 1;
215
216         stateChanged(slot);
217
218         return 0;
219 }
220
221 int eMMI_UI::mmiScreenBegin(int slot, int listmenu)
222 {
223         if (slot >= m_max_slots)
224                 return 0;
225
226         eDebug("eMMI_UI::mmiScreenBegin");
227
228         slot_ui_data &data = slotdata[slot];
229
230         data.mmiScreenReady = 0;
231
232         if (data.mmiScreen)
233                 Py_DECREF(data.mmiScreen);
234
235         data.mmiScreen = PyList_New(1);
236
237         ePyObject tuple = PyTuple_New(1);
238         if (listmenu == 0)                              //menu
239                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString("MENU"));
240         else    //list
241                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString("LIST"));
242
243         PyList_SET_ITEM(data.mmiScreen, 0, tuple);
244
245         data.mmiTuplePos = 1;
246
247         return 0;
248 }
249
250 int eMMI_UI::mmiScreenAddText(int slot, int type, char *value)
251 {
252         if (slot >= m_max_slots)
253                 return 0;
254
255         eDebug("eMMI_UI::mmiScreenAddText(%s)",value ? value : "");
256
257         slot_ui_data &data = slotdata[slot];
258
259         ePyObject tuple = PyTuple_New(3);
260
261         if (type == 0)                                  //title
262                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString("TITLE"));
263         else if (type == 1)                             //subtitle
264                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString("SUBTITLE"));
265         else if (type == 2)                             //bottom
266                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString("BOTTOM"));
267         else
268                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString("TEXT"));
269
270         eDebug("addText %s with id %d", value, type);
271
272         PyTuple_SET_ITEM(tuple, 1, PyString_FromString(value));
273
274         if (type > 2)
275                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(type-2));
276         else
277                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(-1));
278
279         PyList_Append(data.mmiScreen, tuple);
280         Py_DECREF(tuple);
281
282         return 0;
283 }
284
285 int eMMI_UI::mmiScreenFinish(int slot)
286 {
287         if (slot < m_max_slots)
288         {
289                 eDebug("eMMI_UI::mmiScreenFinish");
290                 slotdata[slot].mmiScreenReady = 1;
291                 stateChanged(slot);
292         }
293         return 0;
294 }
295
296 void eMMI_UI::mmiSessionDestroyed(int slot)
297 {
298         mmiScreenClose(slot, 0);
299 }
300
301 PyObject *eMMI_UI::getMMIScreen(int slot)
302 {
303         if (slot < m_max_slots)
304         {
305                 slot_ui_data &data = slotdata[slot];
306                 if (data.mmiScreenReady)
307                 {
308                         data.mmiScreenReady = 0;
309                         Py_INCREF(data.mmiScreen);
310                         return data.mmiScreen;
311                 }
312         }
313         Py_RETURN_NONE;
314 }