tvheadend/src/dvb/dvb_satconf.c

337 lines
6.7 KiB
C

/*
* Satconf
* Copyright (C) 2009 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/>.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
#include "tvheadend.h"
#include "dvb.h"
#include "dtable.h"
#include "notify.h"
/**
*
*/
static void
satconf_notify(th_dvb_adapter_t *tda)
{
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "adapterId", tda->tda_identifier);
notify_by_msg("dvbSatConf", m);
}
/**
*
*/
dvb_satconf_t *
dvb_satconf_entry_find(th_dvb_adapter_t *tda, const char *id, int create)
{
char buf[20];
dvb_satconf_t *sc;
static int tally;
if(id != NULL) {
TAILQ_FOREACH(sc, &tda->tda_satconfs, sc_adapter_link)
if(!strcmp(sc->sc_id, id))
return sc;
}
if(create == 0)
return NULL;
if(id == NULL) {
tally++;
snprintf(buf, sizeof(buf), "%d", tally);
id = buf;
} else {
tally = MAX(atoi(id), tally);
}
sc = calloc(1, sizeof(dvb_satconf_t));
sc->sc_id = strdup(id);
sc->sc_lnb = strdup("Universal");
TAILQ_INSERT_TAIL(&tda->tda_satconfs, sc, sc_adapter_link);
return sc;
}
/**
*
*/
static void
satconf_destroy(th_dvb_adapter_t *tda, dvb_satconf_t *sc)
{
th_dvb_mux_instance_t *tdmi;
while((tdmi = LIST_FIRST(&sc->sc_tdmis)) != NULL) {
tdmi->tdmi_conf.dmc_satconf = NULL;
LIST_REMOVE(tdmi, tdmi_satconf_link);
}
TAILQ_REMOVE(&tda->tda_satconfs, sc, sc_adapter_link);
free(sc->sc_id);
free(sc->sc_name);
free(sc->sc_comment);
free(sc);
}
/**
*
*/
static htsmsg_t *
satconf_record_build(dvb_satconf_t *sc)
{
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "id", sc->sc_id);
htsmsg_add_u32(m, "port", sc->sc_port);
htsmsg_add_str(m, "name", sc->sc_name ?: "");
htsmsg_add_str(m, "comment", sc->sc_comment ?: "");
htsmsg_add_str(m, "lnb", sc->sc_lnb);
return m;
}
/**
*
*/
static htsmsg_t *
satconf_entry_update(void *opaque, const char *id, htsmsg_t *values,
int maycreate)
{
th_dvb_adapter_t *tda = opaque;
uint32_t u32;
dvb_satconf_t *sc;
if((sc = dvb_satconf_entry_find(tda, id, maycreate)) == NULL)
return NULL;
lock_assert(&global_lock);
tvh_str_update(&sc->sc_name, htsmsg_get_str(values, "name"));
tvh_str_update(&sc->sc_comment, htsmsg_get_str(values, "comment"));
tvh_str_update(&sc->sc_lnb, htsmsg_get_str(values, "lnb"));
if(!htsmsg_get_u32(values, "port", &u32))
sc->sc_port = u32;
satconf_notify(tda);
return satconf_record_build(sc);
}
/**
*
*/
static int
satconf_entry_delete(void *opaque, const char *id)
{
th_dvb_adapter_t *tda = opaque;
dvb_satconf_t *sc;
if((sc = dvb_satconf_entry_find(tda, id, 0)) == NULL)
return -1;
satconf_destroy(tda, sc);
satconf_notify(tda);
return 0;
}
/**
*
*/
static htsmsg_t *
satconf_entry_get_all(void *opaque)
{
th_dvb_adapter_t *tda = opaque;
htsmsg_t *r = htsmsg_create_list();
dvb_satconf_t *sc;
TAILQ_FOREACH(sc, &tda->tda_satconfs, sc_adapter_link)
htsmsg_add_msg(r, NULL, satconf_record_build(sc));
return r;
}
/**
*
*/
static htsmsg_t *
satconf_entry_get(void *opaque, const char *id)
{
th_dvb_adapter_t *tda = opaque;
dvb_satconf_t *sc;
if((sc = dvb_satconf_entry_find(tda, id, 0)) == NULL)
return NULL;
return satconf_record_build(sc);
}
/**
*
*/
static htsmsg_t *
satconf_entry_create(void *opaque)
{
th_dvb_adapter_t *tda = opaque;
return satconf_record_build(dvb_satconf_entry_find(tda, NULL, 1));
}
/**
*
*/
static const dtable_class_t satconf_dtc = {
.dtc_record_get = satconf_entry_get,
.dtc_record_get_all = satconf_entry_get_all,
.dtc_record_create = satconf_entry_create,
.dtc_record_update = satconf_entry_update,
.dtc_record_delete = satconf_entry_delete,
.dtc_read_access = ACCESS_ADMIN,
.dtc_write_access = ACCESS_ADMIN,
.dtc_mutex = &global_lock,
};
/**
*
*/
void
dvb_satconf_init(th_dvb_adapter_t *tda)
{
dtable_t *dt;
char name[256];
dvb_satconf_t *sc;
htsmsg_t *r;
snprintf(name, sizeof(name), "dvbsatconf/%s", tda->tda_identifier);
dt = dtable_create(&satconf_dtc, name, tda);
if(!dtable_load(dt)) {
sc = dvb_satconf_entry_find(tda, NULL, 1);
sc->sc_comment = strdup("Default satconf entry");
sc->sc_name = strdup("Default (Port 0, Universal LNB)");
r = satconf_record_build(sc);
dtable_record_store(dt, sc->sc_id, r);
htsmsg_destroy(r);
}
}
/**
*
*/
htsmsg_t *
dvb_satconf_list(th_dvb_adapter_t *tda)
{
dvb_satconf_t *sc;
htsmsg_t *array = htsmsg_create_list();
htsmsg_t *m;
TAILQ_FOREACH(sc, &tda->tda_satconfs, sc_adapter_link) {
m = htsmsg_create_map();
htsmsg_add_str(m, "identifier", sc->sc_id);
htsmsg_add_str(m, "name", sc->sc_name);
htsmsg_add_msg(array, NULL, m);
}
return array;
}
/**
*
*/
static void
add_to_lnblist(htsmsg_t *array, const char *n)
{
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "identifier", n);
htsmsg_add_msg(array, NULL, m);
}
/**
*
*/
htsmsg_t *
dvb_lnblist_get(void)
{
htsmsg_t *array = htsmsg_create_list();
add_to_lnblist(array, "Universal");
add_to_lnblist(array, "DBS");
add_to_lnblist(array, "Standard");
add_to_lnblist(array, "Enhanced");
add_to_lnblist(array, "C-Band");
add_to_lnblist(array, "C-Multi");
add_to_lnblist(array, "Circular 10750");
return array;
}
/**
*
*/
void
dvb_lnb_get_frequencies(const char *id, int *f_low, int *f_hi, int *f_switch)
{
if(!strcmp(id, "Universal")) {
*f_low = 9750000;
*f_hi = 10600000;
*f_switch = 11700000;
} else if(!strcmp(id, "DBS")) {
*f_low = 11250000;
*f_hi = 0;
*f_switch = 0;
} else if(!strcmp(id, "Standard")) {
*f_low = 10000000;
*f_hi = 0;
*f_switch = 0;
} else if(!strcmp(id, "Enhanced")) {
*f_low = 9750000;
*f_hi = 0;
*f_switch = 0;
} else if(!strcmp(id, "C-Band")) {
*f_low = 5150000;
*f_hi = 0;
*f_switch = 0;
} else if(!strcmp(id, "C-Multi")) {
*f_low = 5150000;
*f_hi = 5750000;
*f_switch = 0;
} else if(!strcmp(id, "Circular 10750")) {
*f_low = 10750000;
*f_hi = 0;
*f_switch = 0;
}
}