/* * parsechannels.c - * Copyright (C) 2008 Zaheer Abbas Merali * * Authors: * Zaheer Abbas Merali <zaheerabbas at merali dot org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <glib.h> #include <glib-object.h> #include <stdlib.h> #include <string.h> #include <gst/gst.h> #include <gst/gst-i18n-plugin.h> #include "parsechannels.h" #include <linux/dvb/frontend.h> GST_DEBUG_CATEGORY_EXTERN (dvb_base_bin_debug); #define GST_CAT_DEFAULT dvb_base_bin_debug typedef enum { CHANNEL_CONF_FORMAT_NONE, CHANNEL_CONF_FORMAT_DVBV5, CHANNEL_CONF_FORMAT_ZAP } GstDvbChannelConfFormat; typedef gboolean (*GstDvbV5ChannelsConfPropSetFunction) (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); typedef struct { const gchar *conf_property; const gchar *elem_property; GstDvbV5ChannelsConfPropSetFunction set_func; } GstDvbV5ChannelsConfToPropertyMap; static gboolean parse_and_configure_from_v5_conf_file (GstElement * dvbbasebin, const gchar * filename, const gchar * channel_name, GError ** error); static gboolean parse_and_configure_from_zap_conf_file (GstElement * dvbbasebin, const gchar * filename, const gchar * channel_name, GError ** error); static GstDvbChannelConfFormat detect_file_format (const gchar * filename); static gboolean gst_dvb_base_bin_conf_set_string (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_uint (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_int (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_inversion (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_guard (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_trans_mode (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_code_rate (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_delsys (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_hierarchy (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static gboolean gst_dvb_base_bin_conf_set_modulation (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key); static GHashTable *parse_channels_conf_from_zap_file (GstElement * dvbbasebin, const gchar * filename, GError ** error); static gboolean remove_channel_from_hash (gpointer key, gpointer value, gpointer user_data); static void destroy_channels_hash (GHashTable * channels); GstDvbV5ChannelsConfToPropertyMap dvbv5_prop_map[] = { {"SERVICE_ID", "program-numbers", gst_dvb_base_bin_conf_set_string}, {"FREQUENCY", "frequency", gst_dvb_base_bin_conf_set_uint}, {"BANDWIDTH_HZ", "bandwidth-hz", gst_dvb_base_bin_conf_set_uint}, {"INVERSION", "inversion", gst_dvb_base_bin_conf_set_inversion}, {"GUARD_INTERVAL", "guard", gst_dvb_base_bin_conf_set_guard}, {"TRANSMISSION_MODE", "trans-mode", gst_dvb_base_bin_conf_set_trans_mode}, {"HIERARCHY", "hierarchy", gst_dvb_base_bin_conf_set_hierarchy}, {"MODULATION", "modulation", gst_dvb_base_bin_conf_set_modulation}, {"CODE_RATE_HP", "code-rate-hp", gst_dvb_base_bin_conf_set_code_rate}, {"CODE_RATE_LP", "code-rate-lp", gst_dvb_base_bin_conf_set_code_rate}, {"ISDBT_LAYER_ENABLED", "isdbt-layer-enabled", gst_dvb_base_bin_conf_set_uint}, {"ISDBT_PARTIAL_RECEPTION", "isdbt-partial-reception", gst_dvb_base_bin_conf_set_int}, {"ISDBT_SOUND_BROADCASTING", "isdbt-sound-broadcasting", gst_dvb_base_bin_conf_set_int}, {"ISDBT_SB_SUBCHANNEL_ID", "isdbt-sb-subchannel-id", gst_dvb_base_bin_conf_set_int}, {"ISDBT_SB_SEGMENT_IDX", "isdbt-sb-segment-idx", gst_dvb_base_bin_conf_set_int}, {"ISDBT_SB_SEGMENT_COUNT", "isdbt-sb-segment-count", gst_dvb_base_bin_conf_set_int}, /* Range in files start from 0, property starts from 1 */ {"ISDBT_LAYERA_FEC", "isdbt-layera-fec", gst_dvb_base_bin_conf_set_code_rate}, {"ISDBT_LAYERA_MODULATION", "isdbt-layera-modulation", gst_dvb_base_bin_conf_set_modulation}, {"ISDBT_LAYERA_SEGMENT_COUNT", "isdbt-layera-segment-count", gst_dvb_base_bin_conf_set_int}, {"ISDBT_LAYERA_TIME_INTERLEAVING", "isdbt-layera-time-interleaving", gst_dvb_base_bin_conf_set_int}, {"ISDBT_LAYERB_FEC", "isdbt-layerb-fec", gst_dvb_base_bin_conf_set_code_rate}, {"ISDBT_LAYERB_MODULATION", "isdbt-layerb-modulation", gst_dvb_base_bin_conf_set_modulation}, {"ISDBT_LAYERB_SEGMENT_COUNT", "isdbt-layerb-segment-count", gst_dvb_base_bin_conf_set_int}, {"ISDBT_LAYERB_TIME_INTERLEAVING", "isdbt-layerb-time-interleaving", gst_dvb_base_bin_conf_set_int}, {"ISDBT_LAYERC_FEC", "isdbt-layerc-fec", gst_dvb_base_bin_conf_set_code_rate}, {"ISDBT_LAYERC_MODULATION", "isdbt-layerc-modulation", gst_dvb_base_bin_conf_set_modulation}, {"ISDBT_LAYERC_SEGMENT_COUNT", "isdbt-layerc-segment-count", gst_dvb_base_bin_conf_set_int}, {"ISDBT_LAYERC_TIME_INTERLEAVING", "isdbt-layerc-time-interleaving", gst_dvb_base_bin_conf_set_int}, {"DELIVERY_SYSTEM", "delsys", gst_dvb_base_bin_conf_set_delsys}, {NULL,} }; /* TODO: * Store the channels hash table around instead of constantly parsing it * Detect when the file changed on disk */ static gint gst_dvb_base_bin_find_string_in_array (const gchar ** array, const gchar * str) { gint i = 0; const gchar *cur; while ((cur = array[i])) { if (strcmp (cur, str) == 0) return i; i++; } return -1; } static gboolean gst_dvb_base_bin_conf_set_property_from_string_array (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key, const gchar ** strings, gint default_value) { gchar *str; gint v; str = g_key_file_get_string (kf, channel_name, key, NULL); v = gst_dvb_base_bin_find_string_in_array (strings, str); if (v == -1) { GST_WARNING_OBJECT (dvbbasebin, "Unexpected value '%s' for property " "'%s', using default: '%d'", str, property, default_value); v = default_value; } g_free (str); g_object_set (dvbbasebin, property, v, NULL); return TRUE; } static gboolean gst_dvb_base_bin_conf_set_string (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { gchar *str; str = g_key_file_get_string (kf, channel_name, key, NULL); if (!str) { GST_WARNING_OBJECT (dvbbasebin, "Could not get value for '%s' on channel '%s'", key, channel_name); return FALSE; } g_object_set (dvbbasebin, property, str, NULL); g_free (str); return TRUE; } static gboolean gst_dvb_base_bin_conf_set_uint (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { guint64 v; v = g_key_file_get_uint64 (kf, channel_name, key, NULL); if (!v) { GST_WARNING_OBJECT (dvbbasebin, "Could not get value for '%s' on channel '%s'", key, channel_name); return FALSE; } g_object_set (dvbbasebin, property, (guint) v, NULL); return TRUE; } static gboolean gst_dvb_base_bin_conf_set_int (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { gint v; v = g_key_file_get_integer (kf, channel_name, key, NULL); if (!v) { GST_WARNING_OBJECT (dvbbasebin, "Could not get value for '%s' on channel '%s'", key, channel_name); return FALSE; } g_object_set (dvbbasebin, property, v, NULL); return TRUE; } static gboolean gst_dvb_base_bin_conf_set_inversion (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { gchar *str; gint v; str = g_key_file_get_string (kf, channel_name, key, NULL); if (!str) { GST_WARNING_OBJECT (dvbbasebin, "Could not get value for '%s' on channel '%s'", key, channel_name); return FALSE; } if (strcmp (str, "AUTO") == 0) v = 2; else if (strcmp (str, "ON") == 0) v = 1; else v = 0; /* OFF */ g_free (str); g_object_set (dvbbasebin, property, v, NULL); return TRUE; } static gboolean gst_dvb_base_bin_conf_set_guard (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { const gchar *guards[] = { "1/32", "1/16", "1/8", "1/4", "auto", "1/128", "19/128", "19/256", "PN420", "PN595", "PN945", NULL }; return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin, property, kf, channel_name, key, guards, 4); } static gboolean gst_dvb_base_bin_conf_set_trans_mode (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { const gchar *trans_modes[] = { "2K", "8K", "AUTO", "4K", "1K", "16K", "32K", "C1", "C3780", NULL }; return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin, property, kf, channel_name, key, trans_modes, 2); } static gboolean gst_dvb_base_bin_conf_set_code_rate (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { const gchar *code_rates[] = { "NONE", "1/2", "2/3", "3/4", "4/5", "5/6", "6/7", "7/8", "8/9", "AUTO", "3/5", "9/10", "2/5", NULL }; return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin, property, kf, channel_name, key, code_rates, 9); } static gboolean gst_dvb_base_bin_conf_set_delsys (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { const gchar *delsys[] = { "UNDEFINED", "DVBCA", "DVBCB", "DVBT", "DSS", "DVBS", "DVBS2", "DVBH", "ISDBT", "ISDBS", "ISDBC", "ATSC", "ATSCMH", "DTMB", "CMMB", "DAB", "DVBT2", "TURBO", "DVBCC", NULL }; return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin, property, kf, channel_name, key, delsys, 0); } static gboolean gst_dvb_base_bin_conf_set_hierarchy (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { const gchar *hierarchies[] = { "NONE", "1", "2", "4", "AUTO", NULL }; return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin, property, kf, channel_name, key, hierarchies, 4); } static gboolean gst_dvb_base_bin_conf_set_modulation (GstElement * dvbbasebin, const gchar * property, GKeyFile * kf, const gchar * channel_name, const gchar * key) { const gchar *modulations[] = { "QPSK", "QAM/16", "QAM/32", "QAM/64", "QAM/128", "QAM/256", "QAM/AUTO", "VSB/8", "VSB/16", "PSK/8", "APSK/16", "APSK/32", "DQPSK", "QAM/4_NR", NULL }; return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin, property, kf, channel_name, key, modulations, 6); } /* FIXME: is channel_name guaranteed to be ASCII or UTF-8? */ static gboolean parse_and_configure_from_v5_conf_file (GstElement * dvbbasebin, const gchar * filename, const gchar * channel_name, GError ** error) { GKeyFile *keyfile; gchar **keys, **keys_p; GError *err = NULL; keyfile = g_key_file_new (); if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &err)) goto load_error; if (!g_key_file_has_group (keyfile, channel_name)) goto unknown_channel; keys = g_key_file_get_keys (keyfile, channel_name, NULL, &err); if (!keys) goto no_properties; keys_p = keys; while (*keys_p) { const gchar *k = *keys_p; const GstDvbV5ChannelsConfToPropertyMap *map_entry = dvbv5_prop_map; gboolean property_found = FALSE; GST_LOG_OBJECT (dvbbasebin, "Setting property %s", k); while (map_entry->conf_property) { if (strcmp (map_entry->conf_property, k) == 0) { if (!map_entry->set_func (dvbbasebin, map_entry->elem_property, keyfile, channel_name, k)) goto property_error; property_found = TRUE; break; } map_entry++; } if (!property_found) GST_WARNING_OBJECT (dvbbasebin, "Failed to map property '%s'", k); keys_p++; } GST_DEBUG_OBJECT (dvbbasebin, "Successfully parsed channel configuration " "file '%s'", filename); g_strfreev (keys); g_key_file_unref (keyfile); return TRUE; load_error: if ((err->domain == G_FILE_ERROR && err->code == G_FILE_ERROR_NOENT) || (err->domain == G_KEY_FILE_ERROR && err->code == G_KEY_FILE_ERROR_NOT_FOUND)) { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND, _("Couldn't find channel configuration file")); } else { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, _("Couldn't load channel configuration file: '%s'"), err->message); } g_clear_error (&err); return FALSE; unknown_channel: { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND, _("Couldn't find details for channel '%s'"), channel_name); g_key_file_unref (keyfile); g_clear_error (&err); return FALSE; } no_properties: { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND, _("No properties for channel '%s'"), channel_name); g_key_file_unref (keyfile); g_clear_error (&err); return FALSE; } property_error: { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED, _("Failed to set properties for channel '%s'"), channel_name); g_key_file_unref (keyfile); g_clear_error (&err); return FALSE; } } static GHashTable * parse_channels_conf_from_zap_file (GstElement * dvbbasebin, const gchar * filename, GError ** error) { gchar *contents; gchar **lines; gchar *line; gchar **fields; int i, parsedchannels = 0; GHashTable *res; GError *err = NULL; const gchar *terrestrial[] = { "inversion", "bandwidth", "code-rate-hp", "code-rate-lp", "modulation", "transmission-mode", "guard", "hierarchy" }; const gchar *satellite[] = { "polarity", "diseqc-source", "symbol-rate" }; const gchar *cable[] = { "inversion", "symbol-rate", "code-rate-hp", "modulation" }; GST_INFO_OBJECT (dvbbasebin, "parsing '%s'", filename); if (!g_file_get_contents (filename, &contents, NULL, &err)) goto open_fail; lines = g_strsplit (contents, "\n", 0); res = g_hash_table_new (g_str_hash, g_str_equal); i = 0; line = lines[0]; while (line != NULL) { GHashTable *params; int j, numfields; if (line[0] == '#') goto next_line; params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); fields = g_strsplit (line, ":", 0); numfields = g_strv_length (fields); switch (numfields) { case 13: /* terrestrial */ g_hash_table_insert (params, g_strdup ("type"), g_strdup ("terrestrial")); for (j = 2; j <= 9; j++) { g_hash_table_insert (params, g_strdup (terrestrial[j - 2]), g_strdup (fields[j])); } g_hash_table_insert (params, g_strdup ("frequency"), g_strdup (fields[1])); break; case 9: /* cable */ g_hash_table_insert (params, g_strdup ("type"), g_strdup ("cable")); for (j = 2; j <= 5; j++) { g_hash_table_insert (params, g_strdup (cable[j - 2]), g_strdup (fields[j])); } g_hash_table_insert (params, g_strdup ("frequency"), g_strdup (fields[1])); break; case 8: /* satellite */ g_hash_table_insert (params, g_strdup ("type"), g_strdup ("satellite")); for (j = 2; j <= 4; j++) { g_hash_table_insert (params, g_strdup (satellite[j - 2]), g_strdup (fields[j])); } /* Some ZAP format variations store freqs in MHz * but we internally use kHz for DVB-S/S2. */ if (strlen (fields[1]) < 6) { g_hash_table_insert (params, g_strdup ("frequency"), g_strdup_printf ("%d", atoi (fields[1]) * 1000)); } else { g_hash_table_insert (params, g_strdup ("frequency"), g_strdup_printf ("%d", atoi (fields[1]))); } break; case 6: /* atsc (vsb/qam) */ g_hash_table_insert (params, g_strdup ("type"), g_strdup ("atsc")); g_hash_table_insert (params, g_strdup ("modulation"), g_strdup (fields[2])); g_hash_table_insert (params, g_strdup ("frequency"), g_strdup (fields[1])); break; default: goto not_parsed; } /* parsed */ g_hash_table_insert (params, g_strdup ("sid"), g_strdup (fields[numfields - 1])); g_hash_table_insert (res, g_strdup (fields[0]), params); parsedchannels++; not_parsed: g_strfreev (fields); next_line: line = lines[++i]; } g_strfreev (lines); g_free (contents); if (parsedchannels == 0) goto no_channels; return res; open_fail: if (err->code == G_FILE_ERROR_NOENT) { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND, _("Couldn't find channel configuration file: '%s'"), err->message); } else { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, _("Couldn't load channel configuration file: '%s'"), err->message); } g_clear_error (&err); return NULL; no_channels: g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED, _("Channel configuration file doesn't contain any channels")); g_hash_table_unref (res); return NULL; } static gboolean remove_channel_from_hash (gpointer key, gpointer value, gpointer user_data) { g_free (key); if (value) g_hash_table_destroy ((GHashTable *) value); return TRUE; } static void destroy_channels_hash (GHashTable * channels) { g_hash_table_foreach_remove (channels, remove_channel_from_hash, NULL); } /* FIXME: is channel_name guaranteed to be ASCII or UTF-8? */ static gboolean parse_and_configure_from_zap_conf_file (GstElement * dvbbasebin, const gchar * filename, const gchar * channel_name, GError ** error) { gboolean ret = FALSE; GHashTable *channels, *params; gchar *type; /* Assumptions are made here about a format that is loosely * defined. Particularly, we assume a given delivery system * out of counting the number of fields per line. dvbsrc has * smarter code to auto-detect a delivery system based on * known-correct combinations of parameters so if you ever * encounter cases where the delivery system is being * wrongly set here, just remove the offending * g_object_set line and let dvbsrc work his magic out. */ channels = parse_channels_conf_from_zap_file (dvbbasebin, filename, error); if (!channels) goto beach; params = g_hash_table_lookup (channels, channel_name); if (!params) goto unknown_channel; g_object_set (dvbbasebin, "program-numbers", g_hash_table_lookup (params, "sid"), NULL); /* check if it is terrestrial or satellite */ g_object_set (dvbbasebin, "frequency", atoi (g_hash_table_lookup (params, "frequency")), NULL); type = g_hash_table_lookup (params, "type"); if (strcmp (type, "terrestrial") == 0) { gchar *val; val = g_hash_table_lookup (params, "inversion"); if (strcmp (val, "INVERSION_OFF") == 0) g_object_set (dvbbasebin, "inversion", INVERSION_OFF, NULL); else if (strcmp (val, "INVERSION_ON") == 0) g_object_set (dvbbasebin, "inversion", INVERSION_ON, NULL); else g_object_set (dvbbasebin, "inversion", INVERSION_AUTO, NULL); val = g_hash_table_lookup (params, "bandwidth"); if (strcmp (val, "BANDWIDTH_8_MHZ") == 0) g_object_set (dvbbasebin, "bandwidth", 0, NULL); else if (strcmp (val, "BANDWIDTH_7_MHZ") == 0) g_object_set (dvbbasebin, "bandwidth", 1, NULL); else if (strcmp (val, "BANDWIDTH_6_MHZ") == 0) g_object_set (dvbbasebin, "bandwidth", 2, NULL); else if (strcmp (val, "BANDWIDTH_5_MHZ") == 0) g_object_set (dvbbasebin, "bandwidth", 4, NULL); else if (strcmp (val, "BANDWIDTH_10_MHZ") == 0) g_object_set (dvbbasebin, "bandwidth", 5, NULL); else if (strcmp (val, "BANDWIDTH_1_712_MHZ") == 0) g_object_set (dvbbasebin, "bandwidth", 6, NULL); else g_object_set (dvbbasebin, "bandwidth", 3, NULL); val = g_hash_table_lookup (params, "code-rate-hp"); if (strcmp (val, "FEC_NONE") == 0) g_object_set (dvbbasebin, "code-rate-hp", 0, NULL); else if (strcmp (val, "FEC_1_2") == 0) g_object_set (dvbbasebin, "code-rate-hp", 1, NULL); else if (strcmp (val, "FEC_2_3") == 0) g_object_set (dvbbasebin, "code-rate-hp", 2, NULL); else if (strcmp (val, "FEC_3_4") == 0) g_object_set (dvbbasebin, "code-rate-hp", 3, NULL); else if (strcmp (val, "FEC_4_5") == 0) g_object_set (dvbbasebin, "code-rate-hp", 4, NULL); else if (strcmp (val, "FEC_5_6") == 0) g_object_set (dvbbasebin, "code-rate-hp", 5, NULL); else if (strcmp (val, "FEC_6_7") == 0) g_object_set (dvbbasebin, "code-rate-hp", 6, NULL); else if (strcmp (val, "FEC_7_8") == 0) g_object_set (dvbbasebin, "code-rate-hp", 7, NULL); else if (strcmp (val, "FEC_8_9") == 0) g_object_set (dvbbasebin, "code-rate-hp", 8, NULL); else g_object_set (dvbbasebin, "code-rate-hp", 9, NULL); val = g_hash_table_lookup (params, "code-rate-lp"); if (strcmp (val, "FEC_NONE") == 0) g_object_set (dvbbasebin, "code-rate-lp", 0, NULL); else if (strcmp (val, "FEC_1_2") == 0) g_object_set (dvbbasebin, "code-rate-lp", 1, NULL); else if (strcmp (val, "FEC_2_3") == 0) g_object_set (dvbbasebin, "code-rate-lp", 2, NULL); else if (strcmp (val, "FEC_3_4") == 0) g_object_set (dvbbasebin, "code-rate-lp", 3, NULL); else if (strcmp (val, "FEC_4_5") == 0) g_object_set (dvbbasebin, "code-rate-lp", 4, NULL); else if (strcmp (val, "FEC_5_6") == 0) g_object_set (dvbbasebin, "code-rate-lp", 5, NULL); else if (strcmp (val, "FEC_6_7") == 0) g_object_set (dvbbasebin, "code-rate-lp", 6, NULL); else if (strcmp (val, "FEC_7_8") == 0) g_object_set (dvbbasebin, "code-rate-lp", 7, NULL); else if (strcmp (val, "FEC_8_9") == 0) g_object_set (dvbbasebin, "code-rate-lp", 8, NULL); else g_object_set (dvbbasebin, "code-rate-lp", 9, NULL); val = g_hash_table_lookup (params, "modulation"); if (strcmp (val, "QPSK") == 0) g_object_set (dvbbasebin, "modulation", 0, NULL); else if (strcmp (val, "QAM_16") == 0) g_object_set (dvbbasebin, "modulation", 1, NULL); else if (strcmp (val, "QAM_32") == 0) g_object_set (dvbbasebin, "modulation", 2, NULL); else if (strcmp (val, "QAM_64") == 0) g_object_set (dvbbasebin, "modulation", 3, NULL); else if (strcmp (val, "QAM_128") == 0) g_object_set (dvbbasebin, "modulation", 4, NULL); else if (strcmp (val, "QAM_256") == 0) g_object_set (dvbbasebin, "modulation", 5, NULL); else g_object_set (dvbbasebin, "modulation", 6, NULL); val = g_hash_table_lookup (params, "transmission-mode"); if (strcmp (val, "TRANSMISSION_MODE_2K") == 0) g_object_set (dvbbasebin, "trans-mode", 0, NULL); else if (strcmp (val, "TRANSMISSION_MODE_8K") == 0) g_object_set (dvbbasebin, "trans-mode", 1, NULL); else g_object_set (dvbbasebin, "trans-mode", 2, NULL); val = g_hash_table_lookup (params, "guard"); if (strcmp (val, "GUARD_INTERVAL_1_32") == 0) g_object_set (dvbbasebin, "guard", 0, NULL); else if (strcmp (val, "GUARD_INTERVAL_1_16") == 0) g_object_set (dvbbasebin, "guard", 1, NULL); else if (strcmp (val, "GUARD_INTERVAL_1_8") == 0) g_object_set (dvbbasebin, "guard", 2, NULL); else if (strcmp (val, "GUARD_INTERVAL_1_4") == 0) g_object_set (dvbbasebin, "guard", 3, NULL); else g_object_set (dvbbasebin, "guard", 4, NULL); val = g_hash_table_lookup (params, "hierarchy"); if (strcmp (val, "HIERARCHY_NONE") == 0) g_object_set (dvbbasebin, "hierarchy", 0, NULL); else if (strcmp (val, "HIERARCHY_1") == 0) g_object_set (dvbbasebin, "hierarchy", 1, NULL); else if (strcmp (val, "HIERARCHY_2") == 0) g_object_set (dvbbasebin, "hierarchy", 2, NULL); else if (strcmp (val, "HIERARCHY_4") == 0) g_object_set (dvbbasebin, "hierarchy", 3, NULL); else g_object_set (dvbbasebin, "hierarchy", 4, NULL); ret = TRUE; } else if (strcmp (type, "satellite") == 0) { gchar *val; ret = TRUE; g_object_set (dvbbasebin, "delsys", SYS_DVBS, NULL); val = g_hash_table_lookup (params, "polarity"); if (val) g_object_set (dvbbasebin, "polarity", val, NULL); else ret = FALSE; val = g_hash_table_lookup (params, "diseqc-source"); if (val) g_object_set (dvbbasebin, "diseqc-source", atoi (val), NULL); val = g_hash_table_lookup (params, "symbol-rate"); if (val) g_object_set (dvbbasebin, "symbol-rate", atoi (val), NULL); else ret = FALSE; } else if (strcmp (type, "cable") == 0) { gchar *val; g_object_set (dvbbasebin, "delsys", SYS_DVBC_ANNEX_A, NULL); ret = TRUE; val = g_hash_table_lookup (params, "symbol-rate"); if (val) g_object_set (dvbbasebin, "symbol-rate", atoi (val) / 1000, NULL); val = g_hash_table_lookup (params, "modulation"); if (strcmp (val, "QPSK") == 0) g_object_set (dvbbasebin, "modulation", 0, NULL); else if (strcmp (val, "QAM_16") == 0) g_object_set (dvbbasebin, "modulation", 1, NULL); else if (strcmp (val, "QAM_32") == 0) g_object_set (dvbbasebin, "modulation", 2, NULL); else if (strcmp (val, "QAM_64") == 0) g_object_set (dvbbasebin, "modulation", 3, NULL); else if (strcmp (val, "QAM_128") == 0) g_object_set (dvbbasebin, "modulation", 4, NULL); else if (strcmp (val, "QAM_256") == 0) g_object_set (dvbbasebin, "modulation", 5, NULL); else g_object_set (dvbbasebin, "modulation", 6, NULL); val = g_hash_table_lookup (params, "code-rate-hp"); if (strcmp (val, "FEC_NONE") == 0) g_object_set (dvbbasebin, "code-rate-hp", 0, NULL); else if (strcmp (val, "FEC_1_2") == 0) g_object_set (dvbbasebin, "code-rate-hp", 1, NULL); else if (strcmp (val, "FEC_2_3") == 0) g_object_set (dvbbasebin, "code-rate-hp", 2, NULL); else if (strcmp (val, "FEC_3_4") == 0) g_object_set (dvbbasebin, "code-rate-hp", 3, NULL); else if (strcmp (val, "FEC_4_5") == 0) g_object_set (dvbbasebin, "code-rate-hp", 4, NULL); else if (strcmp (val, "FEC_5_6") == 0) g_object_set (dvbbasebin, "code-rate-hp", 5, NULL); else if (strcmp (val, "FEC_6_7") == 0) g_object_set (dvbbasebin, "code-rate-hp", 6, NULL); else if (strcmp (val, "FEC_7_8") == 0) g_object_set (dvbbasebin, "code-rate-hp", 7, NULL); else if (strcmp (val, "FEC_8_9") == 0) g_object_set (dvbbasebin, "code-rate-hp", 8, NULL); else g_object_set (dvbbasebin, "code-rate-hp", 9, NULL); val = g_hash_table_lookup (params, "inversion"); if (strcmp (val, "INVERSION_OFF") == 0) g_object_set (dvbbasebin, "inversion", 0, NULL); else if (strcmp (val, "INVERSION_ON") == 0) g_object_set (dvbbasebin, "inversion", 1, NULL); else g_object_set (dvbbasebin, "inversion", 2, NULL); } else if (strcmp (type, "atsc") == 0) { gchar *val; ret = TRUE; g_object_set (dvbbasebin, "delsys", SYS_ATSC, NULL); val = g_hash_table_lookup (params, "modulation"); if (strcmp (val, "QAM_64") == 0) g_object_set (dvbbasebin, "modulation", 3, NULL); else if (strcmp (val, "QAM_256") == 0) g_object_set (dvbbasebin, "modulation", 5, NULL); else if (strcmp (val, "8VSB") == 0) g_object_set (dvbbasebin, "modulation", 7, NULL); else if (strcmp (val, "16VSB") == 0) g_object_set (dvbbasebin, "modulation", 8, NULL); else ret = FALSE; } destroy_channels_hash (channels); beach: return ret; unknown_channel: { g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND, _("Couldn't find details for channel '%s'"), channel_name); destroy_channels_hash (channels); return FALSE; } } static GstDvbChannelConfFormat detect_file_format (const gchar * filename) { gchar *contents; gchar **lines; gchar **line; GstDvbChannelConfFormat ret = CHANNEL_CONF_FORMAT_NONE; if (!g_file_get_contents (filename, &contents, NULL, NULL)) return ret; lines = g_strsplit (contents, "\n", 0); line = lines; while (*line) { if (g_str_has_prefix (*line, "[") && g_str_has_suffix (*line, "]")) { ret = CHANNEL_CONF_FORMAT_DVBV5; break; } else if (g_strrstr (*line, ":")) { ret = CHANNEL_CONF_FORMAT_ZAP; break; } line++; } g_strfreev (lines); g_free (contents); return ret; } gboolean set_properties_for_channel (GstElement * dvbbasebin, const gchar * channel_name, GError ** error) { gboolean ret = FALSE; gchar *filename; filename = g_strdup (g_getenv ("GST_DVB_CHANNELS_CONF")); if (filename == NULL) { filename = g_build_filename (g_get_user_config_dir (), "gstreamer-" GST_API_VERSION, "dvb-channels.conf", NULL); } switch (detect_file_format (filename)) { case CHANNEL_CONF_FORMAT_DVBV5: if (!parse_and_configure_from_v5_conf_file (dvbbasebin, filename, channel_name, error)) { GST_WARNING_OBJECT (dvbbasebin, "Problem finding information for " "channel '%s' in configuration file '%s'", channel_name, filename); } else { GST_INFO_OBJECT (dvbbasebin, "Parsed libdvbv5 channel configuration " "file"); ret = TRUE; } break; case CHANNEL_CONF_FORMAT_ZAP: if (!parse_and_configure_from_zap_conf_file (dvbbasebin, filename, channel_name, error)) { GST_WARNING_OBJECT (dvbbasebin, "Problem finding information for " "channel '%s' in configuration file '%s'", channel_name, filename); } else { GST_INFO_OBJECT (dvbbasebin, "Parsed ZAP channel configuration file"); ret = TRUE; } break; default: GST_WARNING_OBJECT (dvbbasebin, "Unknown configuration file format. " "Can not get parameters for channel"); } g_free (filename); return ret; }