From: Jaroslav Kysela Date: Tue, 26 May 2015 19:38:30 +0000 (+0200) Subject: DVR: rewrite postproc spawn substitution with str_substitute(), add %O, %s %p formatters X-Git-Tag: v4.2.1~2455 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5faf8e652a8c85f6f0786d2e828db5a3ac299c58;p=thirdparty%2Ftvheadend.git DVR: rewrite postproc spawn substitution with str_substitute(), add %O, %s %p formatters --- diff --git a/docs/html/config_dvr.html b/docs/html/config_dvr.html index 75188ea64..f0a27403a 100644 --- a/docs/html/config_dvr.html +++ b/docs/html/config_dvr.html @@ -74,8 +74,11 @@ %fFull path to recording/home/user/Videos/News.mkv %bBasename of recordingNews.mkv %cChannel nameBBC world + %OOwner of this recordinguser %CWho created this recordinguser %tProgram titleNews + %sProgram subtitleAfternoon + %pProgram episodeS02.E07 %dProgram descriptionNews and stories... %eError messageAborted by user %SStart time stamp of recording, UNIX epoch1224421200 diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index c633ac880..78d132954 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -246,6 +246,11 @@ static const char *dvr_sub_subtitle(const char *id, const void *aux) return dvr_do_prefix(id, lang_str_get(((dvr_entry_t *)aux)->de_subtitle, NULL)); } +static const char *dvr_sub_description(const char *id, const void *aux) +{ + return dvr_do_prefix(id, lang_str_get(((dvr_entry_t *)aux)->de_desc, NULL)); +} + static const char *dvr_sub_episode(const char *id, const void *aux) { const dvr_entry_t *de = aux; @@ -264,6 +269,35 @@ static const char *dvr_sub_channel(const char *id, const void *aux) return dvr_do_prefix(id, DVR_CH_NAME((dvr_entry_t *)aux)); } +static const char *dvr_sub_owner(const char *id, const void *aux) +{ + return dvr_do_prefix(id, ((dvr_entry_t *)aux)->de_owner); +} + +static const char *dvr_sub_creator(const char *id, const void *aux) +{ + return dvr_do_prefix(id, ((dvr_entry_t *)aux)->de_creator); +} + +static const char *dvr_sub_last_error(const char *id, const void *aux) +{ + return dvr_do_prefix(id, streaming_code2txt(((dvr_entry_t *)aux)->de_last_error)); +} + +static const char *dvr_sub_start(const char *id, const void *aux) +{ + char buf[16]; + snprintf(buf, sizeof(buf), "%"PRItime_t, (time_t)dvr_entry_get_start_time((dvr_entry_t *)aux)); + return dvr_do_prefix(id, buf); +} + +static const char *dvr_sub_stop(const char *id, const void *aux) +{ + char buf[16]; + snprintf(buf, sizeof(buf), "%"PRItime_t, (time_t)dvr_entry_get_stop_time((dvr_entry_t *)aux)); + return dvr_do_prefix(id, buf); +} + static str_substitute_t dvr_subs_entry[] = { { .id = "t", .getval = dvr_sub_title }, { .id = " t", .getval = dvr_sub_title }, @@ -385,6 +419,34 @@ static str_substitute_t dvr_subs_tally[] = { { .id = NULL, .getval = NULL } }; +static str_substitute_t dvr_subs_postproc_entry[] = { + { .id = "t", .getval = dvr_sub_title }, + { .id = "s", .getval = dvr_sub_subtitle }, + { .id = "p", .getval = dvr_sub_episode }, + { .id = "d", .getval = dvr_sub_description }, + { .id = "c", .getval = dvr_sub_channel }, + { .id = "e", .getval = dvr_sub_last_error }, + { .id = "C", .getval = dvr_sub_creator }, + { .id = "O", .getval = dvr_sub_owner }, + { .id = "S", .getval = dvr_sub_start }, + { .id = "E", .getval = dvr_sub_stop }, + { .id = NULL, .getval = NULL } +}; + +static const char *dvr_sub_basename(const char *id, const void *aux) +{ + static char buf[PATH_MAX]; + strncpy(buf, (const char *)aux, sizeof(buf)); + buf[sizeof(buf)-1] = '\0'; + return basename(buf); +} + +static str_substitute_t dvr_subs_postproc_filename[] = { + { .id = "f", .getval = dvr_sub_str }, + { .id = "b", .getval = dvr_sub_basename }, + { .id = NULL, .getval = NULL } +}; + static char *dvr_find_last_path_component(char *path) { char *res, *p; @@ -464,7 +526,7 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) while (*fmtstr == '/') fmtstr++; - /* Substitute DVR entry fields */ + /* Substitute DVR entry formatters */ str_substitute(fmtstr, path + l, sizeof(path) - l, '$', dvr_subs_entry, de); /* Own directory? */ @@ -486,7 +548,7 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) snprintf(path + l + j, sizeof(path) - l + j, "/%s", filename); } - /* Substitute time fields */ + /* Substitute time formatters */ str_substitute(path + l, filename, sizeof(filename), '%', dvr_subs_time, &tm); /* Substitute extension */ @@ -949,57 +1011,33 @@ dvr_thread(void *aux) return NULL; } - /** * */ static void dvr_spawn_postproc(dvr_entry_t *de, const char *dvr_postproc) { - const char *fmap[256], *filename; + char buf1[2048], *buf2; + const char *filename; char **args; - char start[16]; - char stop[16]; - char *fbasename; /* filename dup for basename */ - int i; - args = htsstr_argsplit(dvr_postproc); + filename = dvr_get_filename(de); + if (filename == NULL) + return; + + /* Substitute DVR entry formatters */ + str_substitute(dvr_postproc, buf1, sizeof(buf1), '%', dvr_subs_postproc_entry, de); + buf2 = tvh_strdupa(buf1); + /* Substitute filename formatters */ + str_substitute(buf2, buf1, sizeof(buf1), '%', dvr_subs_postproc_filename, filename); + + args = htsstr_argsplit(buf1); /* no arguments at all */ if(!args[0]) { htsstr_argsplit_free(args); return; } - filename = dvr_get_filename(de); - if (filename == NULL) - return; - - fbasename = tvh_strdupa(filename); - snprintf(start, sizeof(start), "%"PRItime_t, (time_t)dvr_entry_get_start_time(de)); - snprintf(stop, sizeof(stop), "%"PRItime_t, (time_t)dvr_entry_get_stop_time(de)); - - memset(fmap, 0, sizeof(fmap)); - fmap['f'] = filename; /* full path to recoding */ - fmap['b'] = basename(fbasename); /* basename of recoding */ - fmap['c'] = DVR_CH_NAME(de); /* channel name */ - fmap['C'] = de->de_creator; /* user who created this recording */ - fmap['t'] = lang_str_get(de->de_title, NULL); /* program title */ - fmap['d'] = lang_str_get(de->de_desc, NULL); /* program description */ - /* error message, empty if no error (FIXME:?) */ - fmap['e'] = tvh_strdupa(streaming_code2txt(de->de_last_error)); - fmap['S'] = start; /* start time, unix epoch */ - fmap['E'] = stop; /* stop time, unix epoch */ - // TODO: brand, season - - /* format arguments */ - for(i = 0; args[i]; i++) { - char *s; - - s = htsstr_format(args[i], fmap); - free(args[i]); - args[i] = s; - } - spawnv(args[0], (void *)args, NULL, 1, 1); htsstr_argsplit_free(args); diff --git a/src/htsstr.c b/src/htsstr.c index 9671eea11..9be4e3a57 100644 --- a/src/htsstr.c +++ b/src/htsstr.c @@ -24,7 +24,6 @@ static void htsstr_argsplit_add(char ***argv, int *argc, char *s); -static int htsstr_format0(const char *str, char *out, const char **map); char * hts_strndup(const char *src, size_t len) @@ -34,7 +33,6 @@ hts_strndup(const char *src, size_t len) return memcpy(r, src, len); } - char * htsstr_unescape(char *str) { char *s; @@ -148,48 +146,3 @@ htsstr_argsplit_free(char **argv) { free(argv); } - -static int -htsstr_format0(const char *str, char *out, const char **map) { - const char *s = str; - const char *f; - int n = 0; - - while(*s) { - switch(*s) { - case '%': - f = map[(unsigned char)*(s + 1)]; - if(*(s + 1) != '%' && f) { - s += 2; /* skip %f * */ - if(out) - strcpy(&out[n], f); - n += strlen(f); - break; - } - /* fallthru */ - default: - if(out) - out[n] = *s; - s++; - n++; - break; - } - } - - if(out) - out[n] = '\0'; - - return n + 1; /* + \0 */ -} - -char * -htsstr_format(const char *str, const char **map) -{ - char *s; - - s = malloc(htsstr_format0(str, NULL, map)); - htsstr_format0(str, s, map); - - return s; -} - diff --git a/src/htsstr.h b/src/htsstr.h index 971ee6be4..ff98b15cf 100644 --- a/src/htsstr.h +++ b/src/htsstr.h @@ -29,6 +29,4 @@ char **htsstr_argsplit(const char *str); void htsstr_argsplit_free(char **argv); -char *htsstr_format(const char *str, const char **map); - #endif /* HTSSTR_H__ */