Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
DVR: rewrite postproc spawn substitution with str_substitute(), add %…
…O, %s %p formatters
  • Loading branch information
perexg committed May 26, 2015
1 parent 2c8f91a commit 5faf8e6
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 88 deletions.
3 changes: 3 additions & 0 deletions docs/html/config_dvr.html
Expand Up @@ -74,8 +74,11 @@
<tr><td>%f</td><td>Full path to recording</td><td>/home/user/Videos/News.mkv</td></tr>
<tr><td>%b</td><td>Basename of recording</td><td>News.mkv</td></tr>
<tr><td>%c</td><td>Channel name</td><td>BBC world</td></tr>
<tr><td>%O</td><td>Owner of this recording</td><td>user</td></tr>
<tr><td>%C</td><td>Who created this recording</td><td>user</td></tr>
<tr><td>%t</td><td>Program title</td><td>News</td></tr>
<tr><td>%s</td><td>Program subtitle</td><td>Afternoon</td></tr>
<tr><td>%p</td><td>Program episode</td><td>S02.E07</td></tr>
<tr><td>%d</td><td>Program description</td><td>News and stories...</td></tr>
<tr><td>%e</td><td>Error message</td><td>Aborted by user</td></tr>
<tr><td>%S</td><td>Start time stamp of recording, UNIX epoch</td><td>1224421200</td></tr>
Expand Down
116 changes: 77 additions & 39 deletions src/dvr/dvr_rec.c
Expand Up @@ -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;
Expand All @@ -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 },
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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? */
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
47 changes: 0 additions & 47 deletions src/htsstr.c
Expand Up @@ -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)
Expand All @@ -34,7 +33,6 @@ hts_strndup(const char *src, size_t len)
return memcpy(r, src, len);
}


char *
htsstr_unescape(char *str) {
char *s;
Expand Down Expand Up @@ -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;
}

2 changes: 0 additions & 2 deletions src/htsstr.h
Expand Up @@ -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__ */

0 comments on commit 5faf8e6

Please sign in to comment.