From: Jaroslav Kysela Date: Wed, 2 Dec 2015 09:14:41 +0000 (+0100) Subject: DVR / WEBUI: Mark view levels for DVR tabs, add PO_NOUI, remove de_mc (unused) X-Git-Tag: v4.2.1~1413 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=09a33b6500bcee50ff1258c47660dcd6dd992166;p=thirdparty%2Ftvheadend.git DVR / WEBUI: Mark view levels for DVR tabs, add PO_NOUI, remove de_mc (unused) --- diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index af97401a7..137c167d2 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -177,7 +177,6 @@ typedef struct dvr_entry { int de_pri; int de_dont_reschedule; int de_dont_rerecord; - int de_mc; uint32_t de_retention; uint32_t de_removal; diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 6e8c745c5..3d2266914 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -939,8 +939,8 @@ dvr_autorec_entry_class_owner_opts(void *o) dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)o; if (dae && dae->dae_id.in_access && !access_verify2(dae->dae_id.in_access, ACCESS_ADMIN)) - return 0; - return PO_RDONLY; + return PO_ADVANCED; + return PO_RDONLY | PO_ADVANCED; } const idclass_t dvr_autorec_entry_class = { @@ -1000,6 +1000,7 @@ const idclass_t dvr_autorec_entry_class = { .get = dvr_autorec_entry_class_tag_get, .rend = dvr_autorec_entry_class_tag_rend, .list = channel_tag_class_get_list, + .opts = PO_ADVANCED }, { .type = PT_STR, @@ -1025,7 +1026,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Extra start time"), .off = offsetof(dvr_autorec_entry_t, dae_start_extra), .list = dvr_autorec_entry_class_extra_list, - .opts = PO_DURATION | PO_SORTKEY + .opts = PO_DURATION | PO_SORTKEY | PO_ADVANCED }, { .type = PT_TIME, @@ -1033,7 +1034,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Extra stop time"), .off = offsetof(dvr_autorec_entry_t, dae_stop_extra), .list = dvr_autorec_entry_class_extra_list, - .opts = PO_DURATION | PO_SORTKEY + .opts = PO_DURATION | PO_SORTKEY | PO_ADVANCED }, { .type = PT_U32, @@ -1052,6 +1053,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Minimum duration"), .list = dvr_autorec_entry_class_minduration_list, .off = offsetof(dvr_autorec_entry_t, dae_minduration), + .opts = PO_ADVANCED }, { .type = PT_INT, @@ -1059,6 +1061,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Maximum duration"), .list = dvr_autorec_entry_class_maxduration_list, .off = offsetof(dvr_autorec_entry_t, dae_maxduration), + .opts = PO_ADVANCED }, { .type = PT_U32, @@ -1066,6 +1069,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Content type"), .list = dvr_autorec_entry_class_content_type_list, .off = offsetof(dvr_autorec_entry_t, dae_content_type), + .opts = PO_ADVANCED }, { .type = PT_U32, @@ -1074,6 +1078,7 @@ const idclass_t dvr_autorec_entry_class = { .list = dvr_entry_class_pri_list, .def.i = DVR_PRIO_NORMAL, .off = offsetof(dvr_autorec_entry_t, dae_pri), + .opts = PO_ADVANCED }, { .type = PT_U32, @@ -1082,34 +1087,35 @@ const idclass_t dvr_autorec_entry_class = { .def.i = DVR_AUTOREC_RECORD_ALL, .off = offsetof(dvr_autorec_entry_t, dae_record), .list = dvr_autorec_entry_class_dedup_list, + .opts = PO_ADVANCED }, { .type = PT_U32, .id = "retention", .name = N_("DVR log retention (days)"), .off = offsetof(dvr_autorec_entry_t, dae_retention), - .opts = PO_HIDDEN, + .opts = PO_HIDDEN | PO_EXPERT, }, { .type = PT_U32, .id = "removal", .name = N_("DVR file retention period (days)"), .off = offsetof(dvr_autorec_entry_t, dae_removal), - .opts = PO_HIDDEN, + .opts = PO_HIDDEN | PO_EXPERT, }, { .type = PT_U32, .id = "maxcount", .name = N_("Maximum count (0=default)"), .off = offsetof(dvr_autorec_entry_t, dae_max_count), - .opts = PO_HIDDEN, + .opts = PO_HIDDEN | PO_EXPERT, }, { .type = PT_U32, .id = "maxsched", .name = N_("Maximum schedules limit (0=default)"), .off = offsetof(dvr_autorec_entry_t, dae_max_sched_count), - .opts = PO_HIDDEN, + .opts = PO_HIDDEN | PO_EXPERT, }, { .type = PT_STR, @@ -1119,6 +1125,7 @@ const idclass_t dvr_autorec_entry_class = { .get = dvr_autorec_entry_class_config_name_get, .rend = dvr_autorec_entry_class_config_name_rend, .list = dvr_entry_class_config_name_list, + .opts = PO_ADVANCED }, { .type = PT_STR, @@ -1126,7 +1133,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Brand"), .set = dvr_autorec_entry_class_brand_set, .get = dvr_autorec_entry_class_brand_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_ADVANCED, }, { .type = PT_STR, @@ -1134,7 +1141,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Season"), .set = dvr_autorec_entry_class_season_set, .get = dvr_autorec_entry_class_season_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_ADVANCED, }, { .type = PT_STR, @@ -1142,7 +1149,7 @@ const idclass_t dvr_autorec_entry_class = { .name = N_("Series link"), .set = dvr_autorec_entry_class_series_link_set, .get = dvr_autorec_entry_class_series_link_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_ADVANCED, }, { .type = PT_STR, diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 729dfdc00..9540ee37e 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -256,14 +256,6 @@ dvr_entry_get_extra_time_post( dvr_entry_t *de ) return extra; } -int -dvr_entry_get_mc( dvr_entry_t *de ) -{ - if (de->de_mc >= 0) - return de->de_mc; - return profile_get_mc(de->de_config->dvr_profile); -} - uint32_t dvr_entry_get_retention_days( dvr_entry_t *de ) { @@ -674,7 +666,6 @@ dvr_entry_create(const char *uuid, htsmsg_t *conf, int clone) } de->de_enabled = 1; - de->de_mc = -1; de->de_config = dvr_config_find_by_name_default(NULL); if (de->de_config) LIST_INSERT_HEAD(&de->de_config->dvr_entries, de, de_config_link); @@ -1922,8 +1913,8 @@ dvr_entry_class_start_opts(void *o) { dvr_entry_t *de = (dvr_entry_t *)o; if (de && !dvr_entry_is_editable(de)) - return PO_RDONLY; - return 0; + return PO_RDONLY | PO_ADVANCED; + return PO_ADVANCED; } static uint32_t @@ -1932,8 +1923,8 @@ dvr_entry_class_owner_opts(void *o) dvr_entry_t *de = (dvr_entry_t *)o; if (de && de->de_id.in_access && !access_verify2(de->de_id.in_access, ACCESS_ADMIN)) - return 0; - return PO_RDONLY; + return PO_ADVANCED; + return PO_RDONLY | PO_ADVANCED; } static uint32_t @@ -2160,28 +2151,6 @@ dvr_entry_class_removal_set(void *o, const void *v) return dvr_entry_class_int_set(de, (int *)&de->de_removal, *(int *)v); } -static int -dvr_entry_class_mc_set(void *o, const void *v) -{ - dvr_entry_t *de = (dvr_entry_t *)o; - return dvr_entry_class_int_set(de, &de->de_mc, *(int *)v); -} - -htsmsg_t * -dvr_entry_class_mc_list ( void *o, const char *lang ) -{ - static const struct strtab tab[] = { - { N_("Not set"), -1 }, - { N_("Matroska (mkv)"), MC_MATROSKA, }, - { N_("Same as source (pass through)"), MC_PASS, }, -#if ENABLE_LIBAV - { N_("MPEG-TS"), MC_MPEGTS }, - { N_("MPEG-PS (DVD)"), MC_MPEGPS }, -#endif - }; - return strtab2htsmsg(tab, 1, lang); -} - static int dvr_entry_class_autorec_set(void *o, const void *v) { @@ -2603,6 +2572,7 @@ const idclass_t dvr_entry_class = { .id = "enabled", .name = N_("Enabled"), .off = offsetof(dvr_entry_t, de_enabled), + .opts = PO_ADVANCED }, { .type = PT_TIME, @@ -2620,7 +2590,7 @@ const idclass_t dvr_entry_class = { .set = dvr_entry_class_start_extra_set, .list = dvr_entry_class_extra_list, .get_opts = dvr_entry_class_start_extra_opts, - .opts = PO_SORTKEY, + .opts = PO_SORTKEY | PO_ADVANCED, }, { .type = PT_TIME, @@ -2642,7 +2612,7 @@ const idclass_t dvr_entry_class = { .name = N_("Post-recording padding"), .off = offsetof(dvr_entry_t, de_stop_extra), .list = dvr_entry_class_extra_list, - .opts = PO_SORTKEY, + .opts = PO_SORTKEY | PO_ADVANCED, }, { .type = PT_TIME, @@ -2673,7 +2643,7 @@ const idclass_t dvr_entry_class = { .id = "channel_icon", .name = N_("Channel icon"), .get = dvr_entry_class_channel_icon_url_get, - .opts = PO_HIDDEN | PO_RDONLY | PO_NOSAVE, + .opts = PO_HIDDEN | PO_RDONLY | PO_NOSAVE | PO_NOUI, }, { .type = PT_STR, @@ -2744,7 +2714,7 @@ const idclass_t dvr_entry_class = { .name = N_("DVR log retention (days)"), .off = offsetof(dvr_entry_t, de_retention), .set = dvr_entry_class_retention_set, - .opts = PO_HIDDEN + .opts = PO_HIDDEN | PO_ADVANCED }, { .type = PT_U32, @@ -2752,17 +2722,7 @@ const idclass_t dvr_entry_class = { .name = N_("DVR file retention period (days)"), .off = offsetof(dvr_entry_t, de_removal), .set = dvr_entry_class_removal_set, - .opts = PO_HIDDEN - }, - { - .type = PT_INT, - .id = "container", - .name = N_("Container"), - .off = offsetof(dvr_entry_t, de_mc), - .def.i = MC_MATROSKA, - .set = dvr_entry_class_mc_set, - .list = dvr_entry_class_mc_list, - .opts = PO_RDONLY + .opts = PO_HIDDEN | PO_ADVANCED }, { .type = PT_STR, @@ -2794,56 +2754,56 @@ const idclass_t dvr_entry_class = { .id = "filename", .name = N_("Filename"), .get = dvr_entry_class_filename_get, - .opts = PO_RDONLY | PO_NOSAVE, + .opts = PO_RDONLY | PO_NOSAVE | PO_NOUI, }, { .type = PT_STR, .id = "directory", .name = N_("Directory"), .off = offsetof(dvr_entry_t, de_directory), - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_NOUI, }, { .type = PT_U32, .id = "errorcode", .name = N_("Error code"), .off = offsetof(dvr_entry_t, de_last_error), - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_NOUI, }, { .type = PT_U32, .id = "errors", .name = N_("Errors"), .off = offsetof(dvr_entry_t, de_errors), - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_ADVANCED, }, { .type = PT_U32, .id = "data_errors", .name = N_("Data errors"), .off = offsetof(dvr_entry_t, de_data_errors), - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_ADVANCED, }, { .type = PT_U16, .id = "dvb_eid", .name = N_("DVB EPG ID"), .off = offsetof(dvr_entry_t, de_dvb_eid), - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_EXPERT, }, { .type = PT_BOOL, .id = "noresched", .name = N_("Don't reschedule"), .off = offsetof(dvr_entry_t, de_dont_reschedule), - .opts = PO_HIDDEN, + .opts = PO_HIDDEN | PO_NOUI, }, { .type = PT_BOOL, .id = "norerecord", .name = N_("Don't re-record"), .off = offsetof(dvr_entry_t, de_dont_rerecord), - .opts = PO_HIDDEN, + .opts = PO_HIDDEN | PO_ADVANCED, }, { .type = PT_STR, @@ -2851,14 +2811,14 @@ const idclass_t dvr_entry_class = { .name = N_("Auto record"), .set = dvr_entry_class_autorec_set, .get = dvr_entry_class_autorec_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_NOUI, }, { .type = PT_STR, .id = "autorec_caption", .name = N_("Auto record caption"), .get = dvr_entry_class_autorec_caption_get, - .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN, + .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN | PO_NOUI, }, { .type = PT_STR, @@ -2866,14 +2826,14 @@ const idclass_t dvr_entry_class = { .name = N_("Auto time record"), .set = dvr_entry_class_timerec_set, .get = dvr_entry_class_timerec_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_EXPERT, }, { .type = PT_STR, .id = "timerec_caption", .name = N_("Time record caption"), .get = dvr_entry_class_timerec_caption_get, - .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN, + .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN | PO_NOUI, }, { .type = PT_STR, @@ -2881,7 +2841,7 @@ const idclass_t dvr_entry_class = { .name = N_("Parent entry"), .set = dvr_entry_class_parent_set, .get = dvr_entry_class_parent_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_NOUI, }, { .type = PT_STR, @@ -2889,7 +2849,7 @@ const idclass_t dvr_entry_class = { .name = N_("Slave entry"), .set = dvr_entry_class_child_set, .get = dvr_entry_class_child_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_NOUI, }, { .type = PT_U32, @@ -2905,7 +2865,7 @@ const idclass_t dvr_entry_class = { .name = N_("Broadcast"), .set = dvr_entry_class_broadcast_set, .get = dvr_entry_class_broadcast_get, - .opts = PO_RDONLY, + .opts = PO_RDONLY | PO_NOUI, }, { .type = PT_STR, @@ -2919,7 +2879,7 @@ const idclass_t dvr_entry_class = { .id = "url", .name = N_("URL"), .get = dvr_entry_class_url_get, - .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN, + .opts = PO_RDONLY | PO_NOSAVE | PO_NOUI, }, { .type = PT_S64, @@ -2940,14 +2900,14 @@ const idclass_t dvr_entry_class = { .id = "sched_status", .name = N_("Schedule status"), .get = dvr_entry_class_sched_status_get, - .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN, + .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN | PO_NOUI, }, { .type = PT_TIME, .id = "duplicate", .name = N_("Rerun of"), .get = dvr_entry_class_duplicate_get, - .opts = PO_RDONLY | PO_NOSAVE, + .opts = PO_RDONLY | PO_NOSAVE | PO_ADVANCED, }, { .type = PT_STR, diff --git a/src/dvr/dvr_timerec.c b/src/dvr/dvr_timerec.c index 9d4be9c83..14d923643 100644 --- a/src/dvr/dvr_timerec.c +++ b/src/dvr/dvr_timerec.c @@ -518,8 +518,8 @@ dvr_timerec_entry_class_owner_opts(void *o) dvr_timerec_entry_t *dte = (dvr_timerec_entry_t *)o; if (dte && dte->dte_id.in_access && !access_verify2(dte->dte_id.in_access, ACCESS_ADMIN)) - return 0; - return PO_RDONLY; + return PO_ADVANCED; + return PO_RDONLY | PO_ADVANCED; } const idclass_t dvr_timerec_entry_class = { @@ -555,6 +555,7 @@ const idclass_t dvr_timerec_entry_class = { .id = "directory", .name = N_("Directory"), .off = offsetof(dvr_timerec_entry_t, dte_directory), + .opts = PO_EXPERT }, { .type = PT_STR, @@ -603,19 +604,21 @@ const idclass_t dvr_timerec_entry_class = { .list = dvr_entry_class_pri_list, .def.i = DVR_PRIO_NORMAL, .off = offsetof(dvr_timerec_entry_t, dte_pri), - .opts = PO_SORTKEY, + .opts = PO_SORTKEY | PO_ADVANCED, }, { .type = PT_U32, .id = "retention", .name = N_("DVR log retention (days)"), .off = offsetof(dvr_timerec_entry_t, dte_retention), + .opts = PO_EXPERT }, { .type = PT_U32, .id = "removal", .name = N_("DVR file retention period (days)"), .off = offsetof(dvr_timerec_entry_t, dte_removal), + .opts = PO_EXPERT }, { .type = PT_STR, @@ -625,6 +628,7 @@ const idclass_t dvr_timerec_entry_class = { .get = dvr_timerec_entry_class_config_name_get, .rend = dvr_timerec_entry_class_config_name_rend, .list = dvr_entry_class_config_name_list, + .opts = PO_ADVANCED }, { .type = PT_STR, diff --git a/src/muxer.c b/src/muxer.c index 1df4efb13..aa6da806f 100644 --- a/src/muxer.c +++ b/src/muxer.c @@ -134,6 +134,31 @@ muxer_container_type2mime(muxer_container_type_t mc, int video) } +/** + * Get the mime type for a filename + */ +const char* +muxer_container_filename2mime(const char *filename, int video) +{ + int mc = MC_UNKNOWN; + const char *suffix; + + if(filename) { + suffix = strrchr(filename, '.'); + if (suffix == NULL) + suffix = filename; + else + suffix++; + if(video) + mc = str2val(suffix, container_video_file_suffix); + else + mc = str2val(suffix, container_audio_file_suffix); + } + + return muxer_container_type2mime(mc, 1); +} + + /** * Get the suffix used in file names */ diff --git a/src/muxer.h b/src/muxer.h index bb5169590..06abae019 100644 --- a/src/muxer.h +++ b/src/muxer.h @@ -97,6 +97,7 @@ typedef struct muxer { /* type <==> string converters */ const char * muxer_container_type2txt (muxer_container_type_t mc); const char* muxer_container_type2mime (muxer_container_type_t mc, int video); +const char* muxer_container_filename2mime (const char *filename, int video); muxer_container_type_t muxer_container_txt2type (const char *str); muxer_container_type_t muxer_container_mime2type (const char *str); diff --git a/src/prop.c b/src/prop.c index 884205fdf..3ce341cd7 100644 --- a/src/prop.c +++ b/src/prop.c @@ -470,6 +470,8 @@ prop_serialize_value htsmsg_add_bool(m, "expert", 1); else if (opts & PO_ADVANCED) htsmsg_add_bool(m, "advanced", 1); + if (opts & PO_NOUI) + htsmsg_add_bool(m, "noui", 1); if (opts & PO_HIDDEN) htsmsg_add_bool(m, "hidden", 1); if (opts & PO_PASSWORD) diff --git a/src/prop.h b/src/prop.h index cf06b5c17..10a66eeb0 100644 --- a/src/prop.h +++ b/src/prop.h @@ -50,16 +50,17 @@ typedef enum { #define PO_WRONCE (1<<3) // Property is write-once (i.e. on creation) #define PO_ADVANCED (1<<4) // Property is advanced #define PO_EXPERT (1<<5) // Property is for experts -#define PO_HIDDEN (1<<6) // Property is hidden (by default) -#define PO_USERAW (1<<7) // Only save the RAW (off) value if it exists -#define PO_SORTKEY (1<<8) // Sort using key (not display value) -#define PO_PASSWORD (1<<9) // String is a password -#define PO_DURATION (1<<10) // For PT_TIME - differentiate between duration and datetime -#define PO_HEXA (1<<11) // Hexadecimal value -#define PO_DATE (1<<12) // Show date only -#define PO_LOCALE (1<<13) // Call tvh_locale_lang on string -#define PO_LORDER (1<<14) // Manage order in lists -#define PO_MULTILINE (1<<15) // Multiline string +#define PO_NOUI (1<<6) // Property should not be presented in the user interface +#define PO_HIDDEN (1<<7) // Property is hidden (by default) +#define PO_USERAW (1<<8) // Only save the RAW (off) value if it exists +#define PO_SORTKEY (1<<9) // Sort using key (not display value) +#define PO_PASSWORD (1<<10) // String is a password +#define PO_DURATION (1<<11) // For PT_TIME - differentiate between duration and datetime +#define PO_HEXA (1<<12) // Hexadecimal value +#define PO_DATE (1<<13) // Show date only +#define PO_LOCALE (1<<14) // Call tvh_locale_lang on string +#define PO_LORDER (1<<15) // Manage order in lists +#define PO_MULTILINE (1<<16) // Multiline string /* * Property definition diff --git a/src/webui/static/app/idnode.js b/src/webui/static/app/idnode.js index a321acfe7..72c17efeb 100644 --- a/src/webui/static/app/idnode.js +++ b/src/webui/static/app/idnode.js @@ -240,6 +240,7 @@ tvheadend.IdNodeField = function(conf) this.rdonly = conf.rdonly; this.wronly = conf.wronly; this.wronce = conf.wronce; + this.noui = conf.noui; this.hidden = conf.hidden; this.uilevel = conf.expert ? 'expert' : (conf.advanced ? 'advanced' : 'basic'); this.password = conf.showpwd ? false : conf.password; @@ -277,7 +278,7 @@ tvheadend.IdNodeField = function(conf) } this.get_hidden = function(uilevel) { - var hidden = this.hidden; + var hidden = this.hidden || this.noui; if (uilevel !== 'expert') { if (uilevel === 'advanced' && this.uilevel === 'expert') hidden = true; @@ -834,6 +835,8 @@ tvheadend.idnode_editor_form = function(uilevel, d, meta, panel, conf) var p = d[i]; if (conf.uuids && p.rdonly) continue; + if (conf.noui) + continue; var f = tvheadend.idnode_editor_field(p, conf); if (!f) continue; @@ -1395,13 +1398,15 @@ tvheadend.idnode_grid = function(panel, conf) for (var i = 0; i < idnode.length(); i++) { var f = idnode.field(i); var c = f.column(uilevel, conf.columns); - fields.push(f.id); - ifields.push(f); - c['tooltip'] = f.text; - columns.push(c); - if (c.filter) - filters.push(c.filter); - f.onrefresh(update2); + if (!f.noui) { + fields.push(f.id); + ifields.push(f); + c['tooltip'] = f.text; + columns.push(c); + if (c.filter) + filters.push(c.filter); + f.onrefresh(update2); + } } /* Right-hand columns */ diff --git a/src/webui/webui.c b/src/webui/webui.c index 80411520c..4d4ddf7c3 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -1516,7 +1516,7 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) } fname = tvh_strdupa(filename); - content = muxer_container_type2mime(de->de_mc, 1); + content = muxer_container_filename2mime(fname, 1); charset = de->de_config ? de->de_config->dvr_charset_id : NULL; pthread_mutex_unlock(&global_lock);