[Mplayer-cvslog] CVS: main cfg-common.h,1.84,1.85 m_config.c,1.5,1.6 m_option.c,1.6,1.7 m_option.h,1.3,1.4 mplayer.c,1.684,1.685

Alban Bedel CVS albeu at mplayerhq.hu
Sat Mar 15 19:01:34 CET 2003


Update of /cvsroot/mplayer/main
In directory mail:/var/tmp.root/cvs-serv1650

Modified Files:
	cfg-common.h m_config.c m_option.c m_option.h mplayer.c 
Log Message:
Add the new -vf option wich is the same as vop in reverse order.
Syntax is we decided, so you can give the nomes or not with both
vop and vf. vf take precedence over vop.  


Index: cfg-common.h
===================================================================
RCS file: /cvsroot/mplayer/main/cfg-common.h,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -r1.84 -r1.85
--- cfg-common.h	5 Mar 2003 10:19:54 -0000	1.84
+++ cfg-common.h	15 Mar 2003 18:00:28 -0000	1.85
@@ -150,7 +150,8 @@
         {"pphelp", &pp_help, CONF_TYPE_PRINT_INDIRECT, CONF_NOCFG, 0, 0, NULL},
 #endif
 
-	{"vop", &vo_plugin_args, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
+	{"vop", &vo_plugin_args, CONF_TYPE_OBJ_SETTINGS_LIST, 0, 0, 0,&vf_obj_list },
+	{"vf", &vf_settings, CONF_TYPE_OBJ_SETTINGS_LIST, 0, 0, 0, &vf_obj_list},
 
 	// scaling:
 	{"sws", &sws_flags, CONF_TYPE_INT, 0, 0, 2, NULL},
@@ -336,6 +337,8 @@
 extern int    mf_h;
 extern float  mf_fps;
 extern char * mf_type;
+extern m_obj_settings_t* vf_settings;
+extern m_obj_list_t vf_obj_list;
 
 struct config mfopts_conf[]={
         {"on", &mf_support, CONF_TYPE_FLAG, 0, 0, 1, NULL},
@@ -346,7 +349,7 @@
         {NULL, NULL, 0, 0, 0, 0, NULL}
 };
 						
-extern char** vo_plugin_args;
+extern m_obj_settings_t* vo_plugin_args;
 
 #include "libaf/af.h"
 extern af_cfg_t af_cfg; // Audio filter configuration, defined in libmpcodecs/dec_audio.c

Index: m_config.c
===================================================================
RCS file: /cvsroot/mplayer/main/m_config.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- m_config.c	2 Feb 2003 15:06:56 -0000	1.5
+++ m_config.c	15 Mar 2003 18:00:28 -0000	1.6
@@ -239,7 +239,7 @@
     char** lst = NULL;
     int i,sr;
     // Parse the child options
-    r = m_option_parse(co->opt,arg,param,&lst,config->mode);
+    r = m_option_parse(co->opt,arg,param,&lst,M_COMMAND_LINE);
     // Set them now
     if(r >= 0)
     for(i = 0 ; lst && lst[2*i] ; i++) {

Index: m_option.c
===================================================================
RCS file: /cvsroot/mplayer/main/m_option.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- m_option.c	30 Jan 2003 21:28:01 -0000	1.6
+++ m_option.c	15 Mar 2003 18:00:28 -0000	1.7
@@ -15,6 +15,26 @@
 //#include "m_config.h"
 #include "mp_msg.h"
 
+// Don't free for 'production' atm
+#ifndef MP_DEBUG
+#define NO_FREE
+#endif
+
+m_option_t* m_option_list_find(m_option_t* list,char* name) {
+  int i;
+
+  for(i = 0 ; list[i].name ; i++) {
+    int l = strlen(list[i].name) - 1;
+    if((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD) &&
+       (l > 0) && (list[i].name[l] == '*')) {
+      if(strncasecmp(list[i].name,name,l) == 0)
+	return &list[i];
+    } else if(strcasecmp(list[i].name,name) == 0)
+      return &list[i];
+  }
+  return NULL;
+}
+
 // Default function that just do a memcpy
 
 static void copy_opt(m_option_t* opt,void* dst,void* src) {
@@ -321,14 +341,18 @@
 
 static void copy_str(m_option_t* opt,void* dst, void* src) {
   if(dst && src) {
-//    if(VAL(dst)) free(VAL(dst)); //FIXME!!!
+#ifndef NO_FREE
+    if(VAL(dst)) free(VAL(dst)); //FIXME!!!
+#endif
     VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL;
   }
 }
   
 static void free_str(void* src) {
-  if(src && VAL(src)){ 
-//    free(VAL(src)); //FIXME!!!
+  if(src && VAL(src)){
+#ifndef NO_FREE
+    free(VAL(src)); //FIXME!!!
+#endif
     VAL(src) = NULL;
   }
 }
@@ -366,9 +390,11 @@
   d = VAL(dst);
 
 // FIXME!!!
-//  for(i = 0 ; d[i] != NULL ; i++)
-//    free(d[i]);
-//  free(d);
+#ifndef NO_FREE
+  for(i = 0 ; d[i] != NULL ; i++)
+    free(d[i]);
+  free(d);
+#endif
   VAL(dst) = NULL;
 }
 
@@ -809,7 +835,7 @@
 static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) {
   char *subparam;
   char *subopt;
-  int nr = 0;
+  int nr = 0,i,r;
   m_option_t *subopts;
   char *token;
   char *p;
@@ -839,6 +865,16 @@
 	case 1:
 	  subparam[0] = 0;
 	case 2:
+	  for(i = 0 ; subopts[i].name ; i++) {
+	    if(!strcmp(subopts[i].name,subopt)) break;
+	  }
+	  if(!subopts[i].name) {
+	    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Unknow suboption %s\n",name,subopt);
+	    return M_OPT_UNKNOW;
+	  }
+	  r = m_option_parse(&subopts[i],subopt,
+			     subparam[0] == 0 ? NULL : subparam,NULL,src);
+	  if(r < 0) return r;
 	  if(dst) {
 	    lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*));
 	    lst[2*nr] = strdup(subopt);
@@ -857,7 +893,8 @@
   free(subparam);
   free(subopt);
   free(p);
-  VAL(dst) = lst;
+  if(dst)
+    VAL(dst) = lst;
 
   return 1;
 }
@@ -1036,6 +1073,397 @@
   NULL,
   copy_opt,
   copy_opt,
+  NULL,
+  NULL
+};
+
+
+//// Objects (ie filters, etc) settings
+
+#include "m_struct.h"
+
+#undef VAL
+#define VAL(x) (*(m_obj_settings_t**)(x))
+
+static int find_obj_desc(char* name,m_obj_list_t* l,m_struct_t** ret) {
+  int i;
+  char* n;
+
+  for(i = 0 ; l->list[i] ; i++) {
+    n = M_ST_MB(char*,l->list[i],l->name_off);
+    if(!strcmp(n,name)) {
+      *ret = M_ST_MB(m_struct_t*,l->list[i],l->desc_off);
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static int get_obj_param(char* opt_name,char* obj_name, m_struct_t* desc,
+			 char* str,int* nold,int oldmax,char** dst) {
+  char* eq,param;
+  m_option_t* opt;
+  int r;
+
+  eq = strchr(str,'=');
+  if(eq && eq == str)
+    eq = NULL;
+
+  if(eq) {
+    char* p = eq + 1;
+    if(p[0] == '\0') p = NULL;
+    eq[0] = '\0';
+    opt = m_option_list_find(desc->fields,str);
+    if(!opt) {
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't have a %s parameter\n",opt_name,obj_name,str);
+      return M_OPT_UNKNOW;
+    }
+    r = m_option_parse(opt,str,p,NULL,M_CONFIG_FILE);
+    if(r < 0) {
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: error while parsing %s parameter %s (%s)\n",opt_name,obj_name,str,p);
+      eq[0] = '=';
+      return r;
+    }
+    if(dst) {
+      dst[0] = strdup(str);
+      dst[1] = p ? strdup(p) : NULL;
+    }
+    eq[0] = '=';
+  } else {
+    if((*nold) >= oldmax) {
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s have only %d params, so yon can't give more than that unnamed params\n",
+	     opt_name,obj_name,oldmax);
+      return M_OPT_OUT_OF_RANGE;
+    }
+    opt = &desc->fields[(*nold)];
+    r = m_option_parse(opt,opt->name,str,NULL,M_CONFIG_FILE);
+    if(r < 0) {
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: error while parsing %s parameter %s (%s)\n",opt_name,obj_name,opt->name,str);
+      return r;
+    }
+    if(dst) {
+      dst[0] = strdup(opt->name);
+      dst[1] = strdup(str);
+    }
+    (*nold)++;
+  }
+  return 1;
+}
+
+static int get_obj_params(char* opt_name, char* name,char* params,
+			  m_struct_t* desc,char*** _ret) {
+  int n = 0,nold = 0, nopts,r;
+  char* ptr,*last_ptr = params,*eq;
+  char** ret;
+
+  if(!strcmp(params,"help")) { // Help
+    char min[50],max[50];
+    if(!desc->fields) {
+      printf("%s doesn't have any options\n\n",name);
+      //exit_player();
+      exit(0);
+    }
+    printf("\n Name                 Type            Min        Max\n\n");
+    for(n = 0 ; desc->fields[n].name ; n++) {
+      m_option_t* opt = &desc->fields[n];
+      if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue;
+      if(opt->flags & M_OPT_MIN)
+	sprintf(min,"%-8.0f",opt->min);
+      else
+	strcpy(min,"No");
+      if(opt->flags & M_OPT_MAX)
+	sprintf(max,"%-8.0f",opt->max);
+      else
+	strcpy(max,"No");
+      printf(" %-20.20s %-15.15s %-10.10s %-10.10s\n",
+	     opt->name,
+	     opt->type->name,
+	     min,
+	     max);
+    }
+    printf("\n");
+    //exit_player() isn't avaible in mencoder
+    exit(0);
+  }
+
+  for(nopts = 0 ; desc->fields[nopts].name ; nopts++)
+    /* NOP */;
+
+  // TODO : Check that each opt can be parsed
+  r = 1;
+  while(last_ptr && last_ptr[0] != '\0') {
+    ptr = strchr(last_ptr,':');
+    if(!ptr) {
+      r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL);
+      n++;
+      break;
+    }
+    ptr[0] = '\0';
+    r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL);
+    ptr[0] = ':';
+    if(r < 0) break;
+    n++;
+    last_ptr = ptr+1;
+  }
+  if(r < 0) return r;
+  if(!_ret) // Just test
+    return 1;
+
+  ret = malloc((n+2)*2*sizeof(char*));
+  n = nold = 0;
+  last_ptr = params;
+  
+  while(last_ptr && last_ptr[0] != '\0') {
+    ptr = strchr(last_ptr,':');
+    if(!ptr) {
+      get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]);
+      n++;
+      break;
+    }
+    ptr[0] = '\0';
+    get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]);
+    n++;
+    last_ptr = ptr+1;
+  }
+  ret[n*2] = ret[n*2+1] = NULL;  
+  *_ret = ret;
+  
+  return 1;
+}
+
+
+static int parse_obj_settings(char* opt,char* str,m_obj_list_t* list,
+			      m_obj_settings_t **_ret, int ret_n) {
+  int r;
+  char *param,**plist = NULL;
+  m_struct_t* desc;
+  m_obj_settings_t *ret = _ret ? *_ret : NULL;
+  
+
+  // Now check that the object exist
+  param = strchr(str,'=');
+  if(param) {
+    param[0] = '\0';
+    param++;
+    if(strlen(param) <= 0)
+      param = NULL;
+  }
+
+
+  if(!find_obj_desc(str,list,&desc)) {
+    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't exist\n",opt,str);
+    return M_OPT_INVALID;
+  }
+
+  if(param) {
+    if(!desc && _ret) {
+      plist = calloc(4,sizeof(char*));
+      plist[0] = strdup("_oldargs_");
+      plist[1] = strdup(param);
+    } else if(desc) {
+      r = get_obj_params(opt,str,param,desc,_ret ? &plist : NULL);
+      if(r < 0)
+	return r;
+    }
+  }
+  if(!_ret)
+    return 1;
+
+  ret = realloc(ret,(ret_n+2)*sizeof(m_obj_settings_t));
+  memset(&ret[ret_n],0,2*sizeof(m_obj_settings_t));
+  ret[ret_n].name = strdup(str);
+  ret[ret_n].attribs = plist;
+
+  *_ret = ret;
+  return 1;
+}
+
+
+static int parse_obj_settings_list(m_option_t* opt,char *name,
+				   char *param, void* dst, int src) {
+  int n = 0,r;
+  char *str;
+  char *ptr, *last_ptr;
+  m_obj_settings_t *res = NULL;
+
+  // We need the objects list
+  if(!opt->priv)
+    return M_OPT_INVALID;
+
+  if (param == NULL || strlen(param) == 0)
+    return M_OPT_MISSING_PARAM;
+
+  if(!strcmp(param,"help")) {
+    m_obj_list_t* ol = opt->priv;
+    for(n = 0 ; ol->list[n] ; n++)
+      mp_msg(MSGT_VFILTER,MSGL_INFO,"  %-15s: %s\n",
+	     M_ST_MB(char*,ol->list[n],ol->name_off),
+	     M_ST_MB(char*,ol->list[n],ol->info_off));
+    exit(0);
+  }
+  ptr = str = strdup(param);
+
+  while(ptr[0] != '\0') {
+    last_ptr = ptr;
+    ptr = strchr(ptr,LIST_SEPARATOR);
+    if(!ptr) {
+      r = parse_obj_settings(name,last_ptr,opt->priv,dst ? &res : NULL,n);
+      if(r < 0) {
+	free(str);
+	return r;
+      }
+      n++;
+      break;
+    }
+    ptr[0] = '\0';
+    r = parse_obj_settings(name,last_ptr,opt->priv,dst ? &res : NULL,n);
+    if(r < 0) {
+      free(str);
+      return r;
+    }
+    ptr++;
+    n++;
+  }
+  free(str);
+  if(n == 0)
+    return M_OPT_INVALID;
+
+  if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) || 
+      ((opt->flags & M_OPT_MAX) && (n > opt->max)) )
+    return M_OPT_OUT_OF_RANGE;
+  
+  if(dst)
+    VAL(dst) = res;
+
+  return 1;
+}
+
+static void free_obj_settings_list(void* dst) {
+  int n;
+  m_obj_settings_t *d;
+
+  if(!dst || !VAL(dst)) return;
+
+  d = VAL(dst);
+#ifndef NO_FREE
+  for(n = 0 ; d[n].name ; n++) {
+    free(d[n].name);
+    free_str_list(&(d[n].attribs));
+  }
+  free(d);
+#endif
+  VAL(dst) = NULL;
+}
+
+static void copy_obj_settings_list(m_option_t* opt,void* dst, void* src) {
+  m_obj_settings_t *d,*s;
+  int n;
+
+  if(!(dst && src))
+    return;
+
+  s = VAL(src);
+
+  if(VAL(dst))
+    free_obj_settings_list(dst);
+  if(!s) return;
+    
+    
+  
+  for(n = 0 ; s[n].name ; n++)
+    /* NOP */;
+  d = malloc((n+1)*sizeof(m_obj_settings_t));
+  for(n = 0 ; s[n].name ; n++) {
+    d[n].name = strdup(s[n].name);
+    d[n].attribs = NULL;
+    copy_str_list(NULL,&(d[n].attribs),&(s[n].attribs));
+  }
+  d[n].name = d[n].attribs = NULL;
+  VAL(dst) = d;
+}
+
+m_option_type_t m_option_type_obj_settings_list = {
+  "Object settings list",
+  "",
+  sizeof(m_obj_settings_t*),
+  M_OPT_TYPE_DYNAMIC,
+  parse_obj_settings_list,
+  NULL,
+  copy_obj_settings_list,
+  copy_obj_settings_list,
+  copy_obj_settings_list,
+  free_obj_settings_list,
+};
+
+
+
+static int parse_obj_presets(m_option_t* opt,char *name,
+			    char *param, void* dst, int src) {
+  m_obj_presets_t* obj_p = (m_obj_presets_t*)opt->priv;
+  m_struct_t *in_desc,*out_desc;
+  int s,i;
+  unsigned char* pre = obj_p->presets;
+  char* pre_name = NULL;
+
+  if(!obj_p) {
+    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: presets need a pointer to a m_obj_presets_t in the priv field\n",name);
+    return M_OPT_PARSER_ERR;
+  }
+
+  if(!param)
+    return M_OPT_MISSING_PARAM;
+
+  in_desc = obj_p->in_desc;
+  out_desc = obj_p->out_desc ? obj_p->out_desc : obj_p->in_desc;
+  s = in_desc->size;
+
+  if(!strcmp(param,"help")) {
+    mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Avaible presets for %s->%s :",out_desc->name,name);
+    for(pre = obj_p->presets;(pre_name = M_ST_MB(char*,pre,obj_p->name_off)) ; 
+	pre +=  s) 
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s",pre_name);
+    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n");
+    exit(0);
+  }
+
+  for(pre_name = M_ST_MB(char*,pre,obj_p->name_off) ; pre_name ;
+      pre +=  s, pre_name = M_ST_MB(char*,pre,obj_p->name_off)) {
+    if(!strcmp(pre_name,param)) break;
+  }
+  if(!pre_name) {
+    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: there no preset named %s\n"
+	   "Avaible presets are :",name,param);
+    for(pre = obj_p->presets;(pre_name = M_ST_MB(char*,pre,obj_p->name_off)) ; 
+	pre +=  s) 
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s",pre_name);
+    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n");
+    return M_OPT_INVALID;
+  }
+
+  if(!dst) return 1;
+  
+  for(i = 0 ; in_desc->fields[i].name ; i++) {
+    m_option_t* out_opt = m_option_list_find(out_desc->fields,
+					     in_desc->fields[i].name);
+    if(!out_opt) {
+      mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unable to find the target option for field %s.\nYou should report that to the developpers\n",name,in_desc->fields[i].name);
+      return M_OPT_PARSER_ERR;
+    }
+    m_option_copy(out_opt,M_ST_MB_P(dst,out_opt->p),M_ST_MB_P(pre,in_desc->fields[i].p));
+  }
+  return 1;
+}
+
+
+m_option_type_t m_option_type_obj_presets = {
+  "Object presets",
+  "",
+  0,
+  0,
+  parse_obj_presets,
+  NULL,
+  NULL,
+  NULL,
   NULL,
   NULL
 };

Index: m_option.h
===================================================================
RCS file: /cvsroot/mplayer/main/m_option.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- m_option.h	3 Jan 2003 12:40:09 -0000	1.3
+++ m_option.h	15 Mar 2003 18:00:28 -0000	1.4
@@ -5,6 +5,7 @@
 
 typedef struct m_option_type m_option_type_t;
 typedef struct m_option m_option_t;
+struct m_struct;
 
 ///////////////////////////// Options types declarations ////////////////////////////
 
@@ -52,6 +53,30 @@
 } m_span_t;
 extern m_option_type_t m_option_type_span;
 
+typedef struct {
+  void** list;
+  void* name_off;
+  void* info_off;
+  void* desc_off;
+} m_obj_list_t;
+
+typedef struct {
+  char* name;
+  char** attribs;
+} m_obj_settings_t;
+extern m_option_type_t m_option_type_obj_settings_list;
+
+// Presets are mean to be used with options struct
+
+
+typedef struct {
+  struct m_struct* in_desc;
+  struct m_struct* out_desc;
+  void* presets; // Pointer to an arry of struct defined by in_desc
+  void* name_off; // Offset of the preset name inside the in_struct
+} m_obj_presets_t;
+extern m_option_type_t m_option_type_obj_presets;
+
 // Don't be stupid keep tho old names ;-)
 #define CONF_TYPE_FLAG		(&m_option_type_flag)
 #define CONF_TYPE_INT		(&m_option_type_int)
@@ -67,7 +92,8 @@
 #define CONF_TYPE_POSITION	(&m_option_type_position)
 #define CONF_TYPE_IMGFMT		(&m_option_type_imgfmt)
 #define CONF_TYPE_SPAN		(&m_option_type_span)
-
+#define CONF_TYPE_OBJ_SETTINGS_LIST (&m_option_type_obj_settings_list)
+#define CONF_TYPE_OBJ_PRESETS (&m_option_type_obj_presets)
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -181,6 +207,7 @@
 #define M_OPT_OUT_OF_RANGE	-4
 #define M_OPT_PARSER_ERR		-5
 
+m_option_t* m_option_list_find(m_option_t* list,char* name);
 
 inline static int
 m_option_parse(m_option_t* opt,char *name, char *param, void* dst, int src) {

Index: mplayer.c
===================================================================
RCS file: /cvsroot/mplayer/main/mplayer.c,v
retrieving revision 1.684
retrieving revision 1.685
diff -u -r1.684 -r1.685
--- mplayer.c	10 Mar 2003 00:50:10 -0000	1.684
+++ mplayer.c	15 Mar 2003 18:00:28 -0000	1.685
@@ -772,13 +772,6 @@
     }
 #endif
 
-    if(vo_plugin_args && vo_plugin_args[0] && strcmp(vo_plugin_args[0],"help")==0){
-      mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AvailableVideoOutputPlugins);
-      vf_list_plugins();
-      printf("\n");
-      exit(0);
-    }
-
     if(video_driver_list && strcmp(video_driver_list[0],"help")==0){
       list_video_out();
       exit(0);
@@ -1539,11 +1532,14 @@
 }
 
 current_module="init_video_filters";
-
-sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",(char *)video_out);
+{
+  char* vf_arg[] = { "_oldargs_", (char*)video_out , NULL };
+  sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg);
+}
 #ifdef HAVE_MENU
 if(use_menu) {
-  vf_menu = vf_open_plugin(libmenu_vfs,sh_video->vfilter,"menu",menu_root);
+  char* vf_arg[] = { "_oldargs_", menu_root, NULL };
+  vf_menu = vf_open_plugin(libmenu_vfs,sh_video->vfilter,"menu",vf_arg);
   if(!vf_menu) {
     mp_msg(MSGT_CPLAYER,MSGL_ERR,"Can't open libmenu video filter with root menu %s\n",menu_root);
     use_menu = 0;



More information about the MPlayer-cvslog mailing list