tvheadend/src/api/api_mpegts.c
Adam Sutton eeae897dea mpegts: new feature for scheduling mux tuning events
Could be useful for requesting periodic tuning of mux for EMM harvesting.
Will eventually be used to replace the current OTA EPG scheduling.
2014-04-21 19:39:04 +01:00

371 lines
9.3 KiB
C

/*
* tvheadend - API access to MPEGTS system
*
* Copyright (C) 2013 Adam Sutton
*
* 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 "input.h"
#if ENABLE_MPEGTS_DVB
#include "input/mpegts/scanfile.h"
#endif
/*
* Inputs
*/
static int
api_mpegts_input_network_list
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int i, err = EINVAL;
const char *uuid;
mpegts_input_t *mi;
mpegts_network_t *mn;
idnode_set_t *is;
extern const idclass_t mpegts_input_class;
if (!(uuid = htsmsg_get_str(args, "uuid")))
return EINVAL;
pthread_mutex_lock(&global_lock);
mi = mpegts_input_find(uuid);
if (!mi)
goto exit;
htsmsg_t *l = htsmsg_create_list();
if ((is = mi->mi_network_list(mi))) {
for (i = 0; i < is->is_count; i++) {
char buf[256];
htsmsg_t *e = htsmsg_create_map();
mn = (mpegts_network_t*)is->is_array[i];
htsmsg_add_str(e, "key", idnode_uuid_as_str(is->is_array[i]));
mn->mn_display_name(mn, buf, sizeof(buf));
htsmsg_add_str(e, "val", buf);
htsmsg_add_msg(l, NULL, e);
}
idnode_set_free(is);
}
err = 0;
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
exit:
pthread_mutex_unlock(&global_lock);
return err;
}
/*
* Networks
*/
static void
api_mpegts_network_grid
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
{
mpegts_network_t *mn;
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
idnode_set_add(ins, (idnode_t*)mn, &conf->filter);
}
}
static int
api_mpegts_network_builders
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
mpegts_network_builder_t *mnb;
htsmsg_t *l, *e;
/* List of available builder classes */
l = htsmsg_create_list();
LIST_FOREACH(mnb, &mpegts_network_builders, link)
if ((e = idclass_serialize(mnb->idc)))
htsmsg_add_msg(l, NULL, e);
/* Output */
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
return 0;
}
static int
api_mpegts_network_create
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int err;
const char *class;
htsmsg_t *conf;
mpegts_network_t *mn;
if (!(class = htsmsg_get_str(args, "class")))
return EINVAL;
if (!(conf = htsmsg_get_map(args, "conf")))
return EINVAL;
pthread_mutex_lock(&global_lock);
mn = mpegts_network_build(class, conf);
if (mn) {
err = 0;
*resp = htsmsg_create_map();
mn->mn_config_save(mn);
} else {
err = EINVAL;
}
pthread_mutex_unlock(&global_lock);
return err;
}
static int
api_mpegts_network_muxclass
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int err = EINVAL;
const idclass_t *idc;
mpegts_network_t *mn;
const char *uuid;
if (!(uuid = htsmsg_get_str(args, "uuid")))
return EINVAL;
pthread_mutex_lock(&global_lock);
if (!(mn = mpegts_network_find(uuid)))
goto exit;
if (!(idc = mn->mn_mux_class(mn)))
goto exit;
*resp = idclass_serialize(idc);
err = 0;
exit:
pthread_mutex_unlock(&global_lock);
return err;
}
static int
api_mpegts_network_muxcreate
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int err = EINVAL;
mpegts_network_t *mn;
mpegts_mux_t *mm;
htsmsg_t *conf;
const char *uuid;
if (!(uuid = htsmsg_get_str(args, "uuid")))
return EINVAL;
if (!(conf = htsmsg_get_map(args, "conf")))
return EINVAL;
pthread_mutex_lock(&global_lock);
if (!(mn = mpegts_network_find(uuid)))
goto exit;
if (!(mm = mn->mn_mux_create2(mn, conf)))
goto exit;
mm->mm_config_save(mm);
err = 0;
exit:
pthread_mutex_unlock(&global_lock);
return err;
}
/*
* Muxes
*/
static void
api_mpegts_mux_grid
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
{
mpegts_network_t *mn;
mpegts_mux_t *mm;
int hide = 1;
const char *s = htsmsg_get_str(args, "hidemode");
if (s) {
if (!strcmp(s, "all"))
hide = 2;
else if (!strcmp(s, "none"))
hide = 0;
}
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
//if (hide && !mn->mn_enabled) continue;
LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) {
if (hide == 2 && !mm->mm_is_enabled(mm)) continue;
idnode_set_add(ins, (idnode_t*)mm, &conf->filter);
}
}
}
/*
* Services
*/
static void
api_mpegts_service_grid
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
{
mpegts_network_t *mn;
mpegts_mux_t *mm;
mpegts_service_t *ms;
int hide = 1;
const char *s = htsmsg_get_str(args, "hidemode");
if (s) {
if (!strcmp(s, "all"))
hide = 2;
else if (!strcmp(s, "none"))
hide = 0;
}
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
//if (hide && !mn->mn_enabled) continue;
LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) {
if (hide && !mm->mm_is_enabled(mm)) continue;
LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) {
if (hide == 2 && !ms->s_is_enabled((service_t*)ms)) continue;
idnode_set_add(ins, (idnode_t*)ms, &conf->filter);
}
}
}
}
/*
* Mux scheduler
*/
static void
api_mpegts_mux_sched_grid
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
{
mpegts_mux_sched_t *mms;
LIST_FOREACH(mms, &mpegts_mux_sched_all, mms_link)
idnode_set_add(ins, (idnode_t*)mms, &conf->filter);
}
static int
api_mpegts_mux_sched_create
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
int err;
htsmsg_t *conf;
mpegts_mux_sched_t *mms;
if (!(conf = htsmsg_get_map(args, "conf")))
return EINVAL;
pthread_mutex_lock(&global_lock);
mms = mpegts_mux_sched_create(NULL, conf);
if (mms) {
err = 0;
*resp = htsmsg_create_map();
mpegts_mux_sched_save(mms);
} else {
err = EINVAL;
}
pthread_mutex_unlock(&global_lock);
return err;
}
#if ENABLE_MPEGTS_DVB
static int
api_dvb_scanfile_list
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
char buf[512];
const char *type = htsmsg_get_str(args, "type");
scanfile_region_list_t *list = NULL;
htsmsg_t *l, *e;
scanfile_region_t *r;
scanfile_network_t *n;
if (!type)
return -EINVAL;
if (!strcasecmp(type, "dvbt"))
list = &scanfile_regions_DVBT;
else if (!strcasecmp(type, "dvbc"))
list = &scanfile_regions_DVBC;
else if (!strcasecmp(type, "dvbs"))
list = &scanfile_regions_DVBS;
else if (!strcasecmp(type, "atsc"))
list = &scanfile_regions_ATSC;
else
return -EINVAL;
l = htsmsg_create_list();
LIST_FOREACH(r, list, sfr_link) {
LIST_FOREACH(n, &r->sfr_networks, sfn_link) {
e = htsmsg_create_map();
sprintf(buf, "%s/%s/%s", type, r->sfr_id, n->sfn_id);
htsmsg_add_str(e, "key", buf);
if (list != &scanfile_regions_DVBS) {
sprintf(buf, "%s: %s", r->sfr_name, n->sfn_name);
htsmsg_add_str(e, "val", buf);
} else {
htsmsg_add_str(e, "val", n->sfn_name);
}
htsmsg_add_msg(l, NULL, e);
}
}
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
return 0;
}
#endif
/*
* Init
*/
void
api_mpegts_init ( void )
{
extern const idclass_t mpegts_network_class;
extern const idclass_t mpegts_mux_class;
extern const idclass_t mpegts_service_class;
static api_hook_t ah[] = {
{ "mpegts/input/network_list", ACCESS_ANONYMOUS, api_mpegts_input_network_list, NULL },
{ "mpegts/network/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_network_grid },
{ "mpegts/network/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_network_class },
{ "mpegts/network/builders", ACCESS_ANONYMOUS, api_mpegts_network_builders, NULL },
{ "mpegts/network/create", ACCESS_ANONYMOUS, api_mpegts_network_create, NULL },
{ "mpegts/network/mux_class", ACCESS_ANONYMOUS, api_mpegts_network_muxclass, NULL },
{ "mpegts/network/mux_create", ACCESS_ANONYMOUS, api_mpegts_network_muxcreate, NULL },
{ "mpegts/mux/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_mux_grid },
{ "mpegts/mux/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_class },
{ "mpegts/service/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_service_grid },
{ "mpegts/service/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_service_class },
{ "mpegts/mux_sched/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_sched_class },
{ "mpegts/mux_sched/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_mux_sched_grid },
{ "mpegts/mux_sched/create", ACCESS_ANONYMOUS, api_mpegts_mux_sched_create, NULL },
#if ENABLE_MPEGTS_DVB
{ "dvb/scanfile/list", ACCESS_ANONYMOUS, api_dvb_scanfile_list, NULL },
#endif
{ NULL },
};
api_register_all(ah);
}