1129 lines
26 KiB
JavaScript
1129 lines
26 KiB
JavaScript
tvheadend.weekdays = new Ext.data.SimpleStore({
|
|
fields : [ 'identifier', 'name' ],
|
|
id : 0,
|
|
data : [ [ '1', 'Mon' ], [ '2', 'Tue' ], [ '3', 'Wed' ], [ '4', 'Thu' ],
|
|
[ '5', 'Fri' ], [ '6', 'Sat' ], [ '7', 'Sun' ] ]
|
|
});
|
|
|
|
//This should be loaded from tvheadend
|
|
tvheadend.dvrprio = new Ext.data.SimpleStore({
|
|
fields : [ 'identifier', 'name' ],
|
|
id : 0,
|
|
data : [ [ 'important', 'Important' ], [ 'high', 'High' ],
|
|
[ 'normal', 'Normal' ], [ 'low', 'Low' ],
|
|
[ 'unimportant', 'Unimportant' ] ]
|
|
});
|
|
|
|
|
|
//For the container configuration
|
|
tvheadend.containers = new Ext.data.JsonStore({
|
|
autoLoad : true,
|
|
root : 'entries',
|
|
fields : [ 'name', 'description' ],
|
|
id : 'name',
|
|
url : 'dvr_containers',
|
|
baseParams : {
|
|
op : 'list'
|
|
}
|
|
});
|
|
|
|
//For the cache configuration
|
|
tvheadend.caches = new Ext.data.JsonStore({
|
|
autoLoad : true,
|
|
root : 'entries',
|
|
fields : [ 'index', 'description' ],
|
|
id : 'name',
|
|
url : 'dvr_caches',
|
|
baseParams : {
|
|
op : 'list'
|
|
}
|
|
});
|
|
|
|
|
|
/**
|
|
* Configuration names
|
|
*/
|
|
tvheadend.configNames = new Ext.data.JsonStore({
|
|
autoLoad : true,
|
|
root : 'entries',
|
|
fields : [ 'identifier', 'name' ],
|
|
id : 'identifier',
|
|
url : 'confignames',
|
|
baseParams : {
|
|
op : 'list'
|
|
}
|
|
});
|
|
|
|
tvheadend.configNames.setDefaultSort('name', 'ASC');
|
|
|
|
tvheadend.comet.on('dvrconfig', function(m) {
|
|
if (m.reload != null) tvheadend.configNames.reload();
|
|
});
|
|
|
|
/**
|
|
*
|
|
*/
|
|
tvheadend.dvrDetails = function(entry) {
|
|
|
|
var content = '';
|
|
var but;
|
|
|
|
if (entry.chicon != null && entry.chicon.length > 0) content += '<img class="x-epg-chicon" src="'
|
|
+ entry.chicon + '">';
|
|
|
|
content += '<div class="x-epg-title">' + entry.title + '</div>';
|
|
content += '<div class="x-epg-desc">' + entry.description + '</div>';
|
|
content += '<hr>'
|
|
content += '<div class="x-epg-meta">Status: ' + entry.status + '</div>';
|
|
|
|
if (entry.url != null && entry.filesize > 0) {
|
|
content += '<div class="x-epg-meta">' + '<a href="' + entry.url
|
|
+ '" target="_blank">Download</a> '
|
|
+ parseInt(entry.filesize / 1000000) + ' MB</div>';
|
|
|
|
}
|
|
|
|
var win = new Ext.Window({
|
|
title : entry.title,
|
|
layout : 'fit',
|
|
width : 400,
|
|
height : 300,
|
|
constrainHeader : true,
|
|
buttonAlign : 'center',
|
|
html : content
|
|
});
|
|
|
|
switch (entry.schedstate) {
|
|
case 'scheduled':
|
|
win.addButton({
|
|
handler : cancelEvent,
|
|
text : "Remove from schedule"
|
|
});
|
|
break;
|
|
|
|
case 'recording':
|
|
case 'recordingError':
|
|
win.addButton({
|
|
handler : cancelEvent,
|
|
text : "Abort recording"
|
|
});
|
|
break;
|
|
case 'completedError':
|
|
case 'completed':
|
|
win.addButton({
|
|
handler : deleteEvent,
|
|
text : "Delete recording"
|
|
});
|
|
break;
|
|
}
|
|
|
|
win.show();
|
|
|
|
function cancelEvent() {
|
|
Ext.Ajax.request({
|
|
url : 'dvr',
|
|
params : {
|
|
entryId : entry.id,
|
|
op : 'cancelEntry'
|
|
},
|
|
|
|
success : function(response, options) {
|
|
win.close();
|
|
},
|
|
|
|
failure : function(response, options) {
|
|
Ext.MessageBox.alert('DVR', response.statusText);
|
|
}
|
|
});
|
|
}
|
|
|
|
function deleteEvent() {
|
|
Ext.Ajax.request({
|
|
url : 'dvr',
|
|
params : {
|
|
entryId : entry.id,
|
|
op : 'deleteEntry'
|
|
},
|
|
|
|
success : function(response, options) {
|
|
win.close();
|
|
},
|
|
|
|
failure : function(response, options) {
|
|
Ext.MessageBox.alert('DVR', response.statusText);
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
tvheadend.dvrschedule = function(title, iconCls, dvrStore) {
|
|
|
|
var actions = new Ext.ux.grid.RowActions({
|
|
header : '',
|
|
dataIndex : 'actions',
|
|
width : 45,
|
|
actions : [ {
|
|
iconIndex : 'schedstate'
|
|
} ]
|
|
});
|
|
|
|
function renderDate(value) {
|
|
var dt = new Date(value);
|
|
return dt.format('D j M H:i');
|
|
}
|
|
|
|
function renderDuration(value) {
|
|
value = value / 60; /* Nevermind the seconds */
|
|
|
|
if (value >= 60) {
|
|
var min = parseInt(value % 60);
|
|
var hours = parseInt(value / 60);
|
|
|
|
if (min == 0) {
|
|
return hours + ' hrs';
|
|
}
|
|
return hours + ' hrs, ' + min + ' min';
|
|
}
|
|
else {
|
|
return parseInt(value) + ' min';
|
|
}
|
|
}
|
|
|
|
function renderSize(value)
|
|
{
|
|
if (value == null)
|
|
return '';
|
|
return parseInt(value / 1000000) + ' MB';
|
|
}
|
|
|
|
function renderPri(value) {
|
|
return tvheadend.dvrprio.getById(value).data.name;
|
|
}
|
|
|
|
var dvrCm = new Ext.grid.ColumnModel([ actions, {
|
|
width : 250,
|
|
id : 'title',
|
|
header : "Title",
|
|
dataIndex : 'title'
|
|
}, {
|
|
width : 100,
|
|
id : 'episode',
|
|
header : "Episode",
|
|
dataIndex : 'episode'
|
|
}, {
|
|
width : 100,
|
|
id : 'pri',
|
|
header : "Priority",
|
|
dataIndex : 'pri',
|
|
renderer : renderPri,
|
|
hidden : iconCls != 'clock',
|
|
}, {
|
|
width : 100,
|
|
id : 'start',
|
|
header : iconCls == 'clock' ? "Start" : "Date/Time",
|
|
dataIndex : 'start',
|
|
renderer : renderDate
|
|
}, {
|
|
width : 100,
|
|
hidden : true,
|
|
id : 'end',
|
|
header : "End",
|
|
dataIndex : 'end',
|
|
renderer : renderDate
|
|
}, {
|
|
width : 100,
|
|
id : 'duration',
|
|
header : "Duration",
|
|
dataIndex : 'duration',
|
|
renderer : renderDuration
|
|
}, {
|
|
width : 100,
|
|
id : 'filesize',
|
|
header : "Filesize",
|
|
dataIndex : 'filesize',
|
|
renderer : renderSize,
|
|
hidden : iconCls != 'television'
|
|
}, {
|
|
width : 250,
|
|
id : 'channel',
|
|
header : "Channel",
|
|
dataIndex : 'channel'
|
|
}, {
|
|
width : 200,
|
|
id : 'creator',
|
|
header : "Created by",
|
|
hidden : true,
|
|
dataIndex : 'creator'
|
|
}, {
|
|
width : 200,
|
|
id : 'config_name',
|
|
header : "DVR Configuration",
|
|
renderer : function(value, metadata, record, row, col, store) {
|
|
if (!value) {
|
|
return '<span class="tvh-grid-unset">(default)</span>';
|
|
}
|
|
else {
|
|
return value;
|
|
}
|
|
},
|
|
dataIndex : 'config_name',
|
|
hidden: iconCls != 'clock'
|
|
}, {
|
|
width : 200,
|
|
id : 'status',
|
|
header : "Status",
|
|
dataIndex : 'status',
|
|
hidden: iconCls != 'exclamation'
|
|
} ]);
|
|
|
|
function addEntry() {
|
|
|
|
function createRecording() {
|
|
panel.getForm().submit({
|
|
params : {
|
|
'op' : 'createEntry'
|
|
},
|
|
url : 'dvr/addentry',
|
|
waitMsg : 'Creating entry...',
|
|
failure : function(response, options) {
|
|
Ext.MessageBox.alert('Server Error', 'Unable to create entry');
|
|
},
|
|
success : function() {
|
|
win.close();
|
|
}
|
|
});
|
|
}
|
|
|
|
var panel = new Ext.FormPanel({
|
|
frame : true,
|
|
border : true,
|
|
bodyStyle : 'padding:5px',
|
|
labelAlign : 'right',
|
|
labelWidth : 110,
|
|
defaultType : 'textfield',
|
|
items : [ new Ext.form.ComboBox({
|
|
fieldLabel : 'Channel',
|
|
name : 'channel',
|
|
hiddenName : 'channelid',
|
|
editable : false,
|
|
allowBlank : false,
|
|
displayField : 'val',
|
|
valueField : 'key',
|
|
mode : 'remote',
|
|
triggerAction : 'all',
|
|
store : tvheadend.channels
|
|
}), new Ext.form.DateField({
|
|
allowBlank : false,
|
|
fieldLabel : 'Date',
|
|
name : 'date'
|
|
}), new Ext.form.TimeField({
|
|
allowBlank : false,
|
|
fieldLabel : 'Start time',
|
|
name : 'starttime',
|
|
increment : 10,
|
|
format : 'H:i'
|
|
}), new Ext.form.TimeField({
|
|
allowBlank : false,
|
|
fieldLabel : 'Stop time',
|
|
name : 'stoptime',
|
|
increment : 10,
|
|
format : 'H:i'
|
|
}), new Ext.form.ComboBox({
|
|
store : tvheadend.dvrprio,
|
|
value : "normal",
|
|
triggerAction : 'all',
|
|
mode : 'local',
|
|
fieldLabel : 'Priority',
|
|
valueField : 'identifier',
|
|
displayField : 'name',
|
|
name : 'pri'
|
|
}), {
|
|
allowBlank : false,
|
|
fieldLabel : 'Title',
|
|
name : 'title'
|
|
}, new Ext.form.ComboBox({
|
|
store : tvheadend.configNames,
|
|
triggerAction : 'all',
|
|
mode : 'local',
|
|
fieldLabel : 'DVR Configuration',
|
|
valueField : 'identifier',
|
|
displayField : 'name',
|
|
name : 'config_name',
|
|
emptyText : '(default)',
|
|
value : '',
|
|
editable : false
|
|
}) ],
|
|
buttons : [ {
|
|
text : 'Create',
|
|
handler : createRecording
|
|
} ]
|
|
|
|
});
|
|
|
|
win = new Ext.Window({
|
|
title : 'Add single recording',
|
|
layout : 'fit',
|
|
width : 500,
|
|
height : 300,
|
|
plain : true,
|
|
items : panel
|
|
});
|
|
win.show();
|
|
new Ext.form.ComboBox({
|
|
store : tvheadend.configNames,
|
|
triggerAction : 'all',
|
|
mode : 'local',
|
|
fieldLabel : 'DVR Configuration',
|
|
valueField : 'identifier',
|
|
displayField : 'name',
|
|
name : 'config_name',
|
|
emptyText : '(default)',
|
|
value : '',
|
|
editable : false
|
|
})
|
|
}
|
|
;
|
|
|
|
/* Create combobox to allow user to select page size for upcoming/completed/failed recordings */
|
|
|
|
var itemPageCombo = new Ext.form.ComboBox({
|
|
name : 'itemsperpage',
|
|
width: 50,
|
|
mode : 'local',
|
|
store: new Ext.data.ArrayStore({
|
|
fields: ['perpage'],
|
|
data : [ ['10'], ['20'], ['30'], ['40'], ['50'], ['60'], ['70'], ['80'], ['90'], ['100'] ]
|
|
}),
|
|
value : '20',
|
|
listWidth : 40,
|
|
triggerAction : 'all',
|
|
displayField : 'perpage',
|
|
valueField : 'perpage',
|
|
editable : true,
|
|
forceSelection : true,
|
|
listeners : {
|
|
scope: this,
|
|
'select' : function(combo, record) {
|
|
bbar.pageSize = parseInt(record.get('perpage'), 10);
|
|
bbar.doLoad(bbar.cursor);
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Bottom toolbar to include default previous/goto-page/next and refresh buttons, also number-of-items combobox */
|
|
|
|
var bbar = new Ext.PagingToolbar({
|
|
store : dvrStore,
|
|
displayInfo : true,
|
|
items : [ '-', 'Recordings per page: ', itemPageCombo ],
|
|
displayMsg : 'Programs {0} - {1} of {2}',
|
|
emptyMsg : "No programs to display"
|
|
});
|
|
|
|
var panel = new Ext.grid.GridPanel({
|
|
loadMask : true,
|
|
stripeRows : true,
|
|
disableSelection : true,
|
|
title : title,
|
|
iconCls : iconCls,
|
|
store : dvrStore,
|
|
cm : dvrCm,
|
|
plugins : [ actions ],
|
|
viewConfig : {
|
|
forceFit : true
|
|
},
|
|
tbar : [ {
|
|
tooltip : 'Schedule a new recording session on the server.',
|
|
iconCls : 'add',
|
|
text : 'Add entry',
|
|
handler : addEntry
|
|
}, '->', {
|
|
text : 'Help',
|
|
handler : function() {
|
|
new tvheadend.help('Digital Video Recorder', 'dvrlog.html');
|
|
}
|
|
} ],
|
|
bbar : bbar
|
|
});
|
|
|
|
panel.on('rowclick', rowclicked);
|
|
function rowclicked(grid, index) {
|
|
new tvheadend.dvrDetails(grid.getStore().getAt(index).data);
|
|
}
|
|
return panel;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
|
|
/**
|
|
*
|
|
*/
|
|
tvheadend.autoreceditor = function() {
|
|
var fm = Ext.form;
|
|
|
|
|
|
var cm = new Ext.grid.ColumnModel({
|
|
defaultSortable: true,
|
|
columns :
|
|
[
|
|
{
|
|
header: 'Enabled',
|
|
dataIndex: 'enabled',
|
|
width: 30,
|
|
xtype: 'checkcolumn'
|
|
},
|
|
|
|
{
|
|
header : "Title (Regexp)",
|
|
dataIndex : 'title',
|
|
editor : new fm.TextField({
|
|
allowBlank : true
|
|
})
|
|
},
|
|
{
|
|
header : "Channel",
|
|
dataIndex : 'channel',
|
|
editor : new Ext.form.ComboBox({
|
|
loadingText : 'Loading...',
|
|
displayField : 'val',
|
|
valueField: 'key',
|
|
store : tvheadend.channels,
|
|
mode : 'local',
|
|
editable : false,
|
|
triggerAction : 'all',
|
|
emptyText : 'Only include channel...'
|
|
}),
|
|
renderer : function (v, m, r) {
|
|
var i = tvheadend.channels.find('key', v);
|
|
if (i != -1)
|
|
v = tvheadend.channels.getAt(i).get('val')
|
|
return v
|
|
}
|
|
},
|
|
{
|
|
header : "SeriesLink",
|
|
dataIndex : 'serieslink',
|
|
renderer : function(v) {
|
|
return v ? 'yes' : 'no';
|
|
}
|
|
},
|
|
{
|
|
header : "Channel tag",
|
|
dataIndex : 'tag',
|
|
editor : new Ext.form.ComboBox({
|
|
displayField : 'name',
|
|
store : tvheadend.channelTags,
|
|
mode : 'local',
|
|
editable : false,
|
|
triggerAction : 'all',
|
|
emptyText : 'Only include tag...'
|
|
})
|
|
},
|
|
{
|
|
header : "Genre",
|
|
dataIndex : 'contenttype',
|
|
renderer : function(v) {
|
|
return tvheadend.contentGroupLookupName(v);
|
|
},
|
|
editor : new Ext.form.ComboBox({
|
|
valueField : 'code',
|
|
displayField : 'name',
|
|
store : tvheadend.ContentGroupStore,
|
|
mode : 'local',
|
|
editable : false,
|
|
triggerAction : 'all',
|
|
emptyText : 'Only include content...'
|
|
})
|
|
},
|
|
{
|
|
header : "Weekdays",
|
|
dataIndex : 'weekdays',
|
|
renderer : function(value, metadata, record, row, col, store) {
|
|
if (value.split) value = value.split(',')
|
|
if (value.length == 7) return 'All days';
|
|
if (value.length == 0 || value[0] == "") return 'No days';
|
|
ret = [];
|
|
tags = value;
|
|
for ( var i = 0; i < tags.length; i++) {
|
|
var tag = tvheadend.weekdays.getById(tags[i]);
|
|
if (typeof tag !== 'undefined') ret.push(tag.data.name);
|
|
}
|
|
return ret.join(', ');
|
|
},
|
|
editor : new Ext.ux.form.LovCombo({
|
|
store : tvheadend.weekdays,
|
|
mode : 'local',
|
|
valueField : 'identifier',
|
|
displayField : 'name'
|
|
})
|
|
}, {
|
|
header : "Starting Around",
|
|
dataIndex : 'approx_time',
|
|
renderer : function(value, metadata, record, row, col, store) {
|
|
if (typeof value === 'string') return value;
|
|
|
|
if (value === 0) return '';
|
|
|
|
var hours = Math.floor(value / 60);
|
|
var mins = value % 60;
|
|
var dt = new Date();
|
|
dt.setHours(hours);
|
|
dt.setMinutes(mins);
|
|
return dt.format('H:i');
|
|
},
|
|
editor : new Ext.form.TimeField({
|
|
allowBlank : true,
|
|
increment : 10,
|
|
format : 'H:i'
|
|
})
|
|
}, {
|
|
header : "Priority",
|
|
dataIndex : 'pri',
|
|
width : 100,
|
|
renderer : function(value, metadata, record, row, col, store) {
|
|
return tvheadend.dvrprio.getById(value).data.name;
|
|
},
|
|
editor : new fm.ComboBox({
|
|
store : tvheadend.dvrprio,
|
|
triggerAction : 'all',
|
|
mode : 'local',
|
|
valueField : 'identifier',
|
|
displayField : 'name'
|
|
})
|
|
}, {
|
|
header : "DVR Configuration",
|
|
dataIndex : 'config_name',
|
|
renderer : function(value, metadata, record, row, col, store) {
|
|
if (!value) {
|
|
return '<span class="tvh-grid-unset">(default)</span>';
|
|
}
|
|
else {
|
|
return value;
|
|
}
|
|
},
|
|
editor : new Ext.form.ComboBox({
|
|
store : tvheadend.configNames,
|
|
triggerAction : 'all',
|
|
mode : 'local',
|
|
valueField : 'identifier',
|
|
displayField : 'name',
|
|
name : 'config_name',
|
|
emptyText : '(default)',
|
|
editable : false
|
|
})
|
|
}, {
|
|
header : "Created by",
|
|
dataIndex : 'creator',
|
|
editor : new fm.TextField({
|
|
allowBlank : false
|
|
})
|
|
}, {
|
|
header : "Comment",
|
|
dataIndex : 'comment',
|
|
editor : new fm.TextField({
|
|
allowBlank : false
|
|
})
|
|
} ]});
|
|
|
|
return new tvheadend.tableEditor('Automatic Recorder', 'autorec', cm,
|
|
tvheadend.autorecRecord, [], tvheadend.autorecStore,
|
|
'autorec.html', 'wand');
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
tvheadend.dvr = function() {
|
|
|
|
function datastoreBuilder(url) {
|
|
return new Ext.data.JsonStore({
|
|
root : 'entries',
|
|
totalProperty : 'totalCount',
|
|
fields : [ {
|
|
name : 'id'
|
|
}, {
|
|
name : 'channel'
|
|
}, {
|
|
name : 'title'
|
|
}, {
|
|
name : 'episode'
|
|
}, {
|
|
name : 'pri'
|
|
}, {
|
|
name : 'description'
|
|
}, {
|
|
name : 'chicon'
|
|
}, {
|
|
name : 'start',
|
|
type : 'date',
|
|
dateFormat : 'U' /* unix time */
|
|
}, {
|
|
name : 'end',
|
|
type : 'date',
|
|
dateFormat : 'U' /* unix time */
|
|
}, {
|
|
name : 'config_name'
|
|
}, {
|
|
name : 'status'
|
|
}, {
|
|
name : 'schedstate'
|
|
}, {
|
|
name : 'error'
|
|
}, {
|
|
name : 'creator'
|
|
}, {
|
|
name : 'duration'
|
|
}, {
|
|
name : 'filesize'
|
|
}, {
|
|
name : 'url'
|
|
} ],
|
|
url : url,
|
|
autoLoad : true,
|
|
id : 'id',
|
|
remoteSort : true
|
|
});
|
|
}
|
|
tvheadend.dvrStoreUpcoming = datastoreBuilder('dvrlist_upcoming');
|
|
tvheadend.dvrStoreFinished = datastoreBuilder('dvrlist_finished');
|
|
tvheadend.dvrStoreFailed = datastoreBuilder('dvrlist_failed');
|
|
tvheadend.dvrStores = [tvheadend.dvrStoreUpcoming,
|
|
tvheadend.dvrStoreFinished,
|
|
tvheadend.dvrStoreFailed];
|
|
|
|
|
|
function updateDvrStore(store, r, m) {
|
|
r.data.status = m.status;
|
|
r.data.schedstate = m.schedstate;
|
|
|
|
store.afterEdit(r);
|
|
store.fireEvent('updated', store, r,
|
|
Ext.data.Record.COMMIT);
|
|
}
|
|
|
|
function reloadStores() {
|
|
for (var i = 0; i < tvheadend.dvrStores.length; i++) {
|
|
tvheadend.dvrStores[i].reload();
|
|
}
|
|
}
|
|
|
|
tvheadend.comet.on('dvrdb', function(m) {
|
|
|
|
if (m.reload != null) {
|
|
reloadStores();
|
|
}
|
|
|
|
if (m.updateEntry != null) {
|
|
for (var i = 0; i < tvheadend.dvrStores.length; i++) {
|
|
var store = tvheadend.dvrStores[i];
|
|
r = tvheadend.dvrStoreUpcoming.getById(m.id);
|
|
if (typeof r !== 'undefined') {
|
|
updateDvrStore(store, r, m);
|
|
return;
|
|
}
|
|
}
|
|
reloadStores();
|
|
}
|
|
});
|
|
|
|
tvheadend.autorecRecord = Ext.data.Record.create([ 'enabled', 'title',
|
|
'serieslink', 'channel', 'tag', 'creator', 'contenttype', 'comment',
|
|
'weekdays', 'pri', 'approx_time', 'config_name' ]);
|
|
|
|
tvheadend.autorecStore = new Ext.data.JsonStore({
|
|
root : 'entries',
|
|
fields : tvheadend.autorecRecord,
|
|
url : "tablemgr",
|
|
autoLoad : true,
|
|
id : 'id',
|
|
baseParams : {
|
|
table : "autorec",
|
|
op : "get"
|
|
}
|
|
});
|
|
|
|
tvheadend.comet.on('autorec', function(m) {
|
|
if (m.reload != null) tvheadend.autorecStore.reload();
|
|
});
|
|
|
|
var panel = new Ext.TabPanel({
|
|
activeTab : 0,
|
|
autoScroll : true,
|
|
title : 'Digital Video Recorder',
|
|
iconCls : 'drive',
|
|
items : [
|
|
new tvheadend.dvrschedule('Upcoming recordings', 'clock', tvheadend.dvrStoreUpcoming),
|
|
new tvheadend.dvrschedule('Finished recordings', 'television', tvheadend.dvrStoreFinished),
|
|
new tvheadend.dvrschedule('Failed recordings', 'exclamation', tvheadend.dvrStoreFailed),
|
|
new tvheadend.autoreceditor
|
|
]
|
|
});
|
|
return panel;
|
|
}
|
|
|
|
/**
|
|
* Configuration panel (located under configuration)
|
|
*/
|
|
tvheadend.dvrsettings = function() {
|
|
|
|
var confreader = new Ext.data.JsonReader({
|
|
root : 'dvrSettings'
|
|
}, [ 'storage', 'filePermissions', 'dirPermissions', 'postproc', 'retention', 'dayDirs', 'channelDirs',
|
|
'channelInTitle', 'container', 'cache', 'dateInTitle', 'timeInTitle',
|
|
'preExtraTime', 'postExtraTime', 'whitespaceInTitle', 'titleDirs',
|
|
'episodeInTitle', 'cleanTitle', 'tagFiles', 'commSkip', 'subtitleInTitle',
|
|
'episodeBeforeDate', 'rewritePAT', 'rewritePMT' ]);
|
|
|
|
var confcombo = new Ext.form.ComboBox({
|
|
store : tvheadend.configNames,
|
|
triggerAction : 'all',
|
|
mode : 'local',
|
|
displayField : 'name',
|
|
name : 'config_name',
|
|
emptyText : '(default)',
|
|
value : '',
|
|
editable : true
|
|
});
|
|
|
|
var delButton = new Ext.Toolbar.Button({
|
|
tooltip : 'Delete named configuration',
|
|
iconCls : 'remove',
|
|
text : "Delete configuration",
|
|
handler : deleteConfiguration,
|
|
disabled : true
|
|
});
|
|
|
|
/* Config panel variables */
|
|
|
|
/* DVR Behaviour */
|
|
|
|
var recordingContainer = new Ext.form.ComboBox({
|
|
store : tvheadend.containers,
|
|
fieldLabel : 'Media container',
|
|
triggerAction : 'all',
|
|
displayField : 'description',
|
|
valueField : 'name',
|
|
editable : false,
|
|
width : 200,
|
|
hiddenName : 'container'
|
|
});
|
|
|
|
var cacheScheme = new Ext.form.ComboBox({
|
|
store : tvheadend.caches,
|
|
fieldLabel : 'Cache scheme',
|
|
triggerAction : 'all',
|
|
displayField : 'description',
|
|
valueField : 'index',
|
|
editable : false,
|
|
width : 200,
|
|
hiddenName : 'cache'
|
|
});
|
|
|
|
var logRetention = new Ext.form.NumberField({
|
|
allowNegative : false,
|
|
allowDecimals : false,
|
|
minValue : 1,
|
|
fieldLabel : 'DVR Log retention time (days)',
|
|
name : 'retention'
|
|
});
|
|
|
|
var timeBefore = new Ext.form.NumberField({
|
|
allowDecimals : false,
|
|
fieldLabel : 'Extra time before recordings (minutes)',
|
|
name : 'preExtraTime'
|
|
});
|
|
|
|
var timeAfter = new Ext.form.NumberField({
|
|
allowDecimals : false,
|
|
fieldLabel : 'Extra time after recordings (minutes)',
|
|
name : 'postExtraTime'
|
|
});
|
|
|
|
var postProcessing = new Ext.form.TextField({
|
|
width : 300,
|
|
fieldLabel : 'Post-processor command',
|
|
name : 'postproc'
|
|
});
|
|
|
|
/* Recording File Options */
|
|
|
|
var recordingPath = new Ext.form.TextField({
|
|
width : 300,
|
|
fieldLabel : 'Recording system path',
|
|
name : 'storage'
|
|
});
|
|
|
|
/* NB: recordingPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */
|
|
|
|
var recordingPermissions = new Ext.form.TextField({
|
|
regex : /^[0][0-7]{3}$/,
|
|
maskRe : /[0-7]/,
|
|
width : 100,
|
|
allowBlank : false,
|
|
blankText : 'You must provide a value - use octal chmod notation, e.g. 0664',
|
|
fieldLabel : 'File permissions (octal, e.g. 0664)',
|
|
name : 'filePermissions'
|
|
});
|
|
|
|
/* TO DO - Add 'override user umask?' option, then trigger fchmod in mkmux.c, muxer_pass.c after file created */
|
|
|
|
var PATrewrite = new Ext.form.Checkbox({
|
|
fieldLabel : 'Rewrite PAT in passthrough mode',
|
|
name : 'rewritePAT'
|
|
});
|
|
|
|
var PMTrewrite = new Ext.form.Checkbox({
|
|
fieldLabel : 'Rewrite PMT in passthrough mode',
|
|
name : 'rewritePMT'
|
|
});
|
|
|
|
var tagMetadata = new Ext.form.Checkbox({
|
|
fieldLabel : 'Tag files with metadata',
|
|
name : 'tagFiles'
|
|
});
|
|
|
|
var skipCommercials = new Ext.form.Checkbox({
|
|
fieldLabel : 'Skip commercials',
|
|
name : 'commSkip'
|
|
});
|
|
|
|
/* Subdirectories and filename handling */
|
|
|
|
/* NB: directoryPermissions is defined as a TextField for validation purposes (leading zeros), but is ultimately a number */
|
|
|
|
var directoryPermissions = new Ext.form.TextField({
|
|
regex : /^[0][0-7]{3}$/,
|
|
maskRe : /[0-7]/,
|
|
width : 100,
|
|
allowBlank : false,
|
|
blankText : 'You must provide a value - use octal chmod notation, e.g. 0775',
|
|
fieldLabel : 'Directory permissions (octal, e.g. 0775)',
|
|
name : 'dirPermissions'
|
|
});
|
|
|
|
/* TO DO - Add 'override user umask?' option, then trigger fchmod in utils.c after directory created */
|
|
|
|
var dirsPerDay = new Ext.form.Checkbox({
|
|
fieldLabel : 'Make subdirectories per day',
|
|
name : 'dayDirs'
|
|
});
|
|
|
|
var dirsPerChannel = new Ext.form.Checkbox({
|
|
fieldLabel : 'Make subdirectories per channel',
|
|
name : 'channelDirs'
|
|
});
|
|
|
|
var dirsPerTitle = new Ext.form.Checkbox({
|
|
fieldLabel : 'Make subdirectories per title',
|
|
name : 'titleDirs'
|
|
});
|
|
|
|
var incChannelInTitle = new Ext.form.Checkbox({
|
|
fieldLabel : 'Include channel name in filename',
|
|
name : 'channelInTitle'
|
|
});
|
|
|
|
var incDateInTitle = new Ext.form.Checkbox({
|
|
fieldLabel : 'Include date in filename',
|
|
name : 'dateInTitle'
|
|
});
|
|
|
|
var incTimeInTitle = new Ext.form.Checkbox({
|
|
fieldLabel : 'Include time in filename',
|
|
name : 'timeInTitle'
|
|
});
|
|
|
|
var incEpisodeInTitle = new Ext.form.Checkbox({
|
|
fieldLabel : 'Include episode in filename',
|
|
name : 'episodeInTitle'
|
|
});
|
|
|
|
var incSubtitleInTitle = new Ext.form.Checkbox({
|
|
fieldLabel : 'Include subtitle in filename',
|
|
name : 'subtitleInTitle'
|
|
});
|
|
|
|
var episodeFirst = new Ext.form.Checkbox({
|
|
fieldLabel : 'Put episode in filename before date and time',
|
|
name : 'episodeBeforeDate'
|
|
});
|
|
|
|
var stripUnsafeChars = new Ext.form.Checkbox({
|
|
fieldLabel : 'Remove all unsafe characters from filename',
|
|
name : 'cleanTitle'
|
|
});
|
|
|
|
var stripWhitespace = new Ext.form.Checkbox({
|
|
fieldLabel : 'Replace whitespace in title with \'-\'',
|
|
name : 'whitespaceInTitle'
|
|
});
|
|
|
|
|
|
/* Sub-Panel - DVR behaviour */
|
|
|
|
var DVRBehaviour = new Ext.form.FieldSet({
|
|
title: 'DVR Behaviour',
|
|
width: 700,
|
|
autoHeight: true,
|
|
collapsible: true,
|
|
animCollapse : true,
|
|
items : [ recordingContainer, cacheScheme, logRetention, timeBefore, timeAfter, postProcessing ]
|
|
});
|
|
|
|
/* Sub-Panel - File Output */
|
|
|
|
var FileOutputPanel = new Ext.form.FieldSet({
|
|
title: 'Recording File Options',
|
|
width: 700,
|
|
autoHeight: true,
|
|
collapsible: true,
|
|
animCollapse : true,
|
|
items : [ recordingPath, recordingPermissions, PATrewrite, PMTrewrite, tagMetadata, skipCommercials ]
|
|
});
|
|
|
|
/* Sub-Panel - Directory operations */
|
|
|
|
var DirHandlingPanel = new Ext.form.FieldSet({
|
|
title: 'Subdirectory Options',
|
|
width: 700,
|
|
autoHeight: true,
|
|
collapsible: true,
|
|
animCollapse : true,
|
|
items : [ directoryPermissions, dirsPerDay, dirsPerChannel, dirsPerTitle ]
|
|
});
|
|
|
|
/* Sub-Panel - File operations - Break into two 4-item panels */
|
|
|
|
var FileHandlingPanelA = new Ext.form.FieldSet({
|
|
width: 350,
|
|
border: false,
|
|
autoHeight: true,
|
|
items : [ incChannelInTitle, incDateInTitle, incTimeInTitle, incEpisodeInTitle ]
|
|
});
|
|
|
|
var FileHandlingPanelB = new Ext.form.FieldSet({
|
|
width: 350,
|
|
border: false,
|
|
autoHeight: true,
|
|
items : [ incSubtitleInTitle, episodeFirst, stripUnsafeChars, stripWhitespace ]
|
|
});
|
|
|
|
var FileHandlingPanel = new Ext.form.FieldSet({
|
|
title: 'Filename Options',
|
|
width: 700,
|
|
autoHeight: true,
|
|
collapsible: true,
|
|
animCollapse : true,
|
|
items : [{
|
|
layout: 'column',
|
|
border: false,
|
|
items : [FileHandlingPanelA, FileHandlingPanelB ]
|
|
}]
|
|
});
|
|
|
|
/* Main (form) panel */
|
|
|
|
var confpanel = new Ext.FormPanel({
|
|
title : 'Digital Video Recorder',
|
|
iconCls : 'drive',
|
|
border : false,
|
|
bodyStyle : 'padding:15px',
|
|
anchor : '100% 50%',
|
|
labelAlign : 'right',
|
|
labelWidth : 250,
|
|
waitMsgTarget : true,
|
|
reader : confreader,
|
|
defaultType : 'textfield',
|
|
layout : 'form',
|
|
items : [ DVRBehaviour, FileOutputPanel, DirHandlingPanel, FileHandlingPanel ],
|
|
|
|
tbar : [ confcombo, {
|
|
tooltip : 'Save changes made to dvr configuration below',
|
|
iconCls : 'save',
|
|
text : "Save configuration",
|
|
handler : saveChanges
|
|
}, delButton, '->', {
|
|
text : 'Help',
|
|
handler : function() {
|
|
new tvheadend.help('DVR configuration', 'config_dvr.html');
|
|
}
|
|
} ]
|
|
});
|
|
|
|
function loadConfig() {
|
|
confpanel.getForm().load({
|
|
url : 'dvr',
|
|
params : {
|
|
'op' : 'loadSettings',
|
|
'config_name' : confcombo.getValue()
|
|
},
|
|
success : function(form, action) {
|
|
confpanel.enable();
|
|
}
|
|
});
|
|
}
|
|
|
|
confcombo.on('select', function() {
|
|
if (confcombo.getValue() == '') delButton.disable();
|
|
else delButton.enable();
|
|
loadConfig();
|
|
});
|
|
|
|
confpanel.on('render', function() {
|
|
loadConfig();
|
|
});
|
|
|
|
function saveChanges() {
|
|
var config_name = confcombo.getValue();
|
|
confpanel.getForm().submit({
|
|
url : 'dvr',
|
|
params : {
|
|
'op' : 'saveSettings',
|
|
'config_name' : config_name
|
|
},
|
|
waitMsg : 'Saving Data...',
|
|
success : function(form, action) {
|
|
confcombo.setValue(config_name);
|
|
confcombo.fireEvent('select');
|
|
},
|
|
failure : function(form, action) {
|
|
Ext.Msg.alert('Save failed', action.result.errormsg);
|
|
}
|
|
});
|
|
}
|
|
|
|
function deleteConfiguration() {
|
|
if (confcombo.getValue() != "") {
|
|
Ext.MessageBox.confirm('Message',
|
|
'Do you really want to delete DVR configuration \''
|
|
+ confcombo.getValue() + '\'?', deleteAction);
|
|
}
|
|
}
|
|
|
|
function deleteAction(btn) {
|
|
if (btn == 'yes') {
|
|
confpanel.getForm().submit({
|
|
url : 'dvr',
|
|
params : {
|
|
'op' : 'deleteSettings',
|
|
'config_name' : confcombo.getValue()
|
|
},
|
|
waitMsg : 'Deleting Data...',
|
|
success : function(form, action) {
|
|
confcombo.setValue('');
|
|
confcombo.fireEvent('select');
|
|
},
|
|
failure : function(form, action) {
|
|
Ext.Msg.alert('Delete failed', action.result.errormsg);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
return confpanel;
|
|
}
|