Skip to content

Commit

Permalink
DVR: Add PCRE support
Browse files Browse the repository at this point in the history
  • Loading branch information
perexg committed May 16, 2017
1 parent ee76167 commit 74a1c69
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 41 deletions.
12 changes: 12 additions & 0 deletions configure
Expand Up @@ -54,6 +54,7 @@ OPTIONS=(
"libmfx_static:yes"
"inotify:auto"
"epoll:auto"
"pcre:auto"
"uriparser:auto"
"ccache:auto"
"tvhcsa:auto"
Expand Down Expand Up @@ -384,6 +385,17 @@ if enabled_or_auto satip_client; then
enable upnp
fi

#
# PCRE
#
if enabled_or_auto pcre; then
if check_pkg libpcre; then
enable pcre
elif enabled pcre; then
die "pcre development support not found (use --disable-pcre)"
fi
fi

#
# uriparser
#
Expand Down
8 changes: 8 additions & 0 deletions src/dvr/dvr.h
Expand Up @@ -20,6 +20,9 @@
#define DVR_H

#include <regex.h>
#if ENABLE_PCRE
#include <pcre.h>
#endif
#include "epg.h"
#include "channels.h"
#include "subscriptions.h"
Expand Down Expand Up @@ -338,7 +341,12 @@ typedef struct dvr_autorec_entry {
char *dae_comment;

char *dae_title;
int dae_pcre;
regex_t dae_title_preg;
#if ENABLE_PCRE
pcre *dae_title_pcre;
pcre_extra *dae_title_pcre_extra;
#endif
int dae_fulltext;

uint32_t dae_content_type;
Expand Down
167 changes: 128 additions & 39 deletions src/dvr/dvr_autorec.c
Expand Up @@ -36,6 +36,51 @@

struct dvr_autorec_entry_queue autorec_entries;

/*
*
*/
static inline int autorec_regexec(dvr_autorec_entry_t *dae, const char *str)
{
int r;
#if ENABLE_PCRE
if (dae->dae_pcre) {
int vec[30];
r = pcre_exec(dae->dae_title_pcre, dae->dae_title_pcre_extra,
str, strlen(str), 0, 0, vec, ARRAY_SIZE(vec));
return r < 0;
} else
#endif
{
return regexec(&dae->dae_title_preg, str, 0, NULL, 0);
}
}

/*
*
*/
static void autorec_regfree(dvr_autorec_entry_t *dae)
{
if (dae->dae_title) {
#if ENABLE_PCRE
if (dae->dae_pcre) {
#ifdef PCRE_CONFIG_JIT
pcre_free_study(dae->dae_title_pcre_extra);
#else
pcre_free(dae->dae_title_pcre_extra);
#endif
pcre_free(dae->dae_title_pcre);
dae->dae_title_pcre_extra = NULL;
dae->dae_title_pcre = NULL;
} else
#endif
{
regfree(&dae->dae_title_preg);
}
free(dae->dae_title);
dae->dae_title = NULL;
}
}

/*
*
*/
Expand Down Expand Up @@ -175,33 +220,7 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e)
return 0;
}

/* Do not check title if the event is from the serieslink group */
if(dae->dae_serieslink == NULL &&
dae->dae_title != NULL && dae->dae_title[0] != '\0') {
lang_str_ele_t *ls;
if (!dae->dae_fulltext) {
if(!e->episode->title) return 0;
RB_FOREACH(ls, e->episode->title, link)
if (!regexec(&dae->dae_title_preg, ls->str, 0, NULL, 0)) break;
} else {
ls = NULL;
if (e->episode->title)
RB_FOREACH(ls, e->episode->title, link)
if (!regexec(&dae->dae_title_preg, ls->str, 0, NULL, 0)) break;
if (!ls && e->episode->subtitle)
RB_FOREACH(ls, e->episode->subtitle, link)
if (!regexec(&dae->dae_title_preg, ls->str, 0, NULL, 0)) break;
if (!ls && e->summary)
RB_FOREACH(ls, e->summary, link)
if (!regexec(&dae->dae_title_preg, ls->str, 0, NULL, 0)) break;
if (!ls && e->description)
RB_FOREACH(ls, e->description, link)
if (!regexec(&dae->dae_title_preg, ls->str, 0, NULL, 0)) break;
}
if (!ls) return 0;
}

// Note: ignore channel test if we allow quality unlocking
/* Note: ignore channel test if we allow quality unlocking */
if ((cfg = dae->dae_config) == NULL)
return 0;
if(dae->dae_channel != NULL) {
Expand Down Expand Up @@ -269,6 +288,33 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e)
if(!((1 << ((tm.tm_wday ?: 7) - 1)) & dae->dae_weekdays))
return 0;
}

/* Do not check title if the event is from the serieslink group */
if(dae->dae_serieslink == NULL &&
dae->dae_title != NULL && dae->dae_title[0] != '\0') {
lang_str_ele_t *ls;
if (!dae->dae_fulltext) {
if(!e->episode->title) return 0;
RB_FOREACH(ls, e->episode->title, link)
if (!autorec_regexec(dae, ls->str)) break;
} else {
ls = NULL;
if (e->episode->title)
RB_FOREACH(ls, e->episode->title, link)
if (!autorec_regexec(dae, ls->str)) break;
if (!ls && e->episode->subtitle)
RB_FOREACH(ls, e->episode->subtitle, link)
if (!autorec_regexec(dae, ls->str)) break;
if (!ls && e->summary)
RB_FOREACH(ls, e->summary, link)
if (!autorec_regexec(dae, ls->str)) break;
if (!ls && e->description)
RB_FOREACH(ls, e->description, link)
if (!autorec_regexec(dae, ls->str)) break;
}
if (!ls) return 0;
}

return 1;
}

Expand Down Expand Up @@ -397,10 +443,7 @@ autorec_entry_destroy(dvr_autorec_entry_t *dae, int delconf)
free(dae->dae_creator);
free(dae->dae_comment);

if(dae->dae_title != NULL) {
free(dae->dae_title);
regfree(&dae->dae_title_preg);
}
autorec_regfree(dae);

if(dae->dae_channel != NULL)
LIST_REMOVE(dae, dae_channel_link);
Expand Down Expand Up @@ -526,15 +569,52 @@ dvr_autorec_entry_class_title_set(void *o, const void *v)
dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)o;
const char *title = v ?: "";
if (strcmp(title, dae->dae_title ?: "")) {
if (dae->dae_title) {
regfree(&dae->dae_title_preg);
free(dae->dae_title);
dae->dae_title = NULL;
if (dae->dae_title)
autorec_regfree(dae);
if (title[0] != '\0') {
#if ENABLE_PCRE
if (dae->dae_pcre) {
const char *estr;
int eoff;
dae->dae_title_pcre = pcre_compile(title, PCRE_CASELESS | PCRE_UTF8,
&estr, &eoff, NULL);
if (dae->dae_title_pcre == NULL) {
tvherror(LS_DVR, "Unable to compile PCRE '%s': %s", title, estr);
} else {
dae->dae_title_pcre_extra = pcre_study(dae->dae_title_pcre,
PCRE_STUDY_JIT_COMPILE, &estr);
if (dae->dae_title_pcre_extra == NULL && estr)
tvherror(LS_DVR, "Unable to study PCRE '%s': %s", title, estr);
else
dae->dae_title = strdup(title);
}
} else
#endif
{
if (!regcomp(&dae->dae_title_preg, title,
REG_ICASE | REG_EXTENDED | REG_NOSUB))
dae->dae_title = strdup(title);
else
tvherror(LS_DVR, "Unable to compile regex '%s'", title);
}
}
if (title[0] != '\0' &&
!regcomp(&dae->dae_title_preg, title,
REG_ICASE | REG_EXTENDED | REG_NOSUB))
dae->dae_title = strdup(title);
return 1;
}
return 0;
}

static int
dvr_autorec_entry_class_pcre_set(void *o, const void *v)
{
dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)o;
int pcre = v ? *(int *)v : 0;
char *title;
if (dae->dae_pcre != pcre) {
title = dae->dae_title ? strdup(dae->dae_title) : NULL;
autorec_regfree(dae);
dae->dae_pcre = pcre;
dvr_autorec_entry_class_title_set(o, title);
free(title);
return 1;
}
return 0;
Expand Down Expand Up @@ -1048,6 +1128,15 @@ const idclass_t dvr_autorec_entry_class = {
"matched against title, subtitle, summary and description."),
.off = offsetof(dvr_autorec_entry_t, dae_fulltext),
},
{
.type = PT_BOOL,
.id = "pcre",
.name = N_("PCRE"),
.desc = N_("Use PCRE regular expression library instead posix "
"extended regular expressions."),
.set = dvr_autorec_entry_class_pcre_set,
.off = offsetof(dvr_autorec_entry_t, dae_pcre),
},
{
.type = PT_STR,
.id = "channel",
Expand Down
5 changes: 3 additions & 2 deletions src/webui/static/app/dvr.js
Expand Up @@ -723,7 +723,7 @@ tvheadend.dvr_settings = function(panel, index) {
*/
tvheadend.autorec_editor = function(panel, index) {

var list = 'name,title,fulltext,channel,start,start_window,weekdays,' +
var list = 'name,title,fulltext,pcre,channel,start,start_window,weekdays,' +
'record,tag,btype,content_type,minduration,maxduration,' +
'dedup,directory,config_name,comment';
var elist = 'enabled,start_extra,stop_extra,' +
Expand All @@ -742,6 +742,7 @@ tvheadend.autorec_editor = function(panel, index) {
directory: { width: 200 },
title: { width: 300 },
fulltext: { width: 70 },
pcre: { width: 70 },
channel: { width: 200 },
tag: { width: 200 },
btype: { width: 50 },
Expand Down Expand Up @@ -781,7 +782,7 @@ tvheadend.autorec_editor = function(panel, index) {
},
},
del: true,
list: 'enabled,name,title,fulltext,channel,tag,start,start_window,' +
list: 'enabled,name,title,fulltext,pcre,channel,tag,start,start_window,' +
'weekdays,minduration,maxduration,btype,content_type,' +
'pri,dedup,directory,config_name,owner,creator,comment',
sort: {
Expand Down

0 comments on commit 74a1c69

Please sign in to comment.