changeset 17911:52f95509cd05

Add the new property API and implement a couple properties. Move the volume and mute command to the command to property bridge.
author albeu
date Wed, 22 Mar 2006 00:19:02 +0000
parents 5ae29dc47c17
children 86d341ecb3bc
files Makefile cfg-mplayer.h help/help_mp-en.h input/input.c input/input.h m_property.c m_property.h mplayer.c
diffstat 8 files changed, 699 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Mar 21 23:09:52 2006 +0000
+++ b/Makefile	Wed Mar 22 00:19:02 2006 +0000
@@ -56,6 +56,7 @@
                 xvid_vbr.c \
 
 SRCS_MPLAYER = mplayer.c \
+               m_property.c \
                mp_msg.c \
                $(SRCS_COMMON) \
                mixer.c \
--- a/cfg-mplayer.h	Tue Mar 21 23:09:52 2006 +0000
+++ b/cfg-mplayer.h	Wed Mar 22 00:19:02 2006 +0000
@@ -383,6 +383,7 @@
 	{"term-osd", &term_osd, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 	{"noterm-osd", &term_osd, CONF_TYPE_FLAG, 0, 0, 0, NULL},
     	{"term-osd-esc", &term_osd_esc, CONF_TYPE_STRING, 0, 0, 1, NULL},
+	{"playing-msg", &playing_msg, CONF_TYPE_STRING, 0, 0, 0, NULL},
 
 	{"slave", &slave_mode, CONF_TYPE_FLAG,CONF_GLOBAL , 0, 1, NULL},
 	{"idle", &player_idle_mode, CONF_TYPE_FLAG,CONF_GLOBAL , 0, 1, NULL},
--- a/help/help_mp-en.h	Tue Mar 21 23:09:52 2006 +0000
+++ b/help/help_mp-en.h	Wed Mar 22 00:19:02 2006 +0000
@@ -227,7 +227,17 @@
 #define MSGTR_OSDSubBottom "bottom"
 #define MSGTR_OSDSubCenter "center"
 #define MSGTR_OSDSubTop "top"
-#define MSGTR_OSDMute "Mute: %s"
+
+// property values
+#define MSGTR_Enabled "enabled"
+#define MSGTR_EnabledEdl "enabled (edl)"
+#define MSGTR_Disabled "disabled"
+
+// osd bar names
+#define MSGTR_Volume "Volume"
+
+// property state
+#define MSGTR_MuteStatus "Mute: %s"
 
 // mencoder.c:
 
--- a/input/input.c	Tue Mar 21 23:09:52 2006 +0000
+++ b/input/input.c	Wed Mar 22 00:19:02 2006 +0000
@@ -66,9 +66,9 @@
   { MP_CMD_SUB_STEP, "sub_step",1,  { { MP_CMD_ARG_INT,{0} }, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_OSD, "osd",0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
   { MP_CMD_OSD_SHOW_TEXT, "osd_show_text", 1, { {MP_CMD_ARG_STRING, {0}}, {-1,{0}} } },
-  { MP_CMD_VOLUME, "volume", 1, { { MP_CMD_ARG_INT,{0} }, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
+  { MP_CMD_VOLUME, "volume", 1, { { MP_CMD_ARG_FLOAT,{0} }, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_MIXER_USEMASTER, "use_master", 0, { {-1,{0}} } },
-  { MP_CMD_MUTE, "mute", 0, { {-1,{0}} } },
+  { MP_CMD_MUTE, "mute", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
   { MP_CMD_CONTRAST, "contrast",1,  { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_GAMMA, "gamma", 1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} }  },
   { MP_CMD_BRIGHTNESS, "brightness",1,  { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} }  },
@@ -144,6 +144,8 @@
   { MP_CMD_GET_VO_FULLSCREEN, "get_vo_fullscreen", 0, { {-1,{0}} } },
   { MP_CMD_GET_SUB_VISIBILITY, "get_sub_visibility", 0, { {-1,{0}} } },
   { MP_CMD_KEYDOWN_EVENTS, "key_down_event", 1, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
+  { MP_CMD_SET_PROPERTY, "set_property", 2, { {MP_CMD_ARG_STRING, {0}},  {MP_CMD_ARG_STRING, {0}}, {-1,{0}} } },
+  { MP_CMD_GET_PROPERTY, "get_property", 1, { {MP_CMD_ARG_STRING, {0}},  {-1,{0}} } },
   
   { 0, NULL, 0, {} }
 };
--- a/input/input.h	Tue Mar 21 23:09:52 2006 +0000
+++ b/input/input.h	Wed Mar 22 00:19:02 2006 +0000
@@ -69,6 +69,8 @@
 #define MP_CMD_SUB_REMOVE 65
 #define MP_CMD_KEYDOWN_EVENTS 66
 #define MP_CMD_VO_BORDER 67
+#define MP_CMD_SET_PROPERTY 68
+#define MP_CMD_GET_PROPERTY 69
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m_property.c	Wed Mar 22 00:19:02 2006 +0000
@@ -0,0 +1,278 @@
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include "m_option.h"
+#include "m_property.h"
+#include "help_mp.h"
+
+#define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5))
+
+int m_property_do(m_option_t* prop, int action, void* arg) {
+    if(!prop) return M_PROPERTY_UNKNOWN;
+    return ((m_property_ctrl_f)prop->p)(prop,action,arg);
+}
+
+
+char* m_property_print(m_option_t* prop) {
+    m_property_ctrl_f ctrl;
+    void* val;
+    char* ret;
+    
+    if(!prop) return NULL;
+
+    ctrl = prop->p;
+    // look if the property have it's own print func
+    if(ctrl(prop,M_PROPERTY_PRINT,&ret) >= 0)
+        return ret;
+    // fallback on the default print for this type
+    val = calloc(1,prop->type->size);    
+    if(ctrl(prop,M_PROPERTY_GET,val) <= 0) {
+        free(val);
+        return NULL;
+    }
+    ret = m_option_print(prop,val);
+    free(val);
+    return ret == (char*)-1 ? NULL : ret;
+}
+
+int m_property_parse(m_option_t* prop, char* txt) {
+    m_property_ctrl_f ctrl;
+    void* val;
+    int r;
+    
+    if(!prop) return M_PROPERTY_UNKNOWN;
+
+    ctrl = prop->p;
+    // try the property own parsing func
+    if((r = ctrl(prop,M_PROPERTY_PARSE,txt)) !=  M_PROPERTY_NOT_IMPLEMENTED)
+        return r;
+    // fallback on the default
+    val = calloc(1,prop->type->size);
+    if((r = m_option_parse(prop,prop->name,txt,val,M_CONFIG_FILE)) <= 0) {
+        free(val);
+        return r;
+    }
+    r = ctrl(prop,M_PROPERTY_SET,val);
+    m_option_free(prop,val);
+    free(val);
+    return r;
+}
+
+char* m_properties_expand_string(m_option_t* prop_list,char* str) {
+    int l,fr=0,pos=0,size=strlen(str)+512;
+    char *p = NULL,*e,*ret = malloc(size), num_val;
+    int skip = 0, lvl = 0, skip_lvl = 0;
+    
+    while(str[0]) {
+        if(str[0] == '\\') {
+            int sl = 1;
+            switch(str[1]) {
+            case 'e':
+                p = "\x1b", l = 1; break;
+            case 'n':
+                p = "\n", l = 1; break;
+            case 'r':
+                p = "\r", l = 1; break;
+            case 't':
+                p = "\t", l = 1; break;
+            case 'x': 
+                if(str[2]) {
+                    char num[3] = { str[2], str[3], 0 };
+                    char* end = num;
+                    num_val = strtol(num,&end,16);
+                    sl = end-num;
+                    l = 1;
+                    p = &num_val;
+                } else
+                    l = 0;
+                break;
+            default:
+                p = str+1, l = 1;
+            }
+            str+=1+sl;
+        } else if(lvl > 0 && str[0] == ')') {
+            if(skip && lvl <= skip_lvl) skip = 0;
+            lvl--, str++, l = 0;
+        } else if(str[0] == '$' && str[1] == '{' && (e = strchr(str+2,'}'))) {
+            int pl = e-str-2;
+            char pname[pl+1];
+            m_option_t* prop;
+            memcpy(pname,str+2,pl);
+            pname[pl] = 0;
+            if((prop = m_option_list_find(prop_list,pname)) &&
+               (p = m_property_print(prop)))
+                l = strlen(p), fr = 1;
+            else
+                l = 0;
+            str = e+1;
+        } else if(str[0] == '?' && str[1] == '(' && (e = strchr(str+2,':'))) {
+            int pl = e-str-2;
+            char pname[pl+1];
+            m_option_t* prop;
+            lvl++;
+            if(!skip) {            
+                memcpy(pname,str+2,pl);
+                pname[pl] = 0;
+                if(!(prop = m_option_list_find(prop_list,pname)) ||
+                   m_property_do(prop,M_PROPERTY_GET,NULL) < 0)
+                    skip = 1, skip_lvl = lvl;
+            }
+            str = e+1, l = 0;
+        } else
+            p = str, l = 1, str++;
+        
+        if(skip || l <= 0) continue;
+        
+        if(pos+l+1 > size) {
+            size = pos+l+512;
+            ret = realloc(ret,size);
+        }
+        memcpy(ret+pos,p,l);
+        pos += l;
+        if(fr) free(p), fr = 0;
+    }
+    
+    ret[pos] = 0;
+    return ret;
+}
+
+// Some generic property implementations
+
+int m_property_int_ro(m_option_t* prop,int action,
+                      void* arg,int var) {
+    switch(action) {
+    case M_PROPERTY_GET:
+        if(!arg) return 0;
+        *(int*)arg = var;
+        return 1;
+    }
+    return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
+int m_property_int_range(m_option_t* prop,int action,
+                         void* arg,int* var) {
+    switch(action) {
+    case M_PROPERTY_SET:
+        if(!arg) return 0;
+        M_PROPERTY_CLAMP(prop,*(int*)arg);
+        *var = *(int*)arg;
+        return 1;
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+        *var += (arg ? *(int*)arg : 1) *
+            (action == M_PROPERTY_STEP_DOWN ? -1 : 1);
+        M_PROPERTY_CLAMP(prop,*var);
+        return 1;
+    }
+    return m_property_int_ro(prop,action,arg,*var);
+}
+
+int m_property_choice(m_option_t* prop,int action,
+                      void* arg,int* var) {
+    switch(action) {
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+        *var += action == M_PROPERTY_STEP_UP ? 1 : prop->max;
+        *var %= (int)prop->max+1;
+        return 1;
+    }
+    return m_property_int_range(prop,action,arg,var);
+}
+
+int m_property_flag(m_option_t* prop,int action,
+                    void* arg,int* var) {
+    switch(action) {
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+        *var = *var == prop->min ? prop->max : prop->min;
+        return 1;
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+        *(char**)arg = strdup((*var > prop->min) ? MSGTR_Enabled : MSGTR_Disabled);
+        return 1;
+    }
+    return m_property_int_range(prop,action,arg,var);
+}
+
+int m_property_float_ro(m_option_t* prop,int action,
+                        void* arg,float var) {
+    switch(action) {
+    case M_PROPERTY_GET:
+        if(!arg) return 0;
+        *(float*)arg = var;
+        return 1;
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+        *(char**)arg = malloc(20);
+        sprintf(*(char**)arg,"%.2f",var);
+        return 1;
+    }
+    return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
+int m_property_float_range(m_option_t* prop,int action,
+                           void* arg,float* var) {
+    switch(action) {
+    case M_PROPERTY_SET:
+        if(!arg) return 0;
+        M_PROPERTY_CLAMP(prop,*(float*)arg);
+        *var = *(float*)arg;
+        return 1;
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+        *var += (arg ? *(float*)arg : 0.1) *
+            (action == M_PROPERTY_STEP_DOWN ? -1 : 1);
+        M_PROPERTY_CLAMP(prop,*var);
+        return 1;
+    }
+    return m_property_float_ro(prop,action,arg,*var);
+}
+
+int m_property_delay(m_option_t* prop,int action,
+                     void* arg,float* var) {
+    switch(action) {
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+        *(char**)arg = malloc(20);
+        sprintf(*(char**)arg,"%d ms",ROUND((*var)*1000));
+        return 1;
+    default:
+        return m_property_float_range(prop,action,arg,var);
+    }
+}
+
+int m_property_double_ro(m_option_t* prop,int action,
+                         void* arg,double var) {
+    switch(action) {
+    case M_PROPERTY_GET:
+        if(!arg) return 0;
+        *(double*)arg = var;
+        return 1;
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+        *(char**)arg = malloc(20);
+        sprintf(*(char**)arg,"%.2f",var);
+        return 1;
+    }
+    return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
+int m_property_string_ro(m_option_t* prop,int action,void* arg,char* str) {
+    switch(action) {
+    case M_PROPERTY_GET:
+        if(!arg) return 0;
+        *(char**)arg = str;
+        return 1;
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+        *(char**)arg = str ? strdup(str) : NULL;
+        return 1;
+    }
+    return M_PROPERTY_NOT_IMPLEMENTED;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m_property.h	Wed Mar 22 00:19:02 2006 +0000
@@ -0,0 +1,78 @@
+
+// Get the current value                                                   
+#define M_PROPERTY_GET         0                                           
+// Get a string representing the current value                             
+#define M_PROPERTY_PRINT       1                                           
+// Set a new value                                                         
+#define M_PROPERTY_SET         2                                           
+// Set a new value from a string                                           
+#define M_PROPERTY_PARSE       3                                           
+// Increment the property                                                  
+#define M_PROPERTY_STEP_UP     4                                           
+// Decrement the property                                                  
+#define M_PROPERTY_STEP_DOWN   5                                           
+
+// Return values for the control function
+#define M_PROPERTY_OK                1
+#define M_PROPERTY_ERROR             0
+// Returned when the property can't be used, for ex something about
+// the subs while playing audio only
+#define M_PROPERTY_UNAVAILABLE      -1
+// Returned if the requested action is not implemented
+#define M_PROPERTY_NOT_IMPLEMENTED  -2
+// Returned when asking for a property that doesn't exist
+#define M_PROPERTY_UNKNOWN          -3
+// Returned when the action can't be done (like setting the volume when edl mute)
+#define M_PROPERTY_DISABLED         -4
+
+typedef int(*m_property_ctrl_f)(m_option_t* prop,int action,void* arg);
+
+int m_property_do(m_option_t* prop, int action, void* arg);
+
+char* m_property_print(m_option_t* prop);
+
+int m_property_parse(m_option_t* prop, char* txt);
+
+char* m_properties_expand_string(m_option_t* prop_list,char* str);
+
+#define M_PROPERTY_CLAMP(prop,val) do {                                 \
+        if(((prop)->flags & M_OPT_MIN) && (val) < (prop)->min)          \
+            (val) = (prop)->min;                                        \
+        else if(((prop)->flags & M_OPT_MAX) && (val) > (prop)->max)     \
+            (val) = (prop)->max;                                        \
+    } while(0)
+
+// Implement get
+int m_property_int_ro(m_option_t* prop,int action,
+                      void* arg,int var);
+
+// Implement set, get and step up/down
+int m_property_int_range(m_option_t* prop,int action,
+                         void* arg,int* var);
+
+// Same but cycle
+int m_property_choice(m_option_t* prop,int action,
+                      void* arg,int* var);
+
+// Switch betwen min and max
+int m_property_flag(m_option_t* prop,int action,
+                    void* arg,int* var);
+
+// Implement get, print
+int m_property_float_ro(m_option_t* prop,int action,
+                        void* arg,float var);
+
+// Implement set, get and step up/down
+int m_property_float_range(m_option_t* prop,int action,
+                           void* arg,float* var);
+
+// float with a print function which print the time in ms
+int m_property_delay(m_option_t* prop,int action,
+                     void* arg,float* var);
+
+// Implement get, print
+int m_property_double_ro(m_option_t* prop,int action,
+                         void* arg,double var);
+
+// get/print the string
+int m_property_string_ro(m_option_t* prop,int action,void* arg, char* str);
--- a/mplayer.c	Tue Mar 21 23:09:52 2006 +0000
+++ b/mplayer.c	Wed Mar 22 00:19:02 2006 +0000
@@ -42,6 +42,7 @@
 
 #include "m_option.h"
 #include "m_config.h"
+#include "m_property.h"
 
 #include "cfg-mplayer-def.h"
 
@@ -238,6 +239,7 @@
 
 static int term_osd = 1;
 static char* term_osd_esc = "\x1b[A\r\x1b[K";
+static char* playing_msg = NULL;
 // seek:
 static char *seek_to_sec=NULL;
 static off_t seek_to_byte=0;
@@ -1056,7 +1058,9 @@
 #define OSD_MSG_OSD_STATUS              4
 #define OSD_MSG_BAR                     5
 #define OSD_MSG_PAUSE                   6
-#define OSD_MSG_MUTE                    7
+// Base id for the messages generated from the commmand to property bridge
+#define OSD_MSG_PROPERTY                0x100
+
 
 // These will later be implemented via properties and removed
 #define OSD_MSG_AV_DELAY               100
@@ -1302,6 +1306,288 @@
 }
 
 
+// General properties
+
+static int mp_property_osdlevel(m_option_t* prop,int action,void* arg) {
+    return m_property_choice(prop,action,arg,&osd_level);
+}
+
+static int mp_property_playback_speed(m_option_t* prop,int action,void* arg) {
+    switch(action) {
+    case M_PROPERTY_SET:
+        if(!arg) return 0;
+        M_PROPERTY_CLAMP(prop,*(float*)arg);
+        playback_speed = *(float*)arg;
+        build_afilter_chain(sh_audio, &ao_data);
+        return 1;
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+        playback_speed += (arg ? *(float*)arg : 0.1) *
+            (action == M_PROPERTY_STEP_DOWN ? -1 : 1);
+        M_PROPERTY_CLAMP(prop,playback_speed);
+        build_afilter_chain(sh_audio, &ao_data);
+        return 1;
+    }
+    return m_property_float_range(prop,action,arg,&playback_speed);
+}
+
+static int mp_property_path(m_option_t* prop,int action,void* arg) {
+    return m_property_string_ro(prop,action,arg,filename);
+}
+
+static int mp_property_filename(m_option_t* prop,int action,void* arg) {
+    char* f;
+    if(!filename) return M_PROPERTY_UNAVAILABLE;
+    if(((f = strrchr(filename,'/')) || (f = strrchr(filename,'\\'))) && f[1])
+        f++;
+    else
+        f = filename;
+    return m_property_string_ro(prop,action,arg,f);
+}
+
+
+static int mp_property_demuxer(m_option_t* prop,int action,void* arg) {
+    if(!demuxer) return M_PROPERTY_UNAVAILABLE;
+    return m_property_string_ro(prop,action,arg,(char*)demuxer->desc->name);
+}
+
+static int mp_property_length(m_option_t* prop,int action,void* arg) {
+    double len;
+    
+    if(!demuxer ||
+       !(int)(len = demuxer_get_time_length(demuxer)))
+        return M_PROPERTY_UNAVAILABLE;
+    
+    switch(action) {
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+        else {
+            int h, m, s = len;
+            h = s/3600;
+            s -= h*3600;
+            m = s/60;
+            s -= m*60;
+            *(char**)arg = malloc(20);
+            if(h > 0) sprintf(*(char**)arg,"%d:%02d:%02d",h,m,s);
+            else if(m > 0) sprintf(*(char**)arg,"%d:%02d",m,s);
+            else sprintf(*(char**)arg,"%d",s);
+            return 1;
+        }
+        break;
+    }
+    return m_property_double_ro(prop,action,arg,len);
+}
+
+// Audio properties
+
+static int mp_property_volume(m_option_t* prop,int action,void* arg) {
+
+    if(!sh_audio) return M_PROPERTY_UNAVAILABLE;
+    
+    switch(action) {
+    case M_PROPERTY_GET:
+        if(!arg) return 0;
+        mixer_getbothvolume(&mixer,arg);
+        return 1;
+    case M_PROPERTY_PRINT:{
+        float vol;
+        if(!arg) return 0;
+        mixer_getbothvolume(&mixer,&vol);
+        return m_property_float_range(prop,action,arg,&vol);
+    }        
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+    case M_PROPERTY_SET:
+        break;
+    default:
+        return M_PROPERTY_NOT_IMPLEMENTED;
+    }
+
+#ifdef USE_EDL
+    if (edl_muted) return M_PROPERTY_DISABLED;
+    user_muted = 0;
+#endif
+
+    switch(action) {
+   case M_PROPERTY_SET:
+        if(!arg) return 0;
+        M_PROPERTY_CLAMP(prop,*(float*)arg);
+        mixer_setvolume(&mixer,*(float*)arg,*(float*)arg);
+        return 1;
+    case M_PROPERTY_STEP_UP:
+        if(arg && *(float*)arg <= 0)
+            mixer_decvolume(&mixer);
+        else
+            mixer_incvolume(&mixer);
+        return 1;
+    case M_PROPERTY_STEP_DOWN:
+        if(arg && *(float*)arg <= 0)
+            mixer_incvolume(&mixer);
+        else
+            mixer_decvolume(&mixer);
+        return 1;
+    }
+    return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
+
+static int mp_property_mute(m_option_t* prop,int action,void* arg) {
+    
+    if(!sh_audio) return M_PROPERTY_UNAVAILABLE;
+    
+    switch(action) {
+    case M_PROPERTY_SET:
+#ifdef USE_EDL
+        if(edl_muted) return M_PROPERTY_DISABLED;
+#endif
+        if(!arg) return 0;
+        if((!!*(int*)arg) != mixer.muted)
+            mixer_mute(&mixer);
+        return 1;
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+#ifdef USE_EDL
+        if(edl_muted) return M_PROPERTY_DISABLED;
+#endif
+        mixer_mute(&mixer);
+        return 1;
+    case M_PROPERTY_PRINT:
+        if(!arg) return 0;
+#ifdef USE_EDL
+        if(edl_muted) {
+            *(char**)arg = strdup(MSGTR_EnabledEdl);
+            return 1;
+        }
+#endif
+    default:
+        return m_property_flag(prop,action,arg,&mixer.muted);
+
+    }
+}
+
+
+static m_option_t mp_properties[] = {
+    // General
+    { "osdlevel", mp_property_osdlevel, CONF_TYPE_INT,
+      M_OPT_RANGE, 0, 3, NULL },
+    { "speed", mp_property_playback_speed, CONF_TYPE_FLOAT,
+      M_OPT_RANGE, 0.01, 100.0, NULL },
+    { "filename", mp_property_filename, CONF_TYPE_STRING,
+      0, 0, 0, NULL },
+    { "path", mp_property_path, CONF_TYPE_STRING,
+      0, 0, 0, NULL },
+    { "demuxer", mp_property_demuxer, CONF_TYPE_STRING,
+      0, 0, 0, NULL },
+    { "length", mp_property_length, CONF_TYPE_DOUBLE,
+      0, 0, 0, NULL },
+
+    // Audio
+    { "volume", mp_property_volume, CONF_TYPE_FLOAT,
+      M_OPT_RANGE, 0, 100, NULL },
+    { "mute", mp_property_mute, CONF_TYPE_FLAG,
+      M_OPT_RANGE, 0, 1, NULL },
+    { NULL, NULL, NULL, 0, 0, 0, NULL }
+};
+
+m_option_t*  mp_property_find(char* name) {
+    return m_option_list_find(mp_properties,name);
+}
+
+int mp_property_do(char* name,int action, void* val) {
+    m_option_t* p = mp_property_find(name);
+    if(!p) return M_PROPERTY_UNAVAILABLE;
+    return m_property_do(p,action,val);
+}
+
+
+/*
+ * \brief Commands to property bridge.
+ * 
+ * It is used to handle most commands that just set a property
+ * and optionaly display something on the OSD.
+ * Two kinds of commands are handled: adjust or toggle.
+ *
+ * Adjust commands take 1 or 2 paramter: <value> <abs>
+ * If <abs> is none zero the property is set to the given value
+ * otherwise it is adjusted.
+ *
+ * Toggle commands take 0 or 1 parameter. With no parameter
+ * or a value less than the property minimum it just step the
+ * property to it's next value. Otherwise it set it to the given
+ * value.
+ *
+ */
+
+static struct  {
+    char* name;         // property name
+    int cmd;            // cmd id
+    int toggle;         // set/adjust or toggle command
+    int osd_progbar;    // progbar type
+    int osd_id;         // osd msg id if it must be shared
+    char* osd_msg;      // osd msg template
+} set_prop_cmd[] = {
+    // audio
+    { "volume", MP_CMD_VOLUME, 0, OSD_VOLUME, -1, MSGTR_Volume },
+    { "mute", MP_CMD_MUTE, 1, 0, -1, MSGTR_MuteStatus },
+
+    { NULL, 0, 0, 0, -1, NULL }
+};
+
+static int set_property_command(mp_cmd_t* cmd) {
+    int i,r;
+    m_option_t* prop;
+    
+    // look for the command
+    for(i = 0 ; set_prop_cmd[i].name ; i++)
+        if(set_prop_cmd[i].cmd == cmd->id) break;
+    if(!set_prop_cmd[i].name) return 0;
+     
+    // get the property
+    prop = mp_property_find(set_prop_cmd[i].name);
+    if(!prop) return 0;
+    
+    // toggle command
+    if(set_prop_cmd[i].toggle) {
+        // set to value
+        if(cmd->nargs > 0 && cmd->args[0].v.i >= prop->min)
+            r = m_property_do(prop,M_PROPERTY_SET,&cmd->args[0].v.i);
+        else
+            r = m_property_do(prop,M_PROPERTY_STEP_UP,NULL);
+    } else if(cmd->args[1].v.i) //set
+            r = m_property_do(prop,M_PROPERTY_SET,&cmd->args[0].v);
+    else // adjust
+        r = m_property_do(prop,M_PROPERTY_STEP_UP,&cmd->args[0].v);
+ 
+    if(r <= 0) return 1;
+    
+    if(set_prop_cmd[i].osd_progbar) {
+        if(prop->type == CONF_TYPE_INT) {
+            if(m_property_do(prop,M_PROPERTY_GET,&r) > 0)
+                set_osd_bar(set_prop_cmd[i].osd_progbar,
+                            set_prop_cmd[i].osd_msg,
+                            prop->min,prop->max,r);
+        } else if(prop->type == CONF_TYPE_FLOAT) {
+            float f;
+            if(m_property_do(prop,M_PROPERTY_GET,&f) > 0)
+                set_osd_bar(set_prop_cmd[i].osd_progbar,set_prop_cmd[i].osd_msg,
+                            prop->min,prop->max,f);
+        } else
+            mp_msg(MSGT_CPLAYER,MSGL_ERR, "Property use an unsupported type.\n");
+        return 1;
+    }
+    
+    if(set_prop_cmd[i].osd_msg) {
+        char* val = m_property_print(prop);
+        if(val) {
+            set_osd_msg(set_prop_cmd[i].osd_id >= 0 ? set_prop_cmd[i].osd_id :
+                        OSD_MSG_PROPERTY+i,1,osd_duration,
+                        set_prop_cmd[i].osd_msg,val);
+            free(val);
+        }
+    }
+    return 1;
+}
+
 int main(int argc,char* argv[]){
 
 
@@ -2421,6 +2707,13 @@
 main:
 current_module="main";
 
+    if(playing_msg) {
+        char* msg = m_properties_expand_string(mp_properties,playing_msg);
+        mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s",msg);
+        free(msg);
+    }
+        
+
 // Disable the term osd in verbose mode
 if(verbose) term_osd = 0;
 fflush(stdout);
@@ -3115,6 +3408,7 @@
   mp_cmd_t* cmd;
   int brk_cmd = 0;
   while( !brk_cmd && (cmd = mp_input_get_cmd(0,0,0)) != NULL) {
+   if(!set_property_command(cmd))
     switch(cmd->id) {
     case MP_CMD_SEEK : {
       float v;
@@ -3141,6 +3435,35 @@
       }
       brk_cmd = 1;
     } break;
+    case MP_CMD_SET_PROPERTY: {
+        m_option_t* prop = mp_property_find(cmd->args[0].v.s);
+        if(!prop) mp_msg(MSGT_CPLAYER,MSGL_WARN,"Unkown property: '%s'\n",cmd->args[0].v.s);
+        else if(m_property_parse(prop,cmd->args[1].v.s) <= 0)
+            mp_msg(MSGT_CPLAYER,MSGL_WARN,"Failed to set property '%s' to '%s'.\n",
+                   cmd->args[0].v.s,cmd->args[1].v.s);
+        
+    } break;
+    case MP_CMD_GET_PROPERTY: {
+        m_option_t* prop;
+        void* val;
+        prop = mp_property_find(cmd->args[0].v.s);
+        if(!prop) mp_msg(MSGT_CPLAYER,MSGL_WARN,"Unkown property: '%s'\n",cmd->args[0].v.s);
+        // use m_option_print directly to get easily parsable values
+        val = calloc(1,prop->type->size);
+        if(m_property_do(prop,M_PROPERTY_GET,val) <= 0) {
+            mp_msg(MSGT_CPLAYER,MSGL_WARN,"Failed to get value of property '%s'.\n",
+                   cmd->args[0].v.s);
+            break;
+        }
+        tmp = m_option_print(prop,val);
+        if(!tmp || tmp == (char*)-1) {
+            mp_msg(MSGT_CPLAYER,MSGL_WARN,"Failed to print value of property '%s'.\n",
+                   cmd->args[0].v.s);
+            break;
+        }
+        mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_%s=%s\n",cmd->args[0].v.s,tmp);
+        free(tmp);
+    } break;
 #ifdef USE_EDL
     case MP_CMD_EDL_MARK:
       if( edl_fd ) {
@@ -3292,41 +3615,6 @@
     case MP_CMD_OSD_SHOW_TEXT :  {
       set_osd_msg(OSD_MSG_TEXT,1,osd_duration,"%64s",cmd->args[0].v.s);
     } break;
-    case MP_CMD_VOLUME :  {
-      int v = cmd->args[0].v.i;
-
-		// start change for absolute volume value
-		int abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0;
-		
-#ifdef USE_EDL
-      if (edl_muted) break;
-      user_muted = 0;
-#endif
-		if( abs )
-		{
-			mixer_setvolume(&mixer, (float)v, (float)v );
-		} else {
-      if(v > 0)
-	mixer_incvolume(&mixer);
-      else
-	mixer_decvolume(&mixer);
-		}
-	  
-      if(1){
-        float vol;
-	mixer_getbothvolume(&mixer, &vol);
-	set_osd_bar(OSD_VOLUME,"Volume",0,100,vol);
-      }
-    } break;
-    case MP_CMD_MUTE:
-#ifdef USE_EDL
-      user_muted = !user_muted;
-      if ((edl_muted | user_muted) != mixer.muted)
-#endif
-      mixer_mute(&mixer);
-      set_osd_msg(OSD_MSG_MUTE,1,osd_duration, MSGTR_OSDMute,
-                  mixer.muted ? MSGTR_OSDenabled : MSGTR_OSDdisabled);
-      break;
     case MP_CMD_LOADFILE : {
       play_tree_t* e = play_tree_new();
       play_tree_add_file(e,cmd->args[0].v.s);