Mercurial > pt1
comparison recpt1/recpt1.c @ 78:5a0126d8af17
landed ipc control functionality branch
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 01 Dec 2009 20:24:22 +0900 |
parents | b6607f6e2851 |
children | 6e3bb2c0c5b6 |
comparison
equal
deleted
inserted
replaced
77:517e61637f7b | 78:5a0126d8af17 |
---|---|
26 #include "decoder.h" | 26 #include "decoder.h" |
27 #include "recpt1.h" | 27 #include "recpt1.h" |
28 #include "version.h" | 28 #include "version.h" |
29 #include "mkpath.h" | 29 #include "mkpath.h" |
30 | 30 |
31 #include <sys/ipc.h> | |
32 #include <sys/msg.h> | |
33 | |
31 /* maximum write length at once */ | 34 /* maximum write length at once */ |
32 #define SIZE_CHANK 1316 | 35 #define SIZE_CHANK 1316 |
33 | 36 |
34 /* globals */ | 37 /* ipc message size */ |
35 int f_exit = FALSE; | 38 #define MSGSZ 255 |
36 | 39 |
37 /* type definitions */ | 40 /* type definitions */ |
41 typedef int boolean; | |
42 | |
38 typedef struct sock_data { | 43 typedef struct sock_data { |
39 int sfd; /* socket fd */ | 44 int sfd; /* socket fd */ |
40 struct sockaddr_in addr; | 45 struct sockaddr_in addr; |
41 } sock_data; | 46 } sock_data; |
42 | 47 |
43 typedef struct reader_thread_data { | 48 typedef struct thread_data { |
44 QUEUE_T *queue; | 49 QUEUE_T *queue; |
45 decoder *decoder; | 50 decoder *decoder; |
51 decoder_options *dopt; | |
52 int ch; | |
53 int tfd; /* tuner fd */ | |
46 int wfd; /* output file fd */ | 54 int wfd; /* output file fd */ |
55 ISDB_T_FREQ_CONV_TABLE *table; | |
47 sock_data *sock_data; | 56 sock_data *sock_data; |
48 pthread_t signal_thread; | 57 pthread_t signal_thread; |
49 } reader_thread_data; | 58 int recsec; |
50 | 59 boolean indefinite; |
51 typedef struct signal_thread_data { | 60 int msqid; |
52 QUEUE_T *queue; | 61 time_t start_time; |
53 int tfd; /* tuner fd */ | 62 } thread_data; |
54 } signal_thread_data; | 63 |
64 typedef struct msgbuf { | |
65 long mtype; | |
66 char mtext[MSGSZ]; | |
67 } message_buf; | |
68 | |
69 /* globals */ | |
70 boolean f_exit = FALSE; | |
71 | |
72 /* prototypes */ | |
73 int tune(char *channel, thread_data *tdata, char *device); | |
74 int close_tuner(thread_data *tdata); | |
75 | |
76 | |
77 /* ipc message receive */ | |
78 void * | |
79 mq_recv(void *t) | |
80 { | |
81 thread_data *tdata = (thread_data *)t; | |
82 message_buf rbuf; | |
83 char channel[16]; | |
84 int ch = 0, recsec = 0, time_to_add = 0; | |
85 | |
86 while(1) { | |
87 if(msgrcv(tdata->msqid, &rbuf, MSGSZ, 1, 0) < 0) { | |
88 return NULL; | |
89 } | |
90 | |
91 sscanf(rbuf.mtext, "ch=%s t=%d e=%d", channel, &recsec, &time_to_add); | |
92 ch = atoi(channel); | |
93 // fprintf(stderr, "ch=%d time=%d extend=%d\n", ch, recsec, time_to_add); | |
94 | |
95 if(ch && tdata->ch != ch) { | |
96 /* stop stream */ | |
97 ioctl(tdata->tfd, STOP_REC, 0); | |
98 | |
99 /* flush remainder? */ | |
100 | |
101 #if 0 | |
102 /* re-initialize decoder */ | |
103 if(tdata->decoder) { | |
104 // b25_finish(tdata->decoder); | |
105 b25_shutdown(tdata->decoder); | |
106 tdata->decoder = b25_startup(tdata->dopt); | |
107 if(!tdata->decoder) { | |
108 fprintf(stderr, "Cannot start b25 decoder\n"); | |
109 fprintf(stderr, "Fall back to encrypted recording\n"); | |
110 } | |
111 } | |
112 #endif | |
113 /* tune to new channel */ | |
114 if(close_tuner(tdata) != 0) | |
115 return NULL; | |
116 tune(channel, tdata, NULL); | |
117 | |
118 /* restart recording */ | |
119 if(ioctl(tdata->tfd, START_REC, 0) < 0) { | |
120 fprintf(stderr, "Tuner cannot start recording\n"); | |
121 return NULL; | |
122 } | |
123 } | |
124 | |
125 if(time_to_add) { | |
126 tdata->recsec += time_to_add; | |
127 fprintf(stderr, "Extended %d sec\n", time_to_add); | |
128 } | |
129 | |
130 if(recsec) { | |
131 time_t cur_time; | |
132 time(&cur_time); | |
133 if(cur_time - tdata->start_time > recsec) { | |
134 f_exit = TRUE; | |
135 } | |
136 else { | |
137 tdata->recsec = recsec; | |
138 fprintf(stderr, "Total recording time = %d sec\n", recsec); | |
139 } | |
140 } | |
141 | |
142 if(f_exit) | |
143 return NULL; | |
144 } | |
145 } | |
146 | |
55 | 147 |
56 /* lookup frequency conversion table*/ | 148 /* lookup frequency conversion table*/ |
57 ISDB_T_FREQ_CONV_TABLE * | 149 ISDB_T_FREQ_CONV_TABLE * |
58 searchrecoff(char *channel) | 150 searchrecoff(char *channel) |
59 { | 151 { |
187 | 279 |
188 /* this function will be reader thread */ | 280 /* this function will be reader thread */ |
189 void * | 281 void * |
190 reader_func(void *p) | 282 reader_func(void *p) |
191 { | 283 { |
192 reader_thread_data *data = (reader_thread_data *)p; | 284 thread_data *data = (thread_data *)p; |
193 QUEUE_T *p_queue = data->queue; | 285 QUEUE_T *p_queue = data->queue; |
194 decoder *dec = data->decoder; | 286 decoder *dec = data->decoder; |
195 int wfd = data->wfd; | 287 int wfd = data->wfd; |
196 int use_b25 = dec ? TRUE : FALSE; | 288 boolean use_b25 = dec ? TRUE : FALSE; |
197 int use_udp = data->sock_data ? TRUE : FALSE; | 289 boolean use_udp = data->sock_data ? TRUE : FALSE; |
198 int fileless = FALSE; | 290 boolean fileless = FALSE; |
199 int sfd = -1; | 291 int sfd = -1; |
200 pthread_t signal_thread = data->signal_thread; | 292 pthread_t signal_thread = data->signal_thread; |
201 struct sockaddr_in *addr = NULL; | 293 struct sockaddr_in *addr = NULL; |
202 BUFSZ *qbuf; | 294 BUFSZ *qbuf; |
203 ARIB_STD_B25_BUFFER sbuf, dbuf, buf; | 295 ARIB_STD_B25_BUFFER sbuf, dbuf, buf; |
304 | 396 |
305 break; | 397 break; |
306 } | 398 } |
307 } | 399 } |
308 | 400 |
401 time_t cur_time; | |
402 time(&cur_time); | |
403 fprintf(stderr, "Recorded %d sec\n", | |
404 (int)(cur_time - data->start_time)); | |
405 | |
309 return NULL; | 406 return NULL; |
310 } | 407 } |
311 | 408 |
312 void | 409 void |
313 show_usage(char *cmd) | 410 show_usage(char *cmd) |
339 fprintf(stderr, "--device devicefile: Specify devicefile to use\n"); | 436 fprintf(stderr, "--device devicefile: Specify devicefile to use\n"); |
340 fprintf(stderr, "--help: Show this help\n"); | 437 fprintf(stderr, "--help: Show this help\n"); |
341 fprintf(stderr, "--version: Show version\n"); | 438 fprintf(stderr, "--version: Show version\n"); |
342 fprintf(stderr, "--list: Show channel list\n"); | 439 fprintf(stderr, "--list: Show channel list\n"); |
343 } | 440 } |
441 | |
344 void | 442 void |
345 show_channels(void) | 443 show_channels(void) |
346 { | 444 { |
347 FILE *f; | 445 FILE *f; |
348 char *home; | 446 char *home; |
435 | 533 |
436 if(type == CHTYPE_GROUND) { | 534 if(type == CHTYPE_GROUND) { |
437 P = log10(5505024/(double)rc) * 10; | 535 P = log10(5505024/(double)rc) * 10; |
438 CNR = (0.000024 * P * P * P * P) - (0.0016 * P * P * P) + | 536 CNR = (0.000024 * P * P * P * P) - (0.0016 * P * P * P) + |
439 (0.0398 * P * P) + (0.5491 * P)+3.0965; | 537 (0.0398 * P * P) + (0.5491 * P)+3.0965; |
440 fprintf(stderr, "Signal=%fdB\n", CNR); | 538 fprintf(stderr, "Signal = %f dB\n", CNR); |
441 } | 539 } |
442 else { | 540 else { |
443 CNR = getsignal_isdb_s(rc); | 541 CNR = getsignal_isdb_s(rc); |
444 fprintf(stderr, "Signal=%fdB\n", CNR); | 542 fprintf(stderr, "Signal = %f dB\n", CNR); |
445 } | 543 } |
446 } | 544 } |
447 | 545 |
448 void | 546 void |
449 cleanup(signal_thread_data *sdata) | 547 cleanup(thread_data *tdata) |
450 { | 548 { |
451 /* stop recording */ | 549 /* stop recording */ |
452 ioctl(sdata->tfd, STOP_REC, 0); | 550 ioctl(tdata->tfd, STOP_REC, 0); |
453 | 551 |
454 /* restore LNB state */ | 552 /* restore LNB state */ |
455 #if 0 | 553 #if 0 |
456 if(ptr->type == CHTYPE_SATELLITE) { | 554 if(ptr->type == CHTYPE_SATELLITE) { |
457 if(ioctl(tfd, LNB_DISABLE, 0) < 0) { | 555 if(ioctl(tfd, LNB_DISABLE, 0) < 0) { |
460 } | 558 } |
461 #endif | 559 #endif |
462 /* xxx need mutex? */ | 560 /* xxx need mutex? */ |
463 f_exit = TRUE; | 561 f_exit = TRUE; |
464 | 562 |
465 pthread_cond_signal(&sdata->queue->cond_avail); | 563 pthread_cond_signal(&tdata->queue->cond_avail); |
466 pthread_cond_signal(&sdata->queue->cond_used); | 564 pthread_cond_signal(&tdata->queue->cond_used); |
467 } | 565 } |
468 | 566 |
469 /* will be signal handler thread */ | 567 /* will be signal handler thread */ |
470 void * | 568 void * |
471 process_signals(void *data) | 569 process_signals(void *data) |
472 { | 570 { |
473 sigset_t waitset; | 571 sigset_t waitset; |
474 int sig; | 572 int sig; |
475 signal_thread_data *sdata; | 573 thread_data *tdata = (thread_data *)data; |
476 sdata = (signal_thread_data *)data; | |
477 | 574 |
478 sigemptyset(&waitset); | 575 sigemptyset(&waitset); |
479 sigaddset(&waitset, SIGPIPE); | 576 sigaddset(&waitset, SIGPIPE); |
480 sigaddset(&waitset, SIGINT); | 577 sigaddset(&waitset, SIGINT); |
481 sigaddset(&waitset, SIGTERM); | 578 sigaddset(&waitset, SIGTERM); |
485 sigwait(&waitset, &sig); | 582 sigwait(&waitset, &sig); |
486 | 583 |
487 switch(sig) { | 584 switch(sig) { |
488 case SIGPIPE: | 585 case SIGPIPE: |
489 fprintf(stderr, "\nSIGPIPE received. cleaning up...\n"); | 586 fprintf(stderr, "\nSIGPIPE received. cleaning up...\n"); |
490 cleanup(sdata); | 587 cleanup(tdata); |
491 break; | 588 break; |
492 case SIGINT: | 589 case SIGINT: |
493 fprintf(stderr, "\nSIGINT received. cleaning up...\n"); | 590 fprintf(stderr, "\nSIGINT received. cleaning up...\n"); |
494 cleanup(sdata); | 591 cleanup(tdata); |
495 break; | 592 break; |
496 case SIGTERM: | 593 case SIGTERM: |
497 fprintf(stderr, "\nSIGTERM received. cleaning up...\n"); | 594 fprintf(stderr, "\nSIGTERM received. cleaning up...\n"); |
498 cleanup(sdata); | 595 cleanup(tdata); |
499 break; | 596 break; |
500 case SIGUSR1: /* normal exit*/ | 597 case SIGUSR1: /* normal exit*/ |
501 cleanup(sdata); | 598 cleanup(tdata); |
502 break; | 599 break; |
503 case SIGUSR2: /* error */ | 600 case SIGUSR2: /* error */ |
504 fprintf(stderr, "Detected an error. cleaning up...\n"); | 601 fprintf(stderr, "Detected an error. cleaning up...\n"); |
505 cleanup(sdata); | 602 cleanup(tdata); |
506 break; | 603 break; |
507 } | 604 } |
508 | 605 |
509 return NULL; /* dummy */ | 606 return NULL; /* dummy */ |
510 } | 607 } |
511 | 608 |
512 void | 609 void |
513 init_signal_handlers(pthread_t *signal_thread, signal_thread_data *sdata) | 610 init_signal_handlers(pthread_t *signal_thread, thread_data *tdata) |
514 { | 611 { |
515 sigset_t blockset; | 612 sigset_t blockset; |
516 | 613 |
517 sigemptyset(&blockset); | 614 sigemptyset(&blockset); |
518 sigaddset(&blockset, SIGPIPE); | 615 sigaddset(&blockset, SIGPIPE); |
522 sigaddset(&blockset, SIGUSR2); | 619 sigaddset(&blockset, SIGUSR2); |
523 | 620 |
524 if(pthread_sigmask(SIG_BLOCK, &blockset, NULL)) | 621 if(pthread_sigmask(SIG_BLOCK, &blockset, NULL)) |
525 fprintf(stderr, "pthread_sigmask() failed.\n"); | 622 fprintf(stderr, "pthread_sigmask() failed.\n"); |
526 | 623 |
527 pthread_create(signal_thread, NULL, process_signals, sdata); | 624 pthread_create(signal_thread, NULL, process_signals, tdata); |
625 } | |
626 | |
627 int | |
628 tune(char *channel, thread_data *tdata, char *device) | |
629 { | |
630 char **tuner; | |
631 int num_devs; | |
632 int lp; | |
633 FREQUENCY freq; | |
634 | |
635 /* get channel */ | |
636 tdata->table = searchrecoff(channel); | |
637 if(tdata->table == NULL) { | |
638 fprintf(stderr, "Invalid Channel: %s\n", channel); | |
639 return 1; | |
640 } | |
641 | |
642 freq.frequencyno = tdata->table->set_freq; | |
643 freq.slot = tdata->table->add_freq; | |
644 | |
645 /* open tuner */ | |
646 /* case 1: specified tuner device */ | |
647 if(device) { | |
648 tdata->tfd = open(device, O_RDONLY); | |
649 if(tdata->tfd < 0) { | |
650 fprintf(stderr, "Cannot open tuner device: %s\n", device); | |
651 return 1; | |
652 } | |
653 | |
654 /* power on LNB */ | |
655 if(tdata->table->type == CHTYPE_SATELLITE) { | |
656 if(ioctl(tdata->tfd, LNB_ENABLE, 0) < 0) { | |
657 close(tdata->tfd); | |
658 fprintf(stderr, "Power on LNB failed: %s\n", device); | |
659 return 1; | |
660 } | |
661 } | |
662 | |
663 /* tune to specified channel */ | |
664 if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) { | |
665 close(tdata->tfd); | |
666 fprintf(stderr, "Cannot tune to the specified channel: %s\n", device); | |
667 return 1; | |
668 } | |
669 else { | |
670 tdata->ch = atoi(channel); | |
671 } | |
672 } | |
673 else { | |
674 /* case 2: loop around available devices */ | |
675 if(tdata->table->type == CHTYPE_SATELLITE) { | |
676 tuner = bsdev; | |
677 num_devs = NUM_BSDEV; | |
678 } | |
679 else { | |
680 tuner = isdb_t_dev; | |
681 num_devs = NUM_ISDB_T_DEV; | |
682 } | |
683 | |
684 for(lp = 0; lp < num_devs; lp++) { | |
685 tdata->tfd = open(tuner[lp], O_RDONLY); | |
686 if(tdata->tfd >= 0) { | |
687 /* power on LNB */ | |
688 if(tdata->table->type == CHTYPE_SATELLITE) { | |
689 if(ioctl(tdata->tfd, LNB_ENABLE, 0) < 0) { | |
690 close(tdata->tfd); | |
691 tdata->tfd = -1; | |
692 continue; | |
693 } | |
694 } | |
695 | |
696 /* tune to specified channel */ | |
697 if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) { | |
698 close(tdata->tfd); | |
699 tdata->tfd = -1; | |
700 continue; | |
701 } | |
702 | |
703 break; /* found suitable tuner */ | |
704 } | |
705 } | |
706 | |
707 /* all tuners cannot be used */ | |
708 if(tdata->tfd < 0) { | |
709 fprintf(stderr, "Cannot tune to the specified channel\n"); | |
710 return 1; | |
711 } | |
712 else { | |
713 tdata->ch = atoi(channel); | |
714 } | |
715 } | |
716 | |
717 /* show signal strength */ | |
718 calc_cn(tdata->tfd, tdata->table->type); | |
719 | |
720 return 0; /* success */ | |
721 } | |
722 | |
723 int | |
724 parse_time(char *rectimestr, thread_data *tdata) | |
725 { | |
726 /* indefinite */ | |
727 if(!strcmp("-", rectimestr)) { | |
728 tdata->indefinite = TRUE; | |
729 tdata->recsec = -1; | |
730 } | |
731 /* colon */ | |
732 else if(strchr(rectimestr, ':')) { | |
733 int n1, n2, n3; | |
734 if(sscanf(rectimestr, "%d:%d:%d", &n1, &n2, &n3) == 3) | |
735 tdata->recsec = n1 * 3600 + n2 * 60 + n3; | |
736 else if(sscanf(rectimestr, "%d:%d", &n1, &n2) == 2) | |
737 tdata->recsec = n1 * 3600 + n2 * 60; | |
738 } | |
739 /* HMS */ | |
740 else { | |
741 char *tmpstr; | |
742 char *p1, *p2; | |
743 | |
744 tmpstr = strdup(rectimestr); | |
745 p1 = tmpstr; | |
746 while(*p1 && !isdigit(*p1)) | |
747 p1++; | |
748 | |
749 /* hour */ | |
750 if((p2 = strchr(p1, 'H')) || (p2 = strchr(p1, 'h'))) { | |
751 *p2 = '\0'; | |
752 tdata->recsec += atoi(p1) * 3600; | |
753 p1 = p2 + 1; | |
754 while(*p1 && !isdigit(*p1)) | |
755 p1++; | |
756 } | |
757 | |
758 /* minute */ | |
759 if((p2 = strchr(p1, 'M')) || (p2 = strchr(p1, 'm'))) { | |
760 *p2 = '\0'; | |
761 tdata->recsec += atoi(p1) * 60; | |
762 p1 = p2 + 1; | |
763 while(*p1 && !isdigit(*p1)) | |
764 p1++; | |
765 } | |
766 | |
767 /* second */ | |
768 tdata->recsec += atoi(p1); | |
769 | |
770 free(tmpstr); | |
771 } | |
772 | |
773 return 0; /* success */ | |
774 } | |
775 | |
776 int | |
777 close_tuner(thread_data *tdata) | |
778 { | |
779 if(tdata->table->type == CHTYPE_SATELLITE) { | |
780 if(ioctl(tdata->tfd, LNB_DISABLE, 0) < 0) { | |
781 return 1; | |
782 } | |
783 } | |
784 close(tdata->tfd); | |
785 | |
786 return 0; | |
528 } | 787 } |
529 | 788 |
530 int | 789 int |
531 main(int argc, char **argv) | 790 main(int argc, char **argv) |
532 { | 791 { |
533 int tfd, wfd; | 792 time_t cur_time; |
534 int lp; | 793 pthread_t signal_thread; |
535 int recsec = 0; | |
536 int indefinite = FALSE; | |
537 time_t start_time, cur_time; | |
538 FREQUENCY freq; | |
539 ISDB_T_FREQ_CONV_TABLE *ptr; | |
540 pthread_t reader_thread; | 794 pthread_t reader_thread; |
541 pthread_t signal_thread; | 795 pthread_t ipc_thread; |
542 QUEUE_T *p_queue = create_queue(MAX_QUEUE); | 796 QUEUE_T *p_queue = create_queue(MAX_QUEUE); |
543 BUFSZ *bufptr; | 797 BUFSZ *bufptr; |
544 decoder *dec = NULL; | 798 decoder *dec = NULL; |
545 static reader_thread_data tdata; | 799 static thread_data tdata; |
546 static signal_thread_data sdata; | |
547 decoder_options dopt = { | 800 decoder_options dopt = { |
548 4, /* round */ | 801 4, /* round */ |
549 0, /* strip */ | 802 0, /* strip */ |
550 0 /* emm */ | 803 0 /* emm */ |
551 }; | 804 }; |
805 tdata.dopt = &dopt; | |
552 | 806 |
553 int result; | 807 int result; |
554 int option_index; | 808 int option_index; |
555 struct option long_options[] = { | 809 struct option long_options[] = { |
556 #ifdef HAVE_LIBARIB25 | 810 #ifdef HAVE_LIBARIB25 |
569 { "version", 0, NULL, 'v'}, | 823 { "version", 0, NULL, 'v'}, |
570 { "list", 0, NULL, 'l'}, | 824 { "list", 0, NULL, 'l'}, |
571 {0, 0, NULL, 0} /* terminate */ | 825 {0, 0, NULL, 0} /* terminate */ |
572 }; | 826 }; |
573 | 827 |
574 int use_b25 = FALSE; | 828 boolean use_b25 = FALSE; |
575 int use_udp = FALSE; | 829 boolean use_udp = FALSE; |
576 int fileless = FALSE; | 830 boolean fileless = FALSE; |
577 int use_stdout = FALSE; | 831 boolean use_stdout = FALSE; |
578 char *host_to = NULL; | 832 char *host_to = NULL; |
579 int port_to = 1234; | 833 int port_to = 1234; |
580 sock_data *sockdata = NULL; | 834 sock_data *sockdata = NULL; |
581 char *device = NULL; | 835 char *device = NULL; |
582 char **tuner; | |
583 int num_devs; | |
584 | 836 |
585 while((result = getopt_long(argc, argv, "br:smua:p:d:hvl", | 837 while((result = getopt_long(argc, argv, "br:smua:p:d:hvl", |
586 long_options, &option_index)) != -1) { | 838 long_options, &option_index)) != -1) { |
587 switch(result) { | 839 switch(result) { |
588 case 'b': | 840 case 'b': |
644 | 896 |
645 if(argc - optind < 3) { | 897 if(argc - optind < 3) { |
646 if(argc - optind == 2 && use_udp) { | 898 if(argc - optind == 2 && use_udp) { |
647 fprintf(stderr, "Fileless UDP broadcasting\n"); | 899 fprintf(stderr, "Fileless UDP broadcasting\n"); |
648 fileless = TRUE; | 900 fileless = TRUE; |
649 wfd = -1; | 901 tdata.wfd = -1; |
650 } | 902 } |
651 else { | 903 else { |
652 fprintf(stderr, "Arguments are necessary!\n"); | 904 fprintf(stderr, "Arguments are necessary!\n"); |
653 fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); | 905 fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); |
654 return 1; | 906 return 1; |
655 } | 907 } |
656 } | 908 } |
657 | 909 |
658 /* get channel */ | 910 fprintf(stderr, "pid = %d\n", getpid()); |
659 ptr = searchrecoff(argv[optind]); | 911 |
660 if(ptr == NULL) { | 912 /* tune */ |
661 fprintf(stderr, "Invalid Channel: %s\n", argv[optind]); | 913 if(tune(argv[optind], &tdata, device) != 0) |
662 return 1; | 914 return 1; |
663 } | 915 |
664 | 916 /* set recsec */ |
665 freq.frequencyno = ptr->set_freq; | 917 if(parse_time(argv[optind + 1], &tdata) != 0) |
666 freq.slot = ptr->add_freq; | 918 return 1; |
667 | |
668 /* open tuner */ | |
669 /* case 1: specified tuner device */ | |
670 if(device) { | |
671 tfd = open(device, O_RDONLY); | |
672 if(tfd < 0) { | |
673 fprintf(stderr, "Cannot open tuner device: %s\n", device); | |
674 return 1; | |
675 } | |
676 | |
677 /* power on LNB */ | |
678 if(ptr->type == CHTYPE_SATELLITE) { | |
679 if(ioctl(tfd, LNB_ENABLE, 0) < 0) { | |
680 close(tfd); | |
681 fprintf(stderr, "Power on LNB failed: %s\n", device); | |
682 return 1; | |
683 } | |
684 } | |
685 | |
686 /* tune to specified channel */ | |
687 if(ioctl(tfd, SET_CHANNEL, &freq) < 0) { | |
688 close(tfd); | |
689 fprintf(stderr, "Cannot tune to the specified channel: %s\n", device); | |
690 return 1; | |
691 } | |
692 } | |
693 else { | |
694 /* case 2: loop around available devices */ | |
695 if(ptr->type == CHTYPE_SATELLITE) { | |
696 tuner = bsdev; | |
697 num_devs = NUM_BSDEV; | |
698 } | |
699 else { | |
700 tuner = isdb_t_dev; | |
701 num_devs = NUM_ISDB_T_DEV; | |
702 } | |
703 | |
704 for(lp = 0; lp < num_devs; lp++) { | |
705 tfd = open(tuner[lp], O_RDONLY); | |
706 if(tfd >= 0) { | |
707 /* power on LNB */ | |
708 if(ptr->type == CHTYPE_SATELLITE) { | |
709 if(ioctl(tfd, LNB_ENABLE, 0) < 0) { | |
710 close(tfd); | |
711 tfd = -1; | |
712 continue; | |
713 } | |
714 } | |
715 | |
716 /* tune to specified channel */ | |
717 if(ioctl(tfd, SET_CHANNEL, &freq) < 0) { | |
718 close(tfd); | |
719 tfd = -1; | |
720 continue; | |
721 } | |
722 | |
723 break; /* found suitable tuner */ | |
724 } | |
725 } | |
726 | |
727 /* all tuners cannot be used */ | |
728 if(tfd < 0) { | |
729 fprintf(stderr, "Cannot tune to the specified channel\n"); | |
730 return 1; | |
731 } | |
732 } | |
733 | |
734 /* show signal strength */ | |
735 calc_cn(tfd, ptr->type); | |
736 | |
737 /* get recsec */ | |
738 char *rectimestr = argv[optind + 1]; | |
739 | |
740 /* indefinite */ | |
741 if(!strcmp("-", rectimestr)) { | |
742 indefinite = TRUE; | |
743 recsec = -1; | |
744 } | |
745 /* colon */ | |
746 else if(strchr(rectimestr, ':')) { | |
747 int n1, n2, n3; | |
748 if(sscanf(rectimestr, "%d:%d:%d", &n1, &n2, &n3) == 3) | |
749 recsec = n1 * 3600 + n2 * 60 + n3; | |
750 else if(sscanf(rectimestr, "%d:%d", &n1, &n2) == 2) | |
751 recsec = n1 * 3600 + n2 * 60; | |
752 } | |
753 /* HMS */ | |
754 else { | |
755 char *tmpstr; | |
756 char *p1, *p2; | |
757 | |
758 tmpstr = strdup(rectimestr); | |
759 p1 = tmpstr; | |
760 while(*p1 && !isdigit(*p1)) | |
761 p1++; | |
762 | |
763 /* hour */ | |
764 if((p2 = strchr(p1, 'H')) || (p2 = strchr(p1, 'h'))) { | |
765 *p2 = '\0'; | |
766 recsec += atoi(p1) * 3600; | |
767 p1 = p2 + 1; | |
768 while(*p1 && !isdigit(*p1)) | |
769 p1++; | |
770 } | |
771 | |
772 /* minute */ | |
773 if((p2 = strchr(p1, 'M')) || (p2 = strchr(p1, 'm'))) { | |
774 *p2 = '\0'; | |
775 recsec += atoi(p1) * 60; | |
776 p1 = p2 + 1; | |
777 while(*p1 && !isdigit(*p1)) | |
778 p1++; | |
779 } | |
780 | |
781 /* second */ | |
782 recsec += atoi(p1); | |
783 | |
784 free(tmpstr); | |
785 } | |
786 | |
787 /* fprintf(stderr, "recsec = %d\n", recsec); */ | |
788 | 919 |
789 /* open output file */ | 920 /* open output file */ |
790 char *destfile = argv[optind + 2]; | 921 char *destfile = argv[optind + 2]; |
791 if(destfile && !strcmp("-", destfile)) { | 922 if(destfile && !strcmp("-", destfile)) { |
792 use_stdout = TRUE; | 923 use_stdout = TRUE; |
793 wfd = 1; /* stdout */ | 924 tdata.wfd = 1; /* stdout */ |
794 } | 925 } |
795 else { | 926 else { |
796 if(!fileless) { | 927 if(!fileless) { |
797 int status; | 928 int status; |
798 char *path = strdup(argv[optind + 2]); | 929 char *path = strdup(argv[optind + 2]); |
800 status = mkpath(dir, 0777); | 931 status = mkpath(dir, 0777); |
801 if(status == -1) | 932 if(status == -1) |
802 perror("mkpath"); | 933 perror("mkpath"); |
803 free(path); | 934 free(path); |
804 | 935 |
805 wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); | 936 tdata.wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); |
806 if(wfd < 0) { | 937 if(tdata.wfd < 0) { |
807 fprintf(stderr, "Cannot open output file: %s\n", | 938 fprintf(stderr, "Cannot open output file: %s\n", |
808 argv[optind + 2]); | 939 argv[optind + 2]); |
809 return 1; | 940 return 1; |
810 } | 941 } |
811 } | 942 } |
848 perror("connect"); | 979 perror("connect"); |
849 return 1; | 980 return 1; |
850 } | 981 } |
851 } | 982 } |
852 | 983 |
853 /* spawn signal handler thread */ | 984 /* prepare thread data */ |
854 sdata.queue = p_queue; | |
855 sdata.tfd = tfd; | |
856 init_signal_handlers(&signal_thread, &sdata); | |
857 | |
858 /* spawn reader thread */ | |
859 tdata.queue = p_queue; | 985 tdata.queue = p_queue; |
860 tdata.decoder = dec; | 986 tdata.decoder = dec; |
861 tdata.wfd = wfd; | |
862 tdata.sock_data = sockdata; | 987 tdata.sock_data = sockdata; |
988 | |
989 /* spawn signal handler thread */ | |
990 init_signal_handlers(&signal_thread, &tdata); | |
991 | |
992 /* spawn reader thread */ | |
863 tdata.signal_thread = signal_thread; | 993 tdata.signal_thread = signal_thread; |
864 pthread_create(&reader_thread, NULL, reader_func, &tdata); | 994 pthread_create(&reader_thread, NULL, reader_func, &tdata); |
865 | 995 |
996 /* spawn ipc thread */ | |
997 key_t key; | |
998 key = (key_t)getpid(); | |
999 | |
1000 if ((tdata.msqid = msgget(key, IPC_CREAT | 0666)) < 0) { | |
1001 perror("msgget"); | |
1002 } | |
1003 pthread_create(&ipc_thread, NULL, mq_recv, &tdata); | |
1004 | |
866 /* start recording */ | 1005 /* start recording */ |
867 if(ioctl(tfd, START_REC, 0) < 0) { | 1006 if(ioctl(tdata.tfd, START_REC, 0) < 0) { |
868 fprintf(stderr, "Tuner cannot start recording\n"); | 1007 fprintf(stderr, "Tuner cannot start recording\n"); |
869 return 1; | 1008 return 1; |
870 } | 1009 } |
871 | 1010 |
872 fprintf(stderr, "Recording...\n"); | 1011 fprintf(stderr, "Recording...\n"); |
873 | 1012 |
874 time(&start_time); | 1013 time(&tdata.start_time); |
875 | 1014 |
876 /* read from tuner */ | 1015 /* read from tuner */ |
877 while(1) { | 1016 while(1) { |
878 if(f_exit) | 1017 if(f_exit) |
879 break; | 1018 break; |
880 | 1019 |
881 time(&cur_time); | 1020 time(&cur_time); |
882 bufptr = malloc(sizeof(BUFSZ)); | 1021 bufptr = malloc(sizeof(BUFSZ)); |
883 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE); | 1022 bufptr->size = read(tdata.tfd, bufptr->buffer, MAX_READ_SIZE); |
884 if(bufptr->size <= 0) { | 1023 if(bufptr->size <= 0) { |
885 if((cur_time - start_time) >= recsec && !indefinite) { | 1024 if((cur_time - tdata.start_time) >= tdata.recsec && !tdata.indefinite) { |
886 f_exit = TRUE; | 1025 f_exit = TRUE; |
887 enqueue(p_queue, NULL); | 1026 enqueue(p_queue, NULL); |
888 break; | 1027 break; |
889 } | 1028 } |
890 else { | 1029 else { |
892 } | 1031 } |
893 } | 1032 } |
894 enqueue(p_queue, bufptr); | 1033 enqueue(p_queue, bufptr); |
895 | 1034 |
896 /* stop recording */ | 1035 /* stop recording */ |
897 if((cur_time - start_time) >= recsec && !indefinite) { | 1036 time(&cur_time); |
898 ioctl(tfd, STOP_REC, 0); | 1037 if((cur_time - tdata.start_time) >= tdata.recsec && !tdata.indefinite) { |
1038 ioctl(tdata.tfd, STOP_REC, 0); | |
899 /* read remaining data */ | 1039 /* read remaining data */ |
900 while(1) { | 1040 while(1) { |
901 bufptr = malloc(sizeof(BUFSZ)); | 1041 bufptr = malloc(sizeof(BUFSZ)); |
902 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE); | 1042 bufptr->size = read(tdata.tfd, bufptr->buffer, MAX_READ_SIZE); |
903 if(bufptr->size <= 0) { | 1043 if(bufptr->size <= 0) { |
904 f_exit = TRUE; | 1044 f_exit = TRUE; |
905 enqueue(p_queue, NULL); | 1045 enqueue(p_queue, NULL); |
906 break; | 1046 break; |
907 } | 1047 } |
909 } | 1049 } |
910 break; | 1050 break; |
911 } | 1051 } |
912 } | 1052 } |
913 | 1053 |
1054 /* delete message queue*/ | |
1055 msgctl(tdata.msqid, IPC_RMID, NULL); | |
1056 | |
914 pthread_kill(signal_thread, SIGUSR1); | 1057 pthread_kill(signal_thread, SIGUSR1); |
915 | 1058 |
916 /* wait for threads */ | 1059 /* wait for threads */ |
917 pthread_join(reader_thread, NULL); | 1060 pthread_join(reader_thread, NULL); |
918 pthread_join(signal_thread, NULL); | 1061 pthread_join(signal_thread, NULL); |
1062 pthread_join(ipc_thread, NULL); | |
919 | 1063 |
920 /* close tuner */ | 1064 /* close tuner */ |
921 if(ptr->type == CHTYPE_SATELLITE) { | 1065 if(close_tuner(&tdata) != 0) |
922 if(ioctl(tfd, LNB_DISABLE, 0) < 0) { | 1066 return 1; |
923 return 0 ; | |
924 } | |
925 } | |
926 close(tfd); | |
927 | 1067 |
928 /* release queue */ | 1068 /* release queue */ |
929 destroy_queue(p_queue); | 1069 destroy_queue(p_queue); |
930 | 1070 |
931 /* close output file */ | 1071 /* close output file */ |
932 if(!use_stdout) | 1072 if(!use_stdout) |
933 close(wfd); | 1073 close(tdata.wfd); |
934 | 1074 |
935 /* free socket data */ | 1075 /* free socket data */ |
936 if(use_udp) { | 1076 if(use_udp) { |
937 close(sockdata->sfd); | 1077 close(sockdata->sfd); |
938 free(sockdata); | 1078 free(sockdata); |