
Also since the channel name is no longer unique various other things have had to be updated.
1750 lines
50 KiB
C
1750 lines
50 KiB
C
/*
|
|
* tvheadend, EXTJS based interface
|
|
* Copyright (C) 2008 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 <pthread.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include "htsmsg.h"
|
|
#include "htsmsg_json.h"
|
|
|
|
#include "tvheadend.h"
|
|
#include "http.h"
|
|
#include "webui.h"
|
|
#include "access.h"
|
|
#include "dtable.h"
|
|
#include "channels.h"
|
|
|
|
#include "dvr/dvr.h"
|
|
#include "epggrab.h"
|
|
#include "epg.h"
|
|
#include "muxer.h"
|
|
#include "epggrab/private.h"
|
|
#include "config2.h"
|
|
#include "lang_codes.h"
|
|
#include "subscriptions.h"
|
|
#include "imagecache.h"
|
|
#include "timeshift.h"
|
|
#include "tvhtime.h"
|
|
#include "input.h"
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static void
|
|
extjs_load(htsbuf_queue_t *hq, const char *script)
|
|
{
|
|
htsbuf_qprintf(hq,
|
|
"<script type=\"text/javascript\" "
|
|
"src=\"%s\"></script>\n", script);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static void
|
|
extjs_exec(htsbuf_queue_t *hq, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
htsbuf_qprintf(hq, "<script type=\"text/javascript\">\r\n");
|
|
|
|
va_start(ap, fmt);
|
|
htsbuf_vqprintf(hq, fmt, ap);
|
|
va_end(ap);
|
|
|
|
htsbuf_qprintf(hq, "\r\n</script>\r\n");
|
|
}
|
|
|
|
/**
|
|
* PVR info, deliver info about the given PVR entry
|
|
*/
|
|
static int
|
|
extjs_root(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
|
|
#define EXTJSPATH "static/extjs"
|
|
htsbuf_qprintf(hq, "<html>\n");
|
|
htsbuf_qprintf(hq, "<head>\n");
|
|
|
|
// Issue #1504 - IE9 temporary fix
|
|
htsbuf_qprintf(hq, "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=8\">\n");
|
|
|
|
|
|
htsbuf_qprintf(hq, "<script type=\"text/javascript\" src=\""EXTJSPATH"/adapter/ext/ext-base%s.js\"></script>\n"
|
|
"<script type=\"text/javascript\" src=\""EXTJSPATH"/ext-all%s.js\"></script>\n"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\""EXTJSPATH"/resources/css/ext-all-notheme%s.css\">\n"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\""EXTJSPATH"/resources/css/xtheme-blue.css\">\n"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"static/livegrid/resources/css/ext-ux-livegrid.css\">\n"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"static/extjs/examples/ux/gridfilters/css/GridFilters.css\">\n"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"static/extjs/examples/ux/gridfilters/css/RangeMenu.css\">\n"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"static/app/ext.css\">\n",
|
|
tvheadend_webui_debug ? "-debug" : "",
|
|
tvheadend_webui_debug ? "-debug" : "",
|
|
"");//tvheadend_webui_debug ? "" : "-min");
|
|
|
|
extjs_exec(hq, "Ext.BLANK_IMAGE_URL = " "'"EXTJSPATH"/resources/images/default/s.gif';");
|
|
|
|
/**
|
|
* Load extjs extensions
|
|
*/
|
|
extjs_load(hq, "static/app/extensions.js");
|
|
extjs_load(hq, "static/livegrid/livegrid-all.js");
|
|
extjs_load(hq, "static/lovcombo/lovcombo-all.js");
|
|
extjs_load(hq, "static/multiselect/multiselect.js");
|
|
extjs_load(hq, "static/multiselect/ddview.js");
|
|
extjs_load(hq, "static/checkcolumn/CheckColumn.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/GridFilters.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/filter/Filter.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/filter/BooleanFilter.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/filter/DateFilter.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/filter/ListFilter.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/filter/NumericFilter.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/filter/StringFilter.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/menu/ListMenu.js");
|
|
extjs_load(hq, "static/extjs/examples/ux/gridfilters/menu/RangeMenu.js");
|
|
|
|
/**
|
|
* Create a namespace for our app
|
|
*/
|
|
extjs_exec(hq, "Ext.namespace('tvheadend');");
|
|
|
|
/**
|
|
* Load all components
|
|
*/
|
|
extjs_load(hq, "static/app/comet.js");
|
|
extjs_load(hq, "static/app/tableeditor.js");
|
|
extjs_load(hq, "static/app/cteditor.js");
|
|
extjs_load(hq, "static/app/acleditor.js");
|
|
extjs_load(hq, "static/app/cwceditor.js");
|
|
extjs_load(hq, "static/app/capmteditor.js");
|
|
extjs_load(hq, "static/app/tvadapters.js");
|
|
extjs_load(hq, "static/app/idnode.js");
|
|
#if ENABLE_LINUXDVB
|
|
extjs_load(hq, "static/app/dvb.js");
|
|
extjs_load(hq, "static/app/dvb_networks.js");
|
|
extjs_load(hq, "static/app/mpegts.js");
|
|
#endif
|
|
extjs_load(hq, "static/app/iptv.js");
|
|
#if ENABLE_V4L
|
|
extjs_load(hq, "static/app/v4l.js");
|
|
#endif
|
|
#if ENABLE_TIMESHIFT
|
|
extjs_load(hq, "static/app/timeshift.js");
|
|
#endif
|
|
extjs_load(hq, "static/app/chconf.js");
|
|
extjs_load(hq, "static/app/epg.js");
|
|
extjs_load(hq, "static/app/dvr.js");
|
|
extjs_load(hq, "static/app/epggrab.js");
|
|
extjs_load(hq, "static/app/config.js");
|
|
extjs_load(hq, "static/app/tvhlog.js");
|
|
extjs_load(hq, "static/app/status.js");
|
|
|
|
/**
|
|
* Finally, the app itself
|
|
*/
|
|
extjs_load(hq, "static/app/tvheadend.js");
|
|
extjs_exec(hq, "Ext.onReady(tvheadend.app.init, tvheadend.app);");
|
|
|
|
|
|
|
|
|
|
htsbuf_qprintf(hq,
|
|
"<style type=\"text/css\">\n"
|
|
"html, body {\n"
|
|
"\tfont:normal 12px verdana;\n"
|
|
"\tmargin:0;\n"
|
|
"\tpadding:0;\n"
|
|
"\tborder:0 none;\n"
|
|
"\toverflow:hidden;\n"
|
|
"\theight:100%%;\n"
|
|
"}\n"
|
|
"#systemlog {\n"
|
|
"\tfont:normal 12px courier; font-weight: bold;\n"
|
|
"}\n"
|
|
"p {\n"
|
|
"\tmargin:5px;\n"
|
|
"}\n"
|
|
"</style>\n"
|
|
"<title>HTS Tvheadend %s</title>\n"
|
|
"</head>\n"
|
|
"<body>\n"
|
|
"<div id=\"systemlog\"></div>\n"
|
|
"</body></html>\n",
|
|
tvheadend_version);
|
|
http_output_html(hc);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
page_about(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
|
|
htsbuf_qprintf(hq,
|
|
"<center>"
|
|
"<div class=\"about-title\">"
|
|
"HTS Tvheadend %s"
|
|
"</div><br>"
|
|
"© 2006 - 2013 Andreas \303\226man, et al.<br><br>"
|
|
"<img src=\"docresources/tvheadendlogo.png\"><br>"
|
|
"<a href=\"https://tvheadend.org\">"
|
|
"https://tvheadend.org</a><br><br>"
|
|
"Based on software from "
|
|
"<a target=\"_blank\" href=\"http://www.extjs.com/\">ExtJS</a>. "
|
|
"Icons from "
|
|
"<a target=\"_blank\" href=\"http://www.famfamfam.com/lab/icons/silk/\">"
|
|
"FamFamFam</a>"
|
|
"<br><br>"
|
|
"Build: %s"
|
|
"<p>"
|
|
"If you'd like to support the project, please consider a donation."
|
|
"<br/>"
|
|
"All proceeds are used to support server infrastructure and buy test "
|
|
"equipment."
|
|
"<br/>"
|
|
"<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3Z87UEHP3WZK2'><img src='https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif' alt='' /></a>"
|
|
"</center>",
|
|
tvheadend_version,
|
|
tvheadend_version);
|
|
|
|
http_output_html(hc);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_tablemgr(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
dtable_t *dt;
|
|
htsmsg_t *out = NULL, *in, *array;
|
|
|
|
const char *tablename = http_arg_get(&hc->hc_req_args, "table");
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
const char *entries = http_arg_get(&hc->hc_req_args, "entries");
|
|
|
|
if(op == NULL)
|
|
return 400;
|
|
|
|
if(tablename == NULL || (dt = dtable_find(tablename)) == NULL)
|
|
return 404;
|
|
|
|
if(http_access_verify(hc, dt->dt_dtc->dtc_read_access))
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
|
|
in = entries != NULL ? htsmsg_json_deserialize(entries) : NULL;
|
|
|
|
pthread_mutex_lock(dt->dt_dtc->dtc_mutex);
|
|
|
|
if(!strcmp(op, "create")) {
|
|
if(http_access_verify(hc, dt->dt_dtc->dtc_write_access))
|
|
goto noaccess;
|
|
|
|
out = dtable_record_create(dt);
|
|
|
|
} else if(!strcmp(op, "get")) {
|
|
array = dtable_record_get_all(dt);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
} else if(!strcmp(op, "update")) {
|
|
if(http_access_verify(hc, dt->dt_dtc->dtc_write_access))
|
|
goto noaccess;
|
|
|
|
if(in == NULL)
|
|
goto bad;
|
|
|
|
dtable_record_update_by_array(dt, in);
|
|
|
|
} else if(!strcmp(op, "delete")) {
|
|
if(http_access_verify(hc, dt->dt_dtc->dtc_write_access))
|
|
goto noaccess;
|
|
|
|
if(in == NULL)
|
|
goto bad;
|
|
|
|
dtable_record_delete_by_array(dt, in);
|
|
|
|
} else {
|
|
bad:
|
|
pthread_mutex_unlock(dt->dt_dtc->dtc_mutex);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
noaccess:
|
|
pthread_mutex_unlock(dt->dt_dtc->dtc_mutex);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
pthread_mutex_unlock(dt->dt_dtc->dtc_mutex);
|
|
|
|
if(in != NULL)
|
|
htsmsg_destroy(in);
|
|
|
|
if(out == NULL)
|
|
out = htsmsg_create_map();
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* EPG Content Groups
|
|
*/
|
|
static int
|
|
extjs_ecglist(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *out, *array;
|
|
|
|
out = htsmsg_create_map();
|
|
array = epg_genres_list_all(1, 0);
|
|
htsmsg_add_msg(out, "entries", array);
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static htsmsg_t *
|
|
json_single_record(htsmsg_t *rec, const char *root)
|
|
{
|
|
htsmsg_t *out, *array;
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
htsmsg_add_msg(array, NULL, rec);
|
|
htsmsg_add_msg(out, root, array);
|
|
return out;
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *array, *r, *e;
|
|
htsmsg_field_t *f;
|
|
const char *str;
|
|
uint32_t u32;
|
|
|
|
if(op == NULL)
|
|
return 400;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
/* Basic settings (not the advanced schedule) */
|
|
if(!strcmp(op, "loadSettings")) {
|
|
|
|
pthread_mutex_lock(&epggrab_mutex);
|
|
r = htsmsg_create_map();
|
|
if (epggrab_module)
|
|
htsmsg_add_str(r, "module", epggrab_module->id);
|
|
htsmsg_add_u32(r, "interval", epggrab_interval);
|
|
htsmsg_add_u32(r, "channel_rename", epggrab_channel_rename);
|
|
htsmsg_add_u32(r, "channel_renumber", epggrab_channel_renumber);
|
|
htsmsg_add_u32(r, "channel_reicon", epggrab_channel_reicon);
|
|
htsmsg_add_u32(r, "epgdb_periodicsave", epggrab_epgdb_periodicsave / 3600);
|
|
pthread_mutex_unlock(&epggrab_mutex);
|
|
|
|
out = json_single_record(r, "epggrabSettings");
|
|
|
|
/* List of modules and currently states */
|
|
} else if (!strcmp(op, "moduleList")) {
|
|
out = htsmsg_create_map();
|
|
pthread_mutex_lock(&epggrab_mutex);
|
|
array = epggrab_module_list();
|
|
pthread_mutex_unlock(&epggrab_mutex);
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
/* Channel list */
|
|
} else if (!strcmp(op, "channelList")) {
|
|
out = htsmsg_create_map();
|
|
pthread_mutex_lock(&global_lock);
|
|
array = epggrab_channel_list();
|
|
pthread_mutex_unlock(&global_lock);
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
/* Save settings */
|
|
} else if (!strcmp(op, "saveSettings") ) {
|
|
int save = 0;
|
|
pthread_mutex_lock(&epggrab_mutex);
|
|
str = http_arg_get(&hc->hc_req_args, "channel_rename");
|
|
save |= epggrab_set_channel_rename(str ? 1 : 0);
|
|
str = http_arg_get(&hc->hc_req_args, "channel_renumber");
|
|
save |= epggrab_set_channel_renumber(str ? 1 : 0);
|
|
str = http_arg_get(&hc->hc_req_args, "channel_reicon");
|
|
save |= epggrab_set_channel_reicon(str ? 1 : 0);
|
|
if ( (str = http_arg_get(&hc->hc_req_args, "epgdb_periodicsave")) )
|
|
save |= epggrab_set_periodicsave(atoi(str) * 3600);
|
|
if ( (str = http_arg_get(&hc->hc_req_args, "interval")) )
|
|
save |= epggrab_set_interval(atoi(str));
|
|
if ( (str = http_arg_get(&hc->hc_req_args, "module")) )
|
|
save |= epggrab_set_module_by_id(str);
|
|
if ( (str = http_arg_get(&hc->hc_req_args, "external")) ) {
|
|
if ( (array = htsmsg_json_deserialize(str)) ) {
|
|
HTSMSG_FOREACH(f, array) {
|
|
if ( (e = htsmsg_get_map_by_field(f)) ) {
|
|
str = htsmsg_get_str(e, "id");
|
|
u32 = 0;
|
|
htsmsg_get_u32(e, "enabled", &u32);
|
|
if ( str ) save |= epggrab_enable_module_by_id(str, u32);
|
|
}
|
|
}
|
|
htsmsg_destroy(array);
|
|
}
|
|
}
|
|
if (save) epggrab_save();
|
|
pthread_mutex_unlock(&epggrab_mutex);
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else {
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_channeltags(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *array, *e;
|
|
channel_tag_t *ct;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(op != NULL && !strcmp(op, "listTags")) {
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
TAILQ_FOREACH(ct, &channel_tags, ct_link) {
|
|
if(!ct->ct_enabled)
|
|
continue;
|
|
|
|
e = htsmsg_create_map();
|
|
htsmsg_add_u32(e, "identifier", ct->ct_identifier);
|
|
htsmsg_add_str(e, "name", ct->ct_name);
|
|
htsmsg_add_msg(array, NULL, e);
|
|
}
|
|
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
} else {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_confignames(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *array, *e;
|
|
dvr_config_t *cfg;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(op != NULL && !strcmp(op, "list")) {
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
if (http_access_verify(hc, ACCESS_RECORDER_ALL))
|
|
goto skip;
|
|
|
|
LIST_FOREACH(cfg, &dvrconfigs, config_link) {
|
|
e = htsmsg_create_map();
|
|
htsmsg_add_str(e, "identifier", cfg->dvr_config_name);
|
|
if (strlen(cfg->dvr_config_name) == 0)
|
|
htsmsg_add_str(e, "name", "(default)");
|
|
else
|
|
htsmsg_add_str(e, "name", cfg->dvr_config_name);
|
|
htsmsg_add_msg(array, NULL, e);
|
|
}
|
|
|
|
skip:
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
} else {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_dvr_containers(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *array;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(op != NULL && !strcmp(op, "list")) {
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
if (http_access_verify(hc, ACCESS_RECORDER_ALL))
|
|
goto skip;
|
|
|
|
muxer_container_list(array);
|
|
|
|
skip:
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
} else {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_languages(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *array, *e;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(op != NULL && !strcmp(op, "list")) {
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
const lang_code_t *c = lang_codes;
|
|
while (c->code2b) {
|
|
e = htsmsg_create_map();
|
|
htsmsg_add_str(e, "identifier", c->code2b);
|
|
htsmsg_add_str(e, "name", c->desc);
|
|
htsmsg_add_msg(array, NULL, e);
|
|
c++;
|
|
}
|
|
}
|
|
else if(op != NULL && !strcmp(op, "config")) {
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
const lang_code_t **c = lang_code_split2(NULL);
|
|
if(c) {
|
|
int i = 0;
|
|
while (c[i]) {
|
|
e = htsmsg_create_map();
|
|
htsmsg_add_str(e, "identifier", c[i]->code2b);
|
|
htsmsg_add_str(e, "name", c[i]->desc);
|
|
htsmsg_add_msg(array, NULL, e);
|
|
i++;
|
|
}
|
|
free(c);
|
|
}
|
|
}
|
|
else {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *out, *array, *m;
|
|
epg_query_result_t eqr;
|
|
epg_broadcast_t *e;
|
|
epg_episode_t *ee = NULL;
|
|
epg_genre_t *eg = NULL, genre;
|
|
channel_t *ch;
|
|
int start = 0, end, limit, i;
|
|
const char *s;
|
|
char buf[100];
|
|
const char *channel = http_arg_get(&hc->hc_req_args, "channel");
|
|
const char *tag = http_arg_get(&hc->hc_req_args, "tag");
|
|
const char *title = http_arg_get(&hc->hc_req_args, "title");
|
|
const char *lang = http_arg_get(&hc->hc_args, "Accept-Language");
|
|
|
|
if(channel && !channel[0]) channel = NULL;
|
|
if(tag && !tag[0]) tag = NULL;
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "start")) != NULL)
|
|
start = atoi(s);
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "limit")) != NULL)
|
|
limit = atoi(s);
|
|
else
|
|
limit = 20; /* XXX */
|
|
|
|
if ((s = http_arg_get(&hc->hc_req_args, "contenttype"))) {
|
|
genre.code = atoi(s);
|
|
eg = &genre;
|
|
}
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
epg_query(&eqr, channel, tag, eg, title, lang);
|
|
|
|
epg_query_sort(&eqr);
|
|
|
|
htsmsg_add_u32(out, "totalCount", eqr.eqr_entries);
|
|
|
|
|
|
start = MIN(start, eqr.eqr_entries);
|
|
end = MIN(start + limit, eqr.eqr_entries);
|
|
|
|
for(i = start; i < end; i++) {
|
|
e = eqr.eqr_array[i];
|
|
ee = e->episode;
|
|
ch = e->channel;
|
|
if (!ch||!ee) continue;
|
|
|
|
m = htsmsg_create_map();
|
|
|
|
htsmsg_add_str(m, "channel", ch->ch_name);
|
|
htsmsg_add_u32(m, "channelid", channel_get_id(ch));
|
|
if(ch->ch_icon != NULL)
|
|
htsmsg_add_imageurl(m, "chicon", "imagecache/%d", ch->ch_icon);
|
|
|
|
if((s = epg_episode_get_title(ee, lang)))
|
|
htsmsg_add_str(m, "title", s);
|
|
if((s = epg_episode_get_subtitle(ee, lang)))
|
|
htsmsg_add_str(m, "subtitle", s);
|
|
|
|
if((s = epg_broadcast_get_description(e, lang)))
|
|
htsmsg_add_str(m, "description", s);
|
|
else if((s = epg_broadcast_get_summary(e, lang)))
|
|
htsmsg_add_str(m, "description", s);
|
|
|
|
if (epg_episode_number_format(ee, buf, 100, NULL, "Season %d", ".",
|
|
"Episode %d", "/%d"))
|
|
htsmsg_add_str(m, "episode", buf);
|
|
|
|
htsmsg_add_u32(m, "id", e->id);
|
|
htsmsg_add_u32(m, "start", e->start);
|
|
htsmsg_add_u32(m, "end", e->stop);
|
|
htsmsg_add_u32(m, "duration", e->stop - e->start);
|
|
|
|
if(e->serieslink)
|
|
htsmsg_add_str(m, "serieslink", e->serieslink->uri);
|
|
|
|
if((eg = LIST_FIRST(&ee->genre))) {
|
|
htsmsg_add_u32(m, "contenttype", eg->code);
|
|
}
|
|
|
|
dvr_entry_t *de;
|
|
if((de = dvr_entry_find_by_event(e)) != NULL)
|
|
htsmsg_add_str(m, "schedstate", dvr_entry_schedstatus(de));
|
|
|
|
htsmsg_add_msg(array, NULL, m);
|
|
}
|
|
|
|
epg_query_free(&eqr);
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
extjs_epgrelated(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *out, *array, *m;
|
|
epg_broadcast_t *e, *ebc;
|
|
epg_episode_t *ee, *ee2;
|
|
channel_t *ch;
|
|
uint32_t count = 0;
|
|
const char *s;
|
|
char buf[100];
|
|
|
|
const char *lang = http_arg_get(&hc->hc_args, "Accept-Language");
|
|
const char *id = http_arg_get(&hc->hc_req_args, "id");
|
|
const char *type = http_arg_get(&hc->hc_req_args, "type");
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
if ( id && type ) {
|
|
e = epg_broadcast_find_by_id(atoi(id), NULL);
|
|
if ( e && e->episode ) {
|
|
ee = e->episode;
|
|
|
|
/* Alternative broadcasts */
|
|
if (!strcmp(type, "alternative")) {
|
|
LIST_FOREACH(ebc, &ee->broadcasts, ep_link) {
|
|
ch = ebc->channel;
|
|
if ( !ch ) continue; // skip something not viewable
|
|
if ( ebc == e ) continue; // skip self
|
|
count++;
|
|
m = htsmsg_create_map();
|
|
htsmsg_add_u32(m, "id", ebc->id);
|
|
if ( ch->ch_name ) htsmsg_add_str(m, "channel", ch->ch_name);
|
|
if (ch->ch_icon)
|
|
htsmsg_add_imageurl(m, "chicon", "imagecache/%d", ch->ch_icon);
|
|
htsmsg_add_u32(m, "start", ebc->start);
|
|
htsmsg_add_msg(array, NULL, m);
|
|
}
|
|
|
|
/* Related */
|
|
} else if (!strcmp(type, "related")) {
|
|
if (ee->brand) {
|
|
LIST_FOREACH(ee2, &ee->brand->episodes, blink) {
|
|
if (ee2 == ee) continue;
|
|
if (!ee2->title) continue;
|
|
count++;
|
|
m = htsmsg_create_map();
|
|
htsmsg_add_str(m, "uri", ee2->uri);
|
|
if ((s = epg_episode_get_title(ee2, lang)))
|
|
htsmsg_add_str(m, "title", s);
|
|
if ((s = epg_episode_get_subtitle(ee2, lang)))
|
|
htsmsg_add_str(m, "subtitle", s);
|
|
if (epg_episode_number_format(ee2, buf, 100, NULL, "Season %d",
|
|
".", "Episode %d", "/%d"))
|
|
htsmsg_add_str(m, "episode", buf);
|
|
htsmsg_add_msg(array, NULL, m);
|
|
}
|
|
} else if (ee->season) {
|
|
LIST_FOREACH(ee2, &ee->season->episodes, slink) {
|
|
if (ee2 == ee) continue;
|
|
if (!ee2->title) continue;
|
|
count++;
|
|
m = htsmsg_create_map();
|
|
htsmsg_add_str(m, "uri", ee2->uri);
|
|
if ((s = epg_episode_get_title(ee2, lang)))
|
|
htsmsg_add_str(m, "title", s);
|
|
if ((s = epg_episode_get_subtitle(ee2, lang)))
|
|
htsmsg_add_str(m, "subtitle", s);
|
|
if (epg_episode_number_format(ee2, buf, 100, NULL, "Season %d",
|
|
".", "Episode %d", "/%d"))
|
|
htsmsg_add_str(m, "episode", buf);
|
|
htsmsg_add_msg(array, NULL, m);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_add_u32(out, "totalCount", count);
|
|
htsmsg_add_msg(out, "entries", array);
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_epgobject(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *array;
|
|
|
|
if(op == NULL)
|
|
return 400;
|
|
|
|
if (!strcmp(op, "brandList")) {
|
|
out = htsmsg_create_map();
|
|
pthread_mutex_lock(&global_lock);
|
|
array = epg_brand_list();
|
|
pthread_mutex_unlock(&global_lock);
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
} else {
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *r;
|
|
dvr_entry_t *de;
|
|
const char *s;
|
|
int flags = 0;
|
|
dvr_config_t *cfg;
|
|
epg_broadcast_t *e;
|
|
|
|
if(op == NULL)
|
|
op = "loadSettings";
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_RECORDER)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
if(!strcmp(op, "recordEvent") || !strcmp(op, "recordSeries")) {
|
|
|
|
const char *config_name = http_arg_get(&hc->hc_req_args, "config_name");
|
|
|
|
s = http_arg_get(&hc->hc_req_args, "eventId");
|
|
if((e = epg_broadcast_find_by_id(atoi(s), NULL)) == NULL) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
if (http_access_verify(hc, ACCESS_RECORDER_ALL)) {
|
|
config_name = NULL;
|
|
LIST_FOREACH(cfg, &dvrconfigs, config_link) {
|
|
if (cfg->dvr_config_name && hc->hc_username &&
|
|
strcmp(cfg->dvr_config_name, hc->hc_username) == 0) {
|
|
config_name = cfg->dvr_config_name;
|
|
break;
|
|
}
|
|
}
|
|
if (config_name == NULL && hc->hc_username)
|
|
tvhlog(LOG_INFO,"dvr","User '%s' has no dvr config with identical name, using default...", hc->hc_username);
|
|
}
|
|
|
|
if (!strcmp(op, "recordEvent"))
|
|
dvr_entry_create_by_event(config_name,
|
|
e, 0, 0,
|
|
hc->hc_representative, NULL, DVR_PRIO_NORMAL);
|
|
else
|
|
dvr_autorec_add_series_link(config_name, e, hc->hc_representative, "Created from EPG query");
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
} else if(!strcmp(op, "cancelEntry")) {
|
|
s = http_arg_get(&hc->hc_req_args, "entryId");
|
|
|
|
if((de = dvr_entry_find_by_id(atoi(s))) == NULL) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
dvr_entry_cancel(de);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else if(!strcmp(op, "deleteEntry")) {
|
|
s = http_arg_get(&hc->hc_req_args, "entryId");
|
|
|
|
if((de = dvr_entry_find_by_id(atoi(s))) == NULL) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
dvr_entry_delete(de);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else if(!strcmp(op, "createEntry")) {
|
|
|
|
const char *config_name = http_arg_get(&hc->hc_req_args, "config_name");
|
|
const char *title = http_arg_get(&hc->hc_req_args, "title");
|
|
const char *datestr = http_arg_get(&hc->hc_req_args, "date");
|
|
const char *startstr = http_arg_get(&hc->hc_req_args, "starttime");
|
|
const char *stopstr = http_arg_get(&hc->hc_req_args, "stoptime");
|
|
const char *channel = http_arg_get(&hc->hc_req_args, "channelid");
|
|
const char *pri = http_arg_get(&hc->hc_req_args, "pri");
|
|
|
|
channel_t *ch = channel ? channel_find_by_id(atoi(channel)) : NULL;
|
|
|
|
if(ch == NULL || title == NULL ||
|
|
datestr == NULL || strlen(datestr) != 10 ||
|
|
startstr == NULL || strlen(startstr) != 5 ||
|
|
stopstr == NULL || strlen(stopstr) != 5) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
struct tm t = {0};
|
|
t.tm_year = atoi(datestr + 6) - 1900;
|
|
t.tm_mon = atoi(datestr) - 1;
|
|
t.tm_mday = atoi(datestr + 3);
|
|
t.tm_isdst = -1;
|
|
|
|
t.tm_hour = atoi(startstr);
|
|
t.tm_min = atoi(startstr + 3);
|
|
|
|
time_t start = mktime(&t);
|
|
|
|
t.tm_hour = atoi(stopstr);
|
|
t.tm_min = atoi(stopstr + 3);
|
|
|
|
time_t stop = mktime(&t);
|
|
|
|
if(stop < start)
|
|
stop += 86400;
|
|
|
|
if (http_access_verify(hc, ACCESS_RECORDER_ALL)) {
|
|
config_name = NULL;
|
|
LIST_FOREACH(cfg, &dvrconfigs, config_link) {
|
|
if (cfg->dvr_config_name && hc->hc_username &&
|
|
strcmp(cfg->dvr_config_name, hc->hc_username) == 0) {
|
|
config_name = cfg->dvr_config_name;
|
|
break;
|
|
}
|
|
}
|
|
if (config_name == NULL && hc->hc_username)
|
|
tvhlog(LOG_INFO,"dvr","User '%s' has no dvr config with identical name, using default...", hc->hc_username);
|
|
}
|
|
|
|
dvr_entry_create(config_name,
|
|
ch, start, stop, 0, 0, title, NULL, NULL,
|
|
0, hc->hc_representative,
|
|
NULL, dvr_pri2val(pri));
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else if(!strcmp(op, "createAutoRec")) {
|
|
epg_genre_t genre, *eg = NULL;
|
|
if ((s = http_arg_get(&hc->hc_req_args, "contenttype"))) {
|
|
genre.code = atoi(s);
|
|
eg = &genre;
|
|
}
|
|
|
|
dvr_autorec_add(http_arg_get(&hc->hc_req_args, "config_name"),
|
|
http_arg_get(&hc->hc_req_args, "title"),
|
|
http_arg_get(&hc->hc_req_args, "channel"),
|
|
http_arg_get(&hc->hc_req_args, "tag"),
|
|
eg,
|
|
hc->hc_representative, "Created from EPG query");
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else if(!strcmp(op, "loadSettings")) {
|
|
|
|
s = http_arg_get(&hc->hc_req_args, "config_name");
|
|
if (s == NULL)
|
|
s = "";
|
|
cfg = dvr_config_find_by_name_default(s);
|
|
|
|
r = htsmsg_create_map();
|
|
htsmsg_add_str(r, "storage", cfg->dvr_storage);
|
|
htsmsg_add_str(r, "container", muxer_container_type2txt(cfg->dvr_mc));
|
|
if(cfg->dvr_postproc != NULL)
|
|
htsmsg_add_str(r, "postproc", cfg->dvr_postproc);
|
|
htsmsg_add_u32(r, "retention", cfg->dvr_retention_days);
|
|
htsmsg_add_u32(r, "preExtraTime", cfg->dvr_extra_time_pre);
|
|
htsmsg_add_u32(r, "postExtraTime", cfg->dvr_extra_time_post);
|
|
htsmsg_add_u32(r, "dayDirs", !!(cfg->dvr_flags & DVR_DIR_PER_DAY));
|
|
htsmsg_add_u32(r, "channelDirs", !!(cfg->dvr_flags & DVR_DIR_PER_CHANNEL));
|
|
htsmsg_add_u32(r, "channelInTitle", !!(cfg->dvr_flags & DVR_CHANNEL_IN_TITLE));
|
|
htsmsg_add_u32(r, "dateInTitle", !!(cfg->dvr_flags & DVR_DATE_IN_TITLE));
|
|
htsmsg_add_u32(r, "timeInTitle", !!(cfg->dvr_flags & DVR_TIME_IN_TITLE));
|
|
htsmsg_add_u32(r, "whitespaceInTitle", !!(cfg->dvr_flags & DVR_WHITESPACE_IN_TITLE));
|
|
htsmsg_add_u32(r, "titleDirs", !!(cfg->dvr_flags & DVR_DIR_PER_TITLE));
|
|
htsmsg_add_u32(r, "episodeInTitle", !!(cfg->dvr_flags & DVR_EPISODE_IN_TITLE));
|
|
htsmsg_add_u32(r, "cleanTitle", !!(cfg->dvr_flags & DVR_CLEAN_TITLE));
|
|
htsmsg_add_u32(r, "tagFiles", !!(cfg->dvr_flags & DVR_TAG_FILES));
|
|
htsmsg_add_u32(r, "commSkip", !!(cfg->dvr_flags & DVR_SKIP_COMMERCIALS));
|
|
|
|
out = json_single_record(r, "dvrSettings");
|
|
|
|
} else if(!strcmp(op, "saveSettings")) {
|
|
|
|
s = http_arg_get(&hc->hc_req_args, "config_name");
|
|
cfg = dvr_config_find_by_name(s);
|
|
if (cfg == NULL)
|
|
cfg = dvr_config_create(s);
|
|
|
|
tvhlog(LOG_INFO,"dvr","Saving configuration '%s'", cfg->dvr_config_name);
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "storage")) != NULL)
|
|
dvr_storage_set(cfg,s);
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "container")) != NULL)
|
|
dvr_container_set(cfg,s);
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "postproc")) != NULL)
|
|
dvr_postproc_set(cfg,s);
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "retention")) != NULL)
|
|
dvr_retention_set(cfg,atoi(s));
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "preExtraTime")) != NULL)
|
|
dvr_extra_time_pre_set(cfg,atoi(s));
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "postExtraTime")) != NULL)
|
|
dvr_extra_time_post_set(cfg,atoi(s));
|
|
|
|
if(http_arg_get(&hc->hc_req_args, "dayDirs") != NULL)
|
|
flags |= DVR_DIR_PER_DAY;
|
|
if(http_arg_get(&hc->hc_req_args, "channelDirs") != NULL)
|
|
flags |= DVR_DIR_PER_CHANNEL;
|
|
if(http_arg_get(&hc->hc_req_args, "channelInTitle") != NULL)
|
|
flags |= DVR_CHANNEL_IN_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "cleanTitle") != NULL)
|
|
flags |= DVR_CLEAN_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "dateInTitle") != NULL)
|
|
flags |= DVR_DATE_IN_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "timeInTitle") != NULL)
|
|
flags |= DVR_TIME_IN_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "whitespaceInTitle") != NULL)
|
|
flags |= DVR_WHITESPACE_IN_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "titleDirs") != NULL)
|
|
flags |= DVR_DIR_PER_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "episodeInTitle") != NULL)
|
|
flags |= DVR_EPISODE_IN_TITLE;
|
|
if(http_arg_get(&hc->hc_req_args, "tagFiles") != NULL)
|
|
flags |= DVR_TAG_FILES;
|
|
if(http_arg_get(&hc->hc_req_args, "commSkip") != NULL)
|
|
flags |= DVR_SKIP_COMMERCIALS;
|
|
|
|
|
|
dvr_flags_set(cfg,flags);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else if(!strcmp(op, "deleteSettings")) {
|
|
|
|
s = http_arg_get(&hc->hc_req_args, "config_name");
|
|
dvr_config_delete(s);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else {
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque,
|
|
dvr_entry_filter filter, dvr_entry_comparator cmp)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *out, *array, *m;
|
|
dvr_query_result_t dqr;
|
|
dvr_entry_t *de;
|
|
int start = 0, end, limit, i;
|
|
const char *s;
|
|
int64_t fsize = 0;
|
|
char buf[100];
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "start")) != NULL)
|
|
start = atoi(s);
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "limit")) != NULL)
|
|
limit = atoi(s);
|
|
else
|
|
limit = 20; /* XXX */
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_RECORDER)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
|
|
dvr_query_filter(&dqr, filter);
|
|
|
|
dvr_query_sort_cmp(&dqr, cmp);
|
|
|
|
htsmsg_add_u32(out, "totalCount", dqr.dqr_entries);
|
|
|
|
start = MIN(start, dqr.dqr_entries);
|
|
end = MIN(start + limit, dqr.dqr_entries);
|
|
|
|
for(i = start; i < end; i++) {
|
|
de = dqr.dqr_array[i];
|
|
|
|
m = htsmsg_create_map();
|
|
|
|
htsmsg_add_str(m, "channel", DVR_CH_NAME(de));
|
|
if(de->de_channel != NULL) {
|
|
if (de->de_channel->ch_icon)
|
|
htsmsg_add_imageurl(m, "chicon", "imagecache/%d",
|
|
de->de_channel->ch_icon);
|
|
}
|
|
|
|
htsmsg_add_str(m, "config_name", de->de_config_name);
|
|
|
|
if(de->de_title != NULL)
|
|
htsmsg_add_str(m, "title", lang_str_get(de->de_title, NULL));
|
|
|
|
if(de->de_desc != NULL)
|
|
htsmsg_add_str(m, "description", lang_str_get(de->de_desc, NULL));
|
|
|
|
if (de->de_bcast && de->de_bcast->episode)
|
|
if (epg_episode_number_format(de->de_bcast->episode, buf, 100, NULL, "Season %d", ".", "Episode %d", "/%d"))
|
|
htsmsg_add_str(m, "episode", buf);
|
|
|
|
htsmsg_add_u32(m, "id", de->de_id);
|
|
htsmsg_add_u32(m, "start", de->de_start);
|
|
htsmsg_add_u32(m, "end", de->de_stop);
|
|
htsmsg_add_u32(m, "duration", de->de_stop - de->de_start);
|
|
|
|
htsmsg_add_str(m, "creator", de->de_creator);
|
|
|
|
htsmsg_add_str(m, "pri", dvr_val2pri(de->de_pri));
|
|
|
|
htsmsg_add_str(m, "status", dvr_entry_status(de));
|
|
htsmsg_add_str(m, "schedstate", dvr_entry_schedstatus(de));
|
|
|
|
|
|
if(de->de_sched_state == DVR_COMPLETED) {
|
|
fsize = dvr_get_filesize(de);
|
|
if (fsize > 0) {
|
|
char url[100];
|
|
htsmsg_add_s64(m, "filesize", fsize);
|
|
snprintf(url, sizeof(url), "dvrfile/%d", de->de_id);
|
|
htsmsg_add_str(m, "url", url);
|
|
}
|
|
}
|
|
|
|
htsmsg_add_msg(array, NULL, m);
|
|
}
|
|
|
|
dvr_query_free(&dqr);
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
static int is_dvr_entry_finished(dvr_entry_t *entry)
|
|
{
|
|
dvr_entry_sched_state_t state = entry->de_sched_state;
|
|
return state == DVR_COMPLETED && !entry->de_last_error && dvr_get_filesize(entry) != -1;
|
|
}
|
|
|
|
static int is_dvr_entry_upcoming(dvr_entry_t *entry)
|
|
{
|
|
dvr_entry_sched_state_t state = entry->de_sched_state;
|
|
return state == DVR_RECORDING || state == DVR_SCHEDULED;
|
|
}
|
|
|
|
|
|
static int is_dvr_entry_failed(dvr_entry_t *entry)
|
|
{
|
|
if (is_dvr_entry_finished(entry))
|
|
return 0;
|
|
if (is_dvr_entry_upcoming(entry))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
extjs_dvrlist_finished(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
return extjs_dvrlist(hc, remain, opaque, is_dvr_entry_finished, dvr_sort_start_descending);
|
|
}
|
|
|
|
static int
|
|
extjs_dvrlist_upcoming(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
return extjs_dvrlist(hc, remain, opaque, is_dvr_entry_upcoming, dvr_sort_start_ascending);
|
|
}
|
|
|
|
static int
|
|
extjs_dvrlist_failed(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
return extjs_dvrlist(hc, remain, opaque, is_dvr_entry_failed, dvr_sort_start_descending);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_subscriptions(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *out, *array;
|
|
th_subscription_t *s;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
out = htsmsg_create_map();
|
|
array = htsmsg_create_list();
|
|
|
|
LIST_FOREACH(s, &subscriptions, ths_global_link)
|
|
htsmsg_add_msg(array, NULL, subscription_create_msg(s));
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_add_msg(out, "entries", array);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
void
|
|
extjs_service_delete(htsmsg_t *in)
|
|
{
|
|
htsmsg_field_t *f;
|
|
service_t *t;
|
|
const char *id;
|
|
|
|
TAILQ_FOREACH(f, &in->hm_fields, hmf_link) {
|
|
if((id = htsmsg_field_get_string(f)) != NULL &&
|
|
(t = service_find_by_identifier(id)) != NULL)
|
|
service_destroy(t);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_servicedetails(http_connection_t *hc,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *out, *streams, *c;
|
|
service_t *t;
|
|
elementary_stream_t *st;
|
|
caid_t *ca;
|
|
char buf[128];
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(remain == NULL || (t = service_find_by_identifier(remain)) == NULL) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return 404;
|
|
}
|
|
|
|
streams = htsmsg_create_list();
|
|
|
|
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
|
c = htsmsg_create_map();
|
|
|
|
htsmsg_add_u32(c, "pid", st->es_pid);
|
|
|
|
htsmsg_add_str(c, "type", streaming_component_type2txt(st->es_type));
|
|
|
|
switch(st->es_type) {
|
|
default:
|
|
htsmsg_add_str(c, "details", "");
|
|
break;
|
|
|
|
case SCT_CA:
|
|
buf[0] = 0;
|
|
|
|
LIST_FOREACH(ca, &st->es_caids, link) {
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
|
"%s (0x%04x) [0x%08x]",
|
|
"TODO"/*psi_caid2name(ca->caid)*/, ca->caid, ca->providerid);
|
|
}
|
|
|
|
htsmsg_add_str(c, "details", buf);
|
|
break;
|
|
|
|
case SCT_AC3:
|
|
case SCT_MP4A:
|
|
case SCT_AAC:
|
|
case SCT_MPEG2AUDIO:
|
|
htsmsg_add_str(c, "details", st->es_lang);
|
|
break;
|
|
|
|
case SCT_DVBSUB:
|
|
snprintf(buf, sizeof(buf), "%s (%04x %04x)",
|
|
st->es_lang, st->es_composition_id, st->es_ancillary_id);
|
|
htsmsg_add_str(c, "details", buf);
|
|
break;
|
|
|
|
case SCT_MPEG2VIDEO:
|
|
case SCT_H264:
|
|
buf[0] = 0;
|
|
if(st->es_frame_duration)
|
|
snprintf(buf, sizeof(buf), "%2.2f Hz",
|
|
90000.0 / st->es_frame_duration);
|
|
htsmsg_add_str(c, "details", buf);
|
|
break;
|
|
}
|
|
|
|
htsmsg_add_msg(streams, NULL, c);
|
|
}
|
|
|
|
out = htsmsg_create_map();
|
|
#ifdef TODO_FIX_THIS
|
|
htsmsg_add_str(out, "title", t->s_svcname ?: "unnamed service");
|
|
#endif
|
|
|
|
htsmsg_add_msg(out, "streams", streams);
|
|
|
|
#ifdef TODO_FIX_THIS
|
|
if(t->s_dvb_charset != NULL)
|
|
htsmsg_add_str(out, "dvb_charset", t->s_dvb_charset);
|
|
|
|
htsmsg_add_u32(out, "dvb_eit_enable", t->s_dvb_eit_enable);
|
|
#endif
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_config(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *m;
|
|
const char *str;
|
|
|
|
if(op == NULL)
|
|
return 400;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
/* Basic settings */
|
|
if(!strcmp(op, "loadSettings")) {
|
|
|
|
/* Misc */
|
|
pthread_mutex_lock(&global_lock);
|
|
m = config_get_all();
|
|
|
|
/* Time */
|
|
htsmsg_add_u32(m, "tvhtime_update_enabled", tvhtime_update_enabled);
|
|
htsmsg_add_u32(m, "tvhtime_ntp_enabled", tvhtime_ntp_enabled);
|
|
htsmsg_add_u32(m, "tvhtime_tolerance", tvhtime_tolerance);
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
/* Image cache */
|
|
#if ENABLE_IMAGECACHE
|
|
pthread_mutex_lock(&imagecache_mutex);
|
|
htsmsg_add_u32(m, "imagecache_enabled", imagecache_enabled);
|
|
htsmsg_add_u32(m, "imagecache_ok_period", imagecache_ok_period);
|
|
htsmsg_add_u32(m, "imagecache_fail_period", imagecache_fail_period);
|
|
htsmsg_add_u32(m, "imagecache_ignore_sslcert", imagecache_ignore_sslcert);
|
|
pthread_mutex_unlock(&imagecache_mutex);
|
|
#endif
|
|
|
|
if (!m) return HTTP_STATUS_BAD_REQUEST;
|
|
out = json_single_record(m, "config");
|
|
|
|
/* Save settings */
|
|
} else if (!strcmp(op, "saveSettings") ) {
|
|
int save = 0;
|
|
|
|
/* Misc settings */
|
|
pthread_mutex_lock(&global_lock);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "muxconfpath")))
|
|
save |= config_set_muxconfpath(str);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "language")))
|
|
save |= config_set_language(str);
|
|
if (save)
|
|
config_save();
|
|
|
|
/* Time */
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhtime_update_enabled")))
|
|
tvhtime_set_update_enabled(!!str);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhtime_ntp_enabled")))
|
|
tvhtime_set_ntp_enabled(!!str);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhtime_tolerance")))
|
|
tvhtime_set_tolerance(atoi(str));
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
/* Image Cache */
|
|
#if ENABLE_IMAGECACHE
|
|
pthread_mutex_lock(&imagecache_mutex);
|
|
str = http_arg_get(&hc->hc_req_args, "imagecache_enabled");
|
|
save = imagecache_set_enabled(!!str);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "imagecache_ok_period")))
|
|
save |= imagecache_set_ok_period(atoi(str));
|
|
if ((str = http_arg_get(&hc->hc_req_args, "imagecache_fail_period")))
|
|
save |= imagecache_set_fail_period(atoi(str));
|
|
str = http_arg_get(&hc->hc_req_args, "imagecache_ignore_sslcert");
|
|
save |= imagecache_set_ignore_sslcert(!!str);
|
|
if (save)
|
|
imagecache_save();
|
|
pthread_mutex_unlock(&imagecache_mutex);
|
|
#endif
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else {
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int
|
|
extjs_tvhlog(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *m;
|
|
|
|
if(op == NULL)
|
|
return 400;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
/* Basic settings */
|
|
if(!strcmp(op, "loadSettings")) {
|
|
char str[2048];
|
|
|
|
/* Get config */
|
|
pthread_mutex_lock(&tvhlog_mutex);
|
|
m = htsmsg_create_map();
|
|
htsmsg_add_u32(m, "tvhlog_level", tvhlog_level);
|
|
htsmsg_add_u32(m, "tvhlog_trace_on", tvhlog_level > LOG_DEBUG);
|
|
tvhlog_get_trace(str, sizeof(str));
|
|
htsmsg_add_str(m, "tvhlog_trace", str);
|
|
tvhlog_get_debug(str, sizeof(str));
|
|
htsmsg_add_str(m, "tvhlog_debug", str);
|
|
htsmsg_add_str(m, "tvhlog_path", tvhlog_path ?: "");
|
|
htsmsg_add_u32(m, "tvhlog_options", tvhlog_options);
|
|
htsmsg_add_u32(m, "tvhlog_dbg_syslog",
|
|
tvhlog_options & TVHLOG_OPT_DBG_SYSLOG);
|
|
pthread_mutex_unlock(&tvhlog_mutex);
|
|
|
|
if (!m) return HTTP_STATUS_BAD_REQUEST;
|
|
out = json_single_record(m, "config");
|
|
|
|
/* Save settings */
|
|
} else if (!strcmp(op, "saveSettings") ) {
|
|
const char *str;
|
|
|
|
pthread_mutex_lock(&tvhlog_mutex);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_level")))
|
|
tvhlog_level = atoi(str);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_trace_on")))
|
|
tvhlog_level = LOG_TRACE;
|
|
else
|
|
tvhlog_level = LOG_DEBUG;
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_path"))) {
|
|
free(tvhlog_path);
|
|
if (*str)
|
|
tvhlog_path = strdup(str);
|
|
else
|
|
tvhlog_path = NULL;
|
|
}
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_options")))
|
|
tvhlog_options = atoi(str);
|
|
if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_dbg_syslog")))
|
|
tvhlog_options |= TVHLOG_OPT_DBG_SYSLOG;
|
|
else
|
|
tvhlog_options &= ~TVHLOG_OPT_DBG_SYSLOG;
|
|
tvhlog_set_trace(http_arg_get(&hc->hc_req_args, "tvhlog_trace"));
|
|
tvhlog_set_debug(http_arg_get(&hc->hc_req_args, "tvhlog_debug"));
|
|
pthread_mutex_unlock(&tvhlog_mutex);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else {
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Capability check
|
|
*/
|
|
static int
|
|
extjs_capabilities(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
htsmsg_t *l = tvheadend_capabilities_list(0);
|
|
htsmsg_json_serialize(l, hq, 0);
|
|
htsmsg_destroy(l);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
#if ENABLE_TIMESHIFT
|
|
static int
|
|
extjs_timeshift(http_connection_t *hc, const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *hq = &hc->hc_reply;
|
|
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
|
htsmsg_t *out, *m;
|
|
const char *str;
|
|
|
|
if(op == NULL)
|
|
return 400;
|
|
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
|
pthread_mutex_unlock(&global_lock);
|
|
return HTTP_STATUS_UNAUTHORIZED;
|
|
}
|
|
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
/* Basic settings (not the advanced schedule) */
|
|
if(!strcmp(op, "loadSettings")) {
|
|
pthread_mutex_lock(&global_lock);
|
|
m = htsmsg_create_map();
|
|
htsmsg_add_u32(m, "timeshift_enabled", timeshift_enabled);
|
|
htsmsg_add_u32(m, "timeshift_ondemand", timeshift_ondemand);
|
|
if (timeshift_path)
|
|
htsmsg_add_str(m, "timeshift_path", timeshift_path);
|
|
htsmsg_add_u32(m, "timeshift_unlimited_period", timeshift_unlimited_period);
|
|
htsmsg_add_u32(m, "timeshift_max_period", timeshift_max_period / 60);
|
|
htsmsg_add_u32(m, "timeshift_unlimited_size", timeshift_unlimited_size);
|
|
htsmsg_add_u32(m, "timeshift_max_size", timeshift_max_size / 1048576);
|
|
pthread_mutex_unlock(&global_lock);
|
|
out = json_single_record(m, "config");
|
|
|
|
/* Save settings */
|
|
} else if (!strcmp(op, "saveSettings") ) {
|
|
pthread_mutex_lock(&global_lock);
|
|
timeshift_enabled = http_arg_get(&hc->hc_req_args, "timeshift_enabled") ? 1 : 0;
|
|
timeshift_ondemand = http_arg_get(&hc->hc_req_args, "timeshift_ondemand") ? 1 : 0;
|
|
if ((str = http_arg_get(&hc->hc_req_args, "timeshift_path"))) {
|
|
if (timeshift_path)
|
|
free(timeshift_path);
|
|
timeshift_path = strdup(str);
|
|
}
|
|
timeshift_unlimited_period = http_arg_get(&hc->hc_req_args, "timeshift_unlimited_period") ? 1 : 0;
|
|
if ((str = http_arg_get(&hc->hc_req_args, "timeshift_max_period")))
|
|
timeshift_max_period = (uint32_t)atol(str) * 60;
|
|
timeshift_unlimited_size = http_arg_get(&hc->hc_req_args, "timeshift_unlimited_size") ? 1 : 0;
|
|
if ((str = http_arg_get(&hc->hc_req_args, "timeshift_max_size")))
|
|
timeshift_max_size = atol(str) * 1048576LL;
|
|
timeshift_save();
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
out = htsmsg_create_map();
|
|
htsmsg_add_u32(out, "success", 1);
|
|
|
|
} else {
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
}
|
|
|
|
htsmsg_json_serialize(out, hq, 0);
|
|
htsmsg_destroy(out);
|
|
http_output_content(hc, "text/x-json; charset=UTF-8");
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* WEB user interface
|
|
*/
|
|
void
|
|
extjs_start(void)
|
|
{
|
|
http_path_add("/about.html", NULL, page_about, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/extjs.html", NULL, extjs_root, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/capabilities", NULL, extjs_capabilities, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/tablemgr", NULL, extjs_tablemgr, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/epggrab", NULL, extjs_epggrab, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/channeltags", NULL, extjs_channeltags, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/confignames", NULL, extjs_confignames, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/epg", NULL, extjs_epg, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/epgrelated", NULL, extjs_epgrelated, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/epgobject", NULL, extjs_epgobject, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/dvr", NULL, extjs_dvr, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/dvrlist_upcoming", NULL, extjs_dvrlist_upcoming, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/dvrlist_finished", NULL, extjs_dvrlist_finished, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/dvrlist_failed", NULL, extjs_dvrlist_failed, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/dvr_containers", NULL, extjs_dvr_containers, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/subscriptions", NULL, extjs_subscriptions, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/ecglist", NULL, extjs_ecglist, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/config", NULL, extjs_config, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/languages", NULL, extjs_languages, ACCESS_WEB_INTERFACE);
|
|
http_path_add("/servicedetails", NULL, extjs_servicedetails, ACCESS_ADMIN);
|
|
#if ENABLE_TIMESHIFT
|
|
http_path_add("/timeshift", NULL, extjs_timeshift, ACCESS_ADMIN);
|
|
#endif
|
|
http_path_add("/tvhlog", NULL, extjs_tvhlog, ACCESS_ADMIN);
|
|
|
|
#if ENABLE_V4L
|
|
extjs_start_v4l();
|
|
#endif
|
|
}
|