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);