📄 subreader.c
字号:
if (sub_format==SUB_INVALID) {mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: Could not determine file format\n");return NULL;} srp=sr+sub_format; mp_msg(MSGT_SUBREADER,MSGL_INFO,"SUB: Detected subtitle file format: %s\n", srp->name); rewind (fd);#ifdef USE_ICONV sub_utf8_prev=sub_utf8; { int l,k; k = -1; if ((l=strlen(filename))>4){ char *exts[] = {".utf", ".utf8", ".utf-8" }; for (k=3;--k>=0;) if (!strcasecmp(filename+(l - strlen(exts[k])), exts[k])){ sub_utf8 = 1; break; } } if (k<0) subcp_open(fd); }#endif sub_num=0;n_max=32; first=(subtitle *)malloc(n_max*sizeof(subtitle)); if(!first){#ifdef USE_ICONV subcp_close(); sub_utf8=sub_utf8_prev;#endif return NULL; } #ifdef USE_SORTSUB sub = (subtitle *)malloc(sizeof(subtitle)); //This is to deal with those formats (AQT & Subrip) which define the end of a subtitle //as the beginning of the following previous_sub_end = 0;#endif while(1){ if(sub_num>=n_max){ n_max+=16; first=realloc(first,n_max*sizeof(subtitle)); }#ifndef USE_SORTSUB sub = &first[sub_num];#endif memset(sub, '\0', sizeof(subtitle)); sub=srp->read(fd,sub); if(!sub) break; // EOF#ifdef USE_ICONV if ((sub!=ERR) && (sub_utf8 & 2)) sub=subcp_recode(sub);#endif#ifdef USE_FRIBIDI if (sub!=ERR) sub=sub_fribidi(sub,sub_utf8);#endif if ( sub == ERR ) {#ifdef USE_ICONV subcp_close();#endif if ( first ) free(first); return NULL; } // Apply any post processing that needs recoding first if ((sub!=ERR) && !sub_no_text_pp && srp->post) srp->post(sub);#ifdef USE_SORTSUB if(!sub_num || (first[sub_num - 1].start <= sub->start)){ first[sub_num].start = sub->start; first[sub_num].end = sub->end; first[sub_num].lines = sub->lines; first[sub_num].alignment = sub->alignment; for(i = 0; i < sub->lines; ++i){ first[sub_num].text[i] = sub->text[i]; } if (previous_sub_end){ first[sub_num - 1].end = previous_sub_end; previous_sub_end = 0; } } else { for(j = sub_num - 1; j >= 0; --j){ first[j + 1].start = first[j].start; first[j + 1].end = first[j].end; first[j + 1].lines = first[j].lines; first[j + 1].alignment = first[j].alignment; for(i = 0; i < first[j].lines; ++i){ first[j + 1].text[i] = first[j].text[i]; } if(!j || (first[j - 1].start <= sub->start)){ first[j].start = sub->start; first[j].end = sub->end; first[j].lines = sub->lines; first[j].alignment = sub->alignment; for(i = 0; i < SUB_MAX_TEXT; ++i){ first[j].text[i] = sub->text[i]; } if (previous_sub_end){ first[j].end = first[j - 1].end; first[j - 1].end = previous_sub_end; previous_sub_end = 0; } break; } } }#endif if(sub==ERR) ++sub_errs; else ++sub_num; // Error vs. Valid } fclose(fd);#ifdef USE_ICONV subcp_close();#endif// printf ("SUB: Subtitle format %s time.\n", uses_time?"uses":"doesn't use"); mp_msg(MSGT_SUBREADER,MSGL_INFO,"SUB: Read %i subtitles", sub_num); if (sub_errs) mp_msg(MSGT_SUBREADER,MSGL_INFO,", %i bad line(s).\n", sub_errs); else mp_msg(MSGT_SUBREADER,MSGL_INFO,".\n"); if(sub_num<=0){ free(first); return NULL; } // we do overlap if the user forced it (suboverlap_enable == 2) or // the user didn't forced no-overlapsub and the format is Jacosub or Ssa. // this is because usually overlapping subtitles are found in these formats, // while in others they are probably result of bad timingif ((suboverlap_enabled == 2) || ((suboverlap_enabled) && ((sub_format == SUB_JACOSUB) || (sub_format == SUB_SSA)))) { adjust_subs_time(first, 6.0, fps, 0, sub_num, uses_time);/*~6 secs AST*/// here we manage overlapping subtitles sub_orig = sub_num; n_first = sub_num; sub_num = 0; second = NULL; // for each subtitle in first[] we deal with its 'block' of // bonded subtitles for (sub_first = 0; sub_first < n_first; ++sub_first) { unsigned long global_start = first[sub_first].start, global_end = first[sub_first].end, local_start, local_end; int lines_to_add = first[sub_first].lines, sub_to_add = 0, **placeholder = NULL, higher_line = 0, counter, start_block_sub = sub_num; char real_block = 1; // here we find the number of subtitles inside the 'block' // and its span interval. this works well only with sorted // subtitles while ((sub_first + sub_to_add + 1 < n_first) && (first[sub_first + sub_to_add + 1].start < global_end)) { ++sub_to_add; lines_to_add += first[sub_first + sub_to_add].lines; if (first[sub_first + sub_to_add].start < global_start) { global_start = first[sub_first + sub_to_add].start; } if (first[sub_first + sub_to_add].end > global_end) { global_end = first[sub_first + sub_to_add].end; } } // we need a structure to keep trace of the screen lines // used by the subs, a 'placeholder' counter = 2 * sub_to_add + 1; // the maximum number of subs derived // from a block of sub_to_add+1 subs placeholder = (int **) malloc(sizeof(int *) * counter); for (i = 0; i < counter; ++i) { placeholder[i] = (int *) malloc(sizeof(int) * lines_to_add); for (j = 0; j < lines_to_add; ++j) { placeholder[i][j] = -1; } } counter = 0; local_end = global_start - 1; do { int ls; // here we find the beginning and the end of a new // subtitle in the block local_start = local_end + 1; local_end = global_end; for (j = 0; j <= sub_to_add; ++j) { if ((first[sub_first + j].start - 1 > local_start) && (first[sub_first + j].start - 1 < local_end)) { local_end = first[sub_first + j].start - 1; } else if ((first[sub_first + j].end > local_start) && (first[sub_first + j].end < local_end)) { local_end = first[sub_first + j].end; } } // here we allocate the screen lines to subs we must // display in current local_start-local_end interval. // if the subs were yet presents in the previous interval // they keep the same lines, otherside they get unused lines for (j = 0; j <= sub_to_add; ++j) { if ((first[sub_first + j].start <= local_end) && (first[sub_first + j].end > local_start)) { unsigned long sub_lines = first[sub_first + j].lines, fragment_length = lines_to_add + 1, tmp = 0; char boolean = 0; int fragment_position = -1; // if this is not the first new sub of the block // we find if this sub was present in the previous // new sub if (counter) for (i = 0; i < lines_to_add; ++i) { if (placeholder[counter - 1][i] == sub_first + j) { placeholder[counter][i] = sub_first + j; boolean = 1; } } if (boolean) continue; // we are looking for the shortest among all groups of // sequential blank lines whose length is greater than or // equal to sub_lines. we store in fragment_position the // position of the shortest group, in fragment_length its // length, and in tmp the length of the group currently // examinated for (i = 0; i < lines_to_add; ++i) { if (placeholder[counter][i] == -1) { // placeholder[counter][i] is part of the current group // of blank lines ++tmp; } else { if (tmp == sub_lines) { // current group's size fits exactly the one we // need, so we stop looking fragment_position = i - tmp; tmp = 0; break; } if ((tmp) && (tmp > sub_lines) && (tmp < fragment_length)) { // current group is the best we found till here, // but is still bigger than the one we are looking // for, so we keep on looking fragment_length = tmp; fragment_position = i - tmp; tmp = 0; } else { // current group doesn't fit at all, so we forget it tmp = 0; } } } if (tmp) { // last screen line is blank, a group ends with it if ((tmp >= sub_lines) && (tmp < fragment_length)) { fragment_position = i - tmp; } } if (fragment_position == -1) { // it was not possible to find free screen line(s) for a subtitle, // usually this means a bug in the code; however we do not overlap mp_msg(MSGT_SUBREADER, MSGL_WARN, "SUB: we could not find a suitable position for an overlapping subtitle\n"); higher_line = SUB_MAX_TEXT + 1; break; } else { for (tmp = 0; tmp < sub_lines; ++tmp) { placeholder[counter][fragment_position + tmp] = sub_first + j; } } } } for (j = higher_line + 1; j < lines_to_add; ++j) { if (placeholder[counter][j] != -1) higher_line = j; else break; } if (higher_line >= SUB_MAX_TEXT) { // the 'block' has too much lines, so we don't overlap the // subtitles second = (subtitle *) realloc(second, (sub_num + sub_to_add + 1) * sizeof(subtitle)); for (j = 0; j <= sub_to_add; ++j) { int ls; memset(&second[sub_num + j], '\0', sizeof(subtitle)); second[sub_num + j].start = first[sub_first + j].start; second[sub_num + j].end = first[sub_first + j].end; second[sub_num + j].lines = first[sub_first + j].lines; second[sub_num + j].alignment = first[sub_first + j].alignment; for (ls = 0; ls < second[sub_num + j].lines; ls++) { second[sub_num + j].text[ls] = strdup(first[sub_first + j].text[ls]); } } sub_num += sub_to_add + 1; sub_first += sub_to_add; real_block = 0; break; } // we read the placeholder structure and create the new // subs. second = (subtitle *) realloc(second, (sub_num + 1) * sizeof(subtitle)); memset(&second[sub_num], '\0', sizeof(subtitle)); second[sub_num].start = local_start; second[sub_num].end = local_end; second[sub_num].alignment = first[sub_first].alignment; n_max = (lines_to_add < SUB_MAX_TEXT) ? lines_to_add : SUB_MAX_TEXT; for (i = 0, j = 0; j < n_max; ++j) { if (placeholder[counter][j] != -1) { int lines = first[placeholder[counter][j]].lines; for (ls = 0; ls < lines; ++ls) { second[sub_num].text[i++] = strdup(first[placeholder[counter][j]].text[ls]); } j += lines - 1; } else { second[sub_num].text[i++] = strdup(" "); } } ++sub_num; ++counter; } while (local_end < global_end); if (real_block) for (i = 0; i < counter; ++i) second[start_block_sub + i].lines = higher_line + 1; counter = 2 * sub_to_add + 1; for (i = 0; i < counter; ++i) { free(placeholder[i]); } free(placeholder); sub_first += sub_to_add; } for (j = sub_orig - 1; j >= 0; --j) { for (i = first[j].lines - 1; i >= 0; --i) { free(first[j].text[i]); } } free(first); return_sub = second;} else { //if(suboverlap_enabled) adjust_subs_time(first, 6.0, fps, 1, sub_num, uses_time);/*~6 secs AST*/ return_sub = first;} if (return_sub == NULL) return NULL; subt_data = (sub_data *)malloc(sizeof(sub_data)); subt_data->filename = filename; subt_data->sub_uses_time = uses_time; subt_data->sub_num = sub_num; subt_data->sub_errs = sub_errs; subt_data->subtitles = return_sub; return subt_data;}#if 0char * strreplace( char * in,char * what,char * whereof ){ int i; char * tmp; if ( ( in == NULL )||( what == NULL )||( whereof == NULL )||( ( tmp=strstr( in,what ) ) == NULL ) ) return NULL; for( i=0;i<strlen( whereof );i++ ) tmp[i]=whereof[i]; if ( strlen( what ) > strlen( whereof ) ) tmp[i]=0; return in;}#endifstatic void strcpy_trim(char *d, char *s){ // skip leading whitespace while (*s && !isalnum(*s)) { s++; } for (;;) { // copy word while (*s && isalnum(*s)) { *d = tolower(*s); s++; d++; } if (*s == 0) break; // trim excess whitespace while (*s && !isalnum(*s)) { s++; } if (*s == 0) break; *d++ = ' '; } *d = 0;} static void strcpy_strip_ext(char *d, char *s){ char *tmp = strrchr(s,'.'); if (!tmp) { strcpy(d, s); return; } else { strncpy(d, s, tmp-s); d[tmp-s] = 0; } while (*d) { *d = tolower(*d); d++; }} static void strcpy_get_ext(char *d, char *s){ char *tmp = strrchr(s,'.'); if (!tmp) { strcpy(d, ""); return; } else { strcpy(d, tmp+1); }}static int whiteonly(char *s){ while (*s) { if (isalnum(*s)) return 0; s++; } return 1;}typedef struct _subfn { int priority; char *fname;} subfn;static int compare_sub_priority(const void *a, const void *b){ if (((subfn*)a)->priority > ((subfn*)b)->priority) { return -1; } else if (((subfn*)a)->priority < ((subfn*)b)->priority) { return 1; } else { return strcoll(((subfn*)a)->fname, ((subfn*)b)->fname); }}char** sub_filenames(char* path, char *fname){ char *f_dir, *f_fname, *f_fname_noext, *f_fname_trim, *tmp, *tmp_sub_id; char *tmp_fname_noext, *tmp_fname_trim, *tmp_fname_ext, *tmpresult; int len, pos, found, i, j; char * sub_exts[] = { "utf", "utf8", "utf-8", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL}; subfn *result; char **result2; int subcnt; FILE *f; DIR *d; struct dirent *de; len = (strlen(fname) > 256 ? strlen(fname) : 256) +(strlen(path) > 256 ? strlen(path) : 256)+2; f_dir = (char*)malloc(len); f_fname = (char*)malloc(len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -