//Chris Xiong 2018 //3-Clause BSD License #include "brightness_ctrl.hpp" #include "utils.hpp" #include #include #define log10_n(x) ((x)<1?0:log10(x)) void BrightnessControl::_brightness_slide(int p) { std::lock_guard adjust_lck(adjust_m); p+=offset; if(p>100)p=100; if(p<0)p=0; int pbr=maxbr*p/100; if(pbr%d/%d",br,pbr,maxbr); int d=1;if(pbr0&&br+round(d*dd)<=pbr||d<0&&br+round(d*dd)>=pbr) { br+=(int)round(d*dd);writeint(brpath.c_str(),br); dd=dd*1.2;std::this_thread::sleep_for(std::chrono::milliseconds(10)); } br=pbr;writeint(brpath.c_str(),br); } void BrightnessControl::init(float initv,SensorALS *s) { cur=std::upper_bound(thresh.begin(),thresh.end(),(int)roundf(initv)) -thresh.begin(); if(thresh.size()+1!=value.size())LOG('W', "Size of threshold array should be one more than size of value array",0); als=s;set_offset(0,0); } void BrightnessControl::set_path(filesystem::path p) { cpath=p; brpath=cpath/"brightness"; maxbrpath=cpath/"max_brightness"; maxbr=readint(maxbrpath.c_str()); br=readint(brpath.c_str()); } void BrightnessControl::set_thresh(const std::vector &_th){thresh=_th;} void BrightnessControl::set_value(const std::vector &_v){value=_v;} void BrightnessControl::set_delay(int _d){delay=_d;} void BrightnessControl::set_trigrange(int _tr){tr=_tr;} void BrightnessControl::set_minabr(int _mbr){minabr=_mbr;} void BrightnessControl::set_offset(int rel,int off) { if(rel)offset+=rel*off;else offset=off; if(offset>100)offset=100; if(offset<-100)offset=-100; brightness_slide(value[cur]); } void BrightnessControl::set_frozen(bool frozen) { if(frozen) { doffset=offset; offset=value[cur]+offset; if(offset>100)offset=100; if(offset<0)offset=0; } else { offset=doffset; force_adjust(); } } int BrightnessControl::get_offset(){return offset;} int BrightnessControl::get_brightness() { //On some devices there are EC-controlled key combinations //that bypasses lightsd entirely (e.g. Fn+Space on ThinkPad for //keyboard backlight). So we have to turn to sysfs for the real value... if(brpath.empty())return 0; return round(readint(brpath.c_str())*100./maxbr); } void BrightnessControl::force_adjust() { cur=std::upper_bound(thresh.begin(),thresh.end(),(int)roundf(als->get_value())) -thresh.begin(); brightness_slide(value[cur]); } void BrightnessControl::on_sensor_report(float v) { int lb=cur>0?thresh[cur-1]:0; int ub=cur>1; if(vub+log10_n(ub)*tr) { if(direction!=(v>ub)) { { std::lock_guard lck(interrupt_m); direction=(v>ub); } interrupt.notify_one(); std::this_thread::yield(); } { std::lock_guard lcd(threshnotify_m); //nothing to do within this lock } threshnotify.notify_one(); std::this_thread::yield(); } } void BrightnessControl::brightness_slide(int p) { if(cpath.empty())return; std::thread brth(&BrightnessControl::_brightness_slide,std::ref(*this),p); brth.detach(); } void BrightnessControl::worker() { if(cpath.empty())return; while(1) { std::unique_locklock_thresh(threshnotify_m); threshnotify.wait(lock_thresh); lock_thresh.unlock(); std::cv_status intr; do{ std::unique_locklock_interrupt(interrupt_m); intr=interrupt.wait_for(lock_interrupt,std::chrono::seconds(delay)); lock_interrupt.unlock(); }while(intr==std::cv_status::no_timeout); //carry out brightness adjustment here float val=als->get_value(); int lb=cur>0?thresh[cur-1]:0; int ub=cur>1; while(val>ub) { ++cur;lb=thresh[cur-1]; ub=cur>1; } while(val0?thresh[cur-1]:0; ub=thresh[cur]; } brightness_slide(value[cur]); } }