Skip to content

Commit 85eb7a0

Browse files
committed
player/loadfile: boost score for matching season/episode
1 parent 64e30d8 commit 85eb7a0

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

player/loadfile.c

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <ctype.h>
2424
#include <string.h>
2525

26-
// (helpers moved below includes to ensure prototypes are visible)
2726

2827
#include <libavutil/avutil.h>
2928

@@ -1023,6 +1022,85 @@ static double similarity_ratio(const char *a, const char *b)
10231022
return 1.0 - (double)d / (double)m;
10241023
}
10251024

1025+
// Returns true if a season/episode could be parsed.
1026+
// Recognizes common patterns like S01E02, s1e2, or 1x02 (case-insensitive).
1027+
static bool parse_season_episode(const char *path, int *out_season, int *out_episode)
1028+
{
1029+
if (out_season) *out_season = -1;
1030+
if (out_episode) *out_episode = -1;
1031+
if (!path)
1032+
return false;
1033+
1034+
// Work on a lowercase copy of the basename to simplify matching.
1035+
void *ta = talloc_new(NULL);
1036+
const char *base = mp_basename(path);
1037+
char *s = talloc_strdup(ta, base);
1038+
for (int i = 0; s[i]; i++)
1039+
s[i] = tolower((unsigned char)s[i]);
1040+
1041+
int season = -1, episode = -1;
1042+
1043+
// Try SxxEyy pattern
1044+
for (int i = 0; s[i]; i++) {
1045+
if (s[i] == 's') {
1046+
int j = i + 1;
1047+
int val_s = 0, num_s = 0;
1048+
while (isdigit((unsigned char)s[j])) {
1049+
val_s = val_s * 10 + (s[j] - '0');
1050+
num_s++; j++;
1051+
}
1052+
if (num_s > 0 && s[j] == 'e') {
1053+
j++;
1054+
int val_e = 0, num_e = 0;
1055+
while (isdigit((unsigned char)s[j])) {
1056+
val_e = val_e * 10 + (s[j] - '0');
1057+
num_e++; j++;
1058+
}
1059+
if (num_e > 0) {
1060+
season = val_s;
1061+
episode = val_e;
1062+
break;
1063+
}
1064+
}
1065+
}
1066+
}
1067+
1068+
// Fallback: N x M pattern (e.g., 1x02)
1069+
if (season < 0 || episode < 0) {
1070+
for (int i = 0; s[i]; i++) {
1071+
if (isdigit((unsigned char)s[i])) {
1072+
int j = i;
1073+
int val_s = 0, num_s = 0;
1074+
while (isdigit((unsigned char)s[j])) {
1075+
val_s = val_s * 10 + (s[j] - '0');
1076+
num_s++; j++;
1077+
}
1078+
if (num_s > 0 && s[j] == 'x') {
1079+
j++;
1080+
int val_e = 0, num_e = 0;
1081+
while (isdigit((unsigned char)s[j])) {
1082+
val_e = val_e * 10 + (s[j] - '0');
1083+
num_e++; j++;
1084+
}
1085+
if (num_e > 0) {
1086+
season = val_s;
1087+
episode = val_e;
1088+
break;
1089+
}
1090+
}
1091+
}
1092+
}
1093+
}
1094+
1095+
talloc_free(ta);
1096+
if (season >= 0 && episode >= 0) {
1097+
if (out_season) *out_season = season;
1098+
if (out_episode) *out_episode = episode;
1099+
return true;
1100+
}
1101+
return false;
1102+
}
1103+
10261104
// to be run on a worker thread, locked (temporarily unlocks core)
10271105
static void open_external_files(struct MPContext *mpctx, char **files,
10281106
enum stream_type filter)
@@ -1064,7 +1142,10 @@ void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel)
10641142
if (opts->sub_auto == 3) {
10651143
void *selctx = talloc_new(tmp);
10661144
char *movie_norm = normalize_base_name(selctx, mpctx->filename);
1145+
int mv_season = -1, mv_episode = -1;
1146+
bool mv_has_se = parse_season_episode(mpctx->filename, &mv_season, &mv_episode);
10671147
double best_score = -1.0;
1148+
int best_match_se = 0; // 1 if S/E match; prefer this over plain similarity
10681149
for (int i = 0; list && list[i].fname; i++) {
10691150
struct subfn *e = &list[i];
10701151
if (e->type != STREAM_SUB)
@@ -1083,7 +1164,15 @@ void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel)
10831164
continue;
10841165
char *cand_norm = normalize_base_name(selctx, e->fname);
10851166
double score = similarity_ratio(movie_norm, cand_norm);
1086-
if (score > best_score) {
1167+
int cand_season = -1, cand_episode = -1;
1168+
int match_se = 0;
1169+
if (mv_has_se && parse_season_episode(e->fname, &cand_season, &cand_episode)) {
1170+
if (mv_season == cand_season && mv_episode == cand_episode)
1171+
match_se = 1;
1172+
}
1173+
// Prefer exact S/E match first, then similarity score.
1174+
if (match_se > best_match_se || (match_se == best_match_se && score > best_score)) {
1175+
best_match_se = match_se;
10871176
best_score = score;
10881177
best_sub_index = i;
10891178
}

0 commit comments

Comments
 (0)