755 lines
20 KiB
C
755 lines
20 KiB
C
/*
|
|
* tvheadend, AJAX / HTML user 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 "tvhead.h"
|
|
#include "http.h"
|
|
#include "ajaxui.h"
|
|
#include "channels.h"
|
|
|
|
|
|
|
|
/**
|
|
* Render a channel group widget
|
|
*/
|
|
static void
|
|
ajax_chgroup_build(htsbuf_queue_t *tq, channel_group_t *tcg)
|
|
{
|
|
htsbuf_qprintf(tq, "<li id=\"chgrp_%d\">", tcg->tcg_tag);
|
|
|
|
ajax_box_begin(tq, AJAX_BOX_BORDER, NULL, NULL, NULL);
|
|
|
|
htsbuf_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<div style=\"float: left; width: 60%\">"
|
|
"<a href=\"javascript:void(0)\" "
|
|
"onClick=\"$('cheditortab').innerHTML=''; "
|
|
"new Ajax.Updater('groupeditortab', "
|
|
"'/ajax/chgroup_editor/%d', "
|
|
"{method: 'get', evalScripts: true})\" >"
|
|
"%s</a></div>",
|
|
tcg->tcg_tag, tcg->tcg_name);
|
|
|
|
|
|
if(tcg != defgroup) {
|
|
htsbuf_qprintf(tq,
|
|
"<div style=\"float: left; width: 40%\" "
|
|
"class=\"chgroupaction\">"
|
|
"<a href=\"javascript:void(0)\" "
|
|
"onClick=\"dellistentry('/ajax/chgroup_del','%d', '%s');\""
|
|
">Delete</a></div>",
|
|
tcg->tcg_tag, tcg->tcg_name);
|
|
}
|
|
|
|
|
|
htsbuf_qprintf(tq, "</div>");
|
|
ajax_box_end(tq, AJAX_BOX_BORDER);
|
|
htsbuf_qprintf(tq, "</li>");
|
|
}
|
|
|
|
/**
|
|
* Update order of channel groups
|
|
*/
|
|
static int
|
|
ajax_chgroup_updateorder(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
channel_group_t *tcg;
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
http_arg_t *ra;
|
|
|
|
TAILQ_FOREACH(ra, &hc->hc_req_args, link) {
|
|
if(strcmp(ra->key, "channelgrouplist[]") ||
|
|
(tcg = channel_group_by_tag(atoi(ra->val))) == NULL)
|
|
continue;
|
|
|
|
TAILQ_REMOVE(&all_channel_groups, tcg, tcg_global_link);
|
|
TAILQ_INSERT_TAIL(&all_channel_groups, tcg, tcg_global_link);
|
|
}
|
|
|
|
channel_group_settings_write();
|
|
|
|
htsbuf_qprintf(tq, "<span id=\"updatedok\">Updated on server</span>");
|
|
ajax_js(tq, "Effect.Fade('updatedok')");
|
|
http_output_html(hc, hr);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Add a new channel group
|
|
*/
|
|
static int
|
|
ajax_chgroup_add(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
channel_group_t *tcg;
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
const char *name;
|
|
|
|
if((name = http_arg_get(&hc->hc_req_args, "name")) != NULL) {
|
|
|
|
TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link)
|
|
if(!strcmp(name, tcg->tcg_name))
|
|
break;
|
|
|
|
if(tcg == NULL) {
|
|
tcg = channel_group_find(name, 1);
|
|
|
|
ajax_chgroup_build(tq, tcg);
|
|
|
|
/* We must recreate the Sortable object */
|
|
|
|
ajax_js(tq, "Sortable.destroy(\"channelgrouplist\")");
|
|
|
|
ajax_js(tq, "Sortable.create(\"channelgrouplist\", "
|
|
"{onUpdate:function(){updatelistonserver("
|
|
"'channelgrouplist', "
|
|
"'/ajax/chgroup_updateorder', "
|
|
"'list-info'"
|
|
")}});");
|
|
}
|
|
}
|
|
http_output_html(hc, hr);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Delete a channel group
|
|
*/
|
|
static int
|
|
ajax_chgroup_del(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
channel_group_t *tcg;
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
const char *id;
|
|
|
|
if((id = http_arg_get(&hc->hc_req_args, "id")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
if((tcg = channel_group_by_tag(atoi(id))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
htsbuf_qprintf(tq, "$('chgrp_%d').remove();", tcg->tcg_tag);
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
|
|
channel_group_destroy(tcg);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Channel group & channel configuration
|
|
*/
|
|
int
|
|
ajax_config_channels_tab(http_connection_t *hc, http_reply_t *hr)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_group_t *tcg;
|
|
|
|
htsbuf_qprintf(tq, "<div style=\"float: left; width: 30%\">");
|
|
|
|
ajax_box_begin(tq, AJAX_BOX_SIDEBOX, "channelgroups",
|
|
NULL, "Channel groups");
|
|
|
|
htsbuf_qprintf(tq, "<div style=\"height:15px; text-align:center\" "
|
|
"id=\"list-info\"></div>");
|
|
|
|
htsbuf_qprintf(tq, "<ul id=\"channelgrouplist\" class=\"draglist\">");
|
|
|
|
TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
|
|
if(tcg->tcg_hidden)
|
|
continue;
|
|
ajax_chgroup_build(tq, tcg);
|
|
}
|
|
|
|
htsbuf_qprintf(tq, "</ul>");
|
|
|
|
ajax_js(tq, "Sortable.create(\"channelgrouplist\", "
|
|
"{onUpdate:function(){updatelistonserver("
|
|
"'channelgrouplist', "
|
|
"'/ajax/chgroup_updateorder', "
|
|
"'list-info'"
|
|
")}});");
|
|
|
|
/**
|
|
* Add new group
|
|
*/
|
|
|
|
htsbuf_qprintf(tq, "<hr>");
|
|
|
|
ajax_box_begin(tq, AJAX_BOX_BORDER, NULL, NULL, NULL);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<div style=\"height: 25px\">"
|
|
"<div style=\"float: left\">"
|
|
"<input type=\"text\" id=\"newchgrp\">"
|
|
"</div>"
|
|
"<div style=\"float: right\">"
|
|
"<input type=\"button\" value=\"Add\" "
|
|
"onClick=\"javascript:addlistentry_by_widget("
|
|
"'channelgrouplist', 'chgroup_add', 'newchgrp');\">"
|
|
"</div></div>");
|
|
|
|
ajax_box_end(tq, AJAX_BOX_BORDER);
|
|
|
|
ajax_box_end(tq, AJAX_BOX_SIDEBOX);
|
|
htsbuf_qprintf(tq, "</div>");
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<div id=\"groupeditortab\" "
|
|
"style=\"overflow: auto; float: left; width: 30%\"></div>");
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<div id=\"cheditortab\" "
|
|
"style=\"overflow: auto; float: left; width: 40%\"></div>");
|
|
|
|
http_output_html(hc, hr);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Display all channels within the group
|
|
*/
|
|
static int
|
|
ajax_chgroup_editor(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *ch;
|
|
channel_group_t *tcg, *tcg2;
|
|
th_transport_t *t;
|
|
char buf[10];
|
|
int nsources;
|
|
ajax_table_t ta;
|
|
|
|
if(remain == NULL || (tcg = channel_group_by_tag(atoi(remain))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
htsbuf_qprintf(tq, "<script type=\"text/javascript\">\r\n"
|
|
"//<![CDATA[\r\n");
|
|
|
|
/* Select all */
|
|
htsbuf_qprintf(tq, "select_all = function() {\r\n");
|
|
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
|
|
htsbuf_qprintf(tq,
|
|
"$('sel_%d').checked = true;\r\n",
|
|
ch->ch_tag);
|
|
}
|
|
htsbuf_qprintf(tq, "}\r\n");
|
|
|
|
/* Select none */
|
|
htsbuf_qprintf(tq, "select_none = function() {\r\n");
|
|
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
|
|
htsbuf_qprintf(tq,
|
|
"$('sel_%d').checked = false;\r\n",
|
|
ch->ch_tag);
|
|
}
|
|
htsbuf_qprintf(tq, "}\r\n");
|
|
|
|
/* Invert selection */
|
|
htsbuf_qprintf(tq, "select_invert = function() {\r\n");
|
|
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
|
|
htsbuf_qprintf(tq,
|
|
"$('sel_%d').checked = !$('sel_%d').checked;\r\n",
|
|
ch->ch_tag, ch->ch_tag);
|
|
}
|
|
htsbuf_qprintf(tq, "}\r\n");
|
|
|
|
/* Invert selection */
|
|
htsbuf_qprintf(tq, "select_sources = function() {\r\n");
|
|
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
|
|
htsbuf_qprintf(tq,
|
|
"$('sel_%d').checked = %s;\r\n",
|
|
ch->ch_tag, LIST_FIRST(&ch->ch_transports) ? "true" : "false");
|
|
}
|
|
htsbuf_qprintf(tq, "}\r\n");
|
|
|
|
|
|
|
|
/* Invoke AJAX call containing all selected elements */
|
|
htsbuf_qprintf(tq,
|
|
"select_do = function(op, arg1, arg2, check) {\r\n"
|
|
"if(check == true && !confirm(\"Are you sure?\")) {return;}\r\n"
|
|
"var h = new Hash();\r\n"
|
|
"h.set('arg1', arg1);\r\n"
|
|
"h.set('arg2', arg2);\r\n"
|
|
);
|
|
|
|
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
|
|
htsbuf_qprintf(tq,
|
|
"if($('sel_%d').checked) {h.set('%d', 'selected') }\r\n",
|
|
ch->ch_tag, ch->ch_tag);
|
|
}
|
|
|
|
htsbuf_qprintf(tq, " new Ajax.Request('/ajax/chop/' + op, "
|
|
"{parameters: h});\r\n");
|
|
htsbuf_qprintf(tq, "}\r\n");
|
|
|
|
|
|
htsbuf_qprintf(tq,
|
|
"\r\n//]]>\r\n"
|
|
"</script>\r\n");
|
|
|
|
|
|
ajax_box_begin(tq, AJAX_BOX_SIDEBOX, NULL, NULL, tcg->tcg_name);
|
|
|
|
ajax_table_top(&ta, hc, tq, (const char *[])
|
|
{"Channelname", "Sources", "", NULL},
|
|
(int[]){8,2,1});
|
|
|
|
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
|
|
snprintf(buf, sizeof(buf), "%d", ch->ch_tag);
|
|
ajax_table_row_start(&ta, buf);
|
|
|
|
nsources = 0;
|
|
|
|
LIST_FOREACH(t, &ch->ch_transports, tht_ch_link)
|
|
nsources++;
|
|
|
|
ajax_table_cell(&ta, NULL,
|
|
"<a href=\"javascript:void(0)\" "
|
|
"onclick=\"new Ajax.Updater('cheditortab', "
|
|
"'/ajax/cheditor/%d', {method: 'get'})\""
|
|
">%s</a>", ch->ch_tag, ch->ch_name);
|
|
|
|
ajax_table_cell(&ta, NULL, "%d", nsources);
|
|
ajax_table_cell_checkbox(&ta);
|
|
}
|
|
ajax_table_bottom(&ta);
|
|
|
|
htsbuf_qprintf(tq, "<hr>\r\n");
|
|
htsbuf_qprintf(tq, "<div style=\"text-align: center; "
|
|
"overflow: auto; width: 100%\">");
|
|
|
|
ajax_button(tq, "Select all", "select_all()");
|
|
ajax_button(tq, "Select none", "select_none()");
|
|
ajax_button(tq, "Invert selection", "select_invert()");
|
|
ajax_button(tq, "Select channels with sources", "select_sources()");
|
|
htsbuf_qprintf(tq, "</div>\r\n");
|
|
|
|
htsbuf_qprintf(tq, "<hr>\r\n");
|
|
|
|
htsbuf_qprintf(tq, "<div style=\"text-align: center; "
|
|
"overflow: auto; width: 100%\">");
|
|
|
|
ajax_button(tq,
|
|
"Delete all selected...",
|
|
"select_do('delete', '%d', 0, true);", tcg->tcg_tag);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<select id=\"movetarget\" "
|
|
"onChange=\"select_do('changegroup', "
|
|
"$('movetarget').value, '%d', false)\">", tcg->tcg_tag);
|
|
htsbuf_qprintf(tq,
|
|
"<option value="">Move selected channels to group:</option>");
|
|
|
|
TAILQ_FOREACH(tcg2, &all_channel_groups, tcg_global_link) {
|
|
if(tcg2->tcg_hidden || tcg == tcg2)
|
|
continue;
|
|
htsbuf_qprintf(tq, "<option value=\"%d\">%s</option>",
|
|
tcg2->tcg_tag, tcg2->tcg_name);
|
|
}
|
|
htsbuf_qprintf(tq, "</select></div>");
|
|
htsbuf_qprintf(tq, "</div>");
|
|
htsbuf_qprintf(tq, "</div>");
|
|
ajax_box_end(tq, AJAX_BOX_SIDEBOX);
|
|
|
|
|
|
http_output_html(hc, hr);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static struct strtab sourcetypetab[] = {
|
|
{ "DVB", TRANSPORT_DVB },
|
|
{ "V4L", TRANSPORT_V4L },
|
|
{ "IPTV", TRANSPORT_IPTV },
|
|
{ "AVgen", TRANSPORT_AVGEN },
|
|
{ "File", TRANSPORT_STREAMEDFILE },
|
|
};
|
|
|
|
|
|
static struct strtab cdlongname[] = {
|
|
{ "None", COMMERCIAL_DETECT_NONE },
|
|
{ "Swedish TV4 Teletext", COMMERCIAL_DETECT_TTP192 },
|
|
};
|
|
|
|
/**
|
|
* Display all channels within the group
|
|
*/
|
|
static int
|
|
ajax_cheditor(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *ch, *ch2;
|
|
channel_group_t *chg;
|
|
th_transport_t *t;
|
|
const char *s;
|
|
int i;
|
|
|
|
if(remain == NULL || (ch = channel_by_tag(atoi(remain))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ajax_box_begin(tq, AJAX_BOX_SIDEBOX, NULL, NULL, ch->ch_name);
|
|
|
|
if(ch->ch_icon != NULL) {
|
|
htsbuf_qprintf(tq,
|
|
"<div style=\"width: 100%; text-align:center\">"
|
|
"<img src=\"%s\"></div>", ch->ch_icon);
|
|
}
|
|
|
|
htsbuf_qprintf(tq, "<div>Sources:</div>");
|
|
|
|
LIST_FOREACH(t, &ch->ch_transports, tht_ch_link) {
|
|
ajax_box_begin(tq, AJAX_BOX_BORDER, NULL, NULL, NULL);
|
|
htsbuf_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
|
|
htsbuf_qprintf(tq, "<div style=\"float: left; width: 13%%\">%s</div>",
|
|
val2str(t->tht_type, sourcetypetab) ?: "???");
|
|
htsbuf_qprintf(tq, "<div style=\"float: left; width: 87%%\">\"%s\"%s</div>",
|
|
t->tht_svcname, t->tht_scrambled ? " - (scrambled)" : "");
|
|
s = t->tht_sourcename ? t->tht_sourcename(t) : NULL;
|
|
|
|
htsbuf_qprintf(tq, "</div><div style=\"overflow: auto; width: 100%\">");
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<div style=\"float: left; width: 13%%\">"
|
|
"<input %stype=\"checkbox\" class=\"nicebox\" "
|
|
"onClick=\"new Ajax.Request('/ajax/transport_chdisable/%s', "
|
|
"{parameters: {enabled: this.checked}});\">"
|
|
"</div>", t->tht_disabled ? "" : "checked ",
|
|
t->tht_identifier);
|
|
|
|
if(s != NULL)
|
|
htsbuf_qprintf(tq, "<div style=\"float: left; width: 87%%\">%s</div>",
|
|
s);
|
|
|
|
htsbuf_qprintf(tq, "</div>");
|
|
|
|
ajax_box_end(tq, AJAX_BOX_BORDER);
|
|
}
|
|
|
|
htsbuf_qprintf(tq, "<hr>\r\n");
|
|
|
|
htsbuf_qprintf(tq, "<div style=\"overflow: auto; width:100%%\">");
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<input type=\"button\" value=\"Rename...\" "
|
|
"onClick=\"channel_rename('%d', '%s')\">",
|
|
ch->ch_tag, ch->ch_name);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<input type=\"button\" value=\"Delete...\" "
|
|
"onClick=\"channel_delete('%d', '%s')\">",
|
|
ch->ch_tag, ch->ch_name);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<select "
|
|
"onChange=\"channel_merge('%d', this.value);\">",
|
|
ch->ch_tag);
|
|
|
|
htsbuf_qprintf(tq, "<option value=\"n\">Merge to channel:</option>");
|
|
|
|
|
|
TAILQ_FOREACH(chg, &all_channel_groups, tcg_global_link) {
|
|
TAILQ_FOREACH(ch2, &chg->tcg_channels, ch_group_link) {
|
|
if(ch2 != ch)
|
|
htsbuf_qprintf(tq, "<option value=\"%d\">%s</option>",
|
|
ch2->ch_tag, ch2->ch_name);
|
|
}
|
|
}
|
|
|
|
htsbuf_qprintf(tq, "</select>");
|
|
htsbuf_qprintf(tq, "</div>");
|
|
htsbuf_qprintf(tq, "<hr>\r\n");
|
|
|
|
htsbuf_qprintf(tq,
|
|
"<div class=\"infoprefixwidewidefat\">"
|
|
"Commercial detection:</div>"
|
|
"<div>"
|
|
"<select "
|
|
"onChange=\"new Ajax.Request('/ajax/chsetcomdetect/%d', "
|
|
"{parameters: {how: this.value}});\">",
|
|
ch->ch_tag);
|
|
|
|
for(i = 0; i < sizeof(cdlongname) / sizeof(cdlongname[0]); i++) {
|
|
htsbuf_qprintf(tq, "<option %svalue=%d>%s</option>",
|
|
cdlongname[i].val == ch->ch_commercial_detection ?
|
|
"selected " : "",
|
|
cdlongname[i].val, cdlongname[i].str);
|
|
}
|
|
htsbuf_qprintf(tq, "</select></div>");
|
|
htsbuf_qprintf(tq, "</div>");
|
|
|
|
|
|
ajax_box_end(tq, AJAX_BOX_SIDEBOX);
|
|
http_output_html(hc, hr);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Change group for channel(s)
|
|
*/
|
|
static int
|
|
ajax_changegroup(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *ch;
|
|
channel_group_t *tcg;
|
|
http_arg_t *ra;
|
|
const char *s;
|
|
const char *curgrp;
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "arg1")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
if((curgrp = http_arg_get(&hc->hc_req_args, "arg2")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
tcg = channel_group_by_tag(atoi(s));
|
|
if(tcg == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
TAILQ_FOREACH(ra, &hc->hc_req_args, link) {
|
|
if(strcmp(ra->val, "selected"))
|
|
continue;
|
|
|
|
if((ch = channel_by_tag(atoi(ra->key))) != NULL)
|
|
channel_set_group(ch, tcg);
|
|
}
|
|
|
|
htsbuf_qprintf(tq,
|
|
"$('cheditortab').innerHTML=''; "
|
|
"new Ajax.Updater('groupeditortab', "
|
|
"'/ajax/chgroup_editor/%s', "
|
|
"{method: 'get', evalScripts: true});", curgrp);
|
|
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Change commercial detection type for channel(s)
|
|
*/
|
|
static int
|
|
ajax_chsetcomdetect(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
channel_t *ch;
|
|
const char *s;
|
|
|
|
if(remain == NULL || (ch = channel_by_tag(atoi(remain))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "how")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
ch->ch_commercial_detection = atoi(s);
|
|
|
|
channel_settings_write(ch);
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Rename a channel
|
|
*/
|
|
static int
|
|
ajax_chrename(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *ch;
|
|
const char *s;
|
|
|
|
if(remain == NULL || (ch = channel_by_tag(atoi(remain))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "newname")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
if(channel_rename(ch, s)) {
|
|
htsbuf_qprintf(tq, "alert('Channel already exist');");
|
|
} else {
|
|
htsbuf_qprintf(tq,
|
|
"new Ajax.Updater('groupeditortab', "
|
|
"'/ajax/chgroup_editor/%d', "
|
|
"{method: 'get', evalScripts: true});\r\n",
|
|
ch->ch_group->tcg_tag);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"new Ajax.Updater('cheditortab', "
|
|
"'/ajax/cheditor/%d', "
|
|
"{method: 'get', evalScripts: true});\r\n",
|
|
ch->ch_tag);
|
|
}
|
|
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Delete channel
|
|
*/
|
|
static int
|
|
ajax_chdelete(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *ch;
|
|
channel_group_t *tcg;
|
|
|
|
if(remain == NULL || (ch = channel_by_tag(atoi(remain))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
tcg = ch->ch_group;
|
|
|
|
channel_delete(ch);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"new Ajax.Updater('groupeditortab', "
|
|
"'/ajax/chgroup_editor/%d', "
|
|
"{method: 'get', evalScripts: true});\r\n",
|
|
tcg->tcg_tag);
|
|
|
|
htsbuf_qprintf(tq, "$('cheditortab').innerHTML='';\r\n");
|
|
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Merge channel
|
|
*/
|
|
static int
|
|
ajax_chmerge(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *src, *dst;
|
|
channel_group_t *tcg;
|
|
const char *s;
|
|
|
|
if(remain == NULL || (src = channel_by_tag(atoi(remain))) == NULL)
|
|
return HTTP_STATUS_NOT_FOUND;
|
|
|
|
if((s = http_arg_get(&hc->hc_req_args, "dst")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
if((dst = channel_by_tag(atoi(s))) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
tcg = src->ch_group;
|
|
channel_merge(dst, src);
|
|
|
|
htsbuf_qprintf(tq,
|
|
"new Ajax.Updater('groupeditortab', "
|
|
"'/ajax/chgroup_editor/%d', "
|
|
"{method: 'get', evalScripts: true});\r\n",
|
|
tcg->tcg_tag);
|
|
|
|
htsbuf_qprintf(tq, "$('cheditortab').innerHTML='';\r\n");
|
|
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Change group for channel(s)
|
|
*/
|
|
static int
|
|
ajax_chdeletemulti(http_connection_t *hc, http_reply_t *hr,
|
|
const char *remain, void *opaque)
|
|
{
|
|
htsbuf_queue_t *tq = &hr->hr_q;
|
|
channel_t *ch;
|
|
http_arg_t *ra;
|
|
const char *curgrp;
|
|
|
|
if((curgrp = http_arg_get(&hc->hc_req_args, "arg1")) == NULL)
|
|
return HTTP_STATUS_BAD_REQUEST;
|
|
|
|
TAILQ_FOREACH(ra, &hc->hc_req_args, link) {
|
|
if(strcmp(ra->val, "selected"))
|
|
continue;
|
|
|
|
if((ch = channel_by_tag(atoi(ra->key))) != NULL)
|
|
channel_delete(ch);
|
|
}
|
|
|
|
htsbuf_qprintf(tq,
|
|
"$('cheditortab').innerHTML=''; "
|
|
"new Ajax.Updater('groupeditortab', "
|
|
"'/ajax/chgroup_editor/%s', "
|
|
"{method: 'get', evalScripts: true});", curgrp);
|
|
|
|
http_output(hc, hr, "text/javascript; charset=UTF-8", NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
void
|
|
ajax_config_channels_init(void)
|
|
{
|
|
http_path_add("/ajax/chgroup_add" , NULL, ajax_chgroup_add,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chgroup_del" , NULL, ajax_chgroup_del,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chgroup_updateorder", NULL, ajax_chgroup_updateorder,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chgroup_editor", NULL, ajax_chgroup_editor,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/cheditor", NULL, ajax_cheditor,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chop/changegroup", NULL, ajax_changegroup,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chsetcomdetect", NULL, ajax_chsetcomdetect,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chrename", NULL, ajax_chrename,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chdelete", NULL, ajax_chdelete,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chmerge", NULL, ajax_chmerge,
|
|
AJAX_ACCESS_CONFIG);
|
|
http_path_add("/ajax/chop/delete", NULL, ajax_chdeletemulti,
|
|
AJAX_ACCESS_CONFIG);
|
|
|
|
}
|