Add support for copying a selection of muxes from one DVB adapter to another in the web UI.
This commit is contained in:
parent
55059017fa
commit
8e24c5960e
7 changed files with 226 additions and 60 deletions
|
@ -262,6 +262,8 @@ const char *dvb_mux_add_by_params(th_dvb_adapter_t *tda,
|
|||
int polarisation,
|
||||
const char *satconf);
|
||||
|
||||
int dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src);
|
||||
|
||||
/**
|
||||
* DVB Transport (aka DVB service)
|
||||
*/
|
||||
|
|
|
@ -359,69 +359,19 @@ void
|
|||
dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src)
|
||||
{
|
||||
th_dvb_mux_instance_t *tdmi_src, *tdmi_dst;
|
||||
th_transport_t *t_src, *t_dst;
|
||||
th_stream_t *st_src, *st_dst;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
while((tdmi_dst = LIST_FIRST(&dst->tda_muxes)) != NULL)
|
||||
dvb_mux_destroy(tdmi_dst);
|
||||
|
||||
LIST_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) {
|
||||
LIST_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link)
|
||||
dvb_mux_copy(dst, tdmi_src);
|
||||
|
||||
tdmi_dst = dvb_mux_create(dst,
|
||||
&tdmi_src->tdmi_conf,
|
||||
tdmi_src->tdmi_transport_stream_id,
|
||||
tdmi_src->tdmi_network,
|
||||
"copy operation", tdmi_src->tdmi_enabled,
|
||||
NULL);
|
||||
|
||||
|
||||
assert(tdmi_dst != NULL);
|
||||
|
||||
LIST_FOREACH(t_src, &tdmi_src->tdmi_transports, tht_group_link) {
|
||||
t_dst = dvb_transport_find(tdmi_dst,
|
||||
t_src->tht_dvb_service_id,
|
||||
t_src->tht_pmt_pid, NULL);
|
||||
|
||||
t_dst->tht_pcr_pid = t_src->tht_pcr_pid;
|
||||
t_dst->tht_enabled = t_src->tht_enabled;
|
||||
t_dst->tht_servicetype = t_src->tht_servicetype;
|
||||
t_dst->tht_scrambled = t_src->tht_scrambled;
|
||||
|
||||
if(t_src->tht_provider != NULL)
|
||||
t_dst->tht_provider = strdup(t_src->tht_provider);
|
||||
|
||||
if(t_src->tht_svcname != NULL)
|
||||
t_dst->tht_svcname = strdup(t_src->tht_svcname);
|
||||
|
||||
if(t_src->tht_ch != NULL)
|
||||
transport_map_channel(t_dst, t_src->tht_ch, 0);
|
||||
|
||||
pthread_mutex_lock(&t_src->tht_stream_mutex);
|
||||
|
||||
LIST_FOREACH(st_src, &t_src->tht_components, st_link) {
|
||||
|
||||
st_dst = transport_stream_create(t_dst,
|
||||
st_src->st_pid,
|
||||
st_src->st_type);
|
||||
|
||||
st_dst->st_tb = (AVRational){1, 90000};
|
||||
|
||||
memcpy(st_dst->st_lang, st_src->st_lang, 4);
|
||||
st_dst->st_frame_duration = st_src->st_frame_duration;
|
||||
st_dst->st_caid = st_src->st_caid;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&t_src->tht_stream_mutex);
|
||||
t_dst->tht_config_save(t_dst); // Save config
|
||||
|
||||
}
|
||||
dvb_mux_save(tdmi_dst);
|
||||
}
|
||||
tda_save(dst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -875,3 +875,69 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int
|
||||
dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src)
|
||||
{
|
||||
th_dvb_mux_instance_t *tdmi_dst;
|
||||
th_transport_t *t_src, *t_dst;
|
||||
th_stream_t *st_src, *st_dst;
|
||||
|
||||
tdmi_dst = dvb_mux_create(dst,
|
||||
&tdmi_src->tdmi_conf,
|
||||
tdmi_src->tdmi_transport_stream_id,
|
||||
tdmi_src->tdmi_network,
|
||||
"copy operation", tdmi_src->tdmi_enabled,
|
||||
NULL);
|
||||
|
||||
if(tdmi_dst == NULL)
|
||||
return -1; // Already exist
|
||||
|
||||
LIST_FOREACH(t_src, &tdmi_src->tdmi_transports, tht_group_link) {
|
||||
t_dst = dvb_transport_find(tdmi_dst,
|
||||
t_src->tht_dvb_service_id,
|
||||
t_src->tht_pmt_pid, NULL);
|
||||
|
||||
t_dst->tht_pcr_pid = t_src->tht_pcr_pid;
|
||||
t_dst->tht_enabled = t_src->tht_enabled;
|
||||
t_dst->tht_servicetype = t_src->tht_servicetype;
|
||||
t_dst->tht_scrambled = t_src->tht_scrambled;
|
||||
|
||||
if(t_src->tht_provider != NULL)
|
||||
t_dst->tht_provider = strdup(t_src->tht_provider);
|
||||
|
||||
if(t_src->tht_svcname != NULL)
|
||||
t_dst->tht_svcname = strdup(t_src->tht_svcname);
|
||||
|
||||
if(t_src->tht_ch != NULL)
|
||||
transport_map_channel(t_dst, t_src->tht_ch, 0);
|
||||
|
||||
pthread_mutex_lock(&t_src->tht_stream_mutex);
|
||||
pthread_mutex_lock(&t_dst->tht_stream_mutex);
|
||||
|
||||
LIST_FOREACH(st_src, &t_src->tht_components, st_link) {
|
||||
|
||||
|
||||
st_dst = transport_stream_create(t_dst,
|
||||
st_src->st_pid,
|
||||
st_src->st_type);
|
||||
|
||||
st_dst->st_tb = (AVRational){1, 90000};
|
||||
|
||||
memcpy(st_dst->st_lang, st_src->st_lang, 4);
|
||||
st_dst->st_frame_duration = st_src->st_frame_duration;
|
||||
st_dst->st_caid = st_src->st_caid;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&t_dst->tht_stream_mutex);
|
||||
pthread_mutex_unlock(&t_src->tht_stream_mutex);
|
||||
|
||||
t_dst->tht_config_save(t_dst); // Save config
|
||||
|
||||
}
|
||||
dvb_mux_save(tdmi_dst);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -946,9 +946,10 @@ static int
|
|||
extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
th_dvb_adapter_t *tda;
|
||||
th_dvb_adapter_t *tda, *ref;
|
||||
htsmsg_t *out, *array, *r;
|
||||
const char *op = http_arg_get(&hc->hc_req_args, "op");
|
||||
const char *sibling = http_arg_get(&hc->hc_req_args, "sibling");
|
||||
const char *s, *sc;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
th_transport_t *t;
|
||||
|
@ -958,11 +959,14 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
|
|||
if(remain == NULL) {
|
||||
/* Just list all adapters */
|
||||
|
||||
ref = sibling != NULL ? dvb_adapter_find_by_identifier(sibling) : NULL;
|
||||
|
||||
array = htsmsg_create_list();
|
||||
|
||||
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link)
|
||||
htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda));
|
||||
|
||||
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
|
||||
if(ref == NULL || (ref != tda && ref->tda_type == tda->tda_type))
|
||||
htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda));
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
out = htsmsg_create_map();
|
||||
htsmsg_add_msg(out, "entries", array);
|
||||
|
@ -1504,6 +1508,62 @@ extjs_dvb_addmux(http_connection_t *hc, const char *remain, void *opaque)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque)
|
||||
{
|
||||
htsmsg_t *out;
|
||||
htsbuf_queue_t *hq = &hc->hc_reply;
|
||||
th_dvb_adapter_t *tda;
|
||||
htsmsg_t *in;
|
||||
const char *entries = http_arg_get(&hc->hc_req_args, "entries");
|
||||
const char *id;
|
||||
htsmsg_field_t *f;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
|
||||
in = entries != NULL ? htsmsg_json_deserialize(entries) : NULL;
|
||||
|
||||
if(in == NULL)
|
||||
return 400;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(remain == NULL ||
|
||||
(tda = dvb_adapter_find_by_identifier(remain)) == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return 404;
|
||||
}
|
||||
|
||||
|
||||
TAILQ_FOREACH(f, &in->hm_fields, hmf_link) {
|
||||
if((id = htsmsg_field_get_string(f)) != NULL &&
|
||||
(tdmi = dvb_mux_find_by_identifier(id)) != NULL &&
|
||||
tda != tdmi->tdmi_adapter) {
|
||||
|
||||
if(dvb_mux_copy(tda, tdmi)) {
|
||||
char buf[100];
|
||||
dvb_mux_nicename(buf, sizeof(buf), tdmi);
|
||||
|
||||
tvhlog(LOG_NOTICE, "DVB",
|
||||
"Skipped copy of mux %s to adapter %s, mux already exist",
|
||||
buf, tda->tda_displayname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
out = htsmsg_create_map();
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
htsmsg_destroy(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -1737,6 +1797,9 @@ extjs_start(void)
|
|||
http_path_add("/dvb/addmux",
|
||||
NULL, extjs_dvb_addmux, ACCESS_ADMIN);
|
||||
|
||||
http_path_add("/dvb/copymux",
|
||||
NULL, extjs_dvb_copymux, ACCESS_ADMIN);
|
||||
|
||||
http_path_add("/iptv/services",
|
||||
NULL, extjs_iptvservices, ACCESS_ADMIN);
|
||||
|
||||
|
|
|
@ -194,6 +194,78 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function copySelected() {
|
||||
|
||||
function doCopy() {
|
||||
var selectedKeys = grid.selModel.selections.keys;
|
||||
var target = panel.getForm().getValues('targetID').targetID;
|
||||
|
||||
Ext.Ajax.request({
|
||||
url: "dvb/copymux/" + target,
|
||||
params: {
|
||||
entries:Ext.encode(selectedKeys)
|
||||
},
|
||||
failure:function(response,options) {
|
||||
Ext.MessageBox.alert('Server Error','Unable to copy');
|
||||
},
|
||||
success: function() {
|
||||
win.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
targetStore = new Ext.data.JsonStore({
|
||||
root:'entries',
|
||||
id: 'identifier',
|
||||
url:'dvb/adapter',
|
||||
fields: ['identifier',
|
||||
'name'],
|
||||
baseParams: {sibling: adapterId}
|
||||
});
|
||||
|
||||
var panel = new Ext.FormPanel({
|
||||
frame:true,
|
||||
border:true,
|
||||
bodyStyle:'padding:5px',
|
||||
labelAlign: 'right',
|
||||
labelWidth: 110,
|
||||
defaultType: 'textfield',
|
||||
items: [
|
||||
|
||||
new Ext.form.ComboBox({
|
||||
store: targetStore,
|
||||
fieldLabel: 'Target adapter',
|
||||
name: 'targetadapter',
|
||||
hiddenName: 'targetID',
|
||||
editable: false,
|
||||
allowBlank: false,
|
||||
triggerAction: 'all',
|
||||
mode: 'remote',
|
||||
displayField:'name',
|
||||
valueField:'identifier',
|
||||
emptyText: 'Select target adapter...'
|
||||
})
|
||||
],
|
||||
buttons: [{
|
||||
text: 'Copy',
|
||||
handler: doCopy
|
||||
}]
|
||||
});
|
||||
|
||||
win = new Ext.Window({
|
||||
title: 'Copy multiplex configuration',
|
||||
layout: 'fit',
|
||||
width: 500,
|
||||
height: 120,
|
||||
modal: true,
|
||||
plain: true,
|
||||
items: panel
|
||||
});
|
||||
win.show();
|
||||
}
|
||||
|
||||
|
||||
function saveChanges() {
|
||||
var mr = store.getModifiedRecords();
|
||||
|
@ -226,13 +298,22 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) {
|
|||
var delBtn = new Ext.Toolbar.Button({
|
||||
tooltip: 'Delete one or more selected muxes',
|
||||
iconCls:'remove',
|
||||
text: 'Delete selected',
|
||||
text: 'Delete selected...',
|
||||
handler: delSelected,
|
||||
disabled: true
|
||||
});
|
||||
|
||||
var copyBtn = new Ext.Toolbar.Button({
|
||||
tooltip: 'Copy selected multiplexes to other adapter',
|
||||
iconCls:'clone',
|
||||
text: 'Copy to other adapter...',
|
||||
handler: copySelected,
|
||||
disabled: true
|
||||
});
|
||||
|
||||
selModel.on('selectionchange', function(s) {
|
||||
delBtn.setDisabled(s.getCount() == 0);
|
||||
copyBtn.setDisabled(s.getCount() == 0);
|
||||
});
|
||||
|
||||
var saveBtn = new Ext.Toolbar.Button({
|
||||
|
@ -263,8 +344,8 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) {
|
|||
viewConfig: {forceFit:true},
|
||||
selModel: selModel,
|
||||
tbar: [
|
||||
delBtn, '-', saveBtn, rejectBtn, '-', {
|
||||
text: 'Add mux(es) manually',
|
||||
delBtn, copyBtn, '-', saveBtn, rejectBtn, '-', {
|
||||
text: 'Add mux(es) manually...',
|
||||
iconCls:'add',
|
||||
handler: function() {
|
||||
tvheadend.addMuxManually(adapterData, satConfStore)
|
||||
|
|
|
@ -189,6 +189,10 @@
|
|||
background-image:url(../icons/world.png) !important;
|
||||
}
|
||||
|
||||
.clone {
|
||||
background-image:url(../icons/layers.png) !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.x-smallhdr {
|
||||
|
|
BIN
src/webui/static/icons/layers.png
Normal file
BIN
src/webui/static/icons/layers.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 597 B |
Loading…
Add table
Reference in a new issue