9 #include "sub/find_subfiles.h"
12 static void strcpy_trim(char *d
, char *s
)
14 // skip leading whitespace
15 while (*s
&& isspace(*s
)) {
20 while (*s
&& !isspace(*s
)) {
26 // trim excess whitespace
27 while (*s
&& isspace(*s
)) {
37 static void strcpy_strip_ext(char *d
, char *s
)
39 char *tmp
= strrchr(s
, '.');
53 static void strcpy_get_ext(char *d
, char *s
)
55 char *tmp
= strrchr(s
, '.');
64 static int whiteonly(char *s
)
74 typedef struct subfn
{
79 static int compare_sub_priority(const void *a
, const void *b
)
81 if (((const subfn
*)a
)->priority
> ((const subfn
*)b
)->priority
) {
83 } else if (((const subfn
*)a
)->priority
< ((const subfn
*)b
)->priority
) {
86 return strcoll(((const subfn
*)a
)->fname
, ((const subfn
*)b
)->fname
);
91 * @brief Append all the subtitles in the given path matching fname
92 * @param slist pointer to the subtitles list tallocated
93 * @param nsub pointer to the number of subtitles
94 * @param path Look for subtitles in this directory
95 * @param fname Subtitle filename (pattern)
96 * @param limit_fuzziness Ignore flag when sub_fuziness == 2
98 static void append_dir_subtitles(struct subfn
**slist
, int *nsub
,
99 struct bstr path
, const char *fname
,
102 char *f_fname
, *f_fname_noext
, *f_fname_trim
, *tmp
, *tmp_sub_id
;
103 char *tmp_fname_noext
, *tmp_fname_trim
, *tmp_fname_ext
, *tmpresult
;
106 char *sub_exts
[] = {"utf", "utf8", "utf-8", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL
};
112 len
= (strlen(fname
) > 256 ? strlen(fname
) : 256)
113 + (path
.len
> 256 ? path
.len
: 256) + 2;
115 f_fname
= mp_basename(fname
);
116 f_fname_noext
= malloc(len
);
117 f_fname_trim
= malloc(len
);
119 tmp_fname_noext
= malloc(len
);
120 tmp_fname_trim
= malloc(len
);
121 tmp_fname_ext
= malloc(len
);
123 tmpresult
= malloc(len
);
125 strcpy_strip_ext(f_fname_noext
, f_fname
);
126 strcpy_trim(f_fname_trim
, f_fname_noext
);
128 /* The code using sub language here is broken - it assumes strict
129 * "videoname languagename" syntax for the subtitle file, which is
130 * very unlikely to match especially if language name uses "en,de"
134 if (dvdsub_lang
&& !whiteonly(dvdsub_lang
)) {
135 tmp_sub_id
= malloc(strlen(dvdsub_lang
) + 1);
136 strcpy_trim(tmp_sub_id
, dvdsub_lang
);
141 // 1 = any subtitle file
142 // 2 = any sub file containing movie name
143 // 3 = sub file containing movie name and the lang extension
144 char *path0
= bstrdup0(NULL
, path
);
148 mp_msg(MSGT_SUBREADER
, MSGL_INFO
, "Load subtitles in %.*s\n", BSTR_P(path
));
149 while ((de
= readdir(d
))) {
150 // retrieve various parts of the filename
151 strcpy_strip_ext(tmp_fname_noext
, de
->d_name
);
152 strcpy_get_ext(tmp_fname_ext
, de
->d_name
);
153 strcpy_trim(tmp_fname_trim
, tmp_fname_noext
);
155 // does it end with a subtitle extension?
159 for (i
= ((sub_cp
&& strncasecmp(sub_cp
, "enca", 4) != 0) ? 3 : 0); sub_exts
[i
]; i
++) {
161 for (i
= (sub_cp
? 3 : 0); sub_exts
[i
]; i
++) {
164 for (i
= 0; sub_exts
[i
]; i
++) {
166 if (strcasecmp(sub_exts
[i
], tmp_fname_ext
) == 0) {
172 // we have a (likely) subtitle file
175 if (!prio
&& tmp_sub_id
) {
176 sprintf(tmpresult
, "%s %s", f_fname_trim
, tmp_sub_id
);
177 if (strcmp(tmp_fname_trim
, tmpresult
) == 0 && sub_match_fuzziness
>= 1) {
178 // matches the movie name + lang extension
182 if (!prio
&& strcmp(tmp_fname_trim
, f_fname_trim
) == 0) {
183 // matches the movie name
186 if (!prio
&& (tmp
= strstr(tmp_fname_trim
, f_fname_trim
)) && sub_match_fuzziness
>= 1) {
187 // contains the movie name
188 tmp
+= strlen(f_fname_trim
);
189 if (tmp_sub_id
&& strstr(tmp
, tmp_sub_id
)) {
190 // with sub_id specified prefer localized subtitles
192 } else if ((tmp_sub_id
== NULL
) && whiteonly(tmp
)) {
193 // without sub_id prefer "plain" name
196 // with no localized subs found, try any else instead
201 // doesn't contain the movie name
202 // don't try in the mplayer subtitle directory
203 if (!limit_fuzziness
&& sub_match_fuzziness
>= 2) {
208 mp_msg(MSGT_SUBREADER
, MSGL_DBG2
, "Potential sub file: "
209 "\"%s\" Priority: %d\n", de
->d_name
, prio
);
213 if (i
< 3) // prefer UTF-8 coded
216 char *subpath
= mp_path_join(*slist
, path
, BSTR(de
->d_name
));
217 if ((f
= fopen(subpath
, "rt"))) {
218 MP_GROW_ARRAY(*slist
, *nsub
);
219 struct subfn
*sub
= *slist
+ (*nsub
)++;
222 sub
->priority
= prio
;
223 sub
->fname
= subpath
;
225 talloc_free(subpath
);
237 free(tmp_fname_noext
);
238 free(tmp_fname_trim
);
244 char **find_text_subtitles(const char *fname
)
246 struct subfn
*slist
= talloc_array_ptrtype(NULL
, slist
, 1);
249 // Load subtitles from current media directory
250 append_dir_subtitles(&slist
, &n
, mp_dirname(fname
), fname
, 0);
252 // Load subtitles in ~/.mplayer/sub limiting sub fuzziness
253 char *mp_subdir
= get_path("sub/");
255 append_dir_subtitles(&slist
, &n
, BSTR(mp_subdir
), fname
, 1);
258 // Sort subs by priority and append them
259 qsort(slist
, n
, sizeof(*slist
), compare_sub_priority
);
261 char **subnames
= talloc_array_ptrtype(NULL
, subnames
, n
);
262 for (int i
= 0; i
< n
; i
++)
263 subnames
[i
] = talloc_strdup(subnames
, slist
[i
].fname
);
269 char **find_vob_subtitles(const char *fname
)
271 char **vobs
= talloc_array_ptrtype(NULL
, vobs
, 1);
274 // Potential vobsub in the media directory
275 struct bstr bname
= BSTR(mp_basename(fname
));
276 int pdot
= bstrrchr(bname
, '.');
279 vobs
[n
++] = mp_path_join(vobs
, mp_dirname(fname
), bname
);
281 // Potential vobsub in ~/.mplayer/sub
282 char *mp_subdir
= get_path("sub/");
284 MP_GROW_ARRAY(vobs
, n
);
285 vobs
[n
++] = mp_path_join(vobs
, BSTR(mp_subdir
), bname
);
289 MP_RESIZE_ARRAY(NULL
, vobs
, n
);