diff m_property.c @ 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
children f9cb6fc1608a
line wrap: on
line diff
--- /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;
+}