tvheadend/src/dvr/dvr.h
Adam Sutton ad99676f54 Merge remote-tracking branch 'origin/pr/301'
Conflicts:
	src/dvr/dvr.h
	src/dvr/dvr_db.c
	src/webui/extjs.c
	src/webui/static/app/dvr.js
2014-06-07 22:53:48 +01:00

442 lines
10 KiB
C

/*
* Digital Video Recorder
* Copyright (C) 2008 Andreas Öman
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DVR_H
#define DVR_H
#include <regex.h>
#include "epg.h"
#include "channels.h"
#include "subscriptions.h"
#include "muxer.h"
#include "lang_str.h"
typedef struct dvr_config {
char *dvr_config_name;
char *dvr_storage;
uint32_t dvr_retention_days;
int dvr_flags;
char *dvr_charset;
char *dvr_charset_id;
char *dvr_postproc;
int dvr_extra_time_pre;
int dvr_extra_time_post;
muxer_container_type_t dvr_mc;
muxer_config_t dvr_muxcnf;
/* Series link support */
int dvr_sl_brand_lock;
int dvr_sl_season_lock;
int dvr_sl_channel_lock;
int dvr_sl_time_lock;
int dvr_sl_more_recent;
int dvr_sl_quality_lock;
/* Duplicate detect */
int dvr_dup_detect_episode;
LIST_ENTRY(dvr_config) config_link;
} dvr_config_t;
extern struct dvr_config_list dvrconfigs;
extern struct dvr_entry_list dvrentries;
#define DVR_DIR_PER_DAY 0x1
#define DVR_DIR_PER_CHANNEL 0x2
#define DVR_CHANNEL_IN_TITLE 0x4
#define DVR_DATE_IN_TITLE 0x8
#define DVR_TIME_IN_TITLE 0x10
#define DVR_WHITESPACE_IN_TITLE 0x20
#define DVR_DIR_PER_TITLE 0x40
#define DVR_EPISODE_IN_TITLE 0x80
#define DVR_CLEAN_TITLE 0x100
#define DVR_TAG_FILES 0x200
#define DVR_SKIP_COMMERCIALS 0x400
#define DVR_SUBTITLE_IN_TITLE 0x800
#define DVR_EPISODE_BEFORE_DATE 0x1000
#define DVR_EPISODE_DUPLICATE_DETECTION 0x2000
typedef enum {
DVR_PRIO_IMPORTANT,
DVR_PRIO_HIGH,
DVR_PRIO_NORMAL,
DVR_PRIO_LOW,
DVR_PRIO_UNIMPORTANT,
} dvr_prio_t;
LIST_HEAD(dvr_rec_stream_list, dvr_rec_stream);
typedef enum {
DVR_SCHEDULED, /* Scheduled for recording (in the future) */
DVR_RECORDING,
DVR_COMPLETED, /* If recording failed, de->de_error is set to
a string */
DVR_NOSTATE,
DVR_MISSED_TIME,
} dvr_entry_sched_state_t;
typedef enum {
DVR_RS_PENDING,
DVR_RS_WAIT_PROGRAM_START,
DVR_RS_RUNNING,
DVR_RS_COMMERCIAL,
DVR_RS_ERROR,
} dvr_rs_state_t;
typedef struct dvr_entry {
int de_refcnt; /* Modification is protected under global_lock */
/**
* Upon dvr_entry_remove() this fields will be invalidated (and pointers
* NULLed)
*/
LIST_ENTRY(dvr_entry) de_global_link;
int de_id;
channel_t *de_channel;
LIST_ENTRY(dvr_entry) de_channel_link;
char *de_channel_name;
gtimer_t de_timer;
/**
* These meta fields will stay valid as long as reference count > 0
*/
char *de_config_name;
time_t de_start;
time_t de_stop;
time_t de_start_extra;
time_t de_stop_extra;
char *de_creator;
char *de_filename; /* Initially null if no filename has been
generated yet */
lang_str_t *de_title; /* Title in UTF-8 (from EPG) */
lang_str_t *de_desc; /* Description in UTF-8 (from EPG) */
epg_genre_t de_content_type; /* Content type (from EPG) */
uint16_t de_dvb_eid;
dvr_prio_t de_pri;
uint32_t de_dont_reschedule;
muxer_container_type_t de_mc;
/**
* EPG information / links
*/
epg_broadcast_t *de_bcast;
/**
* Major State
*/
dvr_entry_sched_state_t de_sched_state;
/**
* Recording state (onyl valid if de_sched_state == DVR_RECORDING)
*/
dvr_rs_state_t de_rec_state;
/**
* Number of errors (only to be modified by the recording thread)
*/
uint32_t de_errors;
/**
* Last error, see SM_CODE_ defines
*/
uint32_t de_last_error;
/**
* Autorec linkage
*/
LIST_ENTRY(dvr_entry) de_autorec_link;
struct dvr_autorec_entry *de_autorec;
/**
* Fields for recording
*/
pthread_t de_thread;
th_subscription_t *de_s;
streaming_queue_t de_sq;
streaming_target_t *de_tsfix;
streaming_target_t *de_gh;
/**
* Initialized upon SUBSCRIPTION_TRANSPORT_RUN
*/
struct muxer *de_mux;
/**
* Inotify
*/
#if ENABLE_INOTIFY
LIST_ENTRY(dvr_entry) de_inotify_link;
#endif
} dvr_entry_t;
#define DVR_CH_NAME(e) ((e)->de_channel == NULL ? (e)->de_channel_name : channel_get_name((e)->de_channel))
/**
* Autorec entry
*/
typedef struct dvr_autorec_entry {
TAILQ_ENTRY(dvr_autorec_entry) dae_link;
char *dae_id;
char *dae_config_name;
int dae_enabled;
char *dae_creator;
char *dae_comment;
char *dae_title;
regex_t dae_title_preg;
epg_genre_t dae_content_type;
int dae_approx_time; /* Minutes from midnight */
int dae_weekdays;
channel_t *dae_channel;
LIST_ENTRY(dvr_autorec_entry) dae_channel_link;
channel_tag_t *dae_channel_tag;
LIST_ENTRY(dvr_autorec_entry) dae_channel_tag_link;
dvr_prio_t dae_pri;
struct dvr_entry_list dae_spawns;
epg_brand_t *dae_brand;
epg_season_t *dae_season;
epg_serieslink_t *dae_serieslink;
epg_episode_num_t dae_epnum;
} dvr_autorec_entry_t;
/**
* Prototypes
*/
void dvr_make_title(char *output, size_t outlen, dvr_entry_t *de);
dvr_config_t *dvr_config_find_by_name(const char *name);
dvr_config_t *dvr_config_find_by_name_default(const char *name);
dvr_config_t *dvr_config_create(const char *name);
void dvr_config_delete(const char *name);
void dvr_entry_notify(dvr_entry_t *de);
void dvr_entry_save(dvr_entry_t *de);
const char *dvr_entry_status(dvr_entry_t *de);
const char *dvr_entry_schedstatus(dvr_entry_t *de);
void dvr_entry_create_by_autorec(epg_broadcast_t *e, dvr_autorec_entry_t *dae);
dvr_entry_t *dvr_entry_create_by_event
(const char *dvr_config_name,
epg_broadcast_t *e,
time_t start_extra, time_t stop_extra,
const char *creator,
dvr_autorec_entry_t *dae,
dvr_prio_t pri);
dvr_entry_t *dvr_entry_create
(const char *dvr_config_name,
channel_t *ch, time_t start, time_t stop,
time_t start_extra, time_t stop_extra,
const char *title, const char *description, const char *lang,
epg_genre_t *content_type,
const char *creator, dvr_autorec_entry_t *dae,
dvr_prio_t pri);
dvr_entry_t *dvr_entry_update
(dvr_entry_t *de,
const char* de_title, const char *de_desc, const char *lang,
time_t de_start, time_t de_stop,
time_t de_start_extra, time_t de_stop_extra );
void dvr_init(void);
void dvr_done(void);
void dvr_autorec_init(void);
void dvr_autorec_done(void);
void dvr_autorec_update(void);
void dvr_destroy_by_channel(channel_t *ch, int delconf);
void dvr_rec_subscribe(dvr_entry_t *de);
void dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode);
void dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e);
void dvr_event_updated(epg_broadcast_t *e);
dvr_entry_t *dvr_entry_find_by_id(int id);
dvr_entry_t *dvr_entry_find_by_event(epg_broadcast_t *e);
dvr_entry_t *dvr_entry_find_by_event_fuzzy(epg_broadcast_t *e);
dvr_entry_t *dvr_entry_find_by_episode(epg_broadcast_t *e);
int64_t dvr_get_filesize(dvr_entry_t *de);
dvr_entry_t *dvr_entry_cancel(dvr_entry_t *de);
void dvr_entry_dec_ref(dvr_entry_t *de);
void dvr_storage_set(dvr_config_t *cfg, const char *storage);
void dvr_charset_set(dvr_config_t *cfg, const char *charset);
void dvr_container_set(dvr_config_t *cfg, const char *container);
void dvr_file_permissions_set(dvr_config_t *cfg, int permissions);
void dvr_directory_permissions_set(dvr_config_t *cfg, int permissions);
void dvr_mux_cache_set(dvr_config_t *cfg, int mcache);
void dvr_postproc_set(dvr_config_t *cfg, const char *postproc);
void dvr_retention_set(dvr_config_t *cfg, int days);
void dvr_flags_set(dvr_config_t *cfg, int flags);
void dvr_mux_flags_set(dvr_config_t *cfg, int flags);
void dvr_extra_time_pre_set(dvr_config_t *cfg, int d);
void dvr_extra_time_post_set(dvr_config_t *cfg, int d);
void dvr_entry_delete(dvr_entry_t *de);
void dvr_entry_cancel_delete(dvr_entry_t *de);
/**
* Query interface
*/
typedef struct dvr_query_result {
dvr_entry_t **dqr_array;
int dqr_entries;
int dqr_alloced;
} dvr_query_result_t;
typedef int (dvr_entry_filter)(dvr_entry_t *entry);
typedef int (dvr_entry_comparator)(const void *a, const void *b);
void dvr_query(dvr_query_result_t *dqr);
void dvr_query_filter(dvr_query_result_t *dqr, dvr_entry_filter filter);
void dvr_query_free(dvr_query_result_t *dqr);
void dvr_query_sort_cmp(dvr_query_result_t *dqr, dvr_entry_comparator cmp);
void dvr_query_sort(dvr_query_result_t *dqr);
int dvr_sort_start_descending(const void *A, const void *B);
int dvr_sort_start_ascending(const void *A, const void *B);
/**
*
*/
void dvr_autorec_add(const char *dvr_config_name,
const char *title, const char *channel,
const char *tag, epg_genre_t *content_type,
const char *creator, const char *comment);
void dvr_autorec_add_series_link(const char *dvr_config_name,
epg_broadcast_t *event,
const char *creator, const char *comment);
void dvr_autorec_check_event(epg_broadcast_t *e);
void dvr_autorec_check_brand(epg_brand_t *b);
void dvr_autorec_check_season(epg_season_t *s);
void dvr_autorec_check_serieslink(epg_serieslink_t *s);
void autorec_destroy_by_channel(channel_t *ch, int delconf);
dvr_autorec_entry_t *autorec_entry_find(const char *id, int create);
/**
*
*/
dvr_prio_t dvr_pri2val(const char *s);
const char *dvr_val2pri(dvr_prio_t v);
/**
* Inotify support
*/
void dvr_inotify_init ( void );
void dvr_inotify_done ( void );
void dvr_inotify_add ( dvr_entry_t *de );
void dvr_inotify_del ( dvr_entry_t *de );
/**
* Cutpoints support
**/
typedef struct dvr_cutpoint {
TAILQ_ENTRY(dvr_cutpoint) dc_link;
uint64_t dc_start_ms;
uint64_t dc_end_ms;
enum {
DVR_CP_CUT,
DVR_CP_MUTE,
DVR_CP_SCENE,
DVR_CP_COMM
} dc_type;
} dvr_cutpoint_t;
typedef TAILQ_HEAD(,dvr_cutpoint) dvr_cutpoint_list_t;
dvr_cutpoint_list_t *dvr_get_cutpoint_list (dvr_entry_t *de);
void dvr_cutpoint_list_destroy (dvr_cutpoint_list_t *list);
#endif /* DVR_H */