/** * mod_dvb * ------- * Simple DVB-Streaming via Apache 2.0 * * This work is distributed within the terms of * creative commons attribution-share alike 2.0 germany * * See http://creativecommons.org/licenses/by-sa/2.0/ for more information * * @author Bernd Holzmueller * @revision 01 * @license http://creativecommons.org/licenses/by-sa/2.0/de/ Creative Commons Attribution-Share Alike 2.0 Germany * @homepage http://oss.tiggerswelt.net/mod_dvb/ * @copyright Copyright © 2008 tiggersWelt.net */ #include #include #include "dvb_channels.h" // {{{ dvb_param_value /** * Get the right value from an enumeration-type * * @param char *needle Value to search * @param int c Number of items in enumeration * @param dvb_frontend_param *plist Enumeration-type * * @return int */ int dvb_param_value (char *needle, int c, const dvb_frontend_param *plist) { int i; for (i = 0; i < c; i++) if (strcasecmp (plist [i].name, needle) == 0) return plist [i].value; return -1; } // }}} // {{{ dvb_parse_channel /** * Parse a line from a dvb-c channel file * * @param char *line * * @return dvb_channel */ dvb_channel *dvb_parse_channel (char *channel_line, fe_type_t type) { dvb_channel *chan; char *inv = NULL, *fec = NULL, *mod, *polarity, *bandwidth; char *rHP, *rLP, *constellation, *mode, *guard, *hierarchy; /** * File-formats * gens: service-name * gene: vpid:apid:spid * * mod_qam: {gens}:freq:inv:srate:fec:mod:{gene} * mod_qpsk: {gens}:freq/1k:polarity:sat_num:srate/1k:{gene} * mod_ofdm: {gens}:freq:inv:bw:rHP:rLP:const:tm:gi:hi:{gene} * mod_atsc: {gens}:freq:mod:{gene} */ chan = malloc (sizeof (dvb_channel)); switch (type) { case FE_QAM: if ((sscanf (channel_line, "%a[^:]:%d:%a[^:]:%d:%a[^:]:%a[^:]:%d:%d\n", &chan->name, &chan->freq, &inv, &chan->srate, &fec, &mod, &chan->vpid, &chan->apid) != 8)) return NULL; break; case FE_ATSC: if ((sscanf (channel_line, "%a[^:]:%d:%a[^:]:%d:%d\n", &chan->name, &chan->freq, &mod, &chan->vpid, &chan->apid) != 8)) return NULL; break; case FE_QPSK: if ((sscanf (channel_line, "%a[^:]:%d:%a[^:]:%d:%d:%d:%d\n", &chan->name, &chan->freq, &chan->polarity, &chan->sat_number, &chan->srate, &chan->vpid, &chan->apid) != 8)) return NULL; chan->freq *= 1000; chan->srate *= 1000; break; case FE_OFDM: if ((sscanf (channel_line, "%a[^:]:%d:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%a[^:]:%d:%d\n", &chan->name, &chan->freq, &inv, &bandwidth, &rHP, &rLP, &constellation, &mode, &guard, &hierarchy, &chan->vpid, &chan->apid) != 8)) return NULL; chan->bandwidth = dvb_param_value (bandwidth, 4, bw_name); chan->rHP = dvb_param_value (rHP, 10, dvb_fecs); chan->rLP = dvb_param_value (rLP, 10, dvb_fecs); chan->constellation = dvb_param_value (constellation, 6, dvb_modulations); chan->mode = dvb_param_value (mode, 3, mode_name); chan->guard = dvb_param_value (guard, 5, guard_name); chan->hierarchy = dvb_param_value (hierarchy, 5, hierarchy_name); free (bandwidth); free (rHP); free (rLP); free (constellation); free (mode); free (guard); free (hierarchy); break; } if (inv == NULL) inv = "INVERSION_AUTO"; if (fec == NULL) fec = "FEC_AUTO"; chan->inversion = dvb_param_value (inv, 3, dvb_inversions); chan->fec = dvb_param_value (fec, 10, dvb_fecs); chan->mod = dvb_param_value (mod, 6, dvb_modulations); chan->next = NULL; free (inv); free (fec); free (mod); if ((chan->inversion < 0) || (chan->fec < 0) || (chan->mod < 0)) { dvb_free_channels (chan); return NULL; } return chan; } // }}} // {{{ dvb_load_channels /** * Load channels from a dvb-c file * * @param char *filename * * @return dvb_channel */ dvb_channel *dvb_load_channels (const char *filename) { dvb_channel *chan, *last, *list = NULL; FILE *fh; char *buf; int i = 0, l = 0, c = 0, p = 0; fe_type_t type; buf = malloc (sizeof (char) * 256); if ((fh = fopen(filename, "r")) == NULL) return NULL; while (!feof (fh) && fgets (buf, 256, fh)) { l = strlen (buf); c = p = 0; while (p < l) { if (buf [p] = ":") c++; p++; } switch (c) { case 5: type = FE_ATSC; break; case 7: type = FE_QPSK; break; case 8: type = FE_QAM; break; case 12: type = FE_OFDM; break; default: continue; } if ((chan = dvb_parse_channel (buf, type)) != NULL) { chan->index = ++i; if (list == NULL) list = chan; else last->next = chan; last = chan; } } fclose (fh); free (buf); return list; } // }}} // {{{ dvb_free_channels /** * Free a list of channels * * @param dvb_channel *list * * @return int */ int dvb_free_channels (dvb_channel *list) { dvb_channel *chan, *cc; chan = list; while (chan != NULL) { cc = chan; chan = chan->next; free (cc); } } // }}} // {{{ dvb_find_channel dvb_channel *dvb_find_channel (dvb_channel *channels, char *name) { dvb_channel *chan = channels; dvb_channel *candidate = NULL; int l1, l2; l1 = strlen (name); /* Do not search for an empty string */ if (l1 < 1) return NULL; while (chan != NULL) { l2 = strlen (chan->name); if (!strncasecmp (name, chan->name, (l1 < l2 ? l1 : l2))) return chan; chan = chan->next; } return NULL; } // }}}