src/parsers/parser_hevc.c \
src/parsers/parser_latm.c \
src/parsers/parser_avc.c \
- src/parsers/parser_teletext.c \
+ src/parsers/parser_teletext.c
SRCS-2 += \
- src/epggrab/module.c\
- src/epggrab/channel.c\
- src/epggrab/module/pyepg.c\
- src/epggrab/module/xmltv.c\
+ src/epggrab/module.c \
+ src/epggrab/channel.c \
+ src/epggrab/module/pyepg.c \
+ src/epggrab/module/xmltv.c
SRCS-2 += \
src/plumbing/tsfix.c \
src/webui/extjs.c \
src/webui/simpleui.c \
src/webui/statedump.c \
- src/webui/html.c\
- src/webui/webui_api.c\
- src/webui/xmltv.c
+ src/webui/html.c \
+ src/webui/webui_api.c \
+ src/webui/xmltv.c \
+ src/webui/doc_md.c
SRCS-2 += \
src/muxer.c \
TAILQ_INIT(&passwd_entries);
TAILQ_INIT(&ipblock_entries);
+ idclass_register(&access_entry_class);
+ idclass_register(&passwd_entry_class);
+ idclass_register(&ipblock_entry_class);
+
/* Load ipblock entries */
if ((c = hts_settings_load("ipblock")) != NULL) {
HTSMSG_FOREACH(f, c) {
bouquet_t *bq;
RB_INIT(&bouquets);
+ idclass_register(&bouquet_class);
/* Load */
if ((c = hts_settings_load("bouquet")) != NULL) {
RB_INIT(&channels);
memoryinfo_register(&channels_memoryinfo);
+ idclass_register(&channel_class);
+ idclass_register(&channel_tag_class);
/* Tags */
channel_tag_init();
config_scanfile_ok = 0;
config.theme_ui = strdup("blue");
+ idclass_register(&config_class);
+
/* Generate default */
if (!path) {
const char *homedir = getenv("HOME");
{
htsmsg_t *c, *e;
htsmsg_field_t *f;
+ const idclass_t **r;
pthread_mutex_init(&caclients_mutex, NULL);
TAILQ_INIT(&caclients);
+ idclass_register(&caclient_class);
#if ENABLE_TSDEBUG
tsdebugcw_init();
#endif
+ for (r = caclient_classes; *r; r++)
+ idclass_register(*r);
+
if (!(c = hts_settings_load("caclient")))
return;
HTSMSG_FOREACH(f, c) {
htsmsg_field_t *f;
TAILQ_INIT(&autorec_entries);
+ idclass_register(&dvr_autorec_entry_class);
if((l = hts_settings_load("dvr/autorec")) != NULL) {
HTSMSG_FOREACH(f, l) {
if((c = htsmsg_get_map_by_field(f)) == NULL)
/* Default settings */
LIST_INIT(&dvrconfigs);
+ idclass_register(&dvr_config_class);
if ((l = hts_settings_load("dvr/config")) != NULL) {
HTSMSG_FOREACH(f, l) {
dvr_entry_t *de1, *de2;
dvr_in_init = 1;
+ idclass_register(&dvr_entry_class);
rere = htsmsg_create_map();
/* load config, but remove parent/child fields */
if((l = hts_settings_load("dvr/log")) != NULL) {
htsmsg_field_t *f;
TAILQ_INIT(&timerec_entries);
+ idclass_register(&dvr_timerec_entry_class);
if((l = hts_settings_load("dvr/timerec")) != NULL) {
HTSMSG_FOREACH(f, l) {
if((c = htsmsg_get_map_by_field(f)) == NULL)
pthread_mutex_init(&epggrab_mutex, NULL);
pthread_cond_init(&epggrab_cond, NULL);
+ idclass_register(&epggrab_class);
+ idclass_register(&epggrab_mod_class);
+ idclass_register(&epggrab_mod_int_class);
+ idclass_register(&epggrab_mod_ext_class);
+ idclass_register(&epggrab_mod_ota_class);
+
epggrab_channel_init();
/* Initialise modules */
epggrab_channel_init( void )
{
TAILQ_INIT(&epggrab_channel_entries);
+ idclass_register(&epggrab_channel_class);
}
void
}
};
-const idclass_t epggrab_class_mod_int = {
+const idclass_t epggrab_mod_int_class = {
.ic_super = &epggrab_mod_class,
.ic_class = "epggrab_mod_int",
.ic_caption = N_("Internal EPG grabber"),
}
};
-const idclass_t epggrab_class_mod_ext = {
+const idclass_t epggrab_mod_ext_class = {
.ic_super = &epggrab_mod_class,
.ic_class = "epggrab_mod_ext",
.ic_caption = N_("External EPG grabber"),
}
};
-const idclass_t epggrab_class_mod_ota = {
+const idclass_t epggrab_mod_ota_class = {
.ic_super = &epggrab_mod_class,
.ic_class = "epggrab_mod_ota",
.ic_caption = N_("Over-the-air EPG grabber"),
/* Pass through */
epggrab_module_create((epggrab_module_t*)skel,
- cls ?: &epggrab_class_mod_int,
+ cls ?: &epggrab_mod_int_class,
id, saveid, name, priority);
/* Int data */
/* Pass through */
hts_settings_buildpath(path, sizeof(path), "epggrab/%s.sock", sockid);
epggrab_module_int_create((epggrab_module_int_t*)skel,
- &epggrab_class_mod_ext,
+ &epggrab_mod_ext_class,
id, saveid, name, priority, path,
NULL, parse, trans);
/* Pass through */
epggrab_module_create((epggrab_module_t*)skel,
- &epggrab_class_mod_ota,
+ &epggrab_mod_ota_class,
id, saveid, name, priority);
/* Setup */
size_t freesat_huffman_decode
( char *dst, size_t* dstlen, const uint8_t *src, size_t srclen );
+/* **************************************************************************
+ * Classes
+ * *************************************************************************/
+
+extern const idclass_t epggrab_mod_class;
+extern const idclass_t epggrab_mod_int_class;
+extern const idclass_t epggrab_mod_ext_class;
+extern const idclass_t epggrab_mod_ota_class;
+
/* **************************************************************************
* Module setup(s)
* *************************************************************************/
htsmsg_field_t *f;
int i;
- for (i = 0; i <= ESF_CLASS_LAST; i++)
+ for (i = 0; i <= ESF_CLASS_LAST; i++) {
TAILQ_INIT(&esfilters[i]);
+ if (esfilter_classes[i])
+ idclass_register(esfilter_classes[i]);
+ }
if (!(c = hts_settings_load("esfilter")))
return;
#include "access.h"
static const idnodes_rb_t * idnode_domain ( const idclass_t *idc );
-static void idclass_root_register ( idnode_t *in );
+static idnodes_rb_t * idclass_find_domain ( const idclass_t *idc );
typedef struct idclass_link
{
tvhtrace("idnode", "insert node %s", idnode_uuid_as_str(in, ubuf));
/* Register the class */
- idclass_register(class); // Note: we never actually unregister
- idclass_root_register(in);
- assert(in->in_domain);
+ in->in_domain = idclass_find_domain(class);
+ if (in->in_domain == NULL) {
+ tvherror("idnode", "classs '%s' is not registered", class->ic_class);
+ abort();
+ }
c = RB_INSERT_SORTED(in->in_domain, in, in_domain_link, in_cmp);
assert(c == NULL);
return NULL;
}
-void
-idclass_register(const idclass_t *idc)
+static idnodes_rb_t *
+idclass_find_domain(const idclass_t *idc)
{
- while (idc) {
- SKEL_ALLOC(idclasses_skel);
- idclasses_skel->idc = idc;
- if (RB_INSERT_SORTED(&idclasses, idclasses_skel, link, ic_cmp))
- break;
- RB_INIT(&idclasses_skel->nodes); /* not used, but for sure */
- SKEL_USED(idclasses_skel);
- tvhtrace("idnode", "register class %s", idc->ic_class);
- idc = idc->ic_super;
- }
+ idclass_link_t *r;
+ idc = idnode_root_class(idc);
+ SKEL_ALLOC(idclasses_skel);
+ idclasses_skel->idc = idc;
+ r = RB_FIND(&idrootclasses, idclasses_skel, link, ic_cmp);
+ if (r)
+ return &r->nodes;
+ return NULL;
}
static void
-idclass_root_register(idnode_t *in)
+idclass_root_register(const idclass_t *idc)
{
- const idclass_t *idc = in->in_class;
idclass_link_t *r;
- idc = idnode_root_class(idc);
SKEL_ALLOC(idclasses_skel);
idclasses_skel->idc = idc;
r = RB_INSERT_SORTED(&idrootclasses, idclasses_skel, link, ic_cmp);
- if (r) {
- in->in_domain = &r->nodes;
- return;
- }
+ if (r) return;
RB_INIT(&idclasses_skel->nodes);
r = idclasses_skel;
SKEL_USED(idclasses_skel);
tvhtrace("idnode", "register root class %s", idc->ic_class);
- in->in_domain = &r->nodes;
+}
+
+void
+idclass_register(const idclass_t *idc)
+{
+ const idclass_t *prev = NULL;
+ while (idc) {
+ SKEL_ALLOC(idclasses_skel);
+ idclasses_skel->idc = idc;
+ if (RB_INSERT_SORTED(&idclasses, idclasses_skel, link, ic_cmp)) {
+ prev = NULL;
+ break;
+ }
+ RB_INIT(&idclasses_skel->nodes); /* not used, but for sure */
+ SKEL_USED(idclasses_skel);
+ tvhtrace("idnode", "register class %s", idc->ic_class);
+ prev = idc;
+ idc = idc->ic_super;
+ }
+ if (prev)
+ idclass_root_register(prev);
}
const idclass_t *
return t ? t->idc : NULL;
}
+idclass_t const **
+idclass_find_all(void)
+{
+ idclass_link_t *l;
+ idclass_t const **ret;
+ int i = 0, count = 0;
+ RB_FOREACH(l, &idclasses, link)
+ count++;
+ if (count == 0)
+ return NULL;
+ ret = calloc(count + 1, sizeof(idclass_t *));
+ RB_FOREACH(l, &idclasses, link)
+ ret[i++] = l->idc;
+ ret[i] = NULL;
+ return ret;
+}
+
+idclass_t const **
+idclass_find_children(const char *clazz)
+{
+ const idclass_t *ic = idclass_find(clazz), *root;
+ idclass_link_t *l;
+ idclass_t const **ret;
+ int i, count;
+
+ if (ic == NULL)
+ return NULL;
+ root = idnode_root_class(ic);
+ if (root == NULL)
+ return NULL;
+ ret = NULL;
+ count = i = 0;
+ RB_FOREACH(l, &idclasses, link) {
+ if (root == idnode_root_class(l->idc)) {
+ if (i <= count) {
+ count += 50;
+ ret = realloc(ret, count * sizeof(const idclass_t *));
+ }
+ ret[i++] = ic;
+ }
+ }
+ if (i <= count)
+ ret = realloc(ret, (count + 1) * sizeof(const idclass_t *));
+ ret[i] = NULL;
+ return ret;
+}
+
/*
* Just get the class definition
*/
void idclass_register ( const idclass_t *idc );
const idclass_t *idclass_find ( const char *name );
+idclass_t const **idclass_find_all(void);
+idclass_t const **idclass_find_children(const char *name);
const char *idclass_get_caption ( const idclass_t *idc, const char *lang );
htsmsg_t *idclass_serialize0 (const idclass_t *idc, htsmsg_t *list, int optmask, const char *lang);
htsmsg_t *idnode_serialize0 (idnode_t *self, htsmsg_t *list, int optmask, const char *lang);
imagecache_conf.ignore_sslcert = 0;
#endif
+ idclass_register(&imagecache_class);
+
/* Create threads */
#if ENABLE_IMAGECACHE
tvh_cond_init(&imagecache_cond);
.ic_perm_def = ACCESS_ADMIN
};
+/*
+ *
+ */
+void
+tvh_hardware_init ( void )
+{
+ idclass_register(&tvh_input_class);
+ idclass_register(&tvh_input_instance_class);
+}
+
/*
* Create entry
*/
LIST_ENTRY(tvh_hardware) th_link;
};
+void tvh_hardware_init(void);
+
void *tvh_hardware_create0
( void *o, const idclass_t *idc, const char *uuid, htsmsg_t *conf );
void tvh_hardware_delete ( tvh_hardware_t *th );
* Methods
*/
-void input_init ( void );
-
htsmsg_t * tvh_input_stream_create_msg ( tvh_input_stream_t *st );
void tvh_input_stream_destroy ( tvh_input_stream_t *st );
/* Register classes (avoid API 400 errors due to not yet defined) */
idclass_register(&mpegts_network_class);
idclass_register(&mpegts_mux_class);
+ idclass_register(&mpegts_mux_instance_class);
idclass_register(&mpegts_service_class);
+ idclass_register(&mpegts_service_raw_class);
/* FastScan init */
dvb_fastscan_init();
/* Classes */
extern const idclass_t mpegts_network_class;
extern const idclass_t mpegts_mux_class;
+extern const idclass_t mpegts_mux_instance_class;
extern const idclass_t mpegts_service_class;
+extern const idclass_t mpegts_service_raw_class;
extern const idclass_t mpegts_input_class;
/* **************************************************************************
htsmsg_t *c, *e;
htsmsg_field_t *f;
+ /* Register muxes */
+ idclass_register(&iptv_mux_class);
+
/* Register builders */
mpegts_network_register_builder(&iptv_network_class,
iptv_network_builder);
extern const idclass_t iptv_network_class;
extern const idclass_t iptv_auto_network_class;
+extern const idclass_t iptv_mux_class;
extern iptv_input_t *iptv_input;
extern iptv_network_t *iptv_network;
{
force_dvbs = getenv("TVHEADEND_DEBUG_FORCE_DVBS") != NULL;
+ idclass_register(&linuxdvb_adapter_class);
+
+ idclass_register(&linuxdvb_frontend_dvbt_class);
+ idclass_register(&linuxdvb_frontend_dvbs_class);
+ idclass_register(&linuxdvb_frontend_dvbs_slave_class);
+ idclass_register(&linuxdvb_frontend_dvbc_class);
+ idclass_register(&linuxdvb_frontend_atsc_t_class);
+ idclass_register(&linuxdvb_frontend_atsc_c_class);
+ idclass_register(&linuxdvb_frontend_isdb_t_class);
+ idclass_register(&linuxdvb_frontend_isdb_c_class);
+ idclass_register(&linuxdvb_frontend_isdb_s_class);
+ idclass_register(&linuxdvb_frontend_dab_class);
+
+ idclass_register(&linuxdvb_lnb_class);
+ idclass_register(&linuxdvb_rotor_class);
+ idclass_register(&linuxdvb_rotor_gotox_class);
+ idclass_register(&linuxdvb_rotor_usals_class);
+ idclass_register(&linuxdvb_en50494_class);
+ idclass_register(&linuxdvb_switch_class);
+ idclass_register(&linuxdvb_diseqc_class);
+
+ idclass_register(&linuxdvb_satconf_class);
+ idclass_register(&linuxdvb_satconf_lnbonly_class);
+ idclass_register(&linuxdvb_satconf_2port_class);
+ idclass_register(&linuxdvb_satconf_4port_class);
+ idclass_register(&linuxdvb_satconf_en50494_class);
+ idclass_register(&linuxdvb_satconf_advanced_class);
+ idclass_register(&linuxdvb_satconf_ele_class);
+
+#if ENABLE_LINUXDVB_CA
+ idclass_register(&linuxdvb_ca_class);
+#endif
+
/* Install monitor on /dev */
(void)fsmonitor_add("/dev", &devmon);
const idclass_t linuxdvb_frontend_dvbs_slave_class =
{
.ic_super = &linuxdvb_frontend_class,
- .ic_class = "linuxdvb_frontend_dvbs",
+ .ic_class = "linuxdvb_frontend_dvbs_slave",
.ic_caption = N_("Linux DVB-S slave frontend"),
.ic_properties = (const property_t[]){
{
typedef TAILQ_HEAD(linuxdvb_ca_capmt_queue,linuxdvb_ca_capmt) linuxdvb_ca_capmt_queue_t;
#endif
-extern const idclass_t linuxdvb_adapter_class;
-
struct linuxdvb_adapter
{
tvh_hardware_t;
uint32_t le_tune_freq; /* the real frequency to tune to */
};
+/*
+ * Classes
+ */
+
+extern const idclass_t linuxdvb_adapter_class;
+extern const idclass_t linuxdvb_frontend_dvbt_class;
+extern const idclass_t linuxdvb_frontend_dvbs_class;
+extern const idclass_t linuxdvb_frontend_dvbs_slave_class;
+extern const idclass_t linuxdvb_frontend_dvbc_class;
+extern const idclass_t linuxdvb_frontend_atsc_t_class;
+extern const idclass_t linuxdvb_frontend_atsc_c_class;
+extern const idclass_t linuxdvb_frontend_isdb_t_class;
+extern const idclass_t linuxdvb_frontend_isdb_c_class;
+extern const idclass_t linuxdvb_frontend_isdb_s_class;
+extern const idclass_t linuxdvb_frontend_dab_class;
+
+extern const idclass_t linuxdvb_lnb_class;
+extern const idclass_t linuxdvb_rotor_class;
+extern const idclass_t linuxdvb_rotor_gotox_class;
+extern const idclass_t linuxdvb_rotor_usals_class;
+extern const idclass_t linuxdvb_en50494_class;
+extern const idclass_t linuxdvb_switch_class;
+extern const idclass_t linuxdvb_diseqc_class;
+
+extern const idclass_t linuxdvb_satconf_class;
+extern const idclass_t linuxdvb_satconf_lnbonly_class;
+extern const idclass_t linuxdvb_satconf_2port_class;
+extern const idclass_t linuxdvb_satconf_4port_class;
+extern const idclass_t linuxdvb_satconf_en50494_class;
+extern const idclass_t linuxdvb_satconf_advanced_class;
+extern const idclass_t linuxdvb_satconf_ele_class;
+
/*
* Methods
*/
htsmsg_t *c, *e;
htsmsg_field_t *f;
+ idclass_register(&mpegts_mux_sched_class);
+
/* Load settings */
if ((c = hts_settings_load_r(1, "muxsched"))) {
HTSMSG_FOREACH(f, c) {
mnb->idc = idc;
mnb->build = build;
LIST_INSERT_HEAD(&mpegts_network_builders, mnb, link);
+ idclass_register(idc);
}
void
return (mpegts_network_t*)dvb_network_create0(NULL, idc, conf);
}
-static const idclass_t* dvb_network_classes[] = {
+static const idclass_t * dvb_network_classes[] = {
&dvb_network_dvbt_class,
&dvb_network_dvbc_class,
&dvb_network_dvbs_class,
&dvb_network_isdb_c_class,
&dvb_network_isdb_s_class,
#if 0 /* TODO: write DAB stream parser */
- &dvb_network_dab_class
+ &dvb_network_dab_class,
+#endif
+};
+
+static const idclass_t * dvb_mux_classes[] = {
+ &dvb_network_dvbt_class,
+ &dvb_network_dvbc_class,
+ &dvb_network_dvbs_class,
+ &dvb_network_atsc_t_class,
+ &dvb_network_atsc_c_class,
+ &dvb_network_isdb_t_class,
+ &dvb_network_isdb_c_class,
+ &dvb_network_isdb_s_class,
+#if 0 /* TODO: write DAB stream parser */
+ &dvb_network_dab_class,
#endif
};
/* Load list of mux charset global overrides */
dvb_charset_init();
+ /* Register mux classes */
+ for (i = 0; i < ARRAY_SIZE(dvb_mux_classes); i++)
+ idclass_register(dvb_mux_classes[i]);
+
/* Register class builders */
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++)
mpegts_network_register_builder(dvb_network_classes[i],
void satip_init ( int nosatip, str_list_t *clients )
{
+ idclass_register(&satip_device_class);
+
+ idclass_register(&satip_frontend_class);
+ idclass_register(&satip_frontend_dvbt_class);
+ idclass_register(&satip_frontend_dvbs_class);
+ idclass_register(&satip_frontend_dvbs_slave_class);
+ idclass_register(&satip_frontend_atsc_t_class);
+ idclass_register(&satip_frontend_atsc_c_class);
+
+ idclass_register(&satip_satconf_class);
+
satip_enabled = !nosatip;
TAILQ_INIT(&satip_discoveries);
satip_static_clients = clients;
const idclass_t satip_frontend_dvbs_slave_class =
{
.ic_super = &satip_frontend_class,
- .ic_class = "satip_frontend_dvbs",
+ .ic_class = "satip_frontend_dvbs_slave",
.ic_caption = N_("SAT>IP DVB-S slave frontend"),
.ic_properties = (const property_t[]){
{
idnode_set_t *sfc_networks;
};
+/*
+ * Classes
+ */
+extern const idclass_t satip_frontend_class;
+
+extern const idclass_t satip_frontend_dvbt_class;
+extern const idclass_t satip_frontend_dvbs_class;
+extern const idclass_t satip_frontend_dvbs_slave_class;
+extern const idclass_t satip_frontend_atsc_t_class;
+extern const idclass_t satip_frontend_atsc_c_class;
+
+extern const idclass_t satip_satconf_class;
+
/*
* Methods
*/
hdhomerun_debug_set_filename(hdhomerun_debug_obj, s);
hdhomerun_debug_enable(hdhomerun_debug_obj);
}
+ idclass_register(&tvhdhomerun_device_class);
+ idclass_register(&tvhdhomerun_frontend_dvbt_class);
+ idclass_register(&tvhdhomerun_frontend_dvbc_class);
+ idclass_register(&tvhdhomerun_frontend_atsc_t_class);
+ idclass_register(&tvhdhomerun_frontend_atsc_c_class);
TAILQ_INIT(&tvhdhomerun_discoveries);
pthread_mutex_init(&tvhdhomerun_discovery_lock, NULL);
tvh_cond_init(&tvhdhomerun_discovery_cond);
#ifndef __TVH_tvhdhomerun_H__
#define __TVH_tvhdhomerun_H__
+extern const idclass_t tvhdhomerun_device_class;
+extern const idclass_t tvhdhomerun_frontend_dvbt_class;
+extern const idclass_t tvhdhomerun_frontend_dvbc_class;
+extern const idclass_t tvhdhomerun_frontend_atsc_t_class;
+extern const idclass_t tvhdhomerun_frontend_atsc_c_class;
+
void tvhdhomerun_init( void );
void tvhdhomerun_done( void );
config_init(opt_nobackup == 0);
/* Memoryinfo */
+ idclass_register(&memoryinfo_class);
memoryinfo_register(&tasklet_memoryinfo);
#if ENABLE_SLOW_MEMORYINFO
memoryinfo_register(&htsmsg_memoryinfo);
tvhthread_create(&mtimer_tick_tid, NULL, mtimer_tick_thread, NULL, "mtick");
tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL, "tasklet");
+ tvh_hardware_init();
+
dbus_server_init(opt_dbus, opt_dbus_session);
intlconv_init();
profile_register(const idclass_t *clazz, profile_builder_t builder)
{
profile_build_t *pb = calloc(1, sizeof(*pb)), *pb2;
+ idclass_register(clazz);
pb->clazz = clazz;
pb->build = builder;
pb2 = LIST_FIRST(&profile_builders);
int descramble, rewrite_pmt, muxcnf;
char *nat_ip;
+ idclass_register(&satip_server_class);
+
http_server_ip = NULL;
satip_server_bootid = time(NULL);
satip_server_conf.satip_deviceid = 1;
TAILQ_INIT(&service_all);
TAILQ_INIT(&service_raw_all);
TAILQ_INIT(&service_raw_remove);
+ idclass_register(&service_class);
+ idclass_register(&service_raw_class);
pthread_mutex_init(&pending_save_mutex, NULL);
tvh_cond_init(&pending_save_cond);
tvhthread_create(&service_saver_tid, NULL, service_saver, NULL, "service");
htsmsg_t *m;
TAILQ_INIT(&service_mapper_queue);
+ idclass_register(&service_mapper_conf_class);
tvh_cond_init(&service_mapper_cond);
tvhthread_create(&service_mapper_tid, NULL, service_mapper_thread, NULL, "svcmap");
timeshift_conf.max_period = 60; // Hr (60mins)
timeshift_conf.max_size = 10000 * (size_t)1048576; // 10G
+ idclass_register(×hift_conf_class);
+
/* Load settings */
if ((m = hts_settings_load("timeshift/config"))) {
idnode_load(×hift_conf.idnode, m);
void
tvhlog_start ( void )
{
+ idclass_register(&tvhlog_conf_class);
tvhthread_create(&tvhlog_tid, NULL, tvhlog_thread, NULL, "log");
}
http_path_add("/favicon.ico", NULL, favicon, ACCESS_WEB_INTERFACE);
http_path_add("/playlist", NULL, page_http_playlist, ACCESS_ANONYMOUS);
http_path_add("/xmltv", NULL, page_xmltv, ACCESS_ANONYMOUS);
+ http_path_add("/markdown", NULL, page_markdown, ACCESS_ANONYMOUS);
http_path_add("/state", NULL, page_statedump, ACCESS_ADMIN);
int page_static_file(http_connection_t *hc, const char *remain, void *opaque);
int page_xmltv(http_connection_t *hc, const char *remain, void *opaque);
+int page_markdown(http_connection_t *hc, const char *remain, void *opaque);
#if ENABLE_LINUXDVB
void extjs_start_dvb(void);