Browse Source

Add light_context_mode enum and '-e' option for exponential light changing.

Alexander Lutsai 4 years ago
parent
commit
07a62b97b8
2 changed files with 94 additions and 38 deletions
  1. 84
    37
      src/light.c
  2. 10
    1
      src/light.h

+ 84
- 37
src/light.c View File

16
 #include <inttypes.h> // PRIu64
16
 #include <inttypes.h> // PRIu64
17
 
17
 
18
 /* Static helper functions for this file only, prefix with _ */
18
 /* Static helper functions for this file only, prefix with _ */
19
-
19
+#include <math.h>
20
 
20
 
21
 static void _light_add_enumerator_device(light_device_enumerator_t *enumerator, light_device_t *new_device)
21
 static void _light_add_enumerator_device(light_device_enumerator_t *enumerator, light_device_t *new_device)
22
 {
22
 {
146
     return NULL;
146
     return NULL;
147
 }
147
 }
148
 
148
 
149
-static bool _light_raw_to_percent(light_device_target_t *target, uint64_t inraw, double *outpercent)
149
+static bool _light_raw_to_percent(light_context_t *ctx, uint64_t inraw, double *outpercent)
150
 {
150
 {
151
+        light_device_target_t *target = ctx->run_params.device_target;
151
         double inraw_d = (double)inraw;
152
         double inraw_d = (double)inraw;
152
         uint64_t max_value = 0;
153
         uint64_t max_value = 0;
153
         if(!target->get_max_value(target, &max_value))
154
         if(!target->get_max_value(target, &max_value))
156
             return false;
157
             return false;
157
         }
158
         }
158
         double max_value_d = (double)max_value;
159
         double max_value_d = (double)max_value;
159
-        double percent = light_percent_clamp((inraw_d / max_value_d) * 100.0);
160
-        *outpercent = percent;
160
+        double percent = 0;
161
+        if(ctx->run_params.mode == LC_MODE_EXPONENTIAL)
162
+            percent = pow((inraw_d / max_value_d), 1.0 / LIGHT_EXPONENT) * 100.0;
163
+        else
164
+            percent = (inraw_d / max_value_d) * 100.0;
165
+        
166
+        *outpercent = light_percent_clamp(percent);
161
         
167
         
162
         return true;
168
         return true;
163
 }
169
 }
164
 
170
 
165
-static bool _light_percent_to_raw(light_device_target_t *target, double inpercent, uint64_t *outraw)
171
+static bool _light_percent_to_raw(light_context_t *ctx, double inpercent, uint64_t *outraw)
166
 {
172
 {
173
+    light_device_target_t *target = ctx->run_params.device_target;
167
     uint64_t max_value = 0;
174
     uint64_t max_value = 0;
168
     if(!target->get_max_value(target, &max_value))
175
     if(!target->get_max_value(target, &max_value))
169
     {
176
     {
172
     }
179
     }
173
 
180
 
174
     double max_value_d = (double)max_value;
181
     double max_value_d = (double)max_value;
175
-    double target_value_d = max_value_d * (light_percent_clamp(inpercent) / 100.0);
182
+    double target_value_d = 0;
183
+    if(ctx->run_params.mode == LC_MODE_EXPONENTIAL)
184
+        target_value_d = max_value_d * pow(light_percent_clamp(inpercent) / 100.0, LIGHT_EXPONENT);
185
+    else
186
+        target_value_d = max_value_d * (light_percent_clamp(inpercent) / 100.0);
176
     uint64_t target_value = LIGHT_CLAMP((uint64_t)target_value_d, 0, max_value);
187
     uint64_t target_value = LIGHT_CLAMP((uint64_t)target_value_d, 0, max_value);
177
     *outraw = target_value;
188
     *outraw = target_value;
178
     
189
     
203
         "\n"
214
         "\n"
204
         "Options:\n"
215
         "Options:\n"
205
         "  -r          Interpret input and output values in raw mode (ignored for -T)\n"
216
         "  -r          Interpret input and output values in raw mode (ignored for -T)\n"
217
+        "  -e          Interpret input and output values in exponential mode (ignored for -r and -T)\n"
206
         "  -s          Specify device target path to use, use -L to list available\n"
218
         "  -s          Specify device target path to use, use -L to list available\n"
207
         "  -v          Specify the verbosity level (default 0)\n"
219
         "  -v          Specify the verbosity level (default 0)\n"
208
         "                 0: Values only\n"
220
         "                 0: Values only\n"
240
     bool need_target = true; // default cmd is get brightness
252
     bool need_target = true; // default cmd is get brightness
241
     bool specified_target = false;
253
     bool specified_target = false;
242
     snprintf(ctrl_name, sizeof(ctrl_name), "%s", "sysfs/backlight/auto");
254
     snprintf(ctrl_name, sizeof(ctrl_name), "%s", "sysfs/backlight/auto");
243
-    
244
-    while((curr_arg = getopt(argc, argv, "HhVGSLMNPAUTOIv:s:r")) != -1)
255
+
256
+    while((curr_arg = getopt(argc, argv, "HhVGSLMNPAUTOIv:s:re")) != -1)
245
     {
257
     {
246
         switch(curr_arg)
258
         switch(curr_arg)
247
         {
259
         {
269
                 specified_target = true;
281
                 specified_target = true;
270
                 break;
282
                 break;
271
             case 'r':
283
             case 'r':
272
-                ctx->run_params.raw_mode = true;
284
+                ctx->run_params.mode = LC_MODE_RAW;
285
+                break;
286
+            case 'e':
287
+                ctx->run_params.mode = LC_MODE_EXPONENTIAL;
273
                 break;
288
                 break;
274
             
289
             
275
             // Commands
290
             // Commands
317
                 break;
332
                 break;
318
             case 'T':
333
             case 'T':
319
                 _light_set_context_command(ctx, light_cmd_mul_brightness);
334
                 _light_set_context_command(ctx, light_cmd_mul_brightness);
335
+                ctx->run_params.mode = LC_MODE_PERCENTAGE;
320
                 need_target = true;
336
                 need_target = true;
321
                 need_float_value = true;
337
                 need_float_value = true;
322
                 break;
338
                 break;
368
 
384
 
369
     if(need_value)
385
     if(need_value)
370
     {
386
     {
371
-        if(ctx->run_params.raw_mode)
387
+        if(ctx->run_params.mode == LC_MODE_RAW)
372
         {
388
         {
373
             if(sscanf(argv[optind], "%lu", &ctx->run_params.value) != 1)
389
             if(sscanf(argv[optind], "%lu", &ctx->run_params.value) != 1)
374
             {
390
             {
387
                 return false;
403
                 return false;
388
             }
404
             }
389
             
405
             
390
-            percent_value = light_percent_clamp(percent_value);
391
-            
392
-            uint64_t raw_value = 0;
393
-            if(!_light_percent_to_raw(ctx->run_params.device_target, percent_value, &raw_value))
394
-            {
395
-                LIGHT_ERR("failed to convert from percent to raw for device target");
396
-                return false;
397
-            }
398
-            
399
-            ctx->run_params.value = raw_value;
406
+            percent_value = light_percent_clamp(percent_value);                        
407
+            need_float_value = true;
400
         }
408
         }
401
     }
409
     }
402
 
410
 
429
     new_ctx->run_params.command = NULL;
437
     new_ctx->run_params.command = NULL;
430
     new_ctx->run_params.device_target = NULL;
438
     new_ctx->run_params.device_target = NULL;
431
     new_ctx->run_params.value = 0;
439
     new_ctx->run_params.value = 0;
432
-    new_ctx->run_params.raw_mode = false;
440
+    new_ctx->run_params.mode = LC_MODE_PERCENTAGE;
433
 
441
 
434
     uid_t uid = getuid();
442
     uid_t uid = getuid();
435
     uid_t euid = geteuid();
443
     uid_t euid = geteuid();
754
         return false;
762
         return false;
755
     }
763
     }
756
     
764
     
757
-    if(ctx->run_params.raw_mode)
765
+    if(ctx->run_params.mode == LC_MODE_RAW)
758
     {
766
     {
759
         printf("%" PRIu64 "\n", value);
767
         printf("%" PRIu64 "\n", value);
760
     }
768
     }
761
     else 
769
     else 
762
     {
770
     {
763
         double percent = 0.0;
771
         double percent = 0.0;
764
-        if(!_light_raw_to_percent(target, value, &percent))
772
+        if(!_light_raw_to_percent(ctx, value, &percent))
765
         {
773
         {
766
             LIGHT_ERR("failed to convert from raw to percent from device target");
774
             LIGHT_ERR("failed to convert from raw to percent from device target");
767
             return false;
775
             return false;
781
         return false;
789
         return false;
782
     }
790
     }
783
     
791
     
784
-    if(!ctx->run_params.raw_mode)
792
+    if(ctx->run_params.mode == LC_MODE_PERCENTAGE ||
793
+       ctx->run_params.mode == LC_MODE_EXPONENTIAL)
785
     {
794
     {
786
         printf("100.0\n");
795
         printf("100.0\n");
787
         return true;
796
         return true;
831
     uint64_t minimum_value = 0;
840
     uint64_t minimum_value = 0;
832
     if(!light_file_read_uint64(target_path, &minimum_value))
841
     if(!light_file_read_uint64(target_path, &minimum_value))
833
     {
842
     {
834
-        if(ctx->run_params.raw_mode)
843
+        if(ctx->run_params.mode == LC_MODE_RAW)
835
         {
844
         {
836
             printf("0\n");
845
             printf("0\n");
837
         }
846
         }
843
         return true;
852
         return true;
844
     }
853
     }
845
     
854
     
846
-    if(ctx->run_params.raw_mode)
855
+    if(ctx->run_params.mode == LC_MODE_RAW)
847
     {
856
     {
848
         printf("%" PRIu64 "\n", minimum_value);
857
         printf("%" PRIu64 "\n", minimum_value);
849
     }
858
     }
850
     else 
859
     else 
851
     {
860
     {
852
         double minimum_d = 0.0;
861
         double minimum_d = 0.0;
853
-        if(!_light_raw_to_percent(ctx->run_params.device_target, minimum_value, &minimum_d))
862
+        if(!_light_raw_to_percent(ctx, minimum_value, &minimum_d))
854
         {
863
         {
855
             LIGHT_ERR("failed to convert value from raw to percent for device target");
864
             LIGHT_ERR("failed to convert value from raw to percent for device target");
856
             return false;
865
             return false;
884
         LIGHT_ERR("failed to read from target");
893
         LIGHT_ERR("failed to read from target");
885
         return false;
894
         return false;
886
     }
895
     }
896
+
897
+    double percent = 0.0;
887
     
898
     
888
-    value += ctx->run_params.value;
899
+    switch(ctx->run_params.mode)
900
+    {
901
+    case LC_MODE_RAW:    
902
+        value += ctx->run_params.value;
903
+        break;
904
+    case LC_MODE_PERCENTAGE:
905
+    case LC_MODE_EXPONENTIAL:
906
+        if(!_light_raw_to_percent(ctx, value, &percent))
907
+        {
908
+            LIGHT_ERR("failed to convert value from raw to percent for device target");
909
+            return false;
910
+        }
911
+        percent += ctx->run_params.float_value;
912
+        if(!_light_percent_to_raw(ctx, percent, &value))
913
+        {
914
+            LIGHT_ERR("failed to convert value from percent to raw for device target");
915
+            return false;
916
+        }        
917
+        break;
918
+    }
889
     
919
     
890
     uint64_t mincap = _light_get_min_cap(ctx);
920
     uint64_t mincap = _light_get_min_cap(ctx);
891
     if(mincap > value)
921
     if(mincap > value)
892
     {
922
     {
893
         value = mincap;
923
         value = mincap;
894
     }
924
     }
895
-    
896
-    
897
     if(value > max_value)
925
     if(value > max_value)
898
     {
926
     {
899
         value = max_value;
927
         value = max_value;
904
         LIGHT_ERR("failed to write to target");
932
         LIGHT_ERR("failed to write to target");
905
         return false;
933
         return false;
906
     }
934
     }
907
-    
908
     return true;
935
     return true;
909
 }
936
 }
910
 
937
 
923
         LIGHT_ERR("failed to read from target");
950
         LIGHT_ERR("failed to read from target");
924
         return false;
951
         return false;
925
     }
952
     }
953
+
954
+    double percent = 0.0;
926
     
955
     
927
-    if(value > ctx->run_params.value)
928
-    {
929
-        value -= ctx->run_params.value;
930
-    }
931
-    else 
956
+    switch(ctx->run_params.mode)
932
     {
957
     {
933
-        value = 0;
958
+    case LC_MODE_RAW:
959
+        if(value > ctx->run_params.value)
960
+            value -= ctx->run_params.value;
961
+        else 
962
+            value = 0;
963
+        break;
964
+    case LC_MODE_PERCENTAGE:
965
+    case LC_MODE_EXPONENTIAL:
966
+        if(!_light_raw_to_percent(ctx, value, &percent))
967
+        {
968
+            LIGHT_ERR("failed to convert value from raw to percent for device target");
969
+            return false;
970
+        }
971
+        if(percent > ctx->run_params.float_value)
972
+            percent -= ctx->run_params.float_value;
973
+        else
974
+            percent = 0;
975
+        if(!_light_percent_to_raw(ctx, percent, &value))
976
+        {
977
+            LIGHT_ERR("failed to convert value from percent to raw for device target");
978
+            return false;
979
+        }        
980
+        break;
934
     }
981
     }
935
     
982
     
936
     uint64_t mincap = _light_get_min_cap(ctx);
983
     uint64_t mincap = _light_get_min_cap(ctx);

+ 10
- 1
src/light.h View File

26
 typedef bool (*LFUNCMAXVALGET)(light_device_target_t*, uint64_t*);
26
 typedef bool (*LFUNCMAXVALGET)(light_device_target_t*, uint64_t*);
27
 typedef bool (*LFUNCCUSTOMCMD)(light_device_target_t*, char const *);
27
 typedef bool (*LFUNCCUSTOMCMD)(light_device_target_t*, char const *);
28
 
28
 
29
+/* Constant for exponential mode */
30
+#define LIGHT_EXPONENT 4.0
31
+
29
 /* Describes a target within a device (for example a led on a keyboard, or a controller for a backlight) */
32
 /* Describes a target within a device (for example a led on a keyboard, or a controller for a backlight) */
30
 struct _light_device_target_t
33
 struct _light_device_target_t
31
 {
34
 {
68
 // A command that can be run (set, get, add, subtract, print help, print version, list devices etc.)
71
 // A command that can be run (set, get, add, subtract, print help, print version, list devices etc.)
69
 typedef bool (*LFUNCCOMMAND)(light_context_t *);
72
 typedef bool (*LFUNCCOMMAND)(light_context_t *);
70
 
73
 
74
+typedef enum _light_context_mode {
75
+    LC_MODE_PERCENTAGE,
76
+    LC_MODE_RAW,
77
+    LC_MODE_EXPONENTIAL
78
+} light_context_mode;
79
+
71
 struct _light_context_t
80
 struct _light_context_t
72
 {
81
 {
73
     struct 
82
     struct 
76
         // Only one of value and raw_value is populated; which one depends on the command
85
         // Only one of value and raw_value is populated; which one depends on the command
77
         uint64_t                value; // The input value, in raw mode
86
         uint64_t                value; // The input value, in raw mode
78
         float                   float_value; // The input value as a float
87
         float                   float_value; // The input value as a float
79
-        bool                    raw_mode; // Whether or not we use raw or percentage mode
88
+        light_context_mode      mode; // Whether or not we use raw, exponential or percentage mode
80
         light_device_target_t   *device_target; // The device target to act on
89
         light_device_target_t   *device_target; // The device target to act on
81
     } run_params;
90
     } run_params;
82
 
91