From: Jaroslav Kysela Date: Wed, 20 May 2015 07:45:26 +0000 (+0200) Subject: DVR: Remember all filenames (for deletion or other future operations), fixes#1672 X-Git-Tag: v4.2.1~2518 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a36e86b164fae4171027003587ea44797e6bf99;p=thirdparty%2Ftvheadend.git DVR: Remember all filenames (for deletion or other future operations), fixes#1672 --- diff --git a/src/config.c b/src/config.c index b5e065562..8357da883 100644 --- a/src/config.c +++ b/src/config.c @@ -1185,6 +1185,31 @@ config_migrate_v17 ( void ) } } +static void +config_migrate_v18 ( void ) +{ + htsmsg_t *c, *e, *l, *m; + htsmsg_field_t *f; + const char *filename; + + if ((c = hts_settings_load("dvr/log")) != NULL) { + HTSMSG_FOREACH(f, c) { + if (!(e = htsmsg_field_get_map(f))) continue; + if ((filename = htsmsg_get_str(e, "filename")) == NULL) + continue; + if ((l = htsmsg_get_list(e, "files")) != NULL) + continue; + l = htsmsg_create_list(); + m = htsmsg_create_map(); + htsmsg_add_str(m, "filename", filename); + htsmsg_add_msg(l, NULL, m); + htsmsg_delete_field(e, "filename"); + htsmsg_add_msg(e, "files", l); + hts_settings_save(e, "dvr/log/%s", f->hmf_name); + } + } +} + /* * Perform backup */ @@ -1297,7 +1322,8 @@ static const config_migrate_t config_migrate_table[] = { config_migrate_v14, config_migrate_v15, config_migrate_v16, - config_migrate_v17 + config_migrate_v17, + config_migrate_v18, }; /* diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index e1c223723..540a0ba67 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -157,8 +157,7 @@ typedef struct dvr_entry { char *de_owner; char *de_creator; char *de_comment; - char *de_filename; /* Initially null if no filename has been - generated yet */ + htsmsg_t *de_files; /* List of all used files */ char *de_directory; /* Can be set for autorec entries, will override any directory setting from the configuration */ lang_str_t *de_title; /* Title in UTF-8 (from EPG) */ @@ -480,6 +479,8 @@ dvr_entry_t *dvr_entry_find_by_event_fuzzy(epg_broadcast_t *e); dvr_entry_t *dvr_entry_find_by_episode(epg_broadcast_t *e); +const char *dvr_get_filename(dvr_entry_t *de); + int64_t dvr_get_filesize(dvr_entry_t *de); dvr_entry_t *dvr_entry_cancel(dvr_entry_t *de); diff --git a/src/dvr/dvr_cutpoints.c b/src/dvr/dvr_cutpoints.c index cf3ebba79..4b496d708 100644 --- a/src/dvr/dvr_cutpoints.c +++ b/src/dvr/dvr_cutpoints.c @@ -210,11 +210,13 @@ dvr_get_cutpoint_list (dvr_entry_t *de) { int i; char *path, *sptr; + const char *filename; dvr_cutpoint_list_t *cuts; /* Check this is a valid recording */ assert(de != NULL); - if (de->de_filename == NULL) + filename = dvr_get_filename(de); + if (filename == NULL) return NULL; /* Allocate list space */ @@ -225,8 +227,8 @@ dvr_get_cutpoint_list (dvr_entry_t *de) /* Get base filename */ // TODO: harcoded 3 for max extension - path = alloca(strlen(de->de_filename) + 3); - strcpy(path, de->de_filename); + path = alloca(strlen(filename) + 3); + strcpy(path, filename); sptr = strrchr(path, '.'); if (!sptr) { free(cuts); diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 09458bb82..8672cc5c7 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -347,7 +347,7 @@ dvr_entry_set_timer(dvr_entry_t *de) if(now >= stop || de->de_dont_reschedule) { - if(de->de_filename == NULL) + if(htsmsg_is_empty(de->de_files)) dvr_entry_assign_sched_state(de, DVR_MISSED_TIME); else _dvr_entry_completed(de); @@ -441,6 +441,7 @@ dvr_entry_create(const char *uuid, htsmsg_t *conf) { dvr_entry_t *de, *de2; int64_t start, stop; + htsmsg_t *m; const char *s; if (conf) { @@ -469,12 +470,17 @@ dvr_entry_create(const char *uuid, htsmsg_t *conf) idnode_load(&de->de_id, conf); - /* special case, becaous PO_NOSAVE, load ignores it */ + /* filenames */ + m = htsmsg_get_list(conf, "files"); + if (m) + de->de_files = htsmsg_copy(m); + + /* special case, because PO_NOSAVE, load ignores it */ if (de->de_title == NULL && (s = htsmsg_get_str(conf, "disp_title")) != NULL) dvr_entry_class_disp_title_set(de, s); - /* special case, becaous PO_NOSAVE, load ignores it */ + /* special case, because PO_NOSAVE, load ignores it */ if (de->de_subtitle == NULL && (s = htsmsg_get_str(conf, "disp_subtitle")) != NULL) dvr_entry_class_disp_subtitle_set(de, s); @@ -805,7 +811,7 @@ dvr_entry_dec_ref(dvr_entry_t *de) if(de->de_config != NULL) LIST_REMOVE(de, de_config_link); - free(de->de_filename); + htsmsg_destroy(de->de_files); free(de->de_owner); free(de->de_creator); free(de->de_comment); @@ -879,6 +885,8 @@ dvr_entry_save(dvr_entry_t *de) lock_assert(&global_lock); idnode_save(&de->de_id, m); + if (de->de_files) + htsmsg_add_msg(m, "files", htsmsg_copy(de->de_files)); hts_settings_save(m, "dvr/log/%s", idnode_uuid_as_str(&de->de_id)); htsmsg_destroy(m); } @@ -1116,7 +1124,7 @@ dvr_stop_recording(dvr_entry_t *de, int stopcode, int saveconf) { if (de->de_rec_state == DVR_RS_PENDING || de->de_rec_state == DVR_RS_WAIT_PROGRAM_START || - de->de_filename == NULL) + htsmsg_is_empty(de->de_files)) dvr_entry_assign_sched_state(de, DVR_MISSED_TIME); else _dvr_entry_completed(de); @@ -1424,6 +1432,16 @@ dvr_entry_class_config_name_rend(void *o) return NULL; } +static const void * +dvr_entry_class_filename_get(void *o) +{ + static const char *ret; + dvr_entry_t *de = (dvr_entry_t *)o; + const char *s = dvr_get_filename(de); + ret = s ?: ""; + return &ret; +} + static int dvr_entry_class_channel_set(void *o, const void *v) { @@ -2068,8 +2086,8 @@ const idclass_t dvr_entry_class = { .type = PT_STR, .id = "filename", .name = "Filename", - .off = offsetof(dvr_entry_t, de_filename), - .opts = PO_RDONLY, + .get = dvr_entry_class_filename_get, + .opts = PO_RDONLY | PO_NOSAVE, }, { .type = PT_STR, @@ -2214,25 +2232,43 @@ dvr_destroy_by_channel(channel_t *ch, int delconf) } } +/** + * + */ +const char * +dvr_get_filename(dvr_entry_t *de) +{ + htsmsg_field_t *f; + htsmsg_t *m; + const char *s; + if ((f = htsmsg_field_last(de->de_files)) != NULL && + (m = htsmsg_field_get_map(f)) != NULL && + (s = htsmsg_get_str(m, "filename")) != NULL) + return s; + else + return NULL; +} + /** * */ int64_t dvr_get_filesize(dvr_entry_t *de) { + const char *filename; struct stat st; - if(de->de_filename == NULL) + filename = dvr_get_filename(de); + + if(filename == NULL) return -1; - if(stat(de->de_filename, &st) != 0) + if(stat(filename, &st) != 0) return -1; return st.st_size; } - - /** * */ @@ -2264,8 +2300,11 @@ void dvr_entry_delete(dvr_entry_t *de) { dvr_config_t *cfg = de->de_config; + htsmsg_t *m; + htsmsg_field_t *f; time_t t; struct tm tm; + const char *filename; char tbuf[64], *rdir; int r; @@ -2281,7 +2320,7 @@ dvr_entry_delete(dvr_entry_t *de) de->de_creator ?: "", dvr_entry_get_retention(de)); - if(de->de_filename != NULL) { + if(!htsmsg_is_empty(de->de_files)) { #if ENABLE_INOTIFY dvr_inotify_del(de); #endif @@ -2289,10 +2328,15 @@ dvr_entry_delete(dvr_entry_t *de) if(cfg->dvr_title_dir || cfg->dvr_channel_dir || cfg->dvr_dir_per_day || de->de_directory) rdir = cfg->dvr_storage; - r = deferred_unlink(de->de_filename, rdir); - if(r && r != -ENOENT) - tvhlog(LOG_WARNING, "dvr", "Unable to remove file '%s' from disk -- %s", - de->de_filename, strerror(-errno)); + HTSMSG_FOREACH(f, de->de_files) { + m = htsmsg_field_get_map(f); + if (m == NULL) continue; + filename = htsmsg_get_str(m, "filename"); + r = deferred_unlink(filename, rdir); + if(r && r != -ENOENT) + tvhlog(LOG_WARNING, "dvr", "Unable to remove file '%s' from disk -- %s", + filename, strerror(-errno)); + } } dvr_entry_destroy(de, 1); } diff --git a/src/dvr/dvr_inotify.c b/src/dvr/dvr_inotify.c index 2c29b8d44..044f1235e 100644 --- a/src/dvr/dvr_inotify.c +++ b/src/dvr/dvr_inotify.c @@ -92,15 +92,16 @@ void dvr_inotify_done ( void ) void dvr_inotify_add ( dvr_entry_t *de ) { dvr_inotify_entry_t *e; + const char *filename = dvr_get_filename(de); char *path; if (_inot_fd < 0) return; - if (!de->de_filename || de->de_filename[0] == '\0') + if (filename == NULL) return; - path = strdup(de->de_filename); + path = strdup(filename); SKEL_ALLOC(dvr_inotify_entry_skel); dvr_inotify_entry_skel->path = dirname(path); @@ -164,25 +165,6 @@ _dvr_inotify_find return e; } -/* - * Find DVR entry - */ -static dvr_entry_t * -_dvr_inotify_find2 - ( dvr_inotify_entry_t *die, const char *name ) -{ - dvr_entry_t *de = NULL; - char path[512]; - - snprintf(path, sizeof(path), "%s/%s", die->path, name); - - LIST_FOREACH(de, &die->entries, de_inotify_link) - if (de->de_filename && !strcmp(path, de->de_filename)) - break; - - return de; -} - /* * File moved */ @@ -192,20 +174,43 @@ _dvr_inotify_moved { dvr_inotify_entry_t *die; dvr_entry_t *de; + char path[PATH_MAX]; + const char *filename; + htsmsg_t *m = NULL; + htsmsg_field_t *f = NULL; if (!(die = _dvr_inotify_find(fd))) return; - if (!(de = _dvr_inotify_find2(die, from))) + snprintf(path, sizeof(path), "%s/%s", die->path, from); + + LIST_FOREACH(de, &die->entries, de_inotify_link) { + if (de->de_files == NULL) + continue; + HTSMSG_FOREACH(f, de->de_files) + if ((m = htsmsg_field_get_list(f)) != NULL) { + filename = htsmsg_get_str(m, "filename"); + if (filename && !strcmp(path, filename)) + break; + } + if (f) + break; + } + + if (!de) return; - if (to) { - char path[512]; - snprintf(path, sizeof(path), "%s/%s", die->path, to); - tvh_str_update(&de->de_filename, path); - dvr_entry_save(de); - } else - dvr_inotify_del(de); + if (f && m) { + if (to) { + snprintf(path, sizeof(path), "%s/%s", die->path, to); + htsmsg_set_str(m, "filename", path); + dvr_entry_save(de); + } else { + htsmsg_field_destroy(de->de_files, f); + if (htsmsg_is_empty(de->de_files)) + dvr_inotify_del(de); + } + } htsp_dvr_entry_update(de); idnode_notify_changed(&de->de_id); diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 617a3a2a9..46bc2e398 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -199,6 +199,7 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) char *filename, *s; struct tm tm; dvr_config_t *cfg; + htsmsg_t *m; if (de == NULL) return -1; @@ -287,7 +288,11 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) } free(filename); - tvh_str_set(&de->de_filename, fullname); + if (de->de_files == NULL) + de->de_files = htsmsg_create_list(); + m = htsmsg_create_map(); + htsmsg_add_str(m, "filename", fullname); + htsmsg_add_msg(de->de_files, NULL, m); return 0; } @@ -308,7 +313,7 @@ dvr_rec_fatal_error(dvr_entry_t *de, const char *fmt, ...) tvhlog(LOG_ERR, "dvr", "Recording error: \"%s\": %s", - de->de_filename ?: lang_str_get(de->de_title, NULL), msgbuf); + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL), msgbuf); } /** @@ -386,7 +391,7 @@ dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss) return -1; } - if(muxer_open_file(muxer, de->de_filename)) { + if(muxer_open_file(muxer, dvr_get_filename(de))) { dvr_rec_fatal_error(de, "Unable to open file"); return -1; } @@ -408,7 +413,7 @@ dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss) "network: \"%s\", mux: \"%s\", provider: \"%s\", " "service: \"%s\"", - de->de_filename ?: lang_str_get(de->de_title, NULL), + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL), si->si_adapter ?: "", si->si_network ?: "", si->si_mux ?: "", @@ -575,7 +580,7 @@ dvr_thread(void *aux) muxer_reconfigure(prch->prch_muxer, sm->sm_data) < 0) { tvhlog(LOG_WARNING, "dvr", "Unable to reconfigure \"%s\"", - de->de_filename ?: lang_str_get(de->de_title, NULL)); + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL)); // Try to restart the recording if the muxer doesn't // support reconfiguration of the streams. @@ -605,7 +610,7 @@ dvr_thread(void *aux) de->de_last_error = SM_CODE_OK; tvhlog(LOG_INFO, "dvr", "Recording completed: \"%s\"", - de->de_filename ?: lang_str_get(de->de_title, NULL)); + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL)); dvr_thread_epilog(de); started = 0; @@ -616,7 +621,7 @@ dvr_thread(void *aux) dvr_rec_set_state(de, DVR_RS_ERROR, sm->sm_code); tvhlog(LOG_ERR, "dvr", "Recording stopped: \"%s\": %s", - de->de_filename ?: lang_str_get(de->de_title, NULL), + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL), streaming_code2txt(sm->sm_code)); dvr_thread_epilog(de); @@ -641,7 +646,7 @@ dvr_thread(void *aux) dvr_rec_set_state(de, DVR_RS_ERROR, code); tvhlog(LOG_ERR, "dvr", "Streaming error: \"%s\": %s", - de->de_filename ?: lang_str_get(de->de_title, NULL), + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL), streaming_code2txt(code)); } } @@ -654,7 +659,7 @@ dvr_thread(void *aux) tvhlog(LOG_ERR, "dvr", "Recording unable to start: \"%s\": %s", - de->de_filename ?: lang_str_get(de->de_title, NULL), + dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL), streaming_code2txt(sm->sm_code)); } break; @@ -689,7 +694,7 @@ dvr_thread(void *aux) static void dvr_spawn_postproc(dvr_entry_t *de, const char *dvr_postproc) { - const char *fmap[256]; + const char *fmap[256], *filename; char **args; char start[16]; char stop[16]; @@ -703,12 +708,16 @@ dvr_spawn_postproc(dvr_entry_t *de, const char *dvr_postproc) return; } - fbasename = tvh_strdupa(de->de_filename); + filename = dvr_get_filename(de); + if (filename == NULL) + return; + + fbasename = tvh_strdupa(filename); snprintf(start, sizeof(start), "%"PRItime_t, (time_t)dvr_entry_get_start_time(de)); snprintf(stop, sizeof(stop), "%"PRItime_t, (time_t)dvr_entry_get_stop_time(de)); memset(fmap, 0, sizeof(fmap)); - fmap['f'] = de->de_filename; /* full path to recoding */ + fmap['f'] = filename; /* full path to recoding */ fmap['b'] = basename(fbasename); /* basename of recoding */ fmap['c'] = DVR_CH_NAME(de); /* channel name */ fmap['C'] = de->de_creator; /* user who created this recording */ @@ -748,6 +757,6 @@ dvr_thread_epilog(dvr_entry_t *de) dvr_notify(de, 1); dvr_config_t *cfg = de->de_config; - if(cfg && cfg->dvr_postproc && de->de_filename) + if(cfg && cfg->dvr_postproc) dvr_spawn_postproc(de,cfg->dvr_postproc); } diff --git a/src/htsmsg.c b/src/htsmsg.c index 90bf4f5c7..92f2f4c24 100644 --- a/src/htsmsg.c +++ b/src/htsmsg.c @@ -75,7 +75,6 @@ htsmsg_clear(htsmsg_t *msg) } - /* * */ @@ -121,6 +120,17 @@ htsmsg_field_find(htsmsg_t *msg, const char *name) } +/* + * + */ +htsmsg_field_t * +htsmsg_field_last(htsmsg_t *msg) +{ + if (msg == NULL) + return NULL; + return TAILQ_LAST(&msg->hm_fields, htsmsg_field_queue); +} + /** * @@ -137,6 +147,20 @@ htsmsg_delete_field(htsmsg_t *msg, const char *name) } +/** + * + */ +int +htsmsg_is_empty(htsmsg_t *msg) +{ + if (msg == NULL) + return 1; + + assert(msg->hm_data == NULL); + return TAILQ_EMPTY(&msg->hm_fields); +} + + /* * */ @@ -241,6 +265,21 @@ htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str) f->hmf_str = strdup(str); } +/* + * + */ +int +htsmsg_field_set_str(htsmsg_field_t *f, const char *str) +{ + if (f->hmf_type != HMF_STR) + return 1; + if (f->hmf_flags & HMF_ALLOCED) + free((void *)f->hmf_str); + f->hmf_flags |= HMF_ALLOCED; + f->hmf_str = strdup(str); + return 0; +} + /* * */ @@ -250,14 +289,7 @@ htsmsg_set_str(htsmsg_t *msg, const char *name, const char *str) htsmsg_field_t *f = htsmsg_field_find(msg, name); if (!f) f = htsmsg_field_add(msg, name, HMF_STR, HMF_ALLOCED | HMF_NAME_ALLOCED); - else { - if (f->hmf_type != HMF_STR) - return 1; - if(f->hmf_flags & HMF_ALLOCED) - free((void *)f->hmf_str); - } - f->hmf_str = strdup(str); - return 0; + return htsmsg_field_set_str(f, str); } /* diff --git a/src/htsmsg.h b/src/htsmsg.h index 4964c2bfa..993d213db 100644 --- a/src/htsmsg.h +++ b/src/htsmsg.h @@ -158,6 +158,11 @@ void htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str); */ int htsmsg_set_str(htsmsg_t *msg, const char *name, const char *str); +/** + * Update a string field + */ +int htsmsg_field_set_str(htsmsg_field_t *f, const char *str); + /** * Add an field where source is a list or map message. */ @@ -332,6 +337,11 @@ int32_t htsmsg_get_s32_or_default(htsmsg_t *msg, const char *name, */ int htsmsg_delete_field(htsmsg_t *msg, const char *name); +/** + * Is list/map empty + */ +int htsmsg_is_empty(htsmsg_t *msg); + /** * Detach will remove the given field (and only if it is a list or map) * from the message and make it a 'standalone message'. This means @@ -356,6 +366,11 @@ htsmsg_field_t *htsmsg_field_add(htsmsg_t *msg, const char *name, */ htsmsg_field_t *htsmsg_field_find(htsmsg_t *msg, const char *name); +/** + * Get a last field, return NULL if it does not exist + */ +htsmsg_field_t *htsmsg_field_last(htsmsg_t *msg); + /** * Clone a message. diff --git a/src/htsp_server.c b/src/htsp_server.c index 313179acd..70ac5a7b2 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -68,7 +68,7 @@ static void *htsp_server, *htsp_server_2; -#define HTSP_PROTO_VERSION 20 +#define HTSP_PROTO_VERSION 21 #define HTSP_ASYNC_OFF 0x00 #define HTSP_ASYNC_ON 0x01 @@ -663,9 +663,10 @@ htsp_build_tag(channel_tag_t *ct, const char *method, int include_channels) static htsmsg_t * htsp_build_dvrentry(dvr_entry_t *de, const char *method) { - htsmsg_t *out = htsmsg_create_map(); + htsmsg_t *out = htsmsg_create_map(), *l, *m; + htsmsg_field_t *f; const char *s = NULL, *error = NULL, *subscriptionError = NULL; - const char *p; + const char *p, *last; int64_t fsize = -1; htsmsg_add_u32(out, "id", idnode_get_short_uuid(&de->de_id)); @@ -689,7 +690,7 @@ htsp_build_dvrentry(dvr_entry_t *de, const char *method) htsmsg_add_u32(out, "priority", de->de_pri); htsmsg_add_u32(out, "contentType", de->de_content_type); - if( de->de_title && (s = lang_str_get(de->de_title, NULL))) + if(de->de_title && (s = lang_str_get(de->de_title, NULL))) htsmsg_add_str(out, "title", s); if( de->de_desc && (s = lang_str_get(de->de_desc, NULL))) htsmsg_add_str(out, "description", s); @@ -698,10 +699,23 @@ htsp_build_dvrentry(dvr_entry_t *de, const char *method) if(de->de_creator) htsmsg_add_str(out, "creator", de->de_creator); - if( de->de_filename && de->de_config ) { - if ((p = tvh_strbegins(de->de_filename, de->de_config->dvr_storage))) - htsmsg_add_str(out, "path", p); + last = NULL; + if (!htsmsg_is_empty(de->de_files) && de->de_config) { + l = htsmsg_create_list(); + htsmsg_add_msg(out, "files", l); + HTSMSG_FOREACH(f, de->de_files) { + m = htsmsg_field_get_list(f); + if (m == NULL) continue; + s = last = htsmsg_get_str(m, "filename"); + if (s && (p = tvh_strbegins(s, de->de_config->dvr_storage)) != NULL) + htsmsg_add_msg(l, NULL, htsmsg_copy(m)); + } } + + if(last && de->de_config) + if ((p = tvh_strbegins(last, de->de_config->dvr_storage))) + htsmsg_add_str(out, "path", p); + switch(de->de_sched_state) { case DVR_SCHEDULED: s = "scheduled"; @@ -2251,6 +2265,9 @@ htsp_method_file_open(htsp_connection_t *htsp, htsmsg_t *in) { const char *str, *s2; const char *filename = NULL; + htsmsg_field_t *f; + + if((str = htsmsg_get_str(in, "file")) == NULL) return htsp_error("Missing argument 'file'"); @@ -2270,10 +2287,13 @@ htsp_method_file_open(htsp_connection_t *htsp, htsmsg_t *in) if (!htsp_user_access_channel(htsp, de->de_channel)) return htsp_error("User does not have access"); - if(de->de_filename == NULL) + f = htsmsg_field_last(de->de_files); + if (f) + filename = htsmsg_field_get_str(f); + + if (f == NULL || filename == NULL) return htsp_error("DVR entry does not have a file yet"); - filename = de->de_filename; return htsp_file_open(htsp, filename, 0); } else if ((s2 = tvh_strbegins(str, "imagecache/")) != NULL) { diff --git a/src/webui/webui.c b/src/webui/webui.c index 104d35f8c..e4e9a7cb7 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -1140,7 +1140,7 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) { int fd, i, ret; struct stat st; - const char *content = NULL, *range; + const char *content = NULL, *range, *filename; dvr_entry_t *de; char *fname; char *basename; @@ -1171,7 +1171,7 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) de = dvr_entry_find_by_uuid(remain); if (de == NULL) de = dvr_entry_find_by_id(atoi(remain)); - if(de == NULL || de->de_filename == NULL) { + if(de == NULL || (filename = dvr_get_filename(de)) == NULL) { pthread_mutex_unlock(&global_lock); return HTTP_STATUS_NOT_FOUND; } @@ -1180,7 +1180,7 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) return HTTP_STATUS_NOT_FOUND; } - fname = tvh_strdupa(de->de_filename); + fname = tvh_strdupa(filename); content = muxer_container_type2mime(de->de_mc, 1); pthread_mutex_unlock(&global_lock);