/* * Humax EPG Tool * by af123, 2011 */ #include #include #include #include #include #include #include #include #include #include #include #include "lint.h" int debug = 0; const char *version = "1.0.1"; unsigned long sysopts = 0; int syntax() { fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version); fprintf(stderr, "Syntax: epg [options] [filters] ...\n\n"); fprintf(stderr, " Options:\n" " -b Brief output.\n" " -d[level] Set debug level.\n" " -f Specify alternate EPG data file.\n" " -h Show help text.\n" " -p Parsable output.\n" "\n" ); fprintf(stderr, " Filters: (can be specified multiple times, all must be true)\n" " -C Show only events with this CRID.\n" " -D Show only selected descriptor type.\n" " -E Show only selected event.\n" " -S Show only selected service.\n" " -@ Show only programmes at time.\n" "\n" ); fprintf(stderr, " Commands:\n" " dump Show a parsed summary of the EPG.\n" " now Show what is currently on.\n" " search Search programme names for text.\n" " searchall " "Search programme names/descriptions for text.\n" ); fprintf(stderr, "\n"); return 0; } #define DECOMPRESS(str, len) \ if (*(str) == 0x1f) uncompress_epg(&(str), &(len)) void dumpraw(struct epg *epg __attribute__((unused)), struct section *s, struct data *d, struct descriptor **ds, void *var __attribute__((unused))) { dump_section(s); dump_data(d); if (ds[PARSER_SHORT_EVENT]) dump_descriptor(ds[PARSER_SHORT_EVENT], 1); if (ds[PARSER_USER_DEFINED]) dump_descriptor(ds[PARSER_USER_DEFINED], 1); if (ds[PARSER_CRID_EVENT]) dump_descriptor(ds[PARSER_CRID_EVENT], 1); if (ds[PARSER_CRID_SERIES]) dump_descriptor(ds[PARSER_CRID_SERIES], 1); if (ds[PARSER_CRID_REC]) dump_descriptor(ds[PARSER_CRID_REC], 1); } void dump(struct epg *epg __attribute__((unused)), struct section *s, struct data *d, struct descriptor **ds, void *var __attribute__((unused))) { time_t tm; tm = mjd(d->start_date, d->start_hour, d->start_min, d->start_sec); if (ds[PARSER_SHORT_EVENT]) { struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; DECOMPRESS(d77->content.d77.name, d77->content.d77.namelen); DECOMPRESS(d77->content.d77.text, d77->content.d77.textlen); } if (sysopts & SYSOPT_PARSABLE) { /* service_id, event_id, start, duration, encrypted, name, text * warning, num_crids, crid_type, crid, ... */ printf("%d\t%d\t%ld\t%d\t%d\t", s->service_id, d->event_id, tm, d->dur_hour * 3600 + d->dur_min * 60 + d->dur_sec, d->u1.u.free_CA_mode); if (ds[PARSER_SHORT_EVENT]) { struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; safeprintf("%.*s\t", d77->content.d77.namelen, d77->content.d77.name); safeprintf("%.*s\t", d77->content.d77.textlen, d77->content.d77.text); } else printf("\t\t"); if (ds[PARSER_USER_DEFINED]) { struct descriptor *d137 = ds[PARSER_USER_DEFINED]; safeprintf("%.*s\t", d137->content.d137.warninglen, d137->content.d137.warning); } else printf("\t"); if (ds[PARSER_CRID_EVENT]) { struct descriptor *d = ds[PARSER_CRID_EVENT]; printf("%.*s\t", d->content.d118.crids[0].cridlen, d->content.d118.crids[0].crid); } else printf("\t"); if (ds[PARSER_CRID_SERIES]) { struct descriptor *d = ds[PARSER_CRID_SERIES]; printf("%.*s\t", d->content.d118.crids[0].cridlen, d->content.d118.crids[0].crid); } else printf("\t"); printf("\n"); return; } printf("----------------------------------------------------------\n"); if (sysopts & SYSOPT_BRIEF) { safeprintf("%d/%d: %s+%d\n", s->service_id, d->event_id, ctime_nl(&tm), d->dur_hour * 3600 + d->dur_min * 60 + d->dur_sec); if (ds[PARSER_SHORT_EVENT]) { struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; safeprintf("Name:%.*s\n", d77->content.d77.namelen, d77->content.d77.name); safeprintf("Text:%.*s\n", d77->content.d77.textlen, d77->content.d77.text); } if (ds[PARSER_USER_DEFINED]) { struct descriptor *d137 = ds[PARSER_USER_DEFINED]; safeprintf("Warning:%.*s\n", d137->content.d137.warninglen, d137->content.d137.warning); } return; } printf("%30s: %d\n", "Service ID", s->service_id); printf("%30s: %d\n", "Event ID", d->event_id); printf("%30s: %#x %d:%02d:%02d (%s)\n", "start_date", d->start_date, d->start_hour, d->start_min, d->start_sec, ctime_nl(&tm)); printf("%30s: %d:%02d:%02d\n", "duration", d->dur_hour, d->dur_min, d->dur_sec); printf("%30s: %d\n", "encrypted", d->u1.u.free_CA_mode); if (ds[PARSER_SHORT_EVENT]) { struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; safeprintf("%30s: %.*s\n", "Name", d77->content.d77.namelen, d77->content.d77.name); safeprintf("%30s: %.*s\n", "Text", d77->content.d77.textlen, d77->content.d77.text); } if (ds[PARSER_USER_DEFINED]) { struct descriptor *d137 = ds[PARSER_USER_DEFINED]; safeprintf("%30s: %.*s\n", "Warning", d137->content.d137.warninglen, d137->content.d137.warning); } if (ds[PARSER_CRID_EVENT]) printf("%30s: %.*s\n", "Event CRID", ds[PARSER_CRID_EVENT]->content.d118.crids[0].cridlen, ds[PARSER_CRID_EVENT]->content.d118.crids[0].crid); if (ds[PARSER_CRID_SERIES]) printf("%30s: %.*s\n", "Series CRID", ds[PARSER_CRID_SERIES]->content.d118.crids[0].cridlen, ds[PARSER_CRID_SERIES]->content.d118.crids[0].crid); if (ds[PARSER_CRID_REC]) { struct descriptor *d118 = ds[PARSER_CRID_REC]; int i; for (i = 0; i < d118->content.d118.i; i++) { struct crid *crid = &d118->content.d118.crids[i]; printf("%30s: %.*s\n", "Recommended CRID", crid->cridlen, crid->crid); } } } void search(struct epg *epg __attribute__((unused)), struct section *s, struct data *d, struct descriptor **ds, void *var) { if (ds[PARSER_SHORT_EVENT]) { struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; DECOMPRESS(d77->content.d77.name, d77->content.d77.namelen); if (strcasestr(ds[PARSER_SHORT_EVENT]->content.d77.name, (char *)var)) dump(epg, s, d, ds, NULL); } } void searchall(struct epg *epg __attribute__((unused)), struct section *s, struct data *d, struct descriptor **ds, void *var) { if (ds[PARSER_SHORT_EVENT]) { struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; DECOMPRESS(d77->content.d77.name, d77->content.d77.namelen); DECOMPRESS(d77->content.d77.text, d77->content.d77.textlen); if (strcasestr(ds[PARSER_SHORT_EVENT]->content.d77.name, (char *)var) || strcasestr(ds[PARSER_SHORT_EVENT]->content.d77.text, (char *)var)) dump(epg, s, d, ds, NULL); } } #define GETOPT \ do { \ if (*++cp == '\0' && argc < 2) \ { \ fprintf(stderr, \ "No argument supplied for -%c\n", opt); \ exit(1); \ } \ else if (*cp == '\0') \ { \ argc--, argv++; \ cp = argv[0]; \ } \ while (isspace((int)*cp)) \ cp++; \ } while (0) int main(int argc, char **argv) { char *epgpath = DEFAULT_EPG_FILE; struct epgfilter *filter = NULL; char *cp; argc--, argv++; while (argc > 0 && *argv[0] == '-') { for (cp = &argv[0][1]; *cp; cp++) { char opt; switch (opt = *cp) { case 'b': sysopts |= SYSOPT_BRIEF; break; case 'd': if (*++cp == '\0') debug = 1; else debug = atoi(cp); goto nextopt; case 'f': GETOPT; epgpath = strdup(cp); goto nextopt; case 'h': return syntax(); case 'p': sysopts |= SYSOPT_PARSABLE; break; /* Filters */ case '@': GETOPT; add_epgfilter(&filter, FILTER_TIMESTAMP, atoi(cp), 0, NULL, FT_EQUAL); /* Global flag to indicate that the * timestamp check is required - has overhead * so don't want to do it in all cases. */ sysopts |= SYSOPT_TIMESTAMP; goto nextopt; case 'C': GETOPT; add_epgfilter(&filter, FILTER_CRID, 0, 0, cp, FT_EQUAL); /* Global flag to indicate that CRID filtering * has been requested. Required so that * events with no event CRID aren't shown * when filtering. */ sysopts |= SYSOPT_CRIDFILTER; goto nextopt; case 'D': GETOPT; add_epgfilter(&filter, FILTER_DESCRIPTOR, atoi(cp), 0, NULL, FT_EQUAL); goto nextopt; case 'E': GETOPT; add_epgfilter(&filter, FILTER_EVENT, atoi(cp), 0, NULL, FT_EQUAL); goto nextopt; case 'S': GETOPT; add_epgfilter(&filter, FILTER_SERVICE, atoi(cp), 0, NULL, FT_EQUAL); goto nextopt; } } nextopt: argc--, argv++; } if (argc < 1) return syntax(); if (!strcmp(argv[0], "dump")) parse(epgpath, dump, NULL, filter); else if (!strcmp(argv[0], "dumpraw")) parse(epgpath, dumpraw, NULL, filter); else if (!strcmp(argv[0], "now")) { time_t tm; time(&tm); add_epgfilter(&filter, FILTER_TIMESTAMP, tm, 0, NULL, FT_EQUAL); parse(epgpath, dump, NULL, filter); } else if (!strcmp(argv[0], "search") && argc > 1) parse(epgpath, search, (void *)argv[1], filter); else if (!strcmp(argv[0], "searchall") && argc > 1) parse(epgpath, searchall, (void *)argv[1], filter); else syntax(); return 0; }