From 553ee139c0114023ec3548db4cb26b171c53d5b3 Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sat, 13 Jun 2026 13:57:20 -0400 Subject: [PATCH 1/8] Fix footswitch ghosting and non-bypass feedback Erase the previously drawn keycap on single-widget refresh so a narrower label no longer leaves ghost pixels from a wider one, giving a consistent black backdrop. Track the keycap footprint slot-relative so the erase never touches a neighbouring switch. Make drives_display true for non-:bypass param bindings: only :bypass gets a WS bypass-echo redraw, so footswitches bound to other params (e.g. mixer Solo) must update their own LED/LCD on press. Co-Authored-By: Claude Opus 4.8 --- pistomp/footswitch.py | 9 ++++++--- .../bound.png | Bin 8601 -> 8427 bytes .../unbound.png | Bin 7465 -> 7838 bytes 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pistomp/footswitch.py b/pistomp/footswitch.py index fab0e9caa..6dfacfbed 100755 --- a/pistomp/footswitch.py +++ b/pistomp/footswitch.py @@ -141,9 +141,12 @@ def set_midi_channel(self, midi_channel): @property def drives_display(self) -> bool: - """True when unbound: no inbound echo will arrive, so the press updates - indicators itself. When bound to a plugin :bypass, the WS broadcast does.""" - return self.parameter is None + """True unless an inbound WS echo will repaint this switch on press. + Only a plugin :bypass binding gets that echo (mod-host bypass feedback); + unbound switches and non-:bypass param bindings must update their own + indicators since their param_set echo carries no LCD redraw.""" + param = self.parameter + return param is None or param.symbol != Token.COLON_BYPASS def set_value(self, bypass_value: float): self.toggled = (bypass_value < 1) diff --git a/tests/snapshots/v3/test_midi_learn/test_v3_midi_learn_binds_footswitch_live/bound.png b/tests/snapshots/v3/test_midi_learn/test_v3_midi_learn_binds_footswitch_live/bound.png index 2ce42aacb440ce90de80d02815de903efa085179..b8cf8f5a4501df2d4b2e9b58a91b8811db79be54 100644 GIT binary patch literal 8427 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 HH1NLwNhJR0 diff --git a/tests/snapshots/v3/test_midi_learn/test_v3_midi_learn_binds_footswitch_live/unbound.png b/tests/snapshots/v3/test_midi_learn/test_v3_midi_learn_binds_footswitch_live/unbound.png index 2d312520a327a53c23d24ad7ea20ef35e84c258f..32d5c9b93153ce35f50afc7c43cfde52014ee666 100644 GIT binary patch literal 7838 zcmdsc_dnI|ANL_2E4z$rva*hOly$OaHd!HiQx39@l_Z;x9kN3bG7iahaO@c}%U;J` z_toS6<$M1N_xlIl59c`NeZ8*N>$$Ed9W517VtQf-1VXB&s;CEn;5-KRdxW^)=e0Jk zGz7wIr=}=p@G5J2jtF5eenqe+A(}3bp5C9tByWYw77|MFK!ctBalyCovd7Wveff_c zEct(PRr%Io`caQuqYeM{*SFtP-KIHo!s+wFC|HF{<+Ate@S!nN}zl46h?9 zE6rc{z-4n;I%-jSKW`td4csSO8p>0+IN3ds6~(3VCk=0V8yCkcVoMm`?UmW#a-S-S z>dqYj8jWYqvgPwUC9`qdqb6x?>}OCmmMQ7!YRXVKiYDLP9Rw0j2ul|FI3XiLJ)#o5 zINSy1H#vLP^QVwWby0&PTqhIqrAXFu6Bl`r2$EdD=Vz0x9U# zqobpWii#CF6NazM(foY~$!8i2X=uZzPm4#_si>&R%F6r$7NWj?e;CHvyrpJnm}0;i z8y(#ga8lXI*Xnn;hB}$oxR&+ZVGJ5c;d^R7h{$E(6vEk7sCd9kglM+S(c$)8%5cH8lA6`1DH++7_gt z2{TU2@sm?isx11?o^8Y8haF?yy*qHJot~cFoT#v=HfGY2d9`PytE+plPiXb`i9c%I z73S6OYhz>M%^Uo4Cf4NMnD}^Yb@i{t{6WPB)4oWVrX1Oz^9*s9lE2;$87HeOwbj&~ zi=<1q|9bdxMfLgf=aIMBL-Hg{DkfYeE31w9Yo@ngz3YgH@$uSk-ySlO)%VTM2OYbJ zq_eZLH)HNlQVz>1rJ*A5CMFsh(edR=FB@!QCv$Hu z|L7NMon6T`wBCkbZ%M;jEr?4hqX+E4(5Z4z9kA8)+Je=Rl9IOk`j%`sW@3_F)pE`o z-Zs_XRSZ2rt>|IN&nbUEP!NHa0RH~>!ZLMsc2?$Q$pqBZ`xYbW0}osW~-^^#)Yv9D>UuCD&_#dEnU)}||Fy{O_gURY-|Ez3jCkDotlmKw~s z!cZ2LhKAlt9Z`nmMzQqbWtnxe@!t9n_|4@ZcKmo1+Ud`ay2|g^yZZw{7P*}5J5RLZ zW5PeNFjt0gnP$I3(AGV$tZ>K9chp$8 zgMfg5sD1x;|07=UwMf`(ots(ntLjc`qMZqaOXlxaZe8u<@W8Dp;RyNXwWid>or(8V zMn*^1qZwrbr!L$y)zpZBka;?%OVQArhcEK$>Lwh;=t8zqx_ZN=z!=TR5C z!8ZZZU+tLcN@yPMAoc@GN=iO*QMUb9eVLh=xo(yv?vfghrt$TWzLKfE95~-WN4OLH z2HoU*bA7d~t&`j<2DbhO?rAS~E=T6#?$A6cpttV!-w&E=J9AC57*|;4(+bno0EqSn zA-Ph6I`}Oz#)rRyZom*JwBEUG1i@rWJuMi1WvZs2prEA{H_MK*qD6~|?CVo^rlKTy z^ym?G;LJPQeCy~HzNhn9=Fwc*?K!F+7QY(2BAq{>Pwx1GM$jrAz39(Ho-x$dsHAggySl*%~{L*ldE*HkMOq6zUCRi1Psil99=_NZ{h+)J@~` z`ZH)JL$i_vul&Hd-r)}C2*kFlK3ck5m7*WStH^g&(L9ZU1sM)Kl69?@V=OSmSu>KE(jjAl3So*B?rC;Fe>Pvx#C;Q7JnNd5S`zgMw>bMD$vJUTU*RMOi)1CT-rI8 zRl!$$JT9Y-VsgR#QZgU)`FKngL>nl6+k7f3WBTZt`)9s1N43cmhV%?}W;4Q3b zKe&cH7cL`x^RNzL8H-gshq-eF-%fE{AP8ZN5v5{!*6!~aw~dyiH=`z ztsigC=ERwutj5v4Y`DzyXh{b%XQuKY^o0vi_7+!DH2!}G=l?i21Gs2$&7(~#ipc%p zg4r+2;d@$K$+axgEzF%K-u})%eHVX5wAkjgUa)i+`jyELyYJ}O4`%h+ibRs!`|32x zPzaeE< zTPBuaGC7y|Fz$Rcw~M4@VPT=6>9P`fLvl|Zagzsx zvGn)A^*$x|Y&A{2Fo|CC$&;h2N1mSA6&AhcEet>0x6SK=*Nzu%uG7xvMn>2v2B7c(vR z#a0ba&a(EH9GS6!98E4h9-hm6f}awPo)yGc(iDo`C1`FU1~kqAa%N zQL|P;I^hg3SJvFvsLmy7w-UA5+FEx*5gE1OQMdW#M}N!b8ol|hv_EKaH37r`H6Ixn zISoWADt7!GF0c&T?@UTcYHpUc+z7>$s>K~VM;`NXataE@wfqM1WnJIK+S(On7D>)# zfjqN&nFC~{_xZQE)t5|gWLC@C(dJ}R;OKh!`)$TF*PLtGWZBk=T8l(x~o(4VrkK>P*naH{UnKyl~fPz1rU`Mq# z5t7=XVldeCL0aop(Qas0D$wEKr-=q0rMz4Uz{3=9Eh2dm&QwbDiG_I|g4t>w9^l_BOdS@{h67lpi%j1zjC zyKE#p#1`HrO+iJN70K;qeZBr3A1QgXwmKpknMIN_ogq6!HniBMFWiu3{#Z_su3_a z@U?Z8H^7~M8B66ik&iw59Zrt*mzgf>@Cd$`&C1FG4TL&d%UoYyCyrRUI$3B1%5bGO zIZePUH6cOA)HDOg29KAI1=FAw&98vmWF#xj&tC#c@RRTGR4>6*d_7xmz3gyrWO{J zM&;onjrG3R?@Im((BK-U7n@zqwKR9{N}v7?HxS(fG6%#8wq8aUfGOLv_4V#^WqPGR zn9l_!4%dxx4@9C`Wbr4TpwpNrjA z4=1NZ&xfU@rAkUlV_A~fm7hMn&KQLP=L!aK#iPP#c4o#OnEkRR zmUjey=zq9!#>P{>U|8{2&L#r=+xAs_+P8b_3?4C(1#zUIy^_< zHq!U=`??*FEif`ma46AKkx};X;}8APO`qhgmkkGphYpw=lpQ)XD~l0)hYxGn+0|A6Y{aj1!hVinp}tTjzz^GVss>0#a@<~IqoSVi=M!|fV9M!B(goR*S6)` z-*wN2@73+h&CMw;?rpfMdN{7^ri(h923~_XVF}!81Nf6UV1J;O-`pJ7_x{0{D|;eH zW-7ja|9%B5JiWEGb;(W!0V(}m&&U*`@>=lOe0=Ecc}&=^&#r!ckJ7aS(-sd}*VFKp#*q|aG& z<#&Cj9uyZBx3ja;ND~Coys&<<$pORMVBTWgNgSn^l#uYneNM7z?s~tQrG8-vunQP+ zKn{4gq2_{?jfhe+hkWF8OHcsd3_woFNlD+$-NF6VbdAgrH>1@_evX*9I5jnOVNucA z%1Q!;sP*zdqhR$KA77K_I$I7p!pCCpDC~;VgKEh1=G2==NTcdYhZv_=}9DW*zuYa zmEkv7fF0U?EUaf8gWLZPyMWt}p@SQX72{T<45g_&R0+b=dYdWfkH0Dx@ei30g;PcH z#ZNeRXD%EN!hOiZI%0FO3LbdsiSeLk?Erbp-|nzWnJ-X9cFG+MoG@HYp&t;QP~fo# zv!zByM;-b@2OIc}Z!haJuH=;v&e1 z$ffr}6xoToUG~j4s9Jn3b@IKi1_&DFwN{;S-kzIE@OELX{i<=wBNd=)$%Wsa9GCer> z^f$QQ^YhtdWv`>Sb5vDTh3I3!YzaJg@PL;$ANPA>W8;@Epi4o(1fq%9_C*6Dqa10! z15gw2*dHXlog>S^HdDz_0M`UAa&q#?b%gKkeBlg>o4dQL-+?UcKUs8%}-`@m8yYWeZJrRr)Pf8!q zMjJ=|AivR>!NE6%aC33#$$U=`2I|U?ms-3iFE5mpkoQ;>EEafV=UR{_>AU?IiM=NZ zMCjT-tqn&8T3fSEr@|vHZ&my5TKIcSjgeOvMMK`;pj#nDD$uA->*3iC+!u2c#1ZZ_ zQHt#0ZNDFca6ifD_;dJ=txxx!r=dAh)b;iC0Xy{eaF_`co@mOc?8@U?eIz>YvJyDlF7AG`x3-qdTo@rk!0}G}P5g80Mnxa04Q$0$dHW2*4eq z@^MEoKxzLB7t^s9j*utb8I|ON2Tq`sL32CI4t0ZL1V7WVhK2@^0Kwt8vU!u;FF3-TgOVAJu3=9Ci4R}$1asos|MP*Q(augju zBW_1WN0*lYbxR%IMiHf0pb`&4Ep|VZCq^#aot7lPKO!}BAaP%{X~rXo@iS_RrPS@tXA-XS z@X*xOdu_9r9o3f!&^%EQk!DNYFUFq%l!?&A0LxK6z9Cpy0p0tSj2p_z$r(WpqAoym zwY7$MI>r@7tw!U%uND-zk{=}Za!?V)cY_2UmN{Tu4U)$cb&w-nJ~M;&nFE7TGaaK` zU|KQZT#NHr$m+QwCP}@J1iyV9p{%6jP5&eBb(@vvEbxV2zlvlID8Hrw$_s2NbG!;m z`=aM-dA3|kYru&hWuvj%E9o2q-to;NLqkI#Umaj`qd1Jz)ON5;px0ep`2i3Z&_u)l zrU88@65=O454JhUGGm+~`}&tt(!zc_ zk#umz#BKkJgE|fIaY9A8|kMhZYnR5QRCqxpB%zE3&f@=2un@t|O>!eHgIU=edg~r>Ly_W`)Q}x2hZ?>j=fa@7xqfP5DzdHk`xT9>1oM&D}*vDnOs%u--^| zHJGz^r~|#(Z(ZFJ?GVN~=3G0v&ZrY1WKwmXf>3^!Dx=p{l94P8Jw7Wna?!(pq=}|> z=KP|`RWrM7z}eKkIOHfs6~)2N|GB$t%fFrqoCtJ(dm)((I82cc{06w%X2tr(#4T^u z=Ez6p?vIsayfD_Tc$Qt58gI%Q;}qA(9`)>*8B>6h$-VOYAy2rHb$DXlz8%^;>iEIs zDun?jgc#S#$ja4bb6)aq<&Fnoq8*j_;`F3)6d=?ju11{w`_9fzO1#A@@3`xyxM*9E z;!(e=bMJbM+YRP|G|@m)$12~a94XOogk`$bnksy*t1B$zl$4ZYXSW6-0vuX^10~Q; z5fO>d%7@v5L&&5KTM@APsvPfPW9@3D{ZTF5W%dE=Axi9&k?la;Z+nn{S{w7ny?aMI zF5&&lIZrLm7bcZG2y7N7H}~OLV1xM%%&^pe>K2#Rk(-D0(UdG!5u&1`loWdu$M7kFL8qE4-Er%I*Dy^K2C|w7?dE^Zx+Z+k^u+TLKI8^)nGiwJ^n=Uyyq>?e)hBXBU(dE{=xmH_c1Uq9w;ivXklR7kpSQK?qPz@ zYju`a7#Pp?6lElJd^5M_@N~3or*Ze#KD`N7Xp5t}7xt6Jj_Psi`!CglDk3$TAIAQC zF|c}O(vayrtL7{Zq4M&4#gRu$|(V%bb8WNJkMK3yYCFaeCXnBqJ*u zUsN*YFf%=!q+~5Gj~goo^YZfY@mY5h@`Pj!*hED{U}Iw^!{K!`HB*Wa=V)|fWF-0H z$E2((&EoQRmroq6VAo-8a*~#t~O({P+S7t~U&XXUp<2&>a z;^EO+P;WUOaJ8%E^u(bH{e^RRbwxoCsaFzou&Njo)Qr%c9UN54)nF!x4hsvDl9r|* zkdu&jGeDZ!X%P_>CCJC8qoZ?lsY^pVv~jez=T@XstXHC%RgV}6PfALfFbjBqN8p`X zUCqbFwl!5{TUuJ$LA>kI;l*a5&zRVg-e_Ml4URHRg`A8`$I#FoZPwpftEWUh_9&ugqzQ*0 z9i7y=6o-5N*7|y(4huGBs0yQ_v-1n43U*gl*DS2y2q{U?cmKAwoLpS~9-bF4?j0h< zsYyxmb|*#()ys?vMTqeTYCF~syFO4z?*`X?tE$pwNoGk_TK?TXlq+p&Vlq27mzS5< z*W24+QL*-T*Jg0c9zY{rL551p)U=d0PAYeAf1lgFHaa>wL(tWRC$0I~|MG0Vt*tG) zJ-!vH?Ck8!lKg(aMqgilVq!uYi2=?N3WX{tC#wh6KI*2i`NUO**cyn{JxTM6<#bw-%5Ary` zIbc`6NXOsT_sR3F_Vzs6=%X}#M{@pv#)by5tD}*ordO5)omE3nODZa=)!M=J!$Os` zgQ}dX4_zw{r9pNGPdTbuR7}py%yi1`4k9}{BarKqe*NMBCtIo+0%`DOumH}br6o4< zm;sxQPx;^5lx?C=(Uh`iIU2od5a*yl7H)1$rhq!@FCLU z-&Pbj%P(KP1O^7)#gs&@Yx(!~_nS0&JNx@X;+tpcTw6Rh5)@hA!l32!j~+eh*eRK? zWl&i>8Np`QjFHC?%kV9pot-t&(<6WQklXLTs=`3U#B#+=C{Qd%E-yJbnO{(lQkYdB zL)By-eVB6-xW6o$n8PIKg^7W?XtO+{Y-5V@@bY?a|Nip6Z-=T=zSc|f7!(Q>D{Rli zp$S-|`EXFg6LQrWiuF75ltf$8{GU7~)+C0}Dqz9?d6iRlc6LtZnACf8j+d`!++BS=)cqO!7x_m+X7 zp`o_6w!FN&v9YnW_1gL2`b3$zxJ~~PR`!Wd!Fg|&ApKiTd8ko$QFj#{OwO$ zC618V?_tX6=;-hTm%o1;rJ&0|I={8G^|(O;ecMGVG#&8a#py1mX+!moA8~f=Q(-*3 zyhR~{=@}V`2?-!mA|8G#*dj;$ke%1TRhnaMorO=yUpi3JLYiOsh?0v3Psz$MH8q`^no>lhZES1^yUsU> zUu~#Q{4gykEq&p?V{dO?A953{rZ$KSxrSx&b0eC9va9_3{B9ut=P(6n1t{Qt#PY^S z;m!4F3oj3kzq97Rhv|*=6B^=s-8ptCtu|GZl$1rvCgsr3_!08cN9x*w?Aj&s{x#6# zy9oD{-+*odTs|x1^Spf7({wlZcuYUq<}4sNF;TkORH75gMMwo1g;^yl)dXMpuaNp4 ztoEp?s*2XVvFwVYFuMUb-%Lx*C-L21?j(tpSx^C~mYA66#mJrKjjk63{QF6Kn2lCg zIITe_F)lIY!S9g|s(quyb!O}aFG3%DD=wy^+~5g*Yu4oJuCEVYif_3*Q2v7L_D7yN z$f}=(LT%Bt<*K%_G6BLfl`or9^KHzbNc5)>L+FCo zv*C$0c5Rl;;-aGqYYOHKzV!W4R)-Y3`0(Mg44q-EQ`*Om$nw|im6esx0)_5$dq$pJM@i{@VIflv z(!9#%!IWBhNeK!(5#U|osI{FMHDCh@>C)N$%8wsEI*2WeTzTa*G>DH&WFcDn{Ej0$ zd7HRD$=S+r85?N}hV3{JXLQGfx+QvPp5{lVEjOZG;Su|>5QMw(Rnwud?7Z- zY}H`$m`?NH^B2bxhwI419KgR+PoF9U#>K?s#hsk5=V-Us*xFLo9|3O867ku*@aj!^ z8FJodj<`CRiHyWaR+5!5w_X2Sh5Gl=u*!ylIY|w^4T>9-Mcd;8&{;FXJ9Hcrlov=oWLk<;CUocQ?R^=IfUyLR8v2VW{G;O8O+bmk3f&PnV`SIu3EWV zU3asw0?g#OgR{};d!_(v+`4v~Xk#}$^pEF;wcZMce+MkNp3uvEm_!7L2)q3o%C#NL ztmwWhGi{W+a)@X0+puvqA}{i19Sai`i`LcGx4rDPGCn&#K3Y(RWNJ~3A6>2d9-N_3Wku$2c4N7#^pq6v zk&~ld6(36}sFgTCr^7NveRC$i`3b0ulj$Y?EH!myW!}FmaKDU{Dc#*nyzkm0u1)(m z@VA=j4`mR;RNaa1C5 zs>$EKe+TGqXl%SVKMz806pB)Nap_7+W1ai``KnlkKyQAcmBz%x)GIS{Ui<>*UgKW` z8q1?T^RmGUrMEnv3Ww|42p$wpPa9<^^I$15CT>qwv@ci9RoN09tEbl0or3JIb(wog zMYX-Nv$M3s?Y%WQR-zA2O0oiwhEa9@ml{6h@-G$d+_^J~C+Ivab2WxUmH`DfkwJ_a zFQxx&*x+fO<1^P=*UK3d_GzZaH5fNRNXzAS1EqELQ%joT64PfOOj{?aNzAk;z>&RkzG!x9j))`Hcm!1`d6)# zpJNOhL2;{b(0%;YKjx4wChE>Ni&%n%4fhE5ZdJ~J~jJ-zWJzeCTR z3`f3nunf{VZUz#?fPerXM1H-+?TVvP7CqnaQyh8%v|`IyC+GNgL)gWMbA(i`R#9X}0Ot|1r3H+_z+J&8=x($Wh-r*oig0gE(0|3j+?$kV|b@fL@%Vqg(6Y&l;q zAc98oRF!F;;@u-8R8vp-2qy;WFH#d;7KuCkj%jcQPl_$=qDp1V{5zK9B>MNymz!Ql6|=F z)7=u-6(H1wtxk95fT58oA!)hVb_JRQ&S`%A3zr%c{`(Papq$LNgoJ>Drl6pZl#~R^ z0z!9`5f_-DKR~ZqSQxOSNYI>ZRUyBb@}2BU-LTHRL!z&pfDqQ#(J^W8+}K~~8Xg`7 z72^r8;gpXbGsP=_T_Ud0j*N-ImcI#ne0(ems34yI`qOwtL_`h`4>`>dvqM9~)YPuO z^tyZgY=|T<;E>#)zH;}Xn2$3SEKf^dLaLYQ1Z>RApZeBD%?f;9&BKtQ^3`xI`#)c) zM7&=Gp6%64m?^8P+g42lobDW-o(j5l>XjOK0eY8>As6-CqhV!r1Pq20zqt(9ZLV{g z;xRWjuPlA>G?x7Na|95R$x6xD*$B6#wq3-93kX4ce7xKXE-%M%c(ap0V{L71eSO*) zX^94NcdY<$nj_QG=*3@H$w~mEG4J1}s@TZLgmaGop$&}pY&}e#170$=2{xXRLLO7S zC4E53`~zz@B6KY%oYvkuy6&8%PQM|0zD>$-4p5nEYHLB|hY4l+ECl%g#sI(pjftDfb@7$u9SIyeu=6YX;Zn5x5(5JR2m}J) z56T6k7r0e(C%vGcz%0YPPAF-j9wn%GbMEHi@&o9-j%d>8vYwtEpPgBI7Z;lf15HiM zh=_>QRGzf&U%!Sw8({!B?Xx@oLQFaT511;7h&sW!czkq}>j{Cy!p`O<#C^G=txd`S zwg#{m6Bj4oN$B(^-{yBEt94q&~2U&)53+LlM`=;ykeXJYpy2`=j^<3*1VR{ z%^^1k4Q7S|0R{#J9-f4MHJ{p-z?-wge2k2Y08IN0-s`YzZ*J1H0QcrV?<`Zs+VMQK zed*`VpKLpFS#J?3VhS`udE2x-9`AosgIa5HK8S2TUN4>1u_ffSj9a z$%{3ZJvr|B1_V&L@M)V%^{yR&Ez!^6H0UbD$^l13LQE_{_`1RXr0wtOe?`M~>FMd9 zsb9`~BLre5 zI5^nKXP`au0dHfwQjHO~{|uy()vhhMi(YM0QzkQ0#=yzmUg|4953oiF8ZMjZgai`8 zC|=;f)z#Gj2A15~+S@O-9?lS~di~9or!JW1k@edy4<-$182o<7MJ_C3yKVy9uAW}4 z$C^?|NQgr~Gl(i7K7L<+|LVRkAPUep+1c891zw4KVb<)Q++$TxSO|bxUS6Kes=w*U z=#UU}ae|GD>pETil7S(7zy=o=m(%2@hIvSvjW=hpIw(M|U%v*%$isujJ!cQdDnLi6 z_W4>HVEdr!Kte)dVq!veKSF_FQ=Nu@X7}{ul{ME!C~ne(7)o%z@S<6i`rFp=5JXVW zXM6gVQb(z_wrA=VK)C^}HlXsueiCJ-rGY~1uQoq9dA8q0U1m~$kPkOwVP%~`1YH1L zus!J&2OejwHyPOSMxWj1JXY^CnAzCaUV(Ejqo0}E@5g|R7Y-azIIRu%oWLpmM|}Zb zTk9`daD{7~rlepTgZgxD=5r#vd!6TA;$wf#XjN;<6>%TNV7n9`!4UGp?6az5H?GZu zcsVRSez0g&j*H_4B@d>ad}6}!cs(D3JXDmcm1YtPKcWo_mk^LM6R<6VS#!CtHRGj@orV zK>$lcEDdZPuzJFkv@L)QmY0_SD+1A?o%jq|&dnZ*jVTF*E?%A=z6}c_yWa`Wq6G9Y zK7P+#kTV?2%ut@RDw~1#adCiYKwIfChY4`UKIg*9UA;9<#B&zWExB zlEEKkBS)>l&4bVOUOPLp3u6vn0xArYlEUN;x63^MvD4 z6K7#z;oyktR{1if<$xs98Rf9Tz@fxnz_qEG>X2ou)K#Y=^z>J$1H7B7 zakko%=!!W18$})5-QDemlFJ*O5592D3g*CQZ95Ic!osrWOIJH3#SE3;fFJt43c^#d zsG0(;17J1x_xDMn!|e`2&i0m8BRDY1Eig&5I6=dBw#iSMG4W+`FQA}h^7znT3Q&;` z!@@BClb!R!!e( zZ{V{#DEQqCMQCVlGYUxQ(o#@4K|ydF{iX?lH{QXqPlOC!d56N_ggCrS{TPd_pIR{p z3GfIOTZg_;y}^>Ms{Fq><7kbOiGVcyo^iv&cIUn~|Y>P>VgmV?4F+mqF*7t5uTeS}CCn#=~y+pKJ=-HWgD-`%=e} zw*y25F)dG9F`!Z4sMMU_e5BsmJWKm;!jp9D-#ekWHrw0mUPZS{9J{V;?HoNfx*$vy z{ckc6Fxh^I2o(9*fM2da>VLnE^rRJn%~i%gc*VvC7O^^MNd8ZCF+BWkd*6^D-eFwm zgYVoGn1ZhJU#ISY-x(%@$cHXWb~W?lC=Tm>X}L;~92R~1MiVv35cLqu`s-okoB4Hf zDvL4PvzHp1#YBOG^kDB{Z>{dkbz9;%K9*Qe`akzpz`fMtal-(VX~;<3JXT8kI}Ex{ ziyDR!f;P=XBLou0cjbOWchcUD&$E_X!28Z=`+fT9ry^F%hyOikXDCsp(`L{linufQ z8l0DcTPqt^Qma4{uE?Ha1PB8jVJfz77IAARZRnj$zR(Be>U9D$9COdd?>v;aOM;%p zq=+Osa(?tHwB>#*cwCT*3m+{O{`{<_E~=$b=XMTgnIW_-(Lf+D&H^LFg$Q+f)_9CA zp})oOoqaj3xc8L#2yWl?j0qndOxe?P{uH`>eoB3NQbG#kM^|Fy15=kl(2Uy%WcXKp zK8-OD2tjxJbqxD&K3e>L-i`E?iF^NTk_y0x5Fg4^r2OCFz0 Date: Sat, 13 Jun 2026 14:54:14 -0400 Subject: [PATCH 2/8] Fix non-bypass footswitches being up-to-date with mod-ui --- modalapi/mod.py | 10 +++++----- modalapi/modhandler.py | 10 +++++----- modalapi/plugin.py | 23 ++++++++++++++--------- pistomp/controller.py | 2 +- pistomp/footswitch.py | 14 ++++++++++++-- tests/test_footswitch.py | 37 +++++++++++++++++++++++++++++++++++++ tests/v1/test_midi_learn.py | 29 +++++++++++++++++++++++++++++ tests/v3/test_midi_learn.py | 30 ++++++++++++++++++++++++++++++ 8 files changed, 133 insertions(+), 22 deletions(-) diff --git a/modalapi/mod.py b/modalapi/mod.py index 72a73b923..379f88fd0 100755 --- a/modalapi/mod.py +++ b/modalapi/mod.py @@ -516,14 +516,14 @@ def _handle_ws_message(self, msg: WebSocketMessage): self.update_lcd_fs(footswitch=fs) elif isinstance(msg, ParamSetMessage): - # Keep the cached value fresh so a later edit opens at the current - # value. Not drawn anywhere live, so no LCD refresh. + # Mirror mod-ui's live value: refresh the cache (so a later edit opens + # at the current value) and sync any bound control. The connect-dump + # delivers the real mod-ui state here — :bypass aside, nothing else + # repaints a non-bypass footswitch. if self.current is not None: for plugin in self.current.pedalboard.plugins: if plugin.instance_id == msg.instance: - param = plugin.parameters.get(msg.symbol) - if param is not None: - param.value = msg.value + plugin.set_param_value(msg.symbol, msg.value) break elif isinstance(msg, MidiMapMessage): diff --git a/modalapi/modhandler.py b/modalapi/modhandler.py index 510f89ebb..9e755faa0 100755 --- a/modalapi/modhandler.py +++ b/modalapi/modhandler.py @@ -390,14 +390,14 @@ def _handle_ws_message(self, msg: WebSocketMessage): self.update_lcd_fs(footswitch=fs) elif isinstance(msg, ParamSetMessage): - # Keep the cached value fresh so a later long-press edit opens at the - # current value. Not drawn anywhere live, so no LCD refresh. + # Mirror mod-ui's live value: refresh the cache (so a later edit opens + # at the current value) and sync any bound control. The connect-dump + # delivers the real mod-ui state here — :bypass aside, nothing else + # repaints a non-bypass footswitch. if self.current is not None: for plugin in self.current.pedalboard.plugins: if plugin.instance_id == msg.instance: - param = plugin.parameters.get(msg.symbol) - if param is not None: - param.value = msg.value + plugin.set_param_value(msg.symbol, msg.value) break elif isinstance(msg, MidiMapMessage): diff --git a/modalapi/plugin.py b/modalapi/plugin.py index f13bf3c9d..88155ddbb 100755 --- a/modalapi/plugin.py +++ b/modalapi/plugin.py @@ -18,7 +18,7 @@ import json from common.parameter import Parameter -from pistomp.footswitch import Footswitch +from pistomp.controller import Controller Point = tuple[int, int] @@ -38,7 +38,7 @@ def __init__( self.parameters: dict[str, Parameter] = parameters self.bypass_indicator_xy: tuple[Point, Point] = ((0, 0), (0, 0)) self.lcd_xyz: LcdPosition | None = None - self.controllers: list[Footswitch] = [] + self.controllers: list[Controller] = [] self.has_footswitch: bool = False self.category: str | None = category @@ -56,15 +56,20 @@ def toggle_bypass(self) -> float: param.value = new_value return new_value - def set_bypass(self, bypass: bool) -> None: - param = self.parameters.get(":bypass") + def set_param_value(self, symbol: str, value: float) -> None: + """Cache a param's value and mirror it onto any control bound to it, so + a footswitch's LED/keycap (or a knob/encoder's cached position) tracks + mod-ui's live value. set_value is polymorphic per control type.""" + param = self.parameters.get(symbol) if param is None: return - param.value = 1.0 if bypass else 0.0 - if self.has_footswitch: - for c in self.controllers: - if isinstance(c, Footswitch): - c.set_value(param.value) + param.value = value + for c in self.controllers: + if c.parameter is param: + c.set_value(value) + + def set_bypass(self, bypass: bool) -> None: + self.set_param_value(":bypass", 1.0 if bypass else 0.0) def to_json(self) -> str: return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) diff --git a/pistomp/controller.py b/pistomp/controller.py index 9061613a7..77ffd73a8 100755 --- a/pistomp/controller.py +++ b/pistomp/controller.py @@ -34,7 +34,7 @@ def __init__(self, midi_channel, midi_CC): def to_json(self): return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) - def set_value(self, bypass_value: float): + def set_value(self, value: float): logging.error("Controller subclass hasn't overriden the set_value method") diff --git a/pistomp/footswitch.py b/pistomp/footswitch.py index 6dfacfbed..9b3e53160 100755 --- a/pistomp/footswitch.py +++ b/pistomp/footswitch.py @@ -148,8 +148,18 @@ def drives_display(self) -> bool: param = self.parameter return param is None or param.symbol != Token.COLON_BYPASS - def set_value(self, bypass_value: float): - self.toggled = (bypass_value < 1) + def set_value(self, value: float): + param = self.parameter + if param is not None and param.symbol != Token.COLON_BYPASS: + # Non-:bypass binding: "on" is the max end (the value an on-press + # sends), so compare against the range midpoint. The bypass + # inversion below would light the LED for an OFF param. + lo = param.minimum if param.minimum is not None else 0 + hi = param.maximum if param.maximum is not None else 1 + self.toggled = value >= (lo + hi) / 2 + else: + # :bypass (or relay, param is None): engaged when not bypassed. + self.toggled = (value < 1) self._set_led(self.toggled) self.refresh_callback(footswitch=self) diff --git a/tests/test_footswitch.py b/tests/test_footswitch.py index c504d5085..0a21b0e23 100644 --- a/tests/test_footswitch.py +++ b/tests/test_footswitch.py @@ -125,6 +125,43 @@ def test_relay_toggle_on_longpress(self): relay.enable.assert_called_once() +class TestSetValue: + @staticmethod + def _param(symbol, value, minimum=0, maximum=1): + return MagicMock(symbol=symbol, value=value, minimum=minimum, maximum=maximum) + + def test_bypass_engaged_when_not_bypassed(self): + with _make_footswitch() as fs: + fs.parameter = self._param(":bypass", 0) + fs.set_value(0) # bypass off → effect active + assert fs.toggled is True + + def test_bypass_off_when_bypassed(self): + with _make_footswitch() as fs: + fs.parameter = self._param(":bypass", 1) + fs.set_value(1) # bypassed → effect inactive + assert fs.toggled is False + + def test_non_bypass_off_value_is_off(self): + # Regression: an OFF toggle param (value 0) must not light the switch. + with _make_footswitch() as fs: + fs.parameter = self._param("solo", 0) + fs.set_value(0) + assert fs.toggled is False + + def test_non_bypass_on_value_is_on(self): + with _make_footswitch() as fs: + fs.parameter = self._param("solo", 1) + fs.set_value(1) + assert fs.toggled is True + + def test_non_bypass_handles_missing_range(self): + with _make_footswitch() as fs: + fs.parameter = self._param("gain", 1, minimum=None, maximum=None) + fs.set_value(1) + assert fs.toggled is True + + class TestClearPedalboardInfo: def test_clears_state(self): with _make_footswitch() as fs: diff --git a/tests/v1/test_midi_learn.py b/tests/v1/test_midi_learn.py index a361de37c..6e3284d24 100644 --- a/tests/v1/test_midi_learn.py +++ b/tests/v1/test_midi_learn.py @@ -30,6 +30,35 @@ def test_v1_midi_learn_binds_footswitch_live(v1_system: SystemFixtureLegacy, mak snapshot("bound") +def test_v1_param_set_syncs_bound_footswitch(v1_system: SystemFixtureLegacy, make_plugin, make_parameter): + """A non-:bypass param_set syncs the footswitch bound to that param — its + toggled state mirrors mod-ui's value (no :bypass inversion).""" + handler = v1_system.handler + hw = v1_system.hw + ws_bridge = v1_system.ws_bridge + + assert handler.current + + binding, fs0 = next((k, v) for k, v in hw.controllers.items() if isinstance(v, Footswitch)) + channel, cc = binding.split(":") + + solo = make_parameter("Solo", "mixer", value=0.0) + plugin = make_plugin("mixer", bypassed=False, has_footswitch=False, + parameters={"solo": solo}) + handler.current.pedalboard.plugins = [plugin] + handler.update_lcd() + + ws_bridge.inject(f"midi_map /graph/mixer solo {channel} {cc} 0.0 1.0") + handler.poll_ws_messages() + assert fs0.parameter is solo + assert fs0.toggled is False # value 0.0 → off + + ws_bridge.inject("param_set /graph/mixer solo 1.0") + handler.poll_ws_messages() + assert solo.value == 1.0 + assert fs0.toggled is True # synced on + + def test_v1_midi_learn_replay_is_idempotent(v1_system: SystemFixtureLegacy, make_plugin): """A replayed midi_map matching the current binding is a no-op (no duplicate controllers).""" handler = v1_system.handler diff --git a/tests/v3/test_midi_learn.py b/tests/v3/test_midi_learn.py index 673474fe8..a21cad2e7 100644 --- a/tests/v3/test_midi_learn.py +++ b/tests/v3/test_midi_learn.py @@ -60,6 +60,36 @@ def test_v3_midi_learn_replay_is_idempotent(v3_system: SystemFixture, make_plugi assert plugin.controllers.count(fs0) == 1 +def test_v3_param_set_syncs_bound_footswitch(v3_system: SystemFixture, make_plugin, make_parameter): + """A non-:bypass param_set (e.g. connect-dump or external change) syncs the + footswitch bound to that param — its toggled state mirrors mod-ui's value.""" + handler = v3_system.handler + hw = v3_system.hw + ws_bridge = v3_system.ws_bridge + + assert handler.current + + fs0 = hw.footswitches[0] + channel, cc = _binding_for(hw, fs0).split(":") + + solo = make_parameter("Solo", "mixer", value=0.0) + plugin = make_plugin("mixer", bypassed=False, has_footswitch=False, + parameters={"solo": solo}) + handler.current.pedalboard.plugins = [plugin] + handler.lcd.link_data(handler.pedalboard_list, handler.current, hw.footswitches) + handler.lcd.draw_main_panel() + + ws_bridge.inject(f"midi_map /graph/mixer solo {channel} {cc} 0.0 1.0") + handler.poll_ws_messages() + assert fs0.parameter is solo + assert fs0.toggled is False # value 0.0 → off + + ws_bridge.inject("param_set /graph/mixer solo 1.0") + handler.poll_ws_messages() + assert solo.value == 1.0 + assert fs0.toggled is True # synced on → LED/keycap on + + def test_v3_midi_learn_unknown_instance_is_ignored(v3_system: SystemFixture, make_plugin): """A midi_map for an instance we don't have is a safe no-op.""" handler = v3_system.handler From ae824af5234ef4b6f3c6d46e2ea63a16b9082b73 Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sat, 13 Jun 2026 14:55:33 -0400 Subject: [PATCH 3/8] All footswitches now update optimistically --- GUIDE.md | 23 ++++++++++++++++------- pistomp/footswitch.py | 17 ++++------------- tests/v3/test_plugins.py | 11 +++++------ 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/GUIDE.md b/GUIDE.md index 342f91dbf..24ed50e89 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -342,9 +342,12 @@ never authoritatively sets its own copy. A persistent daemon-thread bridge (`poll_ws_messages`, ~10ms). `output_set` meter/scope spam is dropped at the bridge. Inbound (`parse_message` → typed messages → each handler's `_handle_ws_message`): -- `param_set …/:bypass v` — live bypass delta → set bypass + redraw. -- `param_set …/{sym} v` — control value → refresh cached `Parameter.value` (a later - edit opens at current); no live redraw. +- `param_set …/:bypass v` — live bypass delta → set bypass + redraw. Routed through + `Plugin.set_param_value`, which also reconciles any bound footswitch's indicators. +- `param_set …/{sym} v` — control value → `Plugin.set_param_value` refreshes the cached + `Parameter.value` (a later edit opens at current) and mirrors it onto any control + bound to that param: a footswitch redraws its LED/keycap; a knob/encoder updates its + cached position. Params bound to nothing do no work. - `add {inst} {uri} … {bypassed} …` — appears **only** in the (re)connect/load dump; bypass rides in field 4 — its sole arrival point on connect. Same bypass dispatch. - `loading_start` / `loading_end {snapshot}` — bracket a dump; `loading_end` stashes @@ -360,8 +363,11 @@ Outbound behaviour depends on the initiator: - **Footswitch press** → MIDI CC (absolute `toggled` intent) → mod-host processes internally → mod-host emits `param_set` feedback on port 5556 → `msg_callback` to - ALL clients (including us). Emit-only is correct here; the feedback echo drives the - LCD/LED update. + ALL clients (including us). piStomp updates its LED/LCD **optimistically on press** + from local intent; the feedback echo arrives later and reconciles if it differs. + Waiting for the echo would lag the switch whenever mod-host's feedback stream is + gated on a slow client — the `data_finish`/`output_data_ready` handshake stalls when + a mod-ui browser tab is backgrounded (see `../mod-ui/docs/output-data-flow.md`). - **Non-footswitch UI tap** → WS `send_parameter` → mod-ui calls `host.bypass()` → `msg_callback_broadcast` **skips the origin socket** (us), and mod-host does NOT generate `param_set` feedback for `bypass` commands it received from mod-ui. No echo @@ -457,6 +463,7 @@ changes (not for commands mod-ui itself issued). This determines who sees what: ``` Path A — Footswitch (MIDI CC): poll_controls() → Footswitch.pressed() + → flip toggled, _set_led(), refresh_callback() # optimistic local update → midiout.send_message([CC, midi_CC, 127/0]) # direct to ALSA → JACK → mod-host:midi_in # bypasses mod-ui WS entirely → mod-host applies change @@ -464,8 +471,10 @@ Path A — Footswitch (MIDI CC): → mod-ui process_read_message_body → msg_callback("param_set /graph/X :bypass V") # ALL clients, no skip → pi-stomp poll_ws_messages() receives it - → plugin.set_bypass() + lcd.refresh_plugins() - Emit-only is correct: pi-stomp waits for the feedback echo to update LCD/LED. + → plugin.set_bypass() + lcd.refresh_plugins() # reconciles + Optimistic update keeps the switch responsive even when the echo is delayed by + mod-host's data_finish/output_data_ready handshake (stalls on a backgrounded + mod-ui browser tab); the later echo is authoritative and corrects any divergence. Path B — Non-footswitch UI tap (LCD plugin widget click): toggle_plugin_bypass(widget, plugin) diff --git a/pistomp/footswitch.py b/pistomp/footswitch.py index 9b3e53160..6f9aa2b14 100755 --- a/pistomp/footswitch.py +++ b/pistomp/footswitch.py @@ -139,15 +139,6 @@ def set_midi_CC(self, midi_CC): def set_midi_channel(self, midi_channel): self.midi_channel = midi_channel - @property - def drives_display(self) -> bool: - """True unless an inbound WS echo will repaint this switch on press. - Only a plugin :bypass binding gets that echo (mod-host bypass feedback); - unbound switches and non-:bypass param bindings must update their own - indicators since their param_set echo carries no LCD redraw.""" - param = self.parameter - return param is None or param.symbol != Token.COLON_BYPASS - def set_value(self, value: float): param = self.parameter if param is not None and param.symbol != Token.COLON_BYPASS: @@ -267,11 +258,11 @@ def pressed(self, state): cc = [self.midi_channel | CONTROL_CHANGE, self.midi_CC, 127 if self.toggled else 0] logging.debug("Sending CC event: %d" % self.midi_CC) self.midiout.send_message(cc) - if self.drives_display: - self._set_led(self.toggled) + self._set_led(self.toggled) - if self.drives_display: - self.refresh_callback(footswitch=self) + # Update indicators optimistically + # (mod-host bypass feedback / param_set) reconciles if it ever differs + self.refresh_callback(footswitch=self) def set_display_label(self, label): self.display_label = label diff --git a/tests/v3/test_plugins.py b/tests/v3/test_plugins.py index 63dbb9b39..0847335ee 100644 --- a/tests/v3/test_plugins.py +++ b/tests/v3/test_plugins.py @@ -154,10 +154,10 @@ def test_v3_toggle_plugin_bypass_via_footswitch(v3_system: SystemFixture, make_p assert hw.footswitches[0].toggled is True -def test_v3_bound_footswitch_emits_absolute_values_without_display(v3_system: SystemFixture, make_plugin): +def test_v3_bound_footswitch_emits_absolute_values_and_updates_display(v3_system: SystemFixture, make_plugin): """A bound :bypass footswitch sends alternating absolute CC values from local - intent — so rapid presses that outrun the echo stay correct — and leaves its - indicators and parameter for the inbound echo to update.""" + intent — so rapid presses that outrun the echo stay correct — and updates its + indicators optimistically, while leaving the cached parameter for the echo.""" hw = v3_system.hw fs = hw.footswitches[0] fs.refresh_callback = MagicMock() @@ -165,7 +165,6 @@ def test_v3_bound_footswitch_emits_absolute_values_without_display(v3_system: Sy plugin = make_plugin("fuzz") fs.parameter = plugin.parameters[":bypass"] - assert not fs.drives_display bypass_before = fs.parameter.value for _ in range(3): @@ -173,8 +172,8 @@ def test_v3_bound_footswitch_emits_absolute_values_without_display(v3_system: Sy sent = [c.args[0][2] for c in fs.midiout.send_message.call_args_list] assert sent == [127, 0, 127] - fs.refresh_callback.assert_not_called() - assert fs.parameter.value == bypass_before + assert fs.refresh_callback.call_count == 3 # display updates on each press + assert fs.parameter.value == bypass_before # cached value still echo-authoritative def test_v3_preset_change_leans_on_ws_drain_not_rest(v3_system: SystemFixture, make_plugin, get_urls): From 5c425dc722da7dd772e57b4959a61f345beab1e3 Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sat, 13 Jun 2026 17:38:04 -0400 Subject: [PATCH 4/8] Sync unbound fs state immediately (in case we ever want it to start ON) --- pistomp/lcd320x240.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pistomp/lcd320x240.py b/pistomp/lcd320x240.py index ae9d898e7..223e75887 100644 --- a/pistomp/lcd320x240.py +++ b/pistomp/lcd320x240.py @@ -510,7 +510,7 @@ def draw_unbound_footswitches(self): y = 0 x = self.get_footswitch_pitch() * slot p = FootswitchWidget(Box.xywh(x, y, self.plugin_width, self.footswitch_height), self.small_font, - label, None, True, parent=self.footswitch_panel, object=fs) + label, None, not fs.toggled, parent=self.footswitch_panel, object=fs) self.w_footswitches.append(p) self.footswitch_panel.add_widget(p) self.footswitch_panel.refresh() From 3fac2edf83b89f9095b70faf559b16ab2da5bb3d Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sat, 13 Jun 2026 18:01:28 -0400 Subject: [PATCH 5/8] Remove optimistic updates; increase test coverage --- pistomp/footswitch.py | 9 +- .../toggled.png | Bin 0 -> 9349 bytes tests/test_footswitch.py | 119 +++++++++++++++++- tests/v3/test_plugins.py | 89 +++++++++++-- 4 files changed, 204 insertions(+), 13 deletions(-) create mode 100644 tests/snapshots/v3/test_plugins/test_v3_footswitch_states_snapshot/toggled.png diff --git a/pistomp/footswitch.py b/pistomp/footswitch.py index 6f9aa2b14..a1a77903c 100755 --- a/pistomp/footswitch.py +++ b/pistomp/footswitch.py @@ -259,10 +259,11 @@ def pressed(self, state): logging.debug("Sending CC event: %d" % self.midi_CC) self.midiout.send_message(cc) self._set_led(self.toggled) - - # Update indicators optimistically - # (mod-host bypass feedback / param_set) reconciles if it ever differs - self.refresh_callback(footswitch=self) + # LCD / plugin state is updated only when the echo arrives, so unbound + # footswitches (tap-tempo / relay / preset) still refresh immediately. + if self.parameter is None: + self.refresh_callback(footswitch=self) + return def set_display_label(self, label): self.display_label = label diff --git a/tests/snapshots/v3/test_plugins/test_v3_footswitch_states_snapshot/toggled.png b/tests/snapshots/v3/test_plugins/test_v3_footswitch_states_snapshot/toggled.png new file mode 100644 index 0000000000000000000000000000000000000000..4ec4998c9e835930bc6b5dd4e72ad6a682e50e51 GIT binary patch literal 9349 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 on (MIDI sent) + fs3.pressed(switchstate.Value.RELEASED) # unbound: off -> on (immediate) + + # Simulate mod-host echoing the bypass change for the bound footswitch. + ws_bridge.inject("param_set /graph/delay :bypass 0.0") + handler.poll_ws_messages() + snapshot("toggled") + + +# --------------------------------------------------------------------------- +# Instance ID normalization +# --------------------------------------------------------------------------- + + + def test_v3_websocket_bypass_event_with_multiword_id(v3_system): """WS parser correctly strips /graph/ prefix from multi-word instance IDs.""" handler = v3_system.handler From 5dab114da654fee5e2c8ef120e49742ce28b8d7a Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sat, 13 Jun 2026 18:19:34 -0400 Subject: [PATCH 6/8] Remove optimistic for bound paths --- GUIDE.md | 6 +++--- pistomp/controller.py | 5 ++++- pistomp/footswitch.py | 14 ++++++-------- tests/test_footswitch.py | 30 +++++++++++++----------------- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/GUIDE.md b/GUIDE.md index 24ed50e89..7ee8093fb 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -363,8 +363,8 @@ Outbound behaviour depends on the initiator: - **Footswitch press** → MIDI CC (absolute `toggled` intent) → mod-host processes internally → mod-host emits `param_set` feedback on port 5556 → `msg_callback` to - ALL clients (including us). piStomp updates its LED/LCD **optimistically on press** - from local intent; the feedback echo arrives later and reconciles if it differs. + ALL clients (including us). piStomp updates its **LED optimistically on press**; + the feedback echo drives the LCD/plugin state update and reconciles if it differs. Waiting for the echo would lag the switch whenever mod-host's feedback stream is gated on a slow client — the `data_finish`/`output_data_ready` handshake stalls when a mod-ui browser tab is backgrounded (see `../mod-ui/docs/output-data-flow.md`). @@ -463,7 +463,7 @@ changes (not for commands mod-ui itself issued). This determines who sees what: ``` Path A — Footswitch (MIDI CC): poll_controls() → Footswitch.pressed() - → flip toggled, _set_led(), refresh_callback() # optimistic local update + → flip toggled, _set_led() # LED-only optimistic update → midiout.send_message([CC, midi_CC, 127/0]) # direct to ALSA → JACK → mod-host:midi_in # bypasses mod-ui WS entirely → mod-host applies change diff --git a/pistomp/controller.py b/pistomp/controller.py index 77ffd73a8..f1b0c6505 100755 --- a/pistomp/controller.py +++ b/pistomp/controller.py @@ -16,6 +16,9 @@ from enum import Enum import json import logging +from typing import Optional + +from common.parameter import Parameter class Controller: @@ -25,7 +28,7 @@ def __init__(self, midi_channel, midi_CC): self.midi_CC = midi_CC self.minimum = None self.maximum = None - self.parameter = None + self.parameter: Optional[Parameter] = None self.hardware_name = None #self.type = None # this will conflict with encoder.type for EncoderMidiControl self.midi_min = 0 diff --git a/pistomp/footswitch.py b/pistomp/footswitch.py index a1a77903c..caa67e233 100755 --- a/pistomp/footswitch.py +++ b/pistomp/footswitch.py @@ -16,6 +16,7 @@ import logging import time import sys +from typing import Any, Callable from rtmidi.midiconstants import CONTROL_CHANGE import common.token as Token @@ -91,8 +92,8 @@ def __init__(self, id, led_pin, pixel, midi_CC, midi_channel, midiout, refresh_c self.display_label = None self.toggled = False self.led = None - self.midiout = midiout - self.refresh_callback = refresh_callback + self.midiout: Any = midiout + self.refresh_callback: Callable[..., Any] = refresh_callback self.relay_list = [] self.preset_callback = None self.preset_callback_arg = None @@ -211,11 +212,7 @@ def _log_longpress_events(self): info.timestamps.update({self.id: now}) def pressed(self, state): - # If a footswitch can be mapped to control a relay, preset, MIDI or all 3 - # - # The footswitch will only "toggle" if it's associated with a relay - # (in which case it will toggle with the relay) or with a Midi message - # + """Handle a footswitch press: route to relay, preset, or MIDI CC as configured.""" new_toggled = not self.toggled # First handle Longpress Events @@ -270,7 +267,7 @@ def set_display_label(self, label): def add_relay(self, relay): self.relay_list.append(relay) - self.set_value(not relay.init_state()) + self.set_value(0.0 if relay.init_state() else 1.0) def clear_relays(self): self.relay_list.clear() @@ -283,6 +280,7 @@ def clear_pedalboard_info(self): self.toggled = False self.disabled = False self.display_label = None + self.parameter = None self.set_category(None) self.preset_callback = None self.clear_relays() diff --git a/tests/test_footswitch.py b/tests/test_footswitch.py index 44567ce25..6900535bc 100644 --- a/tests/test_footswitch.py +++ b/tests/test_footswitch.py @@ -4,8 +4,10 @@ from contextlib import contextmanager import time +from typing import Optional, cast from unittest.mock import MagicMock, patch +from common.parameter import Parameter from pistomp.footswitch import Footswitch import pistomp.switchstate as switchstate @@ -32,7 +34,7 @@ def _make_footswitch(**kwargs): ) defaults.update(kwargs) fs = Footswitch(**defaults) - fs._set_led = MagicMock() + fs._set_led = MagicMock() # type: ignore[method-assign] yield fs Footswitch.callbacks = {} Footswitch.all_longpress_groups = {} @@ -131,7 +133,10 @@ def test_taptempo_short_press_does_not_toggle(self): taptempo.is_enabled.assert_called_once() assert fs.toggled is False fs.midiout.send_message.assert_not_called() + assert isinstance(fs.refresh_callback, MagicMock) fs.refresh_callback.assert_not_called() + assert isinstance(fs._set_led, MagicMock) + fs._set_led.assert_not_called() def test_unbound_footswitch_refresh_callback_on_press(self): """A footswitch with MIDI but no bound parameter still refreshes the LCD immediately.""" @@ -139,6 +144,7 @@ def test_unbound_footswitch_refresh_callback_on_press(self): fs.pressed(switchstate.Value.RELEASED) assert fs.toggled is True + assert isinstance(fs.refresh_callback, MagicMock) fs.refresh_callback.assert_called_once_with(footswitch=fs) def test_longpress_logs_timestamp(self): @@ -175,24 +181,11 @@ def test_relay_disable_on_second_longpress(self): fs.pressed(switchstate.Value.LONGPRESSED) relay.disable.assert_called_once() - def test_taptempo_short_press_does_not_toggle(self): - with _make_footswitch(midi_CC=42) as fs: - taptempo = MagicMock() - taptempo.is_enabled.return_value = True - fs.taptempo = taptempo - - fs.pressed(switchstate.Value.RELEASED) - - taptempo.is_enabled.assert_called_once() - assert fs.toggled is False - fs.midiout.send_message.assert_not_called() - fs.refresh_callback.assert_not_called() - class TestSetValue: @staticmethod - def _param(symbol, value, minimum=0, maximum=1): - return MagicMock(symbol=symbol, value=value, minimum=minimum, maximum=maximum) + def _param(symbol: str, value: float, minimum: Optional[int] = 0, maximum: Optional[int] = 1) -> Parameter: + return cast(Parameter, MagicMock(symbol=symbol, value=value, minimum=minimum, maximum=maximum)) def test_bypass_engaged_when_not_bypassed(self): with _make_footswitch() as fs: @@ -229,11 +222,12 @@ def test_set_value_drives_led_and_refresh(self): with _make_footswitch() as fs: fs.parameter = self._param(":bypass", 0) fs.set_value(0) + assert isinstance(fs._set_led, MagicMock) fs._set_led.assert_any_call(True) + assert isinstance(fs.refresh_callback, MagicMock) fs.refresh_callback.assert_called_once_with(footswitch=fs) - class TestLongpressEventPolling: def test_simultaneous_longpress_calls_group_callback(self): Footswitch.init({"toggle_bypass": MagicMock()}) @@ -281,6 +275,7 @@ def test_clears_state(self): fs.set_longpress_groups(["next_snapshot"]) fs.add_relay(MagicMock()) fs.add_preset(MagicMock()) + fs.parameter = MagicMock() # set last: add_relay needs parameter=None fs.clear_pedalboard_info() @@ -290,3 +285,4 @@ def test_clears_state(self): assert fs.category is None assert fs.preset_callback is None assert len(fs.relay_list) == 0 + assert fs.parameter is None From ab6767d00ebbdbae2bb0652bab7003c90e475ecf Mon Sep 17 00:00:00 2001 From: Cam Gorrie Date: Sat, 13 Jun 2026 20:34:23 -0400 Subject: [PATCH 7/8] Refresh all footswitches when one plugin is bound to multiple; fix non-bypass initial state --- pistomp/lcd320x240.py | 7 +- .../beths.png | Bin 0 -> 7889 bytes .../doom_bass.png | Bin 0 -> 8163 bytes tests/v3/test_plugins.py | 76 ++++++++++++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/beths.png create mode 100644 tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/doom_bass.png diff --git a/pistomp/lcd320x240.py b/pistomp/lcd320x240.py index 223e75887..0c6c23a40 100644 --- a/pistomp/lcd320x240.py +++ b/pistomp/lcd320x240.py @@ -483,22 +483,19 @@ def footswitch_label(self, footswitch): return self.shorten_name(param.instance_id, self.footswitch_width) def draw_footswitch(self, plugin): + color = self.get_plugin_color(plugin) for c in plugin.controllers: if isinstance(c, Footswitch): fs_id = c.id - #fss[fs_id] = None label = self.footswitch_label(c) c.set_display_label(label) - y = 0 x = self.get_footswitch_pitch() * fs_id self.footswitch_slots[fs_id] = label - color = self.get_plugin_color(plugin) p = FootswitchWidget(Box.xywh(x, y, self.plugin_width, self.footswitch_height), self.small_font, - label, color, plugin.is_bypassed(), parent=self.footswitch_panel, object=c) + label, color, not c.toggled, parent=self.footswitch_panel, object=c) self.w_footswitches.append(p) self.footswitch_panel.add_widget(p) - break def draw_unbound_footswitches(self): for fs in self.footswitches: diff --git a/tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/beths.png b/tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/beths.png new file mode 100644 index 0000000000000000000000000000000000000000..28f91d61e28b9445bf99815c16ec018bfd26c3a1 GIT binary patch literal 7889 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/doom_bass.png b/tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/doom_bass.png new file mode 100644 index 0000000000000000000000000000000000000000..48fe95f08cb20c5bf27450bffbccddca2547dc56 GIT binary patch literal 8163 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 Date: Thu, 18 Jun 2026 11:48:30 -0400 Subject: [PATCH 8/8] Fix plugins test --- .../bound.png | Bin 8427 -> 8601 bytes .../unbound.png | Bin 7838 -> 7465 bytes .../initial.png | Bin 0 -> 9817 bytes .../toggled.png | Bin 9349 -> 9958 bytes .../beths.png | Bin 7889 -> 8169 bytes .../doom_bass.png | Bin 8163 -> 8838 bytes tests/v3/test_plugins.py | 13 +++++++------ 7 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 tests/snapshots/v3/test_plugins/test_v3_footswitch_states_snapshot/initial.png diff --git a/tests/snapshots/v3/test_midi_learn/test_v3_midi_learn_binds_footswitch_live/bound.png b/tests/snapshots/v3/test_midi_learn/test_v3_midi_learn_binds_footswitch_live/bound.png index b8cf8f5a4501df2d4b2e9b58a91b8811db79be54..2ce42aacb440ce90de80d02815de903efa085179 100644 GIT binary patch literal 8601 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 HH1NLwNhJR0 literal 8427 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 literal 0 HcmV?d00001 diff --git a/tests/snapshots/v3/test_plugins/test_v3_footswitch_states_snapshot/toggled.png b/tests/snapshots/v3/test_plugins/test_v3_footswitch_states_snapshot/toggled.png index 4ec4998c9e835930bc6b5dd4e72ad6a682e50e51..b9f91a8ff3293181d61597fb0b70f50ec452be4e 100644 GIT binary patch literal 9958 zcmdUVLOX^O4_ul7x zIOiWY>jTePdp*oG=R4mR?-(;uMM)Y1l>`+6fndnWNW6zY;KacF2?{*;`>4z)1cA_1 z%1XRd_xg62`CK1wfMUSv9VR?nuoF$53U=WqU93r~XSHMmww2mgHj=e+EE=}{SFiv2 z2-W)A*xm`1&6at!msM)$mXbBR^_PR{3NbLiQ&6p=YRQO?Uvua+*-}wI=RbXVV8~us zSXfAV8fB|9*XN!V#E$Z~?pxXaF%`1kMMv(-kTdU|?E@{Mw2HhT%pc zQcL7dr7F-x_5EOv?l!);yYuz+O-W8ZyY)jGV&~&)dVIJeA|P1D>Cc_sH8C;qJcd

HcS5Hrf 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 literal 9349 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 literal 7889 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 diff --git a/tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/doom_bass.png b/tests/snapshots/v3/test_plugins/test_v3_pedalboard_switch_multi_fs_same_plugin_show_bound_off_color/doom_bass.png index 48fe95f08cb20c5bf27450bffbccddca2547dc56..37d5dbcb92b37b4d3ff8a8d39983c32bbc0ab947 100644 GIT binary patch literal 8838 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 SKdXj^>q>I3WGki3LjM;+!W`-V literal 8163 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