Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add stream profile support
  • Loading branch information
perexg committed Oct 9, 2014
1 parent 29d5c75 commit 2012dc8
Show file tree
Hide file tree
Showing 27 changed files with 1,098 additions and 313 deletions.
8 changes: 5 additions & 3 deletions Makefile
Expand Up @@ -122,7 +122,7 @@ SRCS = src/version.c \
src/trap.c \
src/avg.c \
src/htsstr.c \
src/tvhpoll.c \
src/tvhpoll.c \
src/huffman.c \
src/filebundle.c \
src/config.c \
Expand All @@ -137,7 +137,8 @@ SRCS = src/version.c \
src/fsmonitor.c \
src/cron.c \
src/esfilter.c \
src/intlconv.c
src/intlconv.c \
src/profile.c

SRCS-${CONFIG_UPNP} += \
src/upnp.c
Expand All @@ -157,7 +158,8 @@ SRCS += \
src/api/api_intlconv.c \
src/api/api_access.c \
src/api/api_dvr.c \
src/api/api_caclient.c
src/api/api_caclient.c \
src/api/api_profile.c

SRCS += \
src/parsers/parsers.c \
Expand Down
1 change: 1 addition & 0 deletions src/api.c
Expand Up @@ -134,6 +134,7 @@ void api_init ( void )
api_access_init();
api_dvr_init();
api_caclient_init();
api_profile_init();
}

void api_done ( void )
Expand Down
1 change: 1 addition & 0 deletions src/api.h
Expand Up @@ -74,6 +74,7 @@ void api_intlconv_init ( void );
void api_access_init ( void );
void api_dvr_init ( void );
void api_caclient_init ( void );
void api_profile_init ( void );

/*
* IDnode
Expand Down
2 changes: 2 additions & 0 deletions src/api/api_caclient.c
Expand Up @@ -34,13 +34,15 @@ api_caclient_list
htsmsg_t *l, *e;

l = htsmsg_create_list();
pthread_mutex_lock(&global_lock);
TAILQ_FOREACH(cac, &caclients, cac_link) {
e = htsmsg_create_map();
htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&cac->cac_id));
htsmsg_add_str(e, "title", idnode_get_title(&cac->cac_id));
htsmsg_add_str(e, "status", caclient_get_status(cac));
htsmsg_add_msg(l, NULL, e);
}
pthread_mutex_unlock(&global_lock);
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
return 0;
Expand Down
110 changes: 110 additions & 0 deletions src/api/api_profile.c
@@ -0,0 +1,110 @@
/*
* tvheadend - API access to Stream Profile
*
* Copyright (C) 2014 Jaroslav Kysela
*
* 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/>.
*/

#include "tvheadend.h"
#include "access.h"
#include "htsmsg.h"
#include "api.h"
#include "profile.h"

/*
*
*/
static int
api_profile_list
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
profile_t *pro;
htsmsg_t *l, *e;

l = htsmsg_create_list();
pthread_mutex_lock(&global_lock);
TAILQ_FOREACH(pro, &profiles, pro_link) {
e = htsmsg_create_map();
htsmsg_add_str(e, "key", idnode_uuid_as_str(&pro->pro_id));
htsmsg_add_str(e, "val", profile_get_name(pro));
htsmsg_add_msg(l, NULL, e);
}
pthread_mutex_unlock(&global_lock);
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
return 0;
}

static int
api_profile_builders
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
profile_build_t *pb;
htsmsg_t *l, *e;

l = htsmsg_create_list();

pthread_mutex_lock(&global_lock);
/* List of available builder classes */
LIST_FOREACH(pb, &profile_builders, link)
if ((e = idclass_serialize(pb->clazz)))
htsmsg_add_msg(l, NULL, e);
pthread_mutex_unlock(&global_lock);

/* Output */
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);

return 0;
}

static int
api_profile_create
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int err = 0;
const char *clazz;
htsmsg_t *conf;

if (!(clazz = htsmsg_get_str(args, "class")))
return EINVAL;
if (!(conf = htsmsg_get_map(args, "conf")))
return EINVAL;
htsmsg_set_str(conf, "class", clazz);

pthread_mutex_lock(&global_lock);
if (profile_create(NULL, conf, 1) == NULL)
err = -EINVAL;
pthread_mutex_unlock(&global_lock);

return err;
}

/*
* Init
*/
void
api_profile_init ( void )
{
static api_hook_t ah[] = {
{ "profile/list", ACCESS_ADMIN, api_profile_list, NULL },
{ "profile/class", ACCESS_ADMIN, api_idnode_class, (void*)&profile_class },
{ "profile/builders", ACCESS_ADMIN, api_profile_builders, NULL },
{ "profile/create", ACCESS_ADMIN, api_profile_create, NULL },
{ NULL },
};

api_register_all(ah);
}
16 changes: 8 additions & 8 deletions src/dvr/dvr.h
Expand Up @@ -24,16 +24,19 @@
#include "channels.h"
#include "subscriptions.h"
#include "muxer.h"
#include "profile.h"
#include "lang_str.h"

typedef struct dvr_config {
idnode_t dvr_id;

LIST_ENTRY(dvr_config) config_link;
LIST_ENTRY(dvr_config) profile_link;

int dvr_enabled;
int dvr_valid;
char *dvr_config_name;
profile_t *dvr_profile;
char *dvr_storage;
uint32_t dvr_retention_days;
char *dvr_charset;
Expand All @@ -43,7 +46,6 @@ typedef struct dvr_config {
uint32_t dvr_extra_time_post;
uint32_t dvr_update_window;

int dvr_mc;
muxer_config_t dvr_muxcnf;

int dvr_dir_per_day;
Expand Down Expand Up @@ -208,15 +210,11 @@ typedef struct dvr_entry {
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
* Stream worker chain
*/

struct muxer *de_mux;
profile_chain_t *de_chain;

/**
* Inotify
Expand Down Expand Up @@ -350,6 +348,8 @@ void dvr_config_delete(const char *name);

void dvr_config_save(dvr_config_t *cfg);

void dvr_config_destroy_by_profile(profile_t *pro, int delconf);

/*
*
*/
Expand Down
101 changes: 78 additions & 23 deletions src/dvr/dvr_config.c
Expand Up @@ -139,7 +139,6 @@ dvr_config_create(const char *name, const char *uuid, htsmsg_t *conf)
cfg->dvr_enabled = 1;
cfg->dvr_config_name = strdup(name);
cfg->dvr_retention_days = 31;
cfg->dvr_mc = MC_MATROSKA;
cfg->dvr_tag_files = 1;
cfg->dvr_skip_commercials = 1;
dvr_charset_update(cfg, intlconv_filesystem_charset());
Expand All @@ -155,7 +154,6 @@ dvr_config_create(const char *name, const char *uuid, htsmsg_t *conf)

/* Muxer config */
cfg->dvr_muxcnf.m_cache = MC_CACHE_DONTKEEP;
cfg->dvr_muxcnf.m_rewrite_pat = 1;

/* dup detect */
cfg->dvr_dup_detect_episode = 1; // detect dup episodes
Expand All @@ -172,6 +170,12 @@ dvr_config_create(const char *name, const char *uuid, htsmsg_t *conf)

tvhinfo("dvr", "Creating new configuration '%s'", cfg->dvr_config_name);

if (cfg->dvr_profile == NULL) {
cfg->dvr_profile = profile_find_by_name(NULL);
assert(cfg->dvr_profile);
LIST_INSERT_HEAD(&cfg->dvr_profile->pro_dvr_configs, cfg, profile_link);
}

if (dvr_config_is_default(cfg) && dvr_config_find_by_name(NULL)) {
tvherror("dvr", "Unable to create second default config, removing");
LIST_INSERT_HEAD(&dvrconfigs, cfg, config_link);
Expand Down Expand Up @@ -201,6 +205,11 @@ dvr_config_destroy(dvr_config_t *cfg, int delconf)
LIST_REMOVE(cfg, config_link);
idnode_unlink(&cfg->dvr_id);

if (cfg->dvr_profile) {
LIST_REMOVE(cfg, profile_link);
cfg->dvr_profile = NULL;
}

dvr_entry_destroy_by_config(cfg, delconf);
access_destroy_by_dvr_config(cfg, delconf);
autorec_destroy_by_config(cfg, delconf);
Expand Down Expand Up @@ -327,6 +336,51 @@ dvr_config_class_name_set(void *o, const void *v)
return 0;
}

static int
dvr_config_class_profile_set(void *o, const void *v)
{
dvr_config_t *cfg = (dvr_config_t *)o;
profile_t *pro;

pro = v ? profile_find_by_uuid(v) : NULL;
pro = pro ?: profile_find_by_name(v);
if (pro == NULL) {
if (cfg->dvr_profile) {
LIST_REMOVE(cfg, profile_link);
cfg->dvr_profile = NULL;
return 1;
}
} else if (cfg->dvr_profile != pro) {
if (cfg->dvr_profile)
LIST_REMOVE(cfg, profile_link);
cfg->dvr_profile = pro;
LIST_INSERT_HEAD(&pro->pro_dvr_configs, cfg, profile_link);
return 1;
}
return 0;
}

static const void *
dvr_config_class_profile_get(void *o)
{
static const char *ret;
dvr_config_t *cfg = (dvr_config_t *)o;
if (cfg->dvr_profile)
ret = idnode_uuid_as_str(&cfg->dvr_profile->pro_id);
else
ret = "";
return &ret;
}

static char *
dvr_config_class_profile_rend(void *o)
{
dvr_config_t *cfg = (dvr_config_t *)o;
if (cfg->dvr_profile)
return strdup(profile_get_name(cfg->dvr_profile));
return NULL;
}

static const char *
dvr_config_class_get_title (idnode_t *self)
{
Expand Down Expand Up @@ -433,12 +487,14 @@ const idclass_t dvr_config_class = {
.get_opts = dvr_config_class_enabled_opts,
},
{
.type = PT_INT,
.id = "container",
.name = "Container",
.off = offsetof(dvr_config_t, dvr_mc),
.def.i = MC_MATROSKA,
.list = dvr_entry_class_mc_list,
.type = PT_STR,
.id = "profile",
.name = "Stream Profile",
.off = offsetof(dvr_config_t, dvr_profile),
.set = dvr_config_class_profile_set,
.get = dvr_config_class_profile_get,
.rend = dvr_config_class_profile_rend,
.list = profile_class_get_list,
.group = 1,
},
{
Expand Down Expand Up @@ -522,21 +578,6 @@ const idclass_t dvr_config_class = {
.def.s = "UTF-8",
.group = 2,
},
{
.type = PT_BOOL,
.id = "rewrite-pat",
.name = "Rewrite PAT",
.off = offsetof(dvr_config_t, dvr_muxcnf.m_rewrite_pat),
.def.i = 1,
.group = 2,
},
{
.type = PT_BOOL,
.id = "rewrite-pmt",
.name = "Rewrite PMT",
.off = offsetof(dvr_config_t, dvr_muxcnf.m_rewrite_pmt),
.group = 2,
},
{
.type = PT_BOOL,
.id = "tag-files",
Expand Down Expand Up @@ -649,6 +690,20 @@ const idclass_t dvr_config_class = {
},
};

/**
*
*/
void
dvr_config_destroy_by_profile(profile_t *pro, int delconf)
{
dvr_config_t *cfg;

while((cfg = LIST_FIRST(&pro->pro_dvr_configs)) != NULL) {
LIST_REMOVE(cfg, profile_link);
cfg->dvr_profile = profile_find_by_name(NULL);
}
}

/**
*
*/
Expand Down

0 comments on commit 2012dc8

Please sign in to comment.