comparison subreader.c @ 8207:467ffae428b0

I recently sent a patch for a new subtitles format, JACOsub. Since then I found a better definition of jacosub standard, and this patch is the result. It supports timeresolutions changes and shifts. Salvatore Falco <sfalco@studenti.ing.uniroma1.it>
author arpi
date Sat, 16 Nov 2002 03:25:37 +0000
parents 72647ce8471f
children ad75993b8deb
comparison
equal deleted inserted replaced
8206:72647ce8471f 8207:467ffae428b0
603 return current; 603 return current;
604 } 604 }
605 605
606 subtitle *sub_read_line_jacosub(FILE * fd, subtitle * current) 606 subtitle *sub_read_line_jacosub(FILE * fd, subtitle * current)
607 { 607 {
608 char commands[LINE_LEN], line1[LINE_LEN], line2[LINE_LEN], 608 char line1[LINE_LEN], line2[LINE_LEN], directive[LINE_LEN], *p, *q;
609 text[LINE_LEN], *p, *q; 609 unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0;
610 int a1, a2, a3, a4, b1, b2, b3, b4, comment = 0; 610 static unsigned jacoTimeres = 30;
611 unsigned short directive = 0; 611 static int jacoShift = 0;
612 612
613 bzero(current, sizeof(subtitle)); 613 bzero(current, sizeof(subtitle));
614 bzero(commands, sizeof(char) * LINE_LEN); 614 bzero(line1, LINE_LEN);
615 bzero(line1, sizeof(char) * LINE_LEN); 615 bzero(line2, LINE_LEN);
616 bzero(line2, sizeof(char) * LINE_LEN); 616 bzero(directive, LINE_LEN);
617 while (!current->text[0]) { 617 while (!current->text[0]) {
618 if (!fgets(line1, LINE_LEN, fd)) 618 if (!fgets(line1, LINE_LEN, fd)) {
619 return NULL; 619 return NULL;
620 }
620 if (sscanf 621 if (sscanf
621 (line1, "%d:%d:%d.%d %d:%d:%d.%d %[^\n\r]", &a1, &a2, &a3, &a4, 622 (line1, "%u:%u:%u.%u %u:%u:%u.%u %[^\n\r]", &a1, &a2, &a3, &a4,
622 &b1, &b2, &b3, &b4, line2) < 9) 623 &b1, &b2, &b3, &b4, line2) < 9) {
623 continue; 624 if (sscanf(line1, "@%u @%u %[^\n\r]", &a4, &b4, line2) < 3) {
624 //a Jacosub script *may* have some commands before the text, so let's recognize them 625 if (line1[0] == '#') {
625 switch (toupper(line2[0])) { 626 int hours = 0, minutes = 0, seconds, delta, inverter =
626 case 'C': 627 1;
627 switch (toupper(line2[1])) { 628 unsigned units = jacoShift;
628 case 'F': 629 switch (toupper(line1[1])) {
629 case 'P': 630 case 'S':
630 case 'S': 631 if (isalpha(line1[2])) {
631 case 'B': 632 delta = 6;
632 if (isdigit(line2[2])) 633 } else {
633 directive = 1; 634 delta = 2;
635 }
636 if (sscanf(&line1[delta], "%d", &hours)) {
637 if (hours < 0) {
638 hours *= -1;
639 inverter = -1;
640 }
641 if (sscanf(&line1[delta], "%*d:%d", &minutes)) {
642 if (sscanf
643 (&line1[delta], "%*d:%*d:%d",
644 &seconds)) {
645 sscanf(&line1[delta], "%*d:%*d:%*d.%d",
646 &units);
647 } else {
648 hours = 0;
649 sscanf(&line1[delta], "%d:%d.%d",
650 &minutes, &seconds, &units);
651 minutes *= inverter;
652 }
653 } else {
654 hours = minutes = 0;
655 sscanf(&line1[delta], "%d.%d", &seconds,
656 &units);
657 seconds *= inverter;
658 }
659 jacoShift =
660 ((hours * 3600 + minutes * 60 +
661 seconds) * jacoTimeres +
662 units) * inverter;
663 }
664 break;
665 case 'T':
666 if (isalpha(line1[2])) {
667 delta = 8;
668 } else {
669 delta = 2;
670 }
671 sscanf(&line1[delta], "%u", &jacoTimeres);
672 break;
673 }
674 }
675 continue;
676 } else {
677 current->start =
678 (unsigned long) ((a4 + jacoShift) * 100.0 /
679 jacoTimeres);
680 current->end =
681 (unsigned long) ((b4 + jacoShift) * 100.0 /
682 jacoTimeres);
634 } 683 }
635 break; 684 } else {
636 case 'D': 685 current->start =
637 if ((line2[1] == ' ') || isdigit(line2[1])) 686 (unsigned
638 directive = 1; 687 long) (((a1 * 3600 + a2 * 60 + a3) * jacoTimeres + a4 +
639 // special case 688 jacoShift) * 100.0 / jacoTimeres);
640 if (toupper(line2[1]) == 'C') 689 current->end =
641 directive = 1; 690 (unsigned
642 break; 691 long) (((b1 * 3600 + b2 * 60 + b3) * jacoTimeres + b4 +
643 case 'E': 692 jacoShift) * 100.0 / jacoTimeres);
644 switch (toupper(line2[1])) { 693 }
645 case 'D': 694 current->lines = 0;
646 case 'P': 695 p = line2;
647 if (isdigit(line2[2])) 696 while ((*p == ' ') || (*p == '\t')) {
648 directive = 1; 697 ++p;
649 break; 698 }
650 case 'I': 699 if (isalpha(*p)||*p == '[') {
651 if ((toupper(line2[2]) == 'O') && (isdigit(line2[3]))) 700 int cont, jLength;
652 directive = 1; 701
653 break; 702 if (sscanf(p, "%s %[^\n\r]", directive, line1) < 2)
654 case 'R': 703 return (subtitle *) ERR;
655 if ((toupper(line2[2]) == 'D') && (isdigit(line2[3]))) 704 jLength = strlen(directive);
656 directive = 1; 705 for (cont = 0; cont < jLength; ++cont) {
657 break; 706 if (isalpha(*(directive + cont)))
658 case 'W': 707 *(directive + cont) = toupper(*(directive + cont));
659 if ((toupper(line2[2]) == 'L')
660 || (toupper(line2[2]) == 'R'))
661 directive = 1;
662 break;
663 } 708 }
664 break; 709 if ((strstr(directive, "RDB") != NULL)
665 case 'F': 710 || (strstr(directive, "RDC") != NULL)
666 if (isdigit(line2[1])) 711 || (strstr(directive, "RLB") != NULL)
667 directive = 1; 712 || (strstr(directive, "RLG") != NULL)) {
668 else 713 continue;
669 switch (toupper(line2[1])) {
670 case 'O':
671 if (isdigit(line2[2]))
672 directive = 1;
673 break;
674 case 'S':
675 directive = 1;
676 }
677 break;
678 case 'G':
679 if ((line2[1] == 'G') && (isdigit(line2[2])))
680 directive = 2;
681 break;
682 case 'H':
683 switch (toupper(line2[1])) {
684 case 'L':
685 case 'R':
686 if (isdigit(line2[2]))
687 directive = 1;
688 } 714 }
689 break; 715 strcpy(line2, line1);
690 case 'J': 716 p = line2;
691 switch (toupper(line2[1])) { 717 }
692 case 'B': 718 for (q = line1; (!eol(*p)) && (current->lines < SUB_MAX_TEXT);
693 if (toupper(line2[2]) == 'C') 719 ++p) {
694 directive = 1;
695 break;
696 case 'C':
697 case 'L':
698 case 'R':
699 directive = 1;
700 break;
701 case 'F':
702 if ((line2[2] == ':') && (toupper(line2[3]) == 'L'))
703 directive = 1;
704 }
705 break;
706 case 'R':
707 if (((toupper(line2[1]) == 'D') && (toupper(line2[2]) == 'B'))
708 || ((toupper(line2[1]) == 'D')
709 && (toupper(line2[2]) == 'C'))
710 || ((toupper(line2[1]) == 'L')
711 && (toupper(line2[2]) == 'B')))
712 directive = 2;
713 break;
714 case 'V':
715 switch (toupper(line2[1])) {
716 case 'A':
717 case 'B':
718 case 'M':
719 case 'T':
720 case 'U':
721 directive = 1;
722 break;
723 case 'L':
724 case 'P':
725 if (isdigit(line2[2]))
726 directive = 1;
727 }
728 break;
729 case '[':
730 directive = 1;
731 break;
732 case '~':
733 directive = 2;
734 }
735 if (directive == 1) {
736 strcpy(line1, line2);
737 sscanf(line1, "%s %[^\n\r]", commands, line2);
738 } else if (directive == 2) {
739 continue;
740 }
741 current->start = a1 * 360000 + a2 * 6000 + a3 * 100 + a4;
742 current->end = b1 * 360000 + b2 * 6000 + b3 * 100 + b4;
743 current->lines = 0;
744
745 q = text;
746 p = line2;
747 while ((*p) == ' ')
748 p++;
749
750 for (; (!eol(*p)) && (current->lines < SUB_MAX_TEXT); p++) {
751 switch (*p) { 720 switch (*p) {
752 case '{': 721 case '{':
753 comment++; 722 comment++;
754 break; 723 break;
755 case '}': 724 case '}':
756 comment--; 725 if (comment) {
757 //the next to get rid of a blank after the comment 726 --comment;
758 if ((*(p + 1)) == ' ') 727 //the next line to get rid of a blank after the comment
759 p++; 728 if ((*(p + 1)) == ' ')
729 p++;
730 }
731 break;
732 case '~':
733 if (!comment) {
734 *q = ' ';
735 ++q;
736 }
737 break;
738 case ' ':
739 case '\t':
740 if ((*(p + 1) == ' ') || (*(p + 1) == '\t'))
741 break;
742 if (!comment) {
743 *q = ' ';
744 ++q;
745 }
760 break; 746 break;
761 case '\\': 747 case '\\':
762 if (*(p + 1) == 'n') { 748 if (*(p + 1) == 'n') {
763 *q = '\0'; 749 *q = '\0';
764 q = text; 750 q = line1;
765 current->text[current->lines++] = strdup(text); 751 current->text[current->lines++] = strdup(line1);
766 p++; 752 ++p;
767 break; 753 break;
768 } else if (toupper(*(p + 1)) == 'C') { 754 }
769 p++; 755 if ((toupper(*(p + 1)) == 'C')
770 p++; 756 || (toupper(*(p + 1)) == 'F')) {
757 ++p,++p;
771 break; 758 break;
772 } else if ((toupper(*(p + 1)) == 'I') 759 }
773 || (toupper(*(p + 1)) == 'B') 760 if ((*(p + 1) == 'B') || (*(p + 1) == 'b') || (*(p + 1) == 'D') || //actually this means "insert current date here"
774 || (toupper(*(p + 1)) == 'N')) { 761 (*(p + 1) == 'I') || (*(p + 1) == 'i') || (*(p + 1) == 'N') || (*(p + 1) == 'T') || //actually this means "insert current time here"
775 p++; 762 (*(p + 1) == 'U') || (*(p + 1) == 'u')) {
763 ++p;
776 break; 764 break;
765 }
766 if ((*(p + 1) == '\\') ||
767 (*(p + 1) == '~') || (*(p + 1) == '{')) {
768 ++p;
777 } else if (eol(*(p + 1))) { 769 } else if (eol(*(p + 1))) {
778 if (!fgets(line1, LINE_LEN, fd)) 770 if (!fgets(directive, LINE_LEN, fd))
779 return NULL; 771 return NULL;
780 trail_space(line1); 772 trail_space(directive);
781 p = line1; 773 strncat(line2, directive,
774 (LINE_LEN > 511) ? LINE_LEN : 511);
775 break;
782 } 776 }
783 default: 777 default:
784 if (!comment) { 778 if (!comment) {
785 *q = *p; 779 *q = *p;
786 q++; 780 ++q;
787 } 781 }
788 } 782 } //-- switch
789 } 783 } //-- for
790 *q = '\0'; 784 *q = '\0';
791 current->text[current->lines] = strdup(text); 785 current->text[current->lines] = strdup(line1);
792 } 786 } //-- while
793 current->lines++; 787 current->lines++;
794 return current; 788 return current;
795 } 789 }
796 790
797 int sub_autodetect (FILE *fd) { 791 int sub_autodetect (FILE *fd) {
815 if (sscanf (line, "{T %d:%d:%d:%d",&i, &i, &i, &i)) 809 if (sscanf (line, "{T %d:%d:%d:%d",&i, &i, &i, &i))
816 {sub_uses_time=1;return SUB_SUBVIEWER2;} 810 {sub_uses_time=1;return SUB_SUBVIEWER2;}
817 if (strstr (line, "<SAMI>")) 811 if (strstr (line, "<SAMI>"))
818 {sub_uses_time=1; return SUB_SAMI;} 812 {sub_uses_time=1; return SUB_SAMI;}
819 if (sscanf(line, "%d:%d:%d.%d %d:%d:%d.%d", &i, &i, &i, &i, &i, &i, &i, &i) == 8) 813 if (sscanf(line, "%d:%d:%d.%d %d:%d:%d.%d", &i, &i, &i, &i, &i, &i, &i, &i) == 8)
814 {sub_uses_time = 1; return SUB_JACOSUB;}
815 if (sscanf(line, "@%d @%d", &i, &i) == 2)
820 {sub_uses_time = 1; return SUB_JACOSUB;} 816 {sub_uses_time = 1; return SUB_JACOSUB;}
821 if (sscanf (line, "%d:%d:%d:", &i, &i, &i )==3) 817 if (sscanf (line, "%d:%d:%d:", &i, &i, &i )==3)
822 {sub_uses_time=1;return SUB_VPLAYER;} 818 {sub_uses_time=1;return SUB_VPLAYER;}
823 if (sscanf (line, "%d:%d:%d ", &i, &i, &i )==3) 819 if (sscanf (line, "%d:%d:%d ", &i, &i, &i )==3)
824 {sub_uses_time=1;return SUB_VPLAYER;} 820 {sub_uses_time=1;return SUB_VPLAYER;}