char *icon; ///< Channel icon
int number; ///< Channel number
- struct channel *channel; ///< Mapped channel
+ LIST_HEAD(,epggrab_channel_link) channels; ///< Mapped channels
} epggrab_channel_t;
+typedef struct epggrab_channel_link
+{
+ LIST_ENTRY(epggrab_channel_link) link; ///< Link to grab channel
+ struct channel *channel; ///< Real channel
+} epggrab_channel_link_t;
+
/*
* Access functions
*/
int epggrab_channel_match ( epggrab_channel_t *ec, channel_t *ch )
{
if (!ec || !ch) return 0;
- if (ec->channel) return 0; // ignore already paired
+ if (LIST_FIRST(&ec->channels)) return 0; // ignore already paired
if (ec->name && !strcmp(ec->name, ch->ch_name)) return 1;
return 0;
/* Link epggrab channel to real channel */
void epggrab_channel_link ( epggrab_channel_t *ec, channel_t *ch )
{
+ epggrab_channel_link_t *ecl;
+
/* No change */
- if (!ch || ch == ec->channel) return;
+ if (!ch) return;
+ LIST_FOREACH(ecl, &ec->channels, link)
+ if (ecl->channel == ch) return;
tvhlog(LOG_INFO, ec->mod->id, "linking %s to %s",
ec->id, ch->ch_name);
- ec->channel = ch;
+ ecl = calloc(1, sizeof(epggrab_channel_link_t));
+ ecl->channel = ch;
+ LIST_INSERT_HEAD(&ec->channels, ecl, link);
if (ec->name && epggrab_channel_rename)
channel_rename(ch, ec->name);
if (ec->icon && epggrab_channel_reicon)
int epggrab_channel_set_name ( epggrab_channel_t *ec, const char *name )
{
int save = 0;
+ epggrab_channel_link_t *ecl;
if (!ec || !name) return 0;
if (!ec->name || strcmp(ec->name, name)) {
if (ec->name) free(ec->name);
ec->name = strdup(name);
- if (ec->channel && epggrab_channel_rename)
- channel_rename(ec->channel, name);
+ if (epggrab_channel_rename)
+ LIST_FOREACH(ecl, &ec->channels, link)
+ channel_rename(ecl->channel, name);
save = 1;
}
return save;
int epggrab_channel_set_icon ( epggrab_channel_t *ec, const char *icon )
{
int save = 0;
+ epggrab_channel_link_t *ecl;
if (!ec->icon || strcmp(ec->icon, icon) ) {
if (!ec | !icon) return 0;
if (ec->icon) free(ec->icon);
ec->icon = strdup(icon);
- if (ec->channel && epggrab_channel_reicon)
- channel_set_icon(ec->channel, icon);
+ if (epggrab_channel_reicon)
+ LIST_FOREACH(ecl, &ec->channels, link)
+ channel_set_icon(ecl->channel, icon);
save = 1;
}
return save;
int epggrab_channel_set_number ( epggrab_channel_t *ec, int number )
{
int save = 0;
+ epggrab_channel_link_t *ecl;
if (!ec || (number <= 0)) return 0;
if (ec->number != number) {
ec->number = number;
- if (ec->channel && epggrab_channel_renumber)
- channel_set_number(ec->channel, number);
+ if (epggrab_channel_renumber)
+ LIST_FOREACH(ecl, &ec->channels, link)
+ channel_set_number(ecl->channel, number);
save = 1;
}
return save;
if (!ec) return;
/* Find a link */
- if (!ec->channel)
+ if (!LIST_FIRST(&ec->channels))
RB_FOREACH(ch, &channel_name_tree, ch_name_link)
if (epggrab_channel_match_and_link(ec, ch)) break;
void epggrab_module_ch_save ( void *_m, epggrab_channel_t *ch )
{
- htsmsg_t *m = htsmsg_create_map();
+ htsmsg_t *a = NULL, *m = htsmsg_create_map();
epggrab_module_t *mod = _m;
+ epggrab_channel_link_t *ecl;
if (ch->name)
htsmsg_add_str(m, "name", ch->name);
if (ch->icon)
htsmsg_add_str(m, "icon", ch->icon);
- if (ch->channel)
- htsmsg_add_u32(m, "channel", ch->channel->ch_id);
+ LIST_FOREACH(ecl, &ch->channels, link) {
+ if (!a) a = htsmsg_create_list();
+ htsmsg_add_u32(a, NULL, ecl->channel->ch_id);
+ }
+ if (a) htsmsg_add_msg(m, "channels", a);
if (ch->number)
htsmsg_add_u32(m, "number", ch->number);
void epggrab_module_ch_rem ( void *m, channel_t *ch )
{
epggrab_channel_t *egc;
+ epggrab_channel_link_t *egl;
epggrab_module_int_t *mod = m;
RB_FOREACH(egc, mod->channels, link) {
- if (egc->channel == ch) {
- egc->channel = NULL;
- if (mod->ch_save) mod->ch_save(mod, egc);
- break;
+ LIST_FOREACH(egl, &egc->channels, link) {
+ if (egl->channel == ch) {
+ LIST_REMOVE(egl, link);
+ free(egl);
+ break;
+ }
}
}
}
int save = 0;
const char *str;
uint32_t u32;
+ htsmsg_t *a;
+ htsmsg_field_t *f;
+ channel_t *ch;
- epggrab_channel_t *ch = epggrab_channel_find(mod->channels, id, 1, &save, mod);
+ epggrab_channel_t *egc
+ = epggrab_channel_find(mod->channels, id, 1, &save, mod);
if ((str = htsmsg_get_str(m, "name")))
- ch->name = strdup(str);
+ egc->name = strdup(str);
if ((str = htsmsg_get_str(m, "icon")))
- ch->icon = strdup(str);
+ egc->icon = strdup(str);
if(!htsmsg_get_u32(m, "number", &u32))
- ch->number = u32;
+ egc->number = u32;
+ if ((a = htsmsg_get_list(m, "channels"))) {
+ HTSMSG_FOREACH(f, a) {
+ if ((ch = channel_find_by_identifier((uint32_t)f->hmf_s64))) {
+ epggrab_channel_link_t *ecl = calloc(1, sizeof(epggrab_channel_link_t));
+ ecl->channel = ch;
+ LIST_INSERT_HEAD(&egc->channels, ecl, link);
+ }
+ }
- if (!htsmsg_get_u32(m, "channel", &u32))
- ch->channel = channel_find_by_identifier(u32);
+ /* Compat with older 3.1 code */
+ } else if (!htsmsg_get_u32(m, "channel", &u32)) {
+ if ((ch = channel_find_by_identifier(u32))) {
+ epggrab_channel_link_t *ecl = calloc(1, sizeof(epggrab_channel_link_t));
+ ecl->channel = ch;
+ LIST_INSERT_HEAD(&egc->channels, ecl, link);
+ }
+ }
}
void epggrab_module_channels_load ( epggrab_module_t *mod )
opentv_event_t ev;
epggrab_module_t *src = (epggrab_module_t*)mod;
const char *lang = NULL;
+ epggrab_channel_link_t *ecl;
/* Get language (bit of a hack) */
if (!strcmp(mod->dict->id, "skyit")) lang = "it";
/* Channel */
cid = ((int)buf[0] << 8) | buf[1];
if (!(ec = _opentv_find_epggrab_channel(mod, cid, 0, NULL))) return 0;
- if (!ec->channel) return 0;
- if (!*ec->channel->ch_name) return 0; // ignore unnamed channels
+ if (!(ecl = LIST_FIRST(&ec->channels))) return 0;
+ // TODO: it's assumed that opentv channels are always 1-1 mapping!
/* Time (start/stop referenced to this) */
mjd = ((int)buf[5] << 8) | buf[6];
/* Find broadcast */
if (ev.type & OPENTV_TITLE) {
- ebc = epg_broadcast_find_by_time(ec->channel, ev.start, ev.stop, ev.eid,
+ ebc = epg_broadcast_find_by_time(ecl->channel, ev.start, ev.stop, ev.eid,
1, &save);
/* Store */
- } else if (!(ebc = epg_broadcast_find_by_eid(ec->channel, ev.eid))) {
+ } else if (!(ebc = epg_broadcast_find_by_eid(ecl->channel, ev.eid))) {
opentv_event_t *skel = malloc(sizeof(opentv_event_t));
memcpy(skel, &ev, sizeof(opentv_event_t));
assert(!RB_INSERT_SORTED(&sta->events, skel, ev_link, _ev_cmp));
if (ebc && ev.serieslink) {
char suri[257];
snprintf(suri, 256, "opentv://channel-%d/series-%d",
- ec->channel->ch_id, ev.serieslink);
+ ecl->channel->ch_id, ev.serieslink);
if ((es = epg_serieslink_find_by_uri(suri, 1, &save)))
save |= epg_broadcast_set_serieslink(ebc, es, src);
}
( opentv_module_t *mod, uint8_t *buf, int len, uint16_t tsid )
{
epggrab_channel_t *ec;
+ epggrab_channel_link_t *ecl;
service_t *svc;
int sid, cid, cnum;
int save = 0;
/* Find the service */
svc = _opentv_find_service(tsid, sid);
- if (svc && svc->s_ch) {
+ if (svc && svc->s_ch && service_is_primary_epg(svc)) {
ec =_opentv_find_epggrab_channel(mod, cid, 1, &save);
- if (service_is_primary_epg(svc))
- ec->channel = svc->s_ch;
- else
- ec->channel = NULL;
+ ecl = LIST_FIRST(&ec->channels);
+ if (!ecl) {
+ ecl = calloc(1, sizeof(epggrab_channel_link_t));
+ LIST_INSERT_HEAD(&ec->channels, ecl, link);
+ }
+ ecl->channel = svc->s_ch;
save |= epggrab_channel_set_number(ec, cnum);
}
i += 9;
htsmsg_field_t *f;
epggrab_channel_t *ec;
const char *str;
+ epggrab_channel_link_t *ecl;
if ( data == NULL ) return 0;
if ((str = htsmsg_get_str(attr, "channel")) == NULL) return 0;
if ((ec = _pyepg_channel_find(str, 0, NULL)) == NULL) return 0;
if ((tags = htsmsg_get_map(data, "tags")) == NULL) return 0;
- if (!ec->channel) return 0;
HTSMSG_FOREACH(f, tags) {
if (strcmp(f->hmf_name, "broadcast") == 0) {
- save |= _pyepg_parse_broadcast(mod, htsmsg_get_map_by_field(f),
- ec->channel, stats);
+ LIST_FOREACH(ecl, &ec->channels, link)
+ save |= _pyepg_parse_broadcast(mod, htsmsg_get_map_by_field(f),
+ ecl->channel, stats);
}
}
const char *s, *chid;
time_t start, stop;
epggrab_channel_t *ch;
+ epggrab_channel_link_t *ecl;
if(body == NULL) return 0;
if((tags = htsmsg_get_map(body, "tags")) == NULL) return 0;
if((chid = htsmsg_get_str(attribs, "channel")) == NULL) return 0;
if((ch = _xmltv_channel_find(chid, 0, NULL)) == NULL) return 0;
- if (ch->channel == NULL) return 0;
+ if (!LIST_FIRST(&ch->channels)) return 0;
if((s = htsmsg_get_str(attribs, "start")) == NULL) return 0;
start = _xmltv_str2time(s);
if((s = htsmsg_get_str(attribs, "stop")) == NULL) return 0;
if(stop <= start || stop <= dispatch_clock) return 0;
- save |= _xmltv_parse_programme_tags(mod, ch->channel, tags,
- start, stop, stats);
+ LIST_FOREACH(ecl, &ch->channels, link)
+ save |= _xmltv_parse_programme_tags(mod, ecl->channel, tags,
+ start, stop, stats);
return save;
}
char *modid, *ecid;
epggrab_module_t *mod;
epggrab_channel_t *ec;
+ epggrab_channel_link_t *ecl;
/* Clear existing */
LIST_FOREACH(mod, &epggrab_modules, link) {
if (mod->type != EPGGRAB_OTA && mod->channels) {
RB_FOREACH(ec, mod->channels, link) {
- if (ec->channel == ch) {
- ec->channel = NULL;
- mod->ch_save(mod, ec);
+ LIST_FOREACH(ecl, &ec->channels, link) {
+ if (ecl->channel == ch) {
+ LIST_REMOVE(ecl, link);
+ free(ecl);
+ mod->ch_save(mod, ec);
+ break;
+ }
}
}
}
char *epggrabsrc;
epggrab_module_t *mod;
epggrab_channel_t *ec;
+ epggrab_channel_link_t *ecl;
if(op == NULL)
return 400;
LIST_FOREACH(mod, &epggrab_modules, link) {
if (mod->type != EPGGRAB_OTA && mod->channels) {
RB_FOREACH(ec, mod->channels, link) {
- if (ec->channel == ch) {
- char id[100];
- sprintf(id, "%s|%s", mod->id, ec->id);
- if (!epggrabsrc) {
- epggrabsrc = strdup(id);
- } else {
- epggrabsrc = realloc(epggrabsrc, strlen(epggrabsrc) + 2 + strlen(id));
- strcat(epggrabsrc, ",");
- strcat(epggrabsrc, id);
+ LIST_FOREACH(ecl, &ec->channels, link) {
+ if (ecl->channel == ch) {
+ char id[100];
+ sprintf(id, "%s|%s", mod->id, ec->id);
+ if (!epggrabsrc) {
+ epggrabsrc = strdup(id);
+ } else {
+ epggrabsrc = realloc(epggrabsrc, strlen(epggrabsrc) + 2 + strlen(id));
+ strcat(epggrabsrc, ",");
+ strcat(epggrabsrc, id);
+ }
}
}
}
}, {
header : "EPG Grab source",
dataIndex : 'epggrabsrc',
+ hiddenName : 'epggrabsrc',
width : 150,
editor : new Ext.ux.form.LovCombo({
loadingText : 'Loading...',