Added htsstr.[ch], string helper functions, argument splitting and
formatting functions Added support for post-processing again, now with string formatting Ticket #33
This commit is contained in:
parent
b52656ac5c
commit
539f2e0460
8 changed files with 115 additions and 7 deletions
|
@ -32,12 +32,12 @@ body {
|
|||
padding-right: 60px;
|
||||
}
|
||||
|
||||
.hts-doc-text dt {
|
||||
.hts-doc-text dt,th {
|
||||
padding-top: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hts-doc-text dl {
|
||||
.hts-doc-text dl,td {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
|
@ -53,4 +53,4 @@ body {
|
|||
</style>
|
||||
|
||||
|
||||
<body>
|
||||
<body>
|
||||
|
|
|
@ -42,6 +42,27 @@
|
|||
<dd>If checked, Tvheadend will include the time for the recording in the
|
||||
event title. This applies to both the titled stored in the file
|
||||
and to the filename itself.
|
||||
<dt>Post-processor command
|
||||
<dd>Command to run after finishing a recording. The command will be
|
||||
run in background and is executed even if a recording is aborted
|
||||
or an error occurred. Use the %e error formatting string to check
|
||||
for errors, the error string is empty if recording finished
|
||||
successfully.
|
||||
<br><br>
|
||||
Support format strings:<br>
|
||||
<table class="hts-doc-text" border="0">
|
||||
<tr><th>Format</th><th>Description</th><th>Example value</th></tr>
|
||||
<tr><td>%f</td><td>Full path to recoding</td><td>/home/user/Videos/News.mkv</td></tr>
|
||||
<tr><td>%b</td><td>Basename of recoding</td><td>News.mkv</td></tr>
|
||||
<tr><td>%c</td><td>Channel name</td><td>BBC world</td></tr>
|
||||
<tr><td>%C</td><td>Who created this recoding</td><td>user</td></tr>
|
||||
<tr><td>%t</td><td>Program title</td><td>News</td></tr>
|
||||
<tr><td>%c</td><td>Program description</td><td>News and stories...</td></tr>
|
||||
<tr><td>%S</td><td>Start timestmap of recoding, UNIX epoch</td><td>1224421200</td></tr>
|
||||
<tr><td>%E</td><td>Stop timestamp of recoding, UNIX epoch</td><td>1224426600</td></tr>
|
||||
</table>
|
||||
<br>
|
||||
Example usage: /path/to/ffmpeg -i %f -vcodec libx264 -acodec copy "/path/with white space/%b"
|
||||
</dl>
|
||||
Changes to any of these settings must be confirmed by pressing the
|
||||
'Save configuration' button before taking effect.
|
||||
|
|
|
@ -29,6 +29,7 @@ extern char *dvr_format;
|
|||
extern char *dvr_file_postfix;
|
||||
extern uint32_t dvr_retention_days;
|
||||
extern int dvr_flags;
|
||||
extern char *dvr_postproc;
|
||||
|
||||
#define DVR_DIR_PER_DAY 0x1
|
||||
#define DVR_DIR_PER_CHANNEL 0x2
|
||||
|
@ -144,6 +145,8 @@ void dvr_entry_dec_ref(dvr_entry_t *de);
|
|||
|
||||
void dvr_storage_set(const char *storage);
|
||||
|
||||
void dvr_postproc_set(const char *postproc);
|
||||
|
||||
void dvr_retention_set(int days);
|
||||
|
||||
void dvr_flags_set(int flags);
|
||||
|
|
19
dvr/dvr_db.c
19
dvr/dvr_db.c
|
@ -33,7 +33,7 @@ char *dvr_format;
|
|||
char *dvr_file_postfix;
|
||||
uint32_t dvr_retention_days;
|
||||
int dvr_flags;
|
||||
|
||||
char *dvr_postproc;
|
||||
|
||||
static int de_tally;
|
||||
|
||||
|
@ -488,6 +488,8 @@ dvr_init(void)
|
|||
|
||||
if(!htsmsg_get_u32(m, "time-in-title", &u32) && u32)
|
||||
dvr_flags |= DVR_TIME_IN_TITLE;
|
||||
|
||||
tvh_str_set(&dvr_postproc, htsmsg_get_str(m, "postproc"));
|
||||
|
||||
htsmsg_destroy(m);
|
||||
}
|
||||
|
@ -538,6 +540,8 @@ dvr_save(void)
|
|||
htsmsg_add_u32(m, "channel-in-title", !!(dvr_flags & DVR_CHANNEL_IN_TITLE));
|
||||
htsmsg_add_u32(m, "date-in-title", !!(dvr_flags & DVR_DATE_IN_TITLE));
|
||||
htsmsg_add_u32(m, "time-in-title", !!(dvr_flags & DVR_TIME_IN_TITLE));
|
||||
if(dvr_postproc != NULL)
|
||||
htsmsg_add_str(m, "postproc", dvr_postproc);
|
||||
|
||||
hts_settings_save(m, "dvr/config");
|
||||
htsmsg_destroy(m);
|
||||
|
@ -556,6 +560,19 @@ dvr_storage_set(const char *storage)
|
|||
dvr_save();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvr_postproc_set(const char *postproc)
|
||||
{
|
||||
if(dvr_postproc != NULL && !strcmp(dvr_postproc, postproc))
|
||||
return;
|
||||
|
||||
tvh_str_set(&dvr_postproc, !strcmp(postproc, "") ? NULL : postproc);
|
||||
dvr_save();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -20,13 +20,17 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h> /* basename */
|
||||
|
||||
#include <libavutil/avstring.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#include <libhts/htsstr.h>
|
||||
|
||||
#include "tvhead.h"
|
||||
#include "streaming.h"
|
||||
#include "dvr.h"
|
||||
#include "spawn.h"
|
||||
|
||||
typedef struct dvr_rec_stream {
|
||||
LIST_ENTRY(dvr_rec_stream) drs_link;
|
||||
|
@ -46,6 +50,7 @@ static void dvr_rec_start(dvr_entry_t *de, streaming_pad_t *sp);
|
|||
static void dvr_rec_stop(dvr_entry_t *de);
|
||||
static void *dvr_thread(void *aux);
|
||||
static void dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt);
|
||||
static void dvr_spawn_postproc(dvr_entry_t *de);
|
||||
static void dvr_thread_epilog(dvr_entry_t *de);
|
||||
|
||||
/**
|
||||
|
@ -695,6 +700,57 @@ dvr_thread_new_pkt(dvr_entry_t *de, th_pkt_t *pkt)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void dvr_spawn_postproc(dvr_entry_t *de)
|
||||
{
|
||||
char *fmap[256];
|
||||
char **args;
|
||||
char start[16];
|
||||
char stop[16];
|
||||
char *fbasename; /* filename dup for basename */
|
||||
int i;
|
||||
|
||||
args = htsstr_argsplit(dvr_postproc);
|
||||
/* no arguments at all */
|
||||
if(!args[0]) {
|
||||
htsstr_argsplit_free(args);
|
||||
return;
|
||||
}
|
||||
|
||||
fbasename = strdup(de->de_filename);
|
||||
snprintf(start, sizeof(start), "%ld", de->de_start);
|
||||
snprintf(stop, sizeof(stop), "%ld", de->de_stop);
|
||||
|
||||
memset(fmap, 0, sizeof(fmap));
|
||||
fmap['f'] = de->de_filename; /* full path to recoding */
|
||||
fmap['b'] = basename(fbasename); /* basename of recoding */
|
||||
fmap['c'] = de->de_channel->ch_name; /* channel name */
|
||||
fmap['C'] = de->de_creator; /* user who created this recording */
|
||||
fmap['t'] = de->de_title; /* program title */
|
||||
fmap['d'] = de->de_desc; /* program description */
|
||||
fmap['e'] = de->de_error; /* error message, empty if no error (FIXME:?) */
|
||||
fmap['S'] = start; /* start time, unix epoch */
|
||||
fmap['E'] = stop; /* stop time, unix epoch */
|
||||
|
||||
printf("error=%s\n", de->de_error);
|
||||
|
||||
/* 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);
|
||||
|
||||
free(fbasename);
|
||||
htsstr_argsplit_free(args);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -731,4 +787,7 @@ dvr_thread_epilog(dvr_entry_t *de)
|
|||
LIST_REMOVE(drs, drs_link);
|
||||
free(drs);
|
||||
}
|
||||
|
||||
if(dvr_postproc)
|
||||
dvr_spawn_postproc(de);
|
||||
}
|
||||
|
|
|
@ -1063,6 +1063,7 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
r = htsmsg_create();
|
||||
htsmsg_add_str(r, "storage", dvr_storage);
|
||||
htsmsg_add_str(r, "postproc", dvr_postproc);
|
||||
htsmsg_add_u32(r, "retention", dvr_retention_days);
|
||||
htsmsg_add_u32(r, "dayDirs", !!(dvr_flags & DVR_DIR_PER_DAY));
|
||||
htsmsg_add_u32(r, "channelDirs", !!(dvr_flags & DVR_DIR_PER_CHANNEL));
|
||||
|
@ -1076,6 +1077,9 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "storage")) != NULL)
|
||||
dvr_storage_set(s);
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "postproc")) != NULL)
|
||||
dvr_postproc_set(s);
|
||||
|
||||
if((s = http_arg_get(&hc->hc_req_args, "retention")) != NULL)
|
||||
dvr_retention_set(atoi(s));
|
||||
|
|
|
@ -319,7 +319,7 @@ tvheadend.dvrsettings = function() {
|
|||
|
||||
var confreader = new Ext.data.JsonReader({
|
||||
root: 'dvrSettings',
|
||||
}, ['storage','retention','dayDirs',
|
||||
}, ['storage','postproc','retention','dayDirs',
|
||||
'channelDirs','channelInTitle',
|
||||
'dateInTitle','timeInTitle']);
|
||||
|
||||
|
@ -359,7 +359,11 @@ tvheadend.dvrsettings = function() {
|
|||
}), new Ext.form.Checkbox({
|
||||
fieldLabel: 'Include time in title',
|
||||
name: 'timeInTitle'
|
||||
})],
|
||||
}), {
|
||||
width: 300,
|
||||
fieldLabel: 'Post-processor command',
|
||||
name: 'postproc'
|
||||
}],
|
||||
tbar: [{
|
||||
tooltip: 'Save changes made to channel configuration below',
|
||||
iconCls:'save',
|
||||
|
|
|
@ -154,4 +154,4 @@
|
|||
.about-title {
|
||||
font:normal 24px verdana;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue