From 96bea3b8eb6134d3058eb1c6a66b75b13d8c03e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Thu, 27 Mar 2008 21:21:26 +0000 Subject: [PATCH] Optionally execute a program when a recording is completed --- man/tvheadend.1 | 56 +++++++++++++++++++++++++++++++++++++++++++++---- pvr.c | 40 +++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/man/tvheadend.1 b/man/tvheadend.1 index eb4f96ca..048e562e 100644 --- a/man/tvheadend.1 +++ b/man/tvheadend.1 @@ -458,14 +458,62 @@ disk write out and restart once the commercial break has passed. Before the recorder starts write out it will wait for an I-frame so the output will start in a clean state. This also applies when resuming from a commercial break pause. -.SS "Configuration" -The video recorder is primarily managed from the web interface or -via some of the proprietary interfaces. There are, however some parameters -that is controlled via the configuration file. +.SS "Storage" +The user should configure where the recorder store its files. Note that +the disk write out is done in a separate thread so the system will not +stall if any harddrives need to spin up. .TP \fB\tpvrdir = \fR\fI\fR (optional) Sets the directory where recordings will be saved. If this is omitted the recordings will be stored in the current directory. +.SS "Post processing" +Once a recording has been completed tvheadend can be configured to invoke +an executable program (or script). The program may do any number of things +such as move the file to a permanent location, do some tagging or even +transcode the program. +.PP +The program to execute is set in the configuration: +.TP +\fB\tpvrpostproc = \fR\fI\fR (optional) +Points to an executable to be launched after a recording has been completed. +.PP +The program is invoked with arguments as follows: +.TP +\fB\targ1: \fR\fIfilename\fR +Full path to the recorded file. +.TP +\fB\targ2: \fR\fIStatus\fR +Status of recording. If 'ok' the recording was successful otherwise it is +a short string describing the type of error. +.TP +\fB\targ3: \fR\fIClass\fR +Could be used in the future to differentiate various recording actions. +Currently it is always set to 'default' +.TP +\fB\targ4: \fR\fIChannel\fR +Channelname of the recording. +.TP +\fB\targ5: \fR\fICreator\fR +Username of the creator of the recording. +.TP +\fB\targ6: \fR\fITitle\fR +EPG program title. +.TP +\fB\targ7: \fR\fIDescription\fR +EPG program description. +.PP +The following example script would just print the various arguments passed: +.PP +.nf +#!/bin/sh +echo File.......: $1 +echo Status.....: $2 +echo Class......: $3 +echo Channel....: $4 +echo Creator....: $5 +echo Title......: $6 +echo Description: $7 +.fi .SH "OUTPUT - XBMSP - XBMC Media Streaming Protocol" Tvheadend can act as a native XBMSP server. All channels are presented as virtual files. The channels are located diff --git a/pvr.c b/pvr.c index 3809f73e..56a10f39 100644 --- a/pvr.c +++ b/pvr.c @@ -44,6 +44,7 @@ #include "buffer.h" #include "strtab.h" #include "ffmuxer.h" +#include "spawn.h" static int pvr_id_ceil; /* number generator for database entries */ @@ -59,6 +60,7 @@ static void pvr_subscription_callback(struct th_subscription *s, static void *pvr_recorder_thread(void *aux); +static void postrec(pvr_rec_t *pvrr); /** * Initialize PVR framework @@ -604,6 +606,7 @@ pvr_fsm(pvr_rec_t *pvrr) subscription_unsubscribe(pvrr->pvrr_s); dtimer_disarm(&pvrr->pvrr_timer); + postrec(pvrr); break; } } @@ -836,3 +839,40 @@ pvr_recorder_thread(void *aux) return NULL; } +/** + * After recording is completed, execute a program of users choice + */ + +static struct strtab pvrrstatustab[] = { + { "ok", HTSTV_PVR_STATUS_DONE }, + { "aborted", HTSTV_PVR_STATUS_ABORTED }, + { "transponder", HTSTV_PVR_STATUS_NO_TRANSPONDER }, + { "file-error", HTSTV_PVR_STATUS_FILE_ERROR }, + { "disk-full", HTSTV_PVR_STATUS_DISK_FULL }, + { "buffer-error", HTSTV_PVR_STATUS_BUFFER_ERROR }, +}; + +static void +postrec(pvr_rec_t *pvrr) +{ + const char *prog, *status; + const char *argv[16]; + + if((prog = config_get_str("pvrpostproc", NULL)) == NULL) + return; + + if((status = val2str(pvrr->pvrr_status, pvrrstatustab)) == NULL) + return; + + argv[0] = prog; + argv[1] = pvrr->pvrr_filename; + argv[2] = status; + argv[3] = "default"; /* recording class, currently unused */ + argv[4] = pvrr->pvrr_channel->ch_name; + argv[5] = pvrr->pvrr_creator; + argv[6] = pvrr->pvrr_title ?: ""; + argv[7] = pvrr->pvrr_desc ?: ""; + argv[8] = NULL; + + spawnv(prog, (void *)argv); +}