( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
{
dvr_entry_t *de;
-
- LIST_FOREACH(de, &dvrentries, de_global_link)
- if (dvr_entry_is_upcoming(de))
- idnode_set_add(ins, (idnode_t*)de, &conf->filter, perm->aa_lang_ui);
-}
-
-static void
-api_dvr_entry_grid_duplicate
- ( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
-{
- dvr_entry_t *de;
-
- LIST_FOREACH(de, &dvrentries, de_global_link)
- if (dvr_entry_is_duplicate(de))
- idnode_set_add(ins, (idnode_t*)de, &conf->filter, perm->aa_lang_ui);
+ int duplicates = htsmsg_get_s32_or_default(args, "duplicates", 1);
+
+ if (duplicates) {
+ LIST_FOREACH(de, &dvrentries, de_global_link)
+ if (dvr_entry_is_upcoming(de))
+ idnode_set_add(ins, (idnode_t*)de, &conf->filter, perm->aa_lang_ui);
+ } else {
+ LIST_FOREACH(de, &dvrentries, de_global_link)
+ if (dvr_entry_is_upcoming_nodup(de))
+ idnode_set_add(ins, (idnode_t*)de, &conf->filter, perm->aa_lang_ui);
+ }
}
static void
}
static void
-api_dvr_previouslyrecorded(access_t *perm, idnode_t *self)
+api_dvr_prevrec_toggle(access_t *perm, idnode_t *self)
{
- dvr_entry_t *de = (dvr_entry_t *)self;
- if (de->de_sched_state == DVR_SCHEDULED)
- dvr_entry_previously_recorded(de);
+ dvr_entry_set_prevrec((dvr_entry_t *)self, -1);
+}
+
+static int
+api_dvr_entry_prevrec_toggle
+ ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+ return api_idnode_handler(&dvr_entry_class, perm, args, resp, api_dvr_prevrec_toggle, "prevrec", 0);
+}
+
+static void
+api_dvr_prevrec_unset(access_t *perm, idnode_t *self)
+{
+ dvr_entry_set_prevrec((dvr_entry_t *)self, 0);
+}
+
+static int
+api_dvr_entry_prevrec_unset
+ ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
+{
+ return api_idnode_handler(&dvr_entry_class, perm, args, resp, api_dvr_prevrec_unset, "prevrec", 0);
+}
+
+static void
+api_dvr_prevrec_set(access_t *perm, idnode_t *self)
+{
+ dvr_entry_set_prevrec((dvr_entry_t *)self, 1);
}
static int
-api_dvr_entry_previouslyrecorded
+api_dvr_entry_prevrec_set
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
- return api_idnode_handler(&dvr_entry_class, perm, args, resp, api_dvr_previouslyrecorded, "remove", 0);
+ return api_idnode_handler(&dvr_entry_class, perm, args, resp, api_dvr_prevrec_set, "prevrec", 0);
}
static void
{ "dvr/entry/class", ACCESS_RECORDER, api_idnode_class, (void*)&dvr_entry_class },
{ "dvr/entry/grid", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid },
{ "dvr/entry/grid_upcoming", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_upcoming },
- { "dvr/entry/grid_duplicate", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_duplicate },
{ "dvr/entry/grid_finished", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_finished },
{ "dvr/entry/grid_failed", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_failed },
{ "dvr/entry/grid_removed", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_removed },
{ "dvr/entry/rerecord/allow", ACCESS_RECORDER, api_dvr_entry_rerecord_allow, NULL },
{ "dvr/entry/stop", ACCESS_RECORDER, api_dvr_entry_stop, NULL }, /* Stop active recording gracefully */
{ "dvr/entry/cancel", ACCESS_RECORDER, api_dvr_entry_cancel, NULL }, /* Cancel scheduled or active recording */
- { "dvr/entry/previouslyrecorded", ACCESS_RECORDER, api_dvr_entry_previouslyrecorded, NULL }, /* Add selected schedules as previously recorded */
+ { "dvr/entry/prevrec/toggle", ACCESS_RECORDER, api_dvr_entry_prevrec_toggle, NULL },
+ { "dvr/entry/prevrec/set", ACCESS_RECORDER, api_dvr_entry_prevrec_set, NULL },
+ { "dvr/entry/prevrec/unset", ACCESS_RECORDER, api_dvr_entry_prevrec_unset, NULL },
{ "dvr/entry/remove", ACCESS_RECORDER, api_dvr_entry_remove, NULL }, /* Remove recorded files from storage */
{ "dvr/entry/filemoved", ACCESS_ADMIN, api_dvr_entry_file_moved, NULL },
{ "dvr/entry/move/finished", ACCESS_RECORDER, api_dvr_entry_move_finished, NULL },
int dvr_entry_is_upcoming(dvr_entry_t *entry)
{
dvr_entry_sched_state_t state = entry->de_sched_state;
- return state == DVR_RECORDING || state == DVR_SCHEDULED || state == DVR_NOSTATE;
+ return state == DVR_RECORDING || state == DVR_SCHEDULED || state == DVR_NOSTATE;
}
-int dvr_entry_is_duplicate(dvr_entry_t *entry)
+int dvr_entry_is_upcoming_nodup(dvr_entry_t *entry)
{
- dvr_entry_sched_state_t state = entry->de_sched_state;
- if (_dvr_duplicate_event(entry) == 0){
- return state == DVR_RECORDING || state == DVR_SCHEDULED || state == DVR_NOSTATE;
- }else return 0;
+ dvr_entry_sched_state_t state = entry->de_sched_state;
+ if (_dvr_duplicate_event(entry))
+ return 0;
+ return state == DVR_RECORDING || state == DVR_SCHEDULED || state == DVR_NOSTATE;
}
int dvr_entry_is_finished(dvr_entry_t *entry, int flags)
case SM_CODE_INVALID_TARGET:
return N_("File not created");
case SM_CODE_USER_ACCESS:
- return N_("User access error");
case SM_CODE_USER_LIMIT:
- return N_("User limit reached");
case SM_CODE_NO_SPACE:
+ case SM_CODE_PREVIOUSLY_RECORDED:
return streaming_code2txt(de->de_last_error);
default:
break;
return de;
}
-static void
-dvr_entry_add_previously_recorded(dvr_entry_t *de)
+/*
+ * Toggle/set/unset previously recorded state
+ */
+void
+dvr_entry_set_prevrec(dvr_entry_t *de, int cmd)
{
- de->de_dont_reschedule = 1; // Set as not reschedule
- de->de_file_removed = 1; // Set as file removed
- de->de_start = gclk(); // Need in case you want to record it again after.
- de->de_stop = gclk() + 1000;
- dvr_entry_completed(de, SM_CODE_OK); // mark as completed
- idnode_changed(&de->de_id);
+ if (de->de_sched_state == DVR_RECORDING)
+ return;
- dvr_entry_retention_timer(de);
+ if (cmd < 0) /* toggle */
+ cmd = de->de_dont_reschedule ? 0 : 1;
- htsp_dvr_entry_update(de);
- idnode_notify_changed(&de->de_id);
+ if (cmd == !!de->de_dont_reschedule)
+ return;
- tvhinfo(LS_DVR, "\"%s\" on \"%s\": "
- "set as previously recorded",
- lang_str_get(de->de_title, NULL), DVR_CH_NAME(de));
-}
+ if (cmd) {
+ de->de_dont_reschedule = 1;
+ de->de_dont_rerecord = 1;
+ de->de_file_removed = 1;
+ dvr_entry_completed(de, SM_CODE_PREVIOUSLY_RECORDED);
+ } else {
+ de->de_dont_reschedule = 0;
+ de->de_dont_rerecord = 0;
+ de->de_file_removed = 0;
+ dvr_entry_set_timer(de);
+ }
-/**
- * Add a schedule as previously recorded
- */
-void
-dvr_entry_previously_recorded(dvr_entry_t *de)
-{
- dvr_entry_add_previously_recorded(de);
+ dvr_entry_retention_timer(de);
+
+ htsp_dvr_entry_update(de);
+ idnode_notify_changed(&de->de_id);
+
+ tvhinfo(LS_DVR, "\"%s\" on \"%s\": "
+ "%sset as previously recorded",
+ lang_str_get(de->de_title, NULL), DVR_CH_NAME(de),
+ cmd ? "" : "un");
}
/**
tvheadend.displayDuplicate = function(value, meta, record) {
- if (value == null)
- return '';
- var is_dup = record.data['duplicate'];
- if (is_dup)
- return "<span class='x-epg-duplicate'>" + value + "</span>";
- else
- return value;
+ if (value == null)
+ return '';
+ var is_dup = record.data['duplicate'];
+ if (is_dup)
+ return "<span class='x-epg-duplicate'>" + value + "</span>";
+ else
+ return value;
}
/** Render an entry differently if it is a duplicate */
}
tvheadend.displayWithYearAndDuplicateRenderer = function(value, meta, record) {
- return function() {
- return function(value, meta, record) {
- value = tvheadend.getDisplayTitle(value, record);
- return tvheadend.displayDuplicate(value, meta, record);
+ return function() {
+ return function(value, meta, record) {
+ value = tvheadend.getDisplayTitle(value, record);
+ return tvheadend.displayDuplicate(value, meta, record);
+ }
}
- }
}
tvheadend.displayWithYearRenderer = function(value, meta, record) {
- return function() {
- return function(value, meta, record) {
- value = tvheadend.getDisplayTitle(value, record);
- return value;
+ return function() {
+ return function(value, meta, record) {
+ value = tvheadend.getDisplayTitle(value, record);
+ return value;
+ }
+ }
+}
+
+tvheadend.dvrButtonFcn = function(store, select, _url, q) {
+ var r = select.getSelections();
+ if (r && r.length > 0) {
+ var uuids = [];
+ for (var i = 0; i < r.length; i++)
+ uuids.push(r[i].id);
+ tvheadend.AjaxConfirm({
+ url: _url,
+ params: {
+ uuid: Ext.encode(uuids)
+ },
+ success: function(d) {
+ store.reload();
+ },
+ question: q,
+ });
}
- }
}
/**
var elist = 'enabled,' +
(tvheadend.accessUpdate.admin ?
list + ',owner,creator' : list) + ',retention,removal';
+ var duplicates = 0;
+ var buttonFcn = tvheadend.dvrButtonFcn;
var stopButton = {
name: 'stop',
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.AjaxConfirm({
- url: 'api/dvr/entry/stop',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- },
- question: _('Do you really want to gracefully stop/unschedule the selection?')
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/stop',
+ _('Do you really want to gracefully stop/unschedule the selection?'));
}
};
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.AjaxConfirm({
- url: 'api/dvr/entry/cancel',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- },
- question: _('Do you really want to abort/unschedule the selection?')
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/cancel',
+ _('Do you really want to abort/unschedule the selection?'));
}
};
- var previouslyrecordedButton = {
- name: 'previouslyrecorded',
+ var prevrecButton = {
+ name: 'prevrec',
builder: function() {
return new Ext.Toolbar.Button({
- tooltip: _('Add as recorded the selected program'),
- iconCls: 'previouslyrecorded',
- text: _('Add as recorded'),
+ tooltip: _('Toggle the previously recorded state.'),
+ iconCls: 'prevrec',
+ text: _('Previously recorded'),
disabled: true
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.AjaxConfirm({
- url: 'api/dvr/entry/previouslyrecorded',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- },
- question: _('Do you really want to add the selected recordings as previosly recorded?')
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/prevrec/toggle',
+ _('Do you really want to toggle the previously recorded state for the selected recordings?'));
}
};
- var showSkippedButton = {
- name: 'showskipped',
- builder: function() {
- return new Ext.Toolbar.Button({
- tooltip: _('Show / hide skipped recordings'),
- iconCls: 'showskipped',
- text: _('View skipped recordings'),
- disabled: false,
- pressed: false,
- enableToggle: true
- });
- },
- callback: function(conf, e, store) {
- if (store.proxy.url === 'api/dvr/entry/grid_duplicate'){
- store.proxy.setUrl('api/dvr/entry/grid_upcoming',true);
- store.load();
- }else{
- store.proxy.setUrl('api/dvr/entry/grid_duplicate',true);
- store.load();
- }
- }
- };
+ var dupButton = {
+ name: 'dup',
+ builder: function() {
+ return new Ext.Toolbar.Button({
+ tooltip: _('Toggle the view of the duplicate DVR entries.'),
+ iconCls: 'duprec',
+ text: _('Show duplicates')
+ });
+ },
+ callback: function(conf, e, store, select) {
+ duplicates ^= 1;
+ this.setText(duplicates ? _('Hide duplicates') : _('Show duplicates'));
+ store.baseParams.duplicates = duplicates;
+ store.reload();
+ }
+ };
function selected(s, abuttons) {
var recording = 0;
});
abuttons.stop.setDisabled(recording < 1);
abuttons.abort.setDisabled(recording < 1);
- abuttons.previouslyrecorded.setDisabled(recording >= 1);
+ abuttons.prevrec.setDisabled(recording >= 1);
}
function beforeedit(e, grid) {
tvheadend.idnode_grid(panel, {
url: 'api/dvr/entry',
- gridURL: 'api/dvr/entry/grid_duplicate',
+ gridURL: 'api/dvr/entry/grid_upcoming',
titleS: _('Upcoming Recording'),
titleP: _('Upcoming / Current Recordings'),
iconCls: 'upcomingRec',
tabIndex: index,
+ extraParams: function(params) {
+ params.duplicates = duplicates
+ },
add: {
url: 'api/dvr/entry',
params: {
filesize: {
renderer: tvheadend.filesizeRenderer()
},
- genre : {
+ genre: {
renderer: function(vals, meta, record) {
return function(vals, meta, record) {
var r = [];
actions,
tvheadend.contentTypeAction,
],
- tbar: [stopButton, abortButton, previouslyrecordedButton, showSkippedButton],
+ tbar: [stopButton, abortButton, prevrecButton, dupButton],
selected: selected,
beforeedit: beforeedit
});
tvheadend.dvr_finished = function(panel, index) {
var actions = tvheadend.dvrRowActions();
+ var buttonFcn = tvheadend.dvrButtonFcn;
var downloadButton = {
name: 'download',
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.Ajax({
- url: 'api/dvr/entry/rerecord/toggle',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- }
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/rerecord/toggle');
}
};
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.Ajax({
- url: 'api/dvr/entry/move/failed',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- }
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/move/failed');
}
};
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.AjaxConfirm({
- url: 'api/dvr/entry/remove',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- },
- question: _('Do you really want to remove the selected recordings from storage?')
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/remove',
+ _('Do you really want to remove the selected recordings from storage?'));
}
};
tvheadend.dvr_failed = function(panel, index) {
var actions = tvheadend.dvrRowActions();
+ var buttonFcn = tvheadend.dvrButtonFcn;
var downloadButton = {
name: 'download',
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.Ajax({
- url: 'api/dvr/entry/rerecord/toggle',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- }
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/rerecord/toggle');
}
};
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.Ajax({
- url: 'api/dvr/entry/move/finished',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- }
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/move/finished');
}
};
tvheadend.dvr_removed = function(panel, index) {
var actions = tvheadend.dvrRowActions();
+ var buttonFcn = tvheadend.dvrButtonFcn;
var rerecordButton = {
name: 'rerecord',
});
},
callback: function(conf, e, store, select) {
- var r = select.getSelections();
- if (r && r.length > 0) {
- var uuids = [];
- for (var i = 0; i < r.length; i++)
- uuids.push(r[i].id);
- tvheadend.Ajax({
- url: 'api/dvr/entry/rerecord/toggle',
- params: {
- uuid: Ext.encode(uuids)
- },
- success: function(d) {
- store.reload();
- }
- });
- }
+ buttonFcn(store, select, 'api/dvr/entry/rerecord/toggle');
}
};