f2ffcef54b640626fe754f21b3739389b2c765de
[platform/upstream/gstreamer.git] / sys / dvb / parsechannels.c
1 /*
2  * parsechannels.c - 
3  * Copyright (C) 2008 Zaheer Abbas Merali
4  * 
5  * Authors:
6  *   Zaheer Abbas Merali <zaheerabbas at merali dot org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include <glib.h>
25 #include <glib-object.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <gst/gst.h>
29
30 #include "parsechannels.h"
31
32 /* TODO:
33  * Store the channels hash table around instead of constantly parsing it
34  * Detect when the file changed on disk
35  */
36
37 /* this will do zap style channels.conf only for the moment */
38 static GHashTable *
39 parse_channels_conf_from_file (GstElement * dvbbasebin, const gchar * filename)
40 {
41   gchar *contents;
42   gchar **lines;
43   gchar *line;
44   gchar **fields;
45   const gchar *terrestrial[] = { "inversion", "bandwidth",
46     "code-rate-hp", "code-rate-lp", "modulation", "transmission-mode",
47     "guard", "hierarchy"
48   };
49   const gchar *satellite[] = { "polarity", "diseqc-source",
50     "symbol-rate"
51   };
52   const gchar *cable[] = { "inversion", "symbol-rate", "code-rate-hp",
53     "modulation"
54   };
55   int i, parsedchannels = 0;
56   GHashTable *res;
57   GError *err = NULL;
58
59   if (!g_file_get_contents (filename, &contents, NULL, &err))
60     goto open_fail;
61
62   lines = g_strsplit (contents, "\n", 0);
63   res = g_hash_table_new (g_str_hash, g_str_equal);
64
65   i = 0;
66   line = lines[0];
67   while (line != NULL) {
68     if (line[0] != '#') {
69       int numfields;
70       gboolean parsed = FALSE;
71       GHashTable *params = g_hash_table_new_full (g_str_hash, g_str_equal,
72           g_free, g_free);
73
74       fields = g_strsplit (line, ":", 0);
75       numfields = g_strv_length (fields);
76       if (numfields == 8) {
77         /* satellite */
78         int j;
79
80         g_hash_table_insert (params, g_strdup ("type"), g_strdup ("satellite"));
81         for (j = 2; j <= 4; j++) {
82           g_hash_table_insert (params, g_strdup (satellite[j - 2]),
83               g_strdup (fields[j]));
84         }
85         g_hash_table_insert (params, g_strdup ("frequency"),
86             g_strdup_printf ("%d", atoi (fields[1]) * 1000));
87         parsed = TRUE;
88       } else if (numfields == 13) {
89         /* terrestrial */
90         int j;
91
92         g_hash_table_insert (params, g_strdup ("type"),
93             g_strdup ("terrestrial"));
94         for (j = 2; j <= 9; j++) {
95           g_hash_table_insert (params, g_strdup (terrestrial[j - 2]),
96               g_strdup (fields[j]));
97         }
98         g_hash_table_insert (params, g_strdup ("frequency"),
99             g_strdup (fields[1]));
100         parsed = TRUE;
101       } else if (numfields == 9) {
102         /* cable */
103         int j;
104
105         g_hash_table_insert (params, g_strdup ("type"), g_strdup ("cable"));
106         for (j = 2; j <= 5; j++) {
107           g_hash_table_insert (params, g_strdup (cable[j - 2]),
108               g_strdup (fields[j]));
109         }
110         g_hash_table_insert (params, g_strdup ("frequency"),
111             g_strdup (fields[1]));
112         parsed = TRUE;
113       } else if (numfields == 6) {
114         /* atsc (vsb/qam) */
115         g_hash_table_insert (params, g_strdup ("type"), g_strdup ("atsc"));
116         g_hash_table_insert (params, g_strdup ("modulation"),
117             g_strdup (fields[2]));
118
119         g_hash_table_insert (params, g_strdup ("frequency"),
120             g_strdup (fields[1]));
121         parsed = TRUE;
122       }
123       if (parsed) {
124         g_hash_table_insert (params, g_strdup ("sid"),
125             g_strdup (fields[numfields - 1]));
126         g_hash_table_insert (res, g_strdup (fields[0]), params);
127         parsedchannels++;
128       }
129       g_strfreev (fields);
130     }
131     line = lines[++i];
132   }
133   g_strfreev (lines);
134   g_free (contents);
135
136   if (parsedchannels == 0)
137     goto no_channels;
138
139   return res;
140
141 open_fail:
142   {
143     GST_ELEMENT_ERROR (dvbbasebin, RESOURCE, READ, (NULL),
144         ("Opening channels configuration file '%s' failed : %s", filename,
145             err->message));
146     g_clear_error (&err);
147     return NULL;
148   }
149
150 no_channels:
151   {
152     GST_ELEMENT_ERROR (dvbbasebin, RESOURCE, READ, (NULL),
153         ("Channels configuration file doesn't contain any channels"));
154     g_hash_table_unref (res);
155     return NULL;
156   }
157 }
158
159 static gboolean
160 remove_channel_from_hash (gpointer key, gpointer value, gpointer user_data)
161 {
162   if (key)
163     g_free (key);
164   if (value)
165     g_hash_table_destroy ((GHashTable *) value);
166   return TRUE;
167 }
168
169 static void
170 destroy_channels_hash (GHashTable * channels)
171 {
172   g_hash_table_foreach_remove (channels, remove_channel_from_hash, NULL);
173 }
174
175 gboolean
176 set_properties_for_channel (GstElement * dvbbasebin, const gchar * channel_name)
177 {
178   gboolean ret = FALSE;
179   GHashTable *channels, *params;
180   gchar *filename;
181   gchar *type;
182   const gchar *adapter;
183
184   filename = g_strdup (g_getenv ("GST_DVB_CHANNELS_CONF"));
185   if (filename == NULL) {
186     guint major, minor, micro, nano;
187
188     gst_version (&major, &minor, &micro, &nano);
189     filename = g_strdup_printf ("%s/gstreamer-%d.%d/dvb-channels.conf",
190         g_get_user_config_dir (), major, minor);
191   }
192   channels = parse_channels_conf_from_file (dvbbasebin, filename);
193   g_free (filename);
194
195   if (!channels)
196     goto beach;
197
198   params = g_hash_table_lookup (channels, channel_name);
199
200   if (!params)
201     goto unknown_channel;
202
203   g_object_set (dvbbasebin, "program-numbers",
204       g_hash_table_lookup (params, "sid"), NULL);
205   /* check if it is terrestrial or satellite */
206   adapter = g_getenv ("GST_DVB_ADAPTER");
207   if (adapter)
208     g_object_set (dvbbasebin, "adapter", atoi (adapter), NULL);
209   g_object_set (dvbbasebin, "frequency",
210       atoi (g_hash_table_lookup (params, "frequency")), NULL);
211   type = g_hash_table_lookup (params, "type");
212   if (strcmp (type, "terrestrial") == 0) {
213     gchar *val;
214
215     val = g_hash_table_lookup (params, "inversion");
216     if (strcmp (val, "INVERSION_OFF") == 0)
217       g_object_set (dvbbasebin, "inversion", 0, NULL);
218     else if (strcmp (val, "INVERSION_ON") == 0)
219       g_object_set (dvbbasebin, "inversion", 1, NULL);
220     else
221       g_object_set (dvbbasebin, "inversion", 2, NULL);
222
223     val = g_hash_table_lookup (params, "bandwidth");
224     if (strcmp (val, "BANDWIDTH_8_MHZ") == 0)
225       g_object_set (dvbbasebin, "bandwidth", 0, NULL);
226     else if (strcmp (val, "BANDWIDTH_7_MHZ") == 0)
227       g_object_set (dvbbasebin, "bandwidth", 1, NULL);
228     else if (strcmp (val, "BANDWIDTH_6_MHZ") == 0)
229       g_object_set (dvbbasebin, "bandwidth", 2, NULL);
230     else
231       g_object_set (dvbbasebin, "bandwidth", 3, NULL);
232
233     val = g_hash_table_lookup (params, "code-rate-hp");
234     if (strcmp (val, "FEC_NONE") == 0)
235       g_object_set (dvbbasebin, "code-rate-hp", 0, NULL);
236     else if (strcmp (val, "FEC_1_2") == 0)
237       g_object_set (dvbbasebin, "code-rate-hp", 1, NULL);
238     else if (strcmp (val, "FEC_2_3") == 0)
239       g_object_set (dvbbasebin, "code-rate-hp", 2, NULL);
240     else if (strcmp (val, "FEC_3_4") == 0)
241       g_object_set (dvbbasebin, "code-rate-hp", 3, NULL);
242     else if (strcmp (val, "FEC_4_5") == 0)
243       g_object_set (dvbbasebin, "code-rate-hp", 4, NULL);
244     else if (strcmp (val, "FEC_5_6") == 0)
245       g_object_set (dvbbasebin, "code-rate-hp", 5, NULL);
246     else if (strcmp (val, "FEC_6_7") == 0)
247       g_object_set (dvbbasebin, "code-rate-hp", 6, NULL);
248     else if (strcmp (val, "FEC_7_8") == 0)
249       g_object_set (dvbbasebin, "code-rate-hp", 7, NULL);
250     else if (strcmp (val, "FEC_8_9") == 0)
251       g_object_set (dvbbasebin, "code-rate-hp", 8, NULL);
252     else
253       g_object_set (dvbbasebin, "code-rate-hp", 9, NULL);
254
255     val = g_hash_table_lookup (params, "code-rate-lp");
256     if (strcmp (val, "FEC_NONE") == 0)
257       g_object_set (dvbbasebin, "code-rate-lp", 0, NULL);
258     else if (strcmp (val, "FEC_1_2") == 0)
259       g_object_set (dvbbasebin, "code-rate-lp", 1, NULL);
260     else if (strcmp (val, "FEC_2_3") == 0)
261       g_object_set (dvbbasebin, "code-rate-lp", 2, NULL);
262     else if (strcmp (val, "FEC_3_4") == 0)
263       g_object_set (dvbbasebin, "code-rate-lp", 3, NULL);
264     else if (strcmp (val, "FEC_4_5") == 0)
265       g_object_set (dvbbasebin, "code-rate-lp", 4, NULL);
266     else if (strcmp (val, "FEC_5_6") == 0)
267       g_object_set (dvbbasebin, "code-rate-lp", 5, NULL);
268     else if (strcmp (val, "FEC_6_7") == 0)
269       g_object_set (dvbbasebin, "code-rate-lp", 6, NULL);
270     else if (strcmp (val, "FEC_7_8") == 0)
271       g_object_set (dvbbasebin, "code-rate-lp", 7, NULL);
272     else if (strcmp (val, "FEC_8_9") == 0)
273       g_object_set (dvbbasebin, "code-rate-lp", 8, NULL);
274     else
275       g_object_set (dvbbasebin, "code-rate-lp", 9, NULL);
276
277     val = g_hash_table_lookup (params, "modulation");
278     if (strcmp (val, "QPSK") == 0)
279       g_object_set (dvbbasebin, "modulation", 0, NULL);
280     else if (strcmp (val, "QAM_16") == 0)
281       g_object_set (dvbbasebin, "modulation", 1, NULL);
282     else if (strcmp (val, "QAM_32") == 0)
283       g_object_set (dvbbasebin, "modulation", 2, NULL);
284     else if (strcmp (val, "QAM_64") == 0)
285       g_object_set (dvbbasebin, "modulation", 3, NULL);
286     else if (strcmp (val, "QAM_128") == 0)
287       g_object_set (dvbbasebin, "modulation", 4, NULL);
288     else if (strcmp (val, "QAM_256") == 0)
289       g_object_set (dvbbasebin, "modulation", 5, NULL);
290     else
291       g_object_set (dvbbasebin, "modulation", 6, NULL);
292
293     val = g_hash_table_lookup (params, "transmission-mode");
294     if (strcmp (val, "TRANSMISSION_MODE_2K") == 0)
295       g_object_set (dvbbasebin, "trans-mode", 0, NULL);
296     else if (strcmp (val, "TRANSMISSION_MODE_8K") == 0)
297       g_object_set (dvbbasebin, "trans-mode", 1, NULL);
298     else
299       g_object_set (dvbbasebin, "trans-mode", 2, NULL);
300
301     val = g_hash_table_lookup (params, "guard");
302     if (strcmp (val, "GUARD_INTERVAL_1_32") == 0)
303       g_object_set (dvbbasebin, "guard", 0, NULL);
304     else if (strcmp (val, "GUARD_INTERVAL_1_16") == 0)
305       g_object_set (dvbbasebin, "guard", 1, NULL);
306     else if (strcmp (val, "GUARD_INTERVAL_1_8") == 0)
307       g_object_set (dvbbasebin, "guard", 2, NULL);
308     else if (strcmp (val, "GUARD_INTERVAL_1_4") == 0)
309       g_object_set (dvbbasebin, "guard", 3, NULL);
310     else
311       g_object_set (dvbbasebin, "guard", 4, NULL);
312
313     val = g_hash_table_lookup (params, "hierarchy");
314     if (strcmp (val, "HIERARCHY_NONE") == 0)
315       g_object_set (dvbbasebin, "hierarchy", 0, NULL);
316     else if (strcmp (val, "HIERARCHY_1") == 0)
317       g_object_set (dvbbasebin, "hierarchy", 1, NULL);
318     else if (strcmp (val, "HIERARCHY_2") == 0)
319       g_object_set (dvbbasebin, "hierarchy", 2, NULL);
320     else if (strcmp (val, "HIERARCHY_4") == 0)
321       g_object_set (dvbbasebin, "hierarchy", 3, NULL);
322     else
323       g_object_set (dvbbasebin, "hierarchy", 4, NULL);
324
325     ret = TRUE;
326   } else if (strcmp (type, "satellite") == 0) {
327     gchar *val;
328
329     ret = TRUE;
330
331     val = g_hash_table_lookup (params, "polarity");
332     if (val)
333       g_object_set (dvbbasebin, "polarity", val, NULL);
334     else
335       ret = FALSE;
336
337     val = g_hash_table_lookup (params, "diseqc-source");
338     if (val)
339       g_object_set (dvbbasebin, "diseqc-source", atoi (val), NULL);
340
341     val = g_hash_table_lookup (params, "symbol-rate");
342     if (val)
343       g_object_set (dvbbasebin, "symbol-rate", atoi (val), NULL);
344     else
345       ret = FALSE;
346   } else if (strcmp (type, "cable") == 0) {
347     gchar *val;
348
349     ret = TRUE;
350     val = g_hash_table_lookup (params, "symbol-rate");
351     if (val)
352       g_object_set (dvbbasebin, "symbol-rate", atoi (val) / 1000, NULL);
353     val = g_hash_table_lookup (params, "modulation");
354     if (strcmp (val, "QPSK") == 0)
355       g_object_set (dvbbasebin, "modulation", 0, NULL);
356     else if (strcmp (val, "QAM_16") == 0)
357       g_object_set (dvbbasebin, "modulation", 1, NULL);
358     else if (strcmp (val, "QAM_32") == 0)
359       g_object_set (dvbbasebin, "modulation", 2, NULL);
360     else if (strcmp (val, "QAM_64") == 0)
361       g_object_set (dvbbasebin, "modulation", 3, NULL);
362     else if (strcmp (val, "QAM_128") == 0)
363       g_object_set (dvbbasebin, "modulation", 4, NULL);
364     else if (strcmp (val, "QAM_256") == 0)
365       g_object_set (dvbbasebin, "modulation", 5, NULL);
366     else
367       g_object_set (dvbbasebin, "modulation", 6, NULL);
368     val = g_hash_table_lookup (params, "code-rate-hp");
369     if (strcmp (val, "FEC_NONE") == 0)
370       g_object_set (dvbbasebin, "code-rate-hp", 0, NULL);
371     else if (strcmp (val, "FEC_1_2") == 0)
372       g_object_set (dvbbasebin, "code-rate-hp", 1, NULL);
373     else if (strcmp (val, "FEC_2_3") == 0)
374       g_object_set (dvbbasebin, "code-rate-hp", 2, NULL);
375     else if (strcmp (val, "FEC_3_4") == 0)
376       g_object_set (dvbbasebin, "code-rate-hp", 3, NULL);
377     else if (strcmp (val, "FEC_4_5") == 0)
378       g_object_set (dvbbasebin, "code-rate-hp", 4, NULL);
379     else if (strcmp (val, "FEC_5_6") == 0)
380       g_object_set (dvbbasebin, "code-rate-hp", 5, NULL);
381     else if (strcmp (val, "FEC_6_7") == 0)
382       g_object_set (dvbbasebin, "code-rate-hp", 6, NULL);
383     else if (strcmp (val, "FEC_7_8") == 0)
384       g_object_set (dvbbasebin, "code-rate-hp", 7, NULL);
385     else if (strcmp (val, "FEC_8_9") == 0)
386       g_object_set (dvbbasebin, "code-rate-hp", 8, NULL);
387     else
388       g_object_set (dvbbasebin, "code-rate-hp", 9, NULL);
389     val = g_hash_table_lookup (params, "inversion");
390     if (strcmp (val, "INVERSION_OFF") == 0)
391       g_object_set (dvbbasebin, "inversion", 0, NULL);
392     else if (strcmp (val, "INVERSION_ON") == 0)
393       g_object_set (dvbbasebin, "inversion", 1, NULL);
394     else
395       g_object_set (dvbbasebin, "inversion", 2, NULL);
396   } else if (strcmp (type, "atsc") == 0) {
397     gchar *val;
398
399     ret = TRUE;
400
401     val = g_hash_table_lookup (params, "modulation");
402     if (strcmp (val, "QAM_64") == 0)
403       g_object_set (dvbbasebin, "modulation", 3, NULL);
404     else if (strcmp (val, "QAM_256") == 0)
405       g_object_set (dvbbasebin, "modulation", 5, NULL);
406     else if (strcmp (val, "8VSB") == 0)
407       g_object_set (dvbbasebin, "modulation", 7, NULL);
408     else if (strcmp (val, "16VSB") == 0)
409       g_object_set (dvbbasebin, "modulation", 8, NULL);
410     else
411       ret = FALSE;
412   }
413
414   destroy_channels_hash (channels);
415
416 beach:
417   return ret;
418
419 unknown_channel:
420   {
421     GST_ELEMENT_ERROR (dvbbasebin, RESOURCE, READ, (NULL),
422         ("Couldn't find configuration properties for channel \"%s\"",
423             channel_name));
424     destroy_channels_hash (channels);
425     return FALSE;
426   }
427 }