17 typedef struct _ContentTYPE{
23 static CONTENT_TYPE ContentCatList[CAT_COUNT] = {
24 { "ニュース・報道", "news" },
26 { "情報", "information" },
29 { "バラエティ", "variety" },
31 { "アニメ・特撮", "anime" },
32 { "ドキュメンタリー・教養", "documentary" },
39 { "その他", "etc" } //その他
43 SVT_CONTROL *svttop = NULL;
47 char desc[102400] = {0};
49 char ServiceName[1024];
51 static unsigned char *base64 = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
53 static void base64_char(unsigned long bb, int srclen, unsigned char *dest, int j)
58 for ( i = srclen; i < 2; i++ )
62 for ( base = 18, x = 0; x < srclen + 2; x++, base -= 6) {
63 dest[j++] = base64[ (unsigned long)((bb>>base) & 0x3F) ];
67 for ( i = x; i < 4; i++ ) {
68 dest[j++] = (unsigned char)'='; /* 端数 */
73 static void base64_encode(unsigned char *dest, const unsigned char *src, int len)
75 unsigned char *p = src;
76 unsigned long bb = (unsigned long)0;
82 bb |= (unsigned long)*p;
86 base64_char(bb, i, dest, j);
98 if (i) base64_char(bb, i - 1, dest, j);
102 void xmlspecialchars(char *str)
104 strrep(str, "&", "&");
105 strrep(str, "'", "'");
106 strrep(str, "\"", """);
107 strrep(str, "<", "<");
108 strrep(str, ">", ">");
113 void GetSDT(FILE *infile, SVT_CONTROL *svttop, SECcache *secs,
114 int count, STATION **station, int * station_count, char *header, int is_bs_cs)
117 int pmtpids[SECCOUNT];
118 memset(pmtpids, 0, sizeof(pmtpids));
119 int dsmccpids[SECCOUNT];
120 memset(dsmccpids, 0, sizeof(dsmccpids));
123 while((bsecs = readTS(infile, secs, count)) != NULL) {
125 if(is_bs_cs && (bsecs->pid & 0xFF) == 0x00) {
126 dumpPAT(bsecs->buf, secs, count, pmtpids);
129 else if((bsecs->pid & 0xFF) == 0x11) {
130 dumpSDT(bsecs->buf, svttop, station, station_count, header);
133 else if((bsecs->pid & 0xFF) == 0x14) {
137 else if((bsecs->pid & 0xFF) == 0x23) {
138 dumpSDTT(bsecs->buf, *station, *station_count);
141 else if((bsecs->pid & 0xFF) == 0x29) {
142 dumpCDT(bsecs->buf, *station, *station_count);
144 else if ( is_bs_cs ) {
145 for ( i = 1; i < SECCOUNT; i++ ) {
146 if ( pmtpids[i] == 0 ) {
149 /* PMT specified by PAT */
150 if ( bsecs->pid == pmtpids[i] ) {
151 dumpPMT(bsecs->buf, secs, count, dsmccpids);
155 for ( i = 0; i < SECCOUNT; i++ ) {
156 if ( dsmccpids[i] == 0 ) {
159 /* DSM-CC specified by PMT */
160 if ( bsecs->pid == dsmccpids[i] ) {
161 dumpDSMCC(bsecs->buf, *station, *station_count);
168 void GetEIT(FILE *infile, FILE *outfile, STATION *psta, SECcache *secs)
171 EIT_CONTROL *eitcur ;
172 EIT_CONTROL *eitnext ;
173 EIT_CONTROL *eittop = NULL;
181 memset(secs, 0, sizeof(SECcache) * SECCOUNT);
182 secs[0].pid = 0x12; /* EIT */
183 secs[1].pid = 0x26; /* EIT */
184 secs[2].pid = 0x27; /* EIT */
186 eittop = calloc(1, sizeof(EIT_CONTROL));
188 fseek(infile, 0, SEEK_SET);
189 while((bsecs = readTS(infile, secs, SECCOUNT)) != NULL) {
191 if((bsecs->pid & 0xFF) == 0x12) {
192 dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
193 }else if((bsecs->pid & 0xFF) == 0x26) {
194 dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
195 }else if((bsecs->pid & 0xFF) == 0x27) {
196 dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
200 while(eitcur != NULL){
202 eitcur = eitcur->next ;
205 if(eitcur->content_type > CAT_COUNT){
206 eitcur->content_type = CAT_COUNT -1 ;
208 memset(title, '\0', sizeof(title));
209 strcpy(title, eitcur->title);
210 xmlspecialchars(title);
212 memset(subtitle, '\0', sizeof(subtitle));
213 strcpy(subtitle, eitcur->subtitle);
214 xmlspecialchars(subtitle);
216 memset(desc, '\0', sizeof(desc));
217 if ( eitcur->desc ) {
218 strcpy(desc, eitcur->desc);
219 xmlspecialchars(desc);
222 memset(Category, '\0', sizeof(Category));
223 strcpy(Category, ContentCatList[eitcur->content_type].japanese);
224 xmlspecialchars(Category);
226 tl.tm_sec = eitcur->ss ;
227 tl.tm_min = eitcur->hm ;
228 tl.tm_hour = eitcur->hh ;
229 tl.tm_mday = eitcur->dd ;
230 tl.tm_mon = (eitcur->mm - 1);
231 tl.tm_year = (eitcur->yy - 1900);
235 l_time = mktime(&tl);
236 if((eitcur->ehh == 0) && (eitcur->emm == 0) && (eitcur->ess == 0)){
238 end_time = l_time + (60 * 5); // 5分後に設定
239 endtl = localtime(&end_time);
241 end_time = l_time + eitcur->ehh * 3600 + eitcur->emm * 60 + eitcur->ess;
242 endtl = localtime(&end_time);
244 memset(cendtime, '\0', sizeof(cendtime));
245 memset(cstarttime, '\0', sizeof(cstarttime));
246 strftime(cendtime, (sizeof(cendtime) - 1), "%Y%m%d%H%M%S", endtl);
247 strftime(cstarttime, (sizeof(cstarttime) - 1), "%Y%m%d%H%M%S", &tl);
248 fprintf(outfile, " <programme start=\"%s +0900\" stop=\"%s +0900\" channel=\"%s\" event=\"%d\">\n",
249 cstarttime, cendtime, psta->ontv, eitcur->event_id);
250 fprintf(outfile, " <title lang=\"ja_JP\">%s</title>\n", title);
251 fprintf(outfile, " <desc lang=\"ja_JP\">%s</desc>\n", subtitle);
252 fprintf(outfile, " <longdesc lang=\"ja_JP\">%s</longdesc>\n", desc);
253 fprintf(outfile, " <category lang=\"ja_JP\">%s</category>\n", Category);
254 //fprintf(outfile, " <category lang=\"en\">%s</category>\n", ContentCatList[eitcur->content_type].english);
255 fprintf(outfile, " </programme>\n");
257 fprintf(outfile, "(%x:%x:%x)%s,%s,%s,%s,%s,%s\n",
258 eitcur->servid, eitcur->table_id, eitcur->event_id,
259 cstarttime, cendtime,
262 ContentCatList[eitcur->content_type].english);
264 fprintf(outfile, "(%x:%x)%04d/%02d/%02d,%02d:%02d:%02d,%02d:%02d:%02d,%s,%s,%s,%s\n",
265 eitcur->table_id, eitcur->event_id,
266 eitcur->yy, eitcur->mm, eitcur->dd,
267 eitcur->hh, eitcur->hm, eitcur->ss,
268 eitcur->ehh, eitcur->emm, eitcur->ess,
269 eitcur->title, eitcur->subtitle,
270 ContentCatList[eitcur->content_type].japanese,
271 ContentCatList[eitcur->content_type].english);
273 eitnext = eitcur->next ;
275 free(eitcur->subtitle);
282 void checkSta_BS(STATION **station,int *stalength){
287 STATION * statin= *station;
288 statmp=malloc(sizeof(STATION)*2);
289 for (int i=0;i<*stalength;i++){
291 for (int j=0;j<chlt;j++){
292 if (chl[j]==statin[i].svId || statin[i].svId >= 290){
297 statmp=realloc(statmp,(stal+1)*sizeof(STATION));
298 statmp[stal]=statin[i];
299 //memcpy(statmp[stal-1],station[i],sizeof(STATION));
300 chl[chlt]=statin[i].svId;
305 //*station=realloc(station,(stal+1)*sizeof(STATION));
306 //memcpy(*station,statmp,(stal+1)*sizeof(STATION));
309 //memcpy(statin,statmp,chlt*sizeof(STATION));
313 void checkSta(STATION **station,int *stalength){
318 STATION * statin= *station;
319 statmp=malloc(sizeof(STATION)*2);
320 for (int i=0;i<*stalength;i++){
322 for (int j=0;j<chlt;j++){
323 if (chl[j]==statin[i].svId){
328 statmp=realloc(statmp,(stal+1)*sizeof(STATION));
329 statmp[stal]=statin[i];
330 //memcpy(statmp[stal-1],station[i],sizeof(STATION));
331 chl[chlt]=statin[i].svId;
337 *stalength=stal;//ここいらが怪しい
338 //memcpy(statin,statmp,chlt*sizeof(STATION));
342 int main(int argc, char *argv[])
345 FILE *infile = stdin;
346 FILE *outfile = stdout;
351 SVT_CONTROL *svtcur ;
352 SVT_CONTROL *svtsave ;
353 SECcache secs[SECCOUNT];
360 memset(secs, 0, sizeof(SECcache) * SECCOUNT);
361 secs[0].pid = 0x00; /* PAT */
362 secs[1].pid = 0x11; /* SDT */
363 secs[2].pid = 0x12; /* EIT */
364 secs[3].pid = 0x23; /* SDTT */
365 secs[4].pid = 0x26; /* EIT */
366 secs[5].pid = 0x27; /* EIT */
367 secs[6].pid = 0x29; /* CDT */
371 if(strcmp(argv[2], "-")) {
372 infile = fopen(argv[2], "r");
374 printf( "tsFile not found.\n" );
382 if(strcmp(argv[3], "-")) {
383 outfile = fopen(argv[3], "w+");
385 printf( "xmlfile not found.\n" );
394 fprintf(stdout, "Usage : %s {/BS|/CS} <tsFile> <outfile>\n", argv[0]);
395 fprintf(stdout, "Usage : %s <id> <tsFile> <outfile>\n", argv[0]);
396 fprintf(stdout, "\n");
397 fprintf(stdout, "id チャンネル識別子。地上波の物理チャンネルを与えます。\n");
398 fprintf(stdout, "/BS BSモード。一つのTSからBS全局のデータを読み込みます。\n");
399 fprintf(stdout, "/CS CSモード。一つのTSから複数局のデータを読み込みます。\n");
400 fprintf(stdout, "/TIME 時刻合わせモード。TSからTOT(Time Offset Table)を読み込みます。\n");
401 fprintf(stdout, " recpt1 <任意> 10(秒以上) - | epgdump /TIME - <任意>の形で使用してください。\n");
402 fprintf(stdout, " TOTは5秒に1回しか来ないため、recpt1に与える時間をある程度長くしてください。\n");
404 fprintf(stdout, " ontvcode Channel identifier (ex. ****.ontvjapan.com)\n");
405 fprintf(stdout, " /BS BS mode\n");
406 fprintf(stdout, " This mode reads the data of all BS TV stations\n");
407 fprintf(stdout, " from one TS data.\n");
408 fprintf(stdout, " /CS CS mode\n");
409 fprintf(stdout, " This mode reads the data of two or more CS TV stations\n");
410 fprintf(stdout, " from one TS data.\n");
415 if(strcmp(arg_onTV, "/BS") == 0){
418 svttop = calloc(1, sizeof(SVT_CONTROL));
420 GetSDT(infile, svttop, secs, SECCOUNT,&sta, &sta_count, head, 1);
421 checkSta_BS(&sta,&sta_count);
423 staCount = sta_count;
424 //staCount = sizeof(pStas) / sizeof (STATION);
426 }else if(strcmp(arg_onTV, "/CS") == 0){
429 svttop = calloc(1, sizeof(SVT_CONTROL));
431 GetSDT(infile, svttop, secs, SECCOUNT,&sta, &sta_count, head, 1);
432 checkSta(&sta,&sta_count);
434 staCount = sta_count;
435 //staCount=sizeof(pStas) / sizeof (STATION);
437 }else if(strcmp(arg_onTV, "/TEST") == 0){
440 svttop = calloc(1, sizeof(SVT_CONTROL));
442 GetSDT(infile, svttop, secs, SECCOUNT,&sta, &sta_count, head, 0);
443 checkSta(&sta,&sta_count);
445 printf("Station count: %d\n1st ontv=%s,name=%s\n",sta_count, sta[0].ontv, sta[0].name);
447 staCount = sta_count;// sizeof(pStas) / sizeof (STATION);
449 }else if(strcmp(arg_onTV, "/TIME") == 0){
450 printf("TSに載っている時刻データは2秒ほど早めてあるのかもしれません。\n");
451 memset(secs, 0, sizeof(SECcache) * SECCOUNT);
452 secs[0].pid = 0x14; /* TOT */
454 GetSDT(infile, NULL, secs, SECCOUNT,NULL, NULL,NULL, 0);
460 fprintf(stderr, "Can't open file: %s\n", argv[2]);
465 svttop = calloc(1, sizeof(SVT_CONTROL));
466 GetSDT(infile, svttop, secs, SECCOUNT);
467 svtcur = svttop->next ; //先頭
473 pStas = calloc(1, sizeof(STATION));
474 pStas->tsId = svtcur->transport_stream_id ;
475 pStas->onId = svtcur->original_network_id ;
476 pStas->svId = svtcur->event_id ;
477 pStas->ontv = arg_onTV ;
478 pStas->name = svtcur->servicename ;
485 svttop = calloc(1, sizeof(SVT_CONTROL));
486 //char *head=arg_onTV;
487 GetSDT(infile, svttop, secs, SECCOUNT, &sta, &sta_count, arg_onTV, 0);
488 checkSta(&sta, &sta_count);
489 //if (sta_count) printf("Station count: %d\n1st ontv=%s,name=%s\n",sta_count, sta[0].ontv, sta[0].name);
491 staCount = sta_count;// sizeof(pStas) / sizeof (STATION);
495 fprintf(outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
496 fprintf(outfile, "<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n");
497 fprintf(outfile, "<tv generator-info-name=\"tsEPG2xml\" generator-info-url=\"http://localhost/\">\n");
499 for(lp = 0 ; lp < staCount ; lp++){
500 memset(ServiceName, '\0', sizeof(ServiceName));
501 strcpy(ServiceName, pStas[lp].name);
502 xmlspecialchars(ServiceName);
504 fprintf(outfile, " <channel id=\"%s\">\n", pStas[lp].ontv);
505 fprintf(outfile, " <display-name lang=\"ja_JP\">%s</display-name>\n", ServiceName);
507 memset(Logo, '\0', sizeof(Logo));
508 for ( i = 0 ; i < 6 ; i++) {
509 if (pStas[lp].logo_array[i].logo) {
510 base64_encode(Logo, pStas[lp].logo_array[i].logo, pStas[lp].logo_array[i].logo_size);
511 xmlspecialchars(Logo);
512 fprintf(outfile, " <logo id=\"%02d\">%s</logo>\n", i, Logo);
516 fprintf(outfile, " </channel>\n");
518 for(lp = 0 ; lp < staCount ; lp++){
519 GetEIT(infile, outfile, &pStas[lp], secs);
521 fprintf(outfile, "</tv>\n");
531 svtcur = svttop ; //先頭
532 while(svtcur != NULL){
533 svtsave = svtcur->next ;