From: DeltaMikeCharlie <127641886+DeltaMikeCharlie@users.noreply.github.com> Date: Fri, 27 Jun 2025 07:56:47 +0000 (+1000) Subject: Add Season number and Episode number to file name formatting strings. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da9fa60323a972f66ac3adf5800ef78f571fba82;p=thirdparty%2Ftvheadend.git Add Season number and Episode number to file name formatting strings. --- diff --git a/docs/property/autorec_directory.md b/docs/property/autorec_directory.md new file mode 100644 index 000000000..98b832997 --- /dev/null +++ b/docs/property/autorec_directory.md @@ -0,0 +1,3 @@ +**Note:** If the directory name starts with $$, then format +string substitution from the [DVR profile](class/dvrconfig) is also +performed here. \ No newline at end of file diff --git a/docs/property/pathname.md b/docs/property/pathname.md index 452b24eae..bf6f5aec3 100644 --- a/docs/property/pathname.md +++ b/docs/property/pathname.md @@ -11,6 +11,8 @@ Format | Description | Example `$u` | Event subtitle name | Tennis `$m` | Event summary text | Live Tennis Broadcast from Wimbledon `$e` | Event episode name | S02-E06 +`$A` | Event season number | 2 +`$B` | Event episode number | 6 `$c` | Channel name | SkySport `$g` | Content type | Movie : Science fiction `$Q` | Scraper friendly (see below) | Gladiator (2000) @@ -84,6 +86,17 @@ Examples for `$3Q` are: Typically the `$q` and `$Q` formats would be combined with other modifiers to generate a complete filename such as `$q$n.$x`. +The `$B` and `$A` formats also have numeric modifiers to specify when +zero padded values are required. + +For example, with S02-E06: +- `$A` would insert `2` into the file name. +- `$2A` would insert `02` into the file name. +- `$B` would insert `6` into the file name. +- `$3B` would insert `006` into the file name. + +With sufficiently accurate EPG data, the formatting string `$t/Season $A/$2B-$u$n.$x` would produce a recording named `/path/to/recordings/Bones/Season 2/06-The Girl in Suite 2103.ts`. + Even with correct guide information, external scrapers can retrieve incorrect results. A famous example being the detective tv series "Castle" is often incorrectly retrieved as a much earlier tv show diff --git a/docs/property/postprocessor.md b/docs/property/postprocessor.md index 869b69ca1..f02ffb568 100644 --- a/docs/property/postprocessor.md +++ b/docs/property/postprocessor.md @@ -18,6 +18,8 @@ Format | Description | Example value `%u` | Program subtitle | Afternoon `%m` | Program summary | Afternoon fast news `%p` | Program episode | S02.E07 +`%A` | Program season number | 2 +`%B` | Program episode number | 7 `%d` | Program description | News and stories… `%g` | Program content type | Current affairs `%e` | Error message | Aborted by user diff --git a/docs/property/postremove.md b/docs/property/postremove.md index 210cf0997..2c75eba57 100644 --- a/docs/property/postremove.md +++ b/docs/property/postremove.md @@ -16,6 +16,8 @@ Format | Description | Example value `%t` | Program title | News `%s` | Program subtitle | Afternoon `%p` | Program episode | S02.E07 +`%A` | Program season number | 2 +`%B` | Program episode number | 7 `%d` | Program description | News and stories… `%e` | Error message | Aborted by user `%S` | Start time stamp of recording, UNIX epoch | 1224421200 diff --git a/docs/property/preprocessor.md b/docs/property/preprocessor.md index 74730231e..75f98de33 100644 --- a/docs/property/preprocessor.md +++ b/docs/property/preprocessor.md @@ -16,6 +16,8 @@ Format | Description | Example value `%u` | Program subtitle | Afternoon `%m` | Program summary | Afternoon fast news `%p` | Program episode | S02.E07 +`%A` | Program season number | 2 +`%B` | Program episode number | 7 `%d` | Program description | News and stories… `%S` | Start time stamp of recording, UNIX epoch | 1224421200 `%E` | Stop time stamp of recording, UNIX epoch | 1224426600 diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index d7b2f05b5..9258e65ef 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -1075,6 +1075,7 @@ dvr_autorec_entry_class_owner_opts(void *o, uint32_t opts) CLASS_DOC(dvrautorec) PROP_DOC(duplicate_handling) +PROP_DOC(autorec_directory) /* We provide several category drop-downs to make it easy for user * to select several. So abstract the properties away since they @@ -1132,8 +1133,8 @@ const idclass_t dvr_autorec_entry_class = { "subdirectory rules (except the base directory) " "defined in the DVR configuration and puts all " "recordings done by this entry into the " - "subdirectory named here. Note that Format Strings " - "cannot be used here. See Help for more info."), + "subdirectory named here. See Help for more info."), + .doc = prop_doc_autorec_directory, .off = offsetof(dvr_autorec_entry_t, dae_directory), .opts = PO_EXPERT, }, diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index f9f971be7..680e1c36b 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -405,6 +405,58 @@ dvr_sub_uuid(const char *id, const char *fmt, const void *aux, char *tmp, size_t return tmp; } +static const char * +dvr_sub_episode_numeral(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen) +{ +// *id contains the current field format string +// *fmt contains the whole format string + + enum return_numeral_type { + RETURN_SERIES, RETURN_EPISODE + }; + + const dvr_entry_t *de = aux; + size_t id_len = 0; + int return_type = RETURN_SERIES; + signed char output_len = -1; + epg_episode_num_t ep_num; + int print_val = 0; + + if (de->de_bcast == NULL) + return ""; + + id_len = strlen(id); + if (id[id_len-1] == 'B'){ + return_type = RETURN_EPISODE; + } + + if (id_len != 1){ + output_len = atoi(id); + } + + epg_broadcast_get_epnum(de->de_bcast, &ep_num); + + print_val = ep_num.s_num; + if(return_type == RETURN_EPISODE){ + print_val = ep_num.e_num; + } + + if(print_val == 0){ + snprintf(tmp, tmplen, "%s", _("Unknown")); + } + else + { + if(output_len < 1){ + snprintf(tmp, tmplen, "%d", print_val); + } else { + snprintf(tmp, tmplen, "%0*d", output_len, print_val); + } + } + + return tmp; + +} + static const char * dvr_sub_episode(const char *id, const char *fmt, const void *aux, char *tmp, size_t tmplen) { @@ -804,6 +856,26 @@ static htsstr_substitute_t dvr_subs_entry[] = { { .id = ".e", .getval = dvr_sub_episode }, { .id = ",e", .getval = dvr_sub_episode }, { .id = ";e", .getval = dvr_sub_episode }, + { .id = "B", .getval = dvr_sub_episode_numeral }, + { .id = "1B", .getval = dvr_sub_episode_numeral }, + { .id = "2B", .getval = dvr_sub_episode_numeral }, + { .id = "3B", .getval = dvr_sub_episode_numeral }, + { .id = "4B", .getval = dvr_sub_episode_numeral }, + { .id = "5B", .getval = dvr_sub_episode_numeral }, + { .id = "6B", .getval = dvr_sub_episode_numeral }, + { .id = "7B", .getval = dvr_sub_episode_numeral }, + { .id = "8B", .getval = dvr_sub_episode_numeral }, + { .id = "9B", .getval = dvr_sub_episode_numeral }, + { .id = "A", .getval = dvr_sub_episode_numeral }, + { .id = "1A", .getval = dvr_sub_episode_numeral }, + { .id = "2A", .getval = dvr_sub_episode_numeral }, + { .id = "3A", .getval = dvr_sub_episode_numeral }, + { .id = "4A", .getval = dvr_sub_episode_numeral }, + { .id = "5A", .getval = dvr_sub_episode_numeral }, + { .id = "6A", .getval = dvr_sub_episode_numeral }, + { .id = "7A", .getval = dvr_sub_episode_numeral }, + { .id = "8A", .getval = dvr_sub_episode_numeral }, + { .id = "9A", .getval = dvr_sub_episode_numeral }, { .id = "c", .getval = dvr_sub_channel }, { .id = " c", .getval = dvr_sub_channel }, { .id = "-c", .getval = dvr_sub_channel }, @@ -947,6 +1019,8 @@ static htsstr_substitute_t dvr_subs_postproc_entry[] = { { .id = "r", .getval = dvr_sub_errors }, { .id = "R", .getval = dvr_sub_data_errors }, { .id = "Z", .getval = dvr_sub_comment }, + { .id = "B", .getval = dvr_sub_episode_numeral }, + { .id = "A", .getval = dvr_sub_episode_numeral }, { .id = NULL, .getval = NULL } };