Now the autorec name is by default the epg title.
A new button to show / hidde the skipped recordings in the webui.
A new button to add as completed an upcoming recording to avoid record it again.
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);
+}
+
static void
api_dvr_entry_grid_finished
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
return api_idnode_handler(&dvr_entry_class, perm, args, resp, api_dvr_remove, "remove", 0);
}
+static void
+api_dvr_previouslyrecorded(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);
+}
+
+static int
+api_dvr_entry_previouslyrecorded
+ ( 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);
+}
+
static void
api_dvr_move_finished(access_t *perm, idnode_t *self)
{
{ "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/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 },
void dvr_entry_cancel_remove(dvr_entry_t *de, int rerecord);
+void dvr_entry_previously_recorded(dvr_entry_t *de);
+
int dvr_entry_file_moved(const char *src, const char *dst);
void dvr_entry_destroy(dvr_entry_t *de, int delconf);
htsmsg_t *dvr_entry_class_removal_list ( void *o, const char *lang );
int dvr_entry_is_upcoming(dvr_entry_t *entry);
+int dvr_entry_is_duplicate(dvr_entry_t *entry);
int dvr_entry_is_finished(dvr_entry_t *entry, int flags);
int dvr_entry_verify(dvr_entry_t *de, access_t *a, int readonly);
htsmsg_t *conf;
const char *chname;
char *title;
+ const char *name;
if (!event || !event->episode)
return NULL;
chname = channel_get_name(event->channel, NULL);
return NULL;
conf = htsmsg_create_map();
title = regexp_escape(epg_broadcast_get_title(event, NULL));
+ name = epg_broadcast_get_title(event, NULL);
htsmsg_add_u32(conf, "enabled", 1);
htsmsg_add_str(conf, "title", title);
+ htsmsg_add_str(conf, "name", name);
free(title);
htsmsg_add_str(conf, "config_name", dvr_config_name ?: "");
htsmsg_add_str(conf, "channel", chname);
static int dvr_entry_rerecord(dvr_entry_t *de);
static time_t dvr_entry_get_segment_stop_extra(dvr_entry_t *de);
+static dvr_entry_t *_dvr_duplicate_event(dvr_entry_t *de);
+
/*
*
*/
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)
+{
+ 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;
}
int dvr_entry_is_finished(dvr_entry_t *entry, int flags)
return de;
}
+static void
+dvr_entry_add_previously_recorded(dvr_entry_t *de)
+{
+ 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);
+
+ dvr_entry_retention_timer(de);
+
+ htsp_dvr_entry_update(de);
+ idnode_notify_changed(&de->de_id);
+
+ tvhinfo(LS_DVR, "\"%s\" on \"%s\": "
+ "set as previously recorded",
+ lang_str_get(de->de_title, NULL), DVR_CH_NAME(de));
+}
+
+/**
+ * Add a schedule as previously recorded
+ */
+void
+dvr_entry_previously_recorded(dvr_entry_t *de)
+{
+ dvr_entry_add_previously_recorded(de);
+}
+
/**
* Called by 'dvr_entry_cancel_remove' and 'dvr_entry_cancel_delete'
* delete = 0 -> remove finished and active recordings (visible as removed)
}
};
+ var previouslyrecordedButton = {
+ name: 'previouslyrecorded',
+ builder: function() {
+ return new Ext.Toolbar.Button({
+ tooltip: _('Add as recorded the selected program'),
+ iconCls: 'previouslyrecorded',
+ text: _('Add as 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?')
+ });
+ }
+ }
+ };
+
+ 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();
+ }
+ }
+ };
+
function selected(s, abuttons) {
var recording = 0;
s.each(function(s) {
});
abuttons.stop.setDisabled(recording < 1);
abuttons.abort.setDisabled(recording < 1);
+ abuttons.previouslyrecorded.setDisabled(recording >= 1);
}
function beforeedit(e, grid) {
tvheadend.idnode_grid(panel, {
url: 'api/dvr/entry',
- gridURL: 'api/dvr/entry/grid_upcoming',
+ gridURL: 'api/dvr/entry/grid_duplicate',
titleS: _('Upcoming Recording'),
titleP: _('Upcoming / Current Recordings'),
iconCls: 'upcomingRec',
actions,
tvheadend.contentTypeAction,
],
- tbar: [stopButton, abortButton],
+ tbar: [stopButton, abortButton, previouslyrecordedButton, showSkippedButton],
selected: selected,
beforeedit: beforeedit
});
}
}
};
-
+
function selected(s, abuttons) {
var r = s.getSelections();
abuttons.rerecord.setDisabled(r.length <= 0);
background-image: url(../icons/delete.png) !important;
}
+.previouslyrecorded {
+ background-image: url(../icons/accept.png) !important;
+}
+
+.showskipped {
+ background-image: url(../icons/other_filters.png) !important;
+}
+
.cancel {
background-image: url(../icons/cancel.png) !important;
}