tvheadend/src/api/api_mpegts.c
2015-01-16 18:53:46 +01:00

411 lines
10 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
( access_t *perm, 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;
tvhtrace("mpegts", "network-list: found input '%s'", mi->mi_name ?: "");
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
( access_t *perm, 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
( access_t *perm, 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
( access_t *perm, 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_scan
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
htsmsg_field_t *f;
htsmsg_t *uuids;
mpegts_network_t *mn;
const char *uuid;
if (!(f = htsmsg_field_find(args, "uuid")))
return -EINVAL;
if ((uuids = htsmsg_field_get_list(f))) {
HTSMSG_FOREACH(f, uuids) {
if (!(uuid = htsmsg_field_get_str(f))) continue;
mn = mpegts_network_find(uuid);
if (mn) {
pthread_mutex_lock(&global_lock);
mpegts_network_scan(mn);
pthread_mutex_unlock(&global_lock);
}
}
} else if ((uuid = htsmsg_field_get_str(f))) {
mn = mpegts_network_find(uuid);
if (mn) {
pthread_mutex_lock(&global_lock);
mpegts_network_scan(mn);
pthread_mutex_unlock(&global_lock);
}
else
return -ENOENT;
} else {
return -EINVAL;
}
return 0;
}
static int
api_mpegts_network_muxclass
( access_t *perm, 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
( access_t *perm, 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
( access_t *perm, 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
( access_t *perm, 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, 0)) continue;
idnode_set_add(ins, (idnode_t*)ms, &conf->filter);
}
}
}
}
/*
* Mux scheduler
*/
static void
api_mpegts_mux_sched_grid
( access_t *perm, 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
( access_t *perm, 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
( access_t *perm, 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_ADMIN, api_mpegts_input_network_list, NULL },
{ "mpegts/network/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_network_grid },
{ "mpegts/network/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_network_class },
{ "mpegts/network/builders", ACCESS_ADMIN, api_mpegts_network_builders, NULL },
{ "mpegts/network/create", ACCESS_ADMIN, api_mpegts_network_create, NULL },
{ "mpegts/network/mux_class", ACCESS_ADMIN, api_mpegts_network_muxclass, NULL },
{ "mpegts/network/mux_create", ACCESS_ADMIN, api_mpegts_network_muxcreate, NULL },
{ "mpegts/network/scan", ACCESS_ADMIN, api_mpegts_network_scan, NULL },
{ "mpegts/mux/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_mux_grid },
{ "mpegts/mux/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_mux_class },
{ "mpegts/service/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_service_grid },
{ "mpegts/service/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_service_class },
{ "mpegts/mux_sched/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_mux_sched_class },
{ "mpegts/mux_sched/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_mux_sched_grid },
{ "mpegts/mux_sched/create", ACCESS_ADMIN, api_mpegts_mux_sched_create, NULL },
#if ENABLE_MPEGTS_DVB
{ "dvb/scanfile/list", ACCESS_ADMIN, api_dvb_scanfile_list, NULL },
#endif
{ NULL },
};
api_register_all(ah);
}