tvheadend/src/webui/static/app/dvr.js

669 lines
15 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']
]
});
/**
*
*/
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<br>' +
"<a href=\"javascript:tvheadend.VLC('" + entry.url + "')\">Play</a>" +
'</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;
}
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);
}
});
}
}
/**
*
*/
tvheadend.dvrschedule = function() {
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 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
},{
width: 100,
id:'start',
header: "Start",
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: 250,
id:'channel',
header: "Channel",
dataIndex: 'channel'
},{
width: 200,
id:'creator',
header: "Created by",
hidden:true,
dataIndex: 'creator'
},{
width: 200,
id:'status',
header: "Status",
dataIndex: 'status'
}
]);
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: 'name',
valueField:'chid',
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'
}
],
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();
};
var panel = new Ext.grid.GridPanel({
loadMask: true,
stripeRows: true,
disableSelection: true,
title: 'Recorder schedule',
iconCls: 'clock',
store: tvheadend.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: new Ext.PagingToolbar({
store: tvheadend.dvrStore,
pageSize: 20,
displayInfo: true,
displayMsg: 'Programs {0} - {1} of {2}',
emptyMsg: "No programs to display"
})
});
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 enabledColumn = new Ext.grid.CheckColumn({
header: "Enabled",
dataIndex: 'enabled',
width: 30
});
var cm = new Ext.grid.ColumnModel([
enabledColumn,
{
header: "Title (Regexp)",
dataIndex: 'title',
editor: new fm.TextField({allowBlank: true})
},{
header: "Channel",
dataIndex: 'channel',
editor: new Ext.form.ComboBox({
loadingText: 'Loading...',
displayField:'name',
store: tvheadend.channels,
mode: 'local',
editable: false,
triggerAction: 'all',
emptyText: 'Only include channel...'
})
},{
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: "Content Group",
dataIndex: 'contentgrp',
editor: new Ext.form.ComboBox({
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 (typeof value === 'undefined' || value.length < 1)
return 'No days';
if (value == '1,2,3,4,5,6,7')
return 'All days';
ret = [];
tags = value.split(',');
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: "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,
[enabledColumn], tvheadend.autorecStore,
'autorec.html', 'wand');
}
/**
*
*/
tvheadend.dvr = function() {
tvheadend.dvrStore = 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: 'status'},
{name: 'schedstate'},
{name: 'creator'},
{name: 'duration'},
{name: 'filesize'},
{name: 'url'}
],
url: 'dvrlist',
autoLoad: true,
id: 'id',
remoteSort: true
});
tvheadend.comet.on('dvrdb', function(m) {
if(m.reload != null)
tvheadend.dvrStore.reload();
if(m.updateEntry != null) {
r = tvheadend.dvrStore.getById(m.id)
if(typeof r === 'undefined') {
tvheadend.dvrStore.reload();
return;
}
r.data.status = m.status;
r.data.schedstate = m.schedstate;
tvheadend.dvrStore.afterEdit(r);
tvheadend.dvrStore.fireEvent('updated',
tvheadend.dvrStore, r,
Ext.data.Record.COMMIT);
}
});
tvheadend.autorecRecord = Ext.data.Record.create([
'enabled','title','channel','tag','creator','contentgrp','comment',
'weekdays', 'pri', 'approx_time'
]);
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,
new tvheadend.autoreceditor
]
});
return panel;
}
/**
* Configuration panel (located under configuration)
*/
tvheadend.dvrsettings = function() {
var confreader = new Ext.data.JsonReader({
root: 'dvrSettings'
}, ['storage','postproc','retention','dayDirs',
'channelDirs','channelInTitle',
'dateInTitle','timeInTitle',
'preExtraTime', 'postExtraTime', 'whitespaceInTitle',
'titleDirs', 'episodeInTitle']);
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: [{
width: 300,
fieldLabel: 'Recording system path',
name: 'storage'
}, new Ext.form.NumberField({
allowNegative: false,
allowDecimals: false,
minValue: 1,
fieldLabel: 'DVR Log retention time (days)',
name: 'retention'
}), new Ext.form.NumberField({
allowDecimals: false,
fieldLabel: 'Extra time before recordings (minutes)',
name: 'preExtraTime'
}), new Ext.form.NumberField({
allowDecimals: false,
fieldLabel: 'Extra time after recordings (minutes)',
name: 'postExtraTime'
}), new Ext.form.Checkbox({
fieldLabel: 'Make subdirectories per day',
name: 'dayDirs'
}), new Ext.form.Checkbox({
fieldLabel: 'Make subdirectories per channel',
name: 'channelDirs'
}), new Ext.form.Checkbox({
fieldLabel: 'Make subdirectories per title',
name: 'titleDirs'
}), new Ext.form.Checkbox({
fieldLabel: 'Include channel name in filename',
name: 'channelInTitle'
}), new Ext.form.Checkbox({
fieldLabel: 'Include date in filename',
name: 'dateInTitle'
}), new Ext.form.Checkbox({
fieldLabel: 'Include time in filename',
name: 'timeInTitle'
}), new Ext.form.Checkbox({
fieldLabel: 'Include episode in filename',
name: 'episodeInTitle'
}), new Ext.form.Checkbox({
fieldLabel: 'Replace whitespace in title with \'-\'',
name: 'whitespaceInTitle'
}), {
width: 300,
fieldLabel: 'Post-processor command',
name: 'postproc'
}],
tbar: [{
tooltip: 'Save changes made to channel configuration below',
iconCls:'save',
text: "Save configuration",
handler: saveChanges
}, '->', {
text: 'Help',
handler: function() {
new tvheadend.help('DVR configuration',
'config_dvr.html');
}
}]
});
confpanel.on('render', function() {
confpanel.getForm().load({
url:'dvr',
params:{'op':'loadSettings'},
success:function(form, action) {
confpanel.enable();
}
});
});
function saveChanges() {
confpanel.getForm().submit({
url:'dvr',
params:{'op':'saveSettings'},
waitMsg:'Saving Data...',
failure: function(form, action) {
Ext.Msg.alert('Save failed', action.result.errormsg);
}
});
}
return confpanel;
}