From dcdca87f702e75953fcf260f00138e96f6dce9a7 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 9 Jul 2025 15:40:34 -0500 Subject: [PATCH 1/4] add support for ASCII bell escape. Add fruit jam and bell examples --- adafruit_color_terminal.py | 42 +++++++++-- examples/beep.wav | Bin 0 -> 9644 bytes examples/beep.wav.license | 3 + examples/color_terminal_fruit_jam_belltest.py | 71 ++++++++++++++++++ examples/color_terminal_fruit_jam_test.py | 59 +++++++++++++++ ruff.toml | 3 + 6 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 examples/beep.wav create mode 100644 examples/beep.wav.license create mode 100644 examples/color_terminal_fruit_jam_belltest.py create mode 100644 examples/color_terminal_fruit_jam_test.py diff --git a/adafruit_color_terminal.py b/adafruit_color_terminal.py index 933f249..42701df 100644 --- a/adafruit_color_terminal.py +++ b/adafruit_color_terminal.py @@ -5,7 +5,8 @@ `adafruit_color_terminal` ================================================================================ -Extension of supports ANSI color escapes for subsets of text +Extension of supports ANSI color escapes for subsets of text and optionally the +ASCII bell escape code. * Author(s): Tim Cocks @@ -28,6 +29,7 @@ __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Color_Terminal.git" +from audiocore import WaveFile from displayio import Palette, TileGrid from terminalio import Terminal from tilepalettemapper import TilePaletteMapper @@ -63,9 +65,20 @@ class ColorTerminal: :param height: The height of the terminal in characters. :param custom_palette: A custom palette of colors to use instead of the default ones. Must contain at least 9 colors. + :param audio_interface: The audio interface to use for playing ASCII bell escape codes. + :param bell_audio_file: The wave audio file to use for the ASCII bell escape codes. + Defaults to beep.wav """ - def __init__(self, font, width, height, custom_palette=None): + def __init__( + self, + font, + width, + height, + custom_palette=None, + audio_interface=None, + bell_audio_file="/beep.wav", + ): if custom_palette is None: self.terminal_palette = Palette(9) self.terminal_palette[0] = 0x000000 @@ -99,8 +112,12 @@ def __init__(self, font, width, height, custom_palette=None): self.cur_color_mapping = [0, 1] - @staticmethod - def parse_ansi_colors(text): + self.audio_interface = audio_interface + if audio_interface is not None: + beep_wave_file = open(bell_audio_file, "rb") + self.beep_wave = WaveFile(beep_wave_file) + + def parse_ansi_colors(self, text): """ Parse ANSI color escape codes from a string. @@ -188,13 +205,22 @@ def write(self, s): :param s: The string to write. """ - clean_message, color_map = ColorTerminal.parse_ansi_colors(s) + clean_message, color_map = self.parse_ansi_colors(s) ordered_color_change_indexes = sorted(color_map.keys()) cur_change_index = 0 if not color_map: self.terminal.write(s) + if ( + "\x07" in s + and self.audio_interface is not None + and not self.audio_interface.playing + ): + print("playing beep") + self.audio_interface.play(self.beep_wave) + # while self.audio_interface.playing: + # pass return idx = 0 @@ -222,6 +248,12 @@ def write(self, s): self.apply_color(cur_slice) self.terminal.write(cur_slice) + if ( + "\x07" in cur_slice + and self.audio_interface is not None + and not self.audio_interface.playing + ): + self.audio_interface.play(self.beep_wave) # index after last can be in the color map if color code is last thing in string if idx in color_map: diff --git a/examples/beep.wav b/examples/beep.wav new file mode 100644 index 0000000000000000000000000000000000000000..bdee4e4c10927ca6dd997f19436e4e49effa3897 GIT binary patch literal 9644 zcmaJ`2Y3|K+CDSedrh(_o89ytI*1gNB2q+(bSWZL1tfxkf+9tcE>)z93Q{g8qEzW1 zo%E1oH*GiBB-?wP^Ph3<{2Tv!pMQCFnVI)|@ArQ1`OcZy&6uIDzWPH3025vrKX}f9 zC0Z!}07L&)^+yLQ0lx&Yx=t1x+?W5EI<-LFWpcsE)H`wv^s`LYT`Lhiy;m|%H_QUzdHJSPZ9#eG zxPrB*$K(t!-m*m(DtY56vvjv^7UJJ8pPFjO-`-i5KPL4X6#s$cvaWaOmZt+tZ|PQ| z_|@{xsXyh9>3ldpE%j4*7;dpN>pm(idAg$1tJ{w9&yllI=jBT~&&qeF%#Z`{gC$1) zTdC~Xl~S$#j3olc%8OGvRDT{wCE7!+bBhV^~O?f%*R$=cveu_~>z%*+_-%vKC z*iy@+)V8(83qnojdik$BPFT| zN8NFxZ-NZdmge*=c$nkUj6nJ>TIKblD(XrmRwUQoMDcxP<(geN;rvZG4>Vm-{%6*K z^UL^x}g3+#XF_XDpu4xtr+0RmTMAnKFycs zEYuKE2Ec5G>#@q8OL>*2>IF6o*rmfX`s^3-tFrrRTBQ-FvE8p9RM}iQw6dx`-NpcA zQmy7twl8mgwpjB_O2A&WVEu~9+_JTm+=hNA{;JfLJS+S6ylL4D$$y~u(YCCH%a!k! zU8{Vd;Y}2ORC+x*C;P*^lXFx!^=0yE zDF!~bebvyd%2L+1YFoob8-z=xGm?MFa^(J$H92{XlnHj(E;YPc)xCU4)s2RuHUOqb zyCyHqI-R>PD>Hel6vA^hL&Nc^kIK(h*&8k+eJ@G5$=$OSRc?Y_o@YF|Z4HKS=P z;y)#^B|XeAX5Y#%BpsDR;B0$l)0pc1m6NKwH@%PecS^1$eUot{dws_Fr1dENWBZh* z4b^KZcT~@AT8;RZNwz1A&6u7&GGkrRVido}zNYC>_4Ue<>K#q{>ay`lcZ@uT+h!F*iLy@i`J< z(%$rgSv%8-#8e3e>g-~}x|+|cw${WNEcOVDl~g6pOrMlBDg8+zAK`v`Kf|?}dsVk; zUN;aZJ|I4on3kT9m5}~@qE*ZUV#h*5poaGxuU%${ci^C2{8?g4T4iQ^+Tz4YF#}{f z_8WTD4t@So?J+|)2L}EUk4!v~_HE{ov_Xm2#26UhcxWi9-S~WEZHZx&BLaUFYZ4cw zy_q>TO_}(U7=Wn`pW)Zq2hT6nV#c`+2=|KZ30>0^nK@~ugpDYEi6hHssTEawYP%Re zNBk?rw-P+5B^m9hR}vP9Szx1MyfIrhy1Gy|%eceA0&k1=BwR?{mT@+9L&6lqf84Rg zI9s>9dZBKU@izwnM~LSoEKePiu{d>F!Yg73Z#vExf6zUvKCQcGe1i0K7xzx+mnzNZ zmf9sD3&qzs>Wq3_Oii<{&1i6-`-@nRfTuo652XJHY9s$;Y)bK+pN$gA3^ z9h|mBYf`Nch2U1Fre#B&u6A2pLCa1Q|E}ncYKj(18?F6QHATb%2c6?vuGgjM?$^y| zIpM^>Xwe>(T6;59q1~!_74iS+{JaI$y`y8-Z*2L?8HRmDb5xC*&r>TkZ>#c={!-`J zmOk}A=mytcXlZZ~P%G-KI;QE9dPq~CQi;OQ<*aV`q~54oRo~j;L;2Yvp=zEcl=8L) zs0bkec`lymLVbq*TD{Vwa6xDh>f#DC7g91c#c@qS08(7NP44>H`bhl%Q=SV0#lm0X zEXm7Lnv;*k{UyXeZ`V9iVZ$kX_l6~=fhhip@bkFy$=y>$KsVxHsei;Y8?J~p0j=Xwa}=l54G zPS}?;FQJFBosWT7Pi6aA1NJu<{3IQzhoZc0pKM6yy8-PMdEMq#}r2qKGQSP zJga$_VL|iz<^?GK4*r*l&*FC`E{k8T*nsd)Jlo9&o3|N`HXkvs@-V>1{K<-!_NH2uH@Qkvlaj(WthBYfH-g=oK_LfQ)yHd842jMpFW^13;X)Q0e z?ziqi@pE|-WG7=+sSd}El1<{_;F$M{b$RRlmQ}5PS%2|jU^p*d_FnAEs#&ob*+3M3 z!)vzw+S=H1snutFfa1IH2x&nqu1b$}Npq0CYHy;=(wc7awPx6iUIHfYilw%g8*wc$ zccfBOzsviYEw62sse9X-wg|#;-eKwan3Zv-V)jTqTpS2|AKBh(``%R4w#KIP0bt@T zmVO%ZLfnTjv!!)h05W_(+J0(lHl1$!#a7_Mz*Fu3Y5y2sY>$}U(%T5{?<=)6wPm%o zwbk2R_2J+gH%C7F)m5Bs*-OWQlO)wJ)mpFsHQ+!+$S@>~o{Ia)FV<-hE^Y?qlAwI!JE+VA=z zun#v+QmR-Kb6=4rDM0b1zBcj^m=oLtmWZYqPs; zn>o|rM)fhdrQ!(+vvRcJjyTN00NX#rao60l{gL@ihr|znm2*U#q&TTmDE5eroCwVD zFK`Gfi`u1@m5v-g13cp_6YJ#jmDTcD;%A&7?C(G1c*XKZ`%ud%#~?rY{=yj|J}l2w zekXrXd=ABr^FMKXW(l;fvFII>{TMjHQHkfsjfxp^zIY!e3>W#sj?0!8&DSg<=Z7f& z298OTCqJr4k=Kh>a2Q~sk+Vs3MwYHPD*H1;$XT>c`tlv8SMEU!1riqrw>g4aq-V}91 z@x}i0&NJ5jmUGrS&PqQH(l}j2J!FUFg|bXhJo2Z-Z*rQft1VWm+i6EQkHZiJq|@Y1 zsaJ?290XLZ6x&@(t}WFi2ms(ExHcFnM{t#fUoU8w;aRI+~( zej$A>TOr*gEMueRt-uo3UfT%k5!)(PUlf0X{gH5xbg!(hbb;_ZiXR?0;;ONIX*Jr8 zyCw$+c#J(%$d*o$K}mn%J~j?!1)jNL><_JKd#!5$;@`wh65f}nWH%*J;aWBUR|kTw z33je+s-5fp3gI8JErP9*66x2HdcnIWes`e2z12R#_N~3A`}+WdQ`uJp<0M<9uS?Dd z#-aFgfr;+N_N}&J`+WC>0D7KfZxN^@Bc)Qw8bNP1+K&QXxp|Hfo6xb>{S@(Mvu6sb z#8PRoc$^>w;SGUH?g0*^eT3tN+lutd*_{Q4#SbLkiqi#rR6h|gxK}&I+BZ0?Zf-CF zLo7@%Q@lYkS?uRqSpdWY6`nsGyXd=Zzo(oM3&zKOwp&J}O$sKZ4?C z1P^X;Fj7n1rWxo5j(xRZR{Lg@LMS;pNg_*l4B@Q{0x ziJm7y{e8RK$6fo}BYeX{0Q|x{!5txZQ8-X=kb4~QPYb>8D{;5DYTY0C=7l0~FLMP~ zEC>iVf+FrFChE7)L7&Kz=Z^6l_pJ<}`wR08ZYlpa!4v+=+>e+T*c5u?8|r!AJ;qbv z+k^P$FxA|>{35|Od}$h*ZKLG?43vp7HS7V!`8CUblY4DiF}{Y$+UJS)97{K_x^+Zo+C@AIEy_-S6#o_k?@A)oz zKlCjNEJOV37%SMzxM{q_+z;3*5xyb3H*nk+@}Bkm5ZHtpcu8R}T9>idPOJPqS&A-Bz=f{J$5dRAd7wZOR2KN%D znbnyAKv_5=IMsjCH`CuESdH|hFmAHG4nIG0#T6yFwpGq}$WeLwo&3i`tkau~Z= zLpVCl0M2?A#L@3%ku||`|6qTue@hU3U58eD9*f60#KAakv6>OCjhqe217G?R1DAq% z5dv1=y;+ahQ#rTUU0L^V9Q2IT2S*0}@{bFcgD*z_xPtRpJJ|7@uh|&uEW$@cgrO|~ zc3@XP6`B-bfWx?+IhI|`9>FeQ?nV3yA}@p<1%?EQ1FwcYjNsra{0vjY-pN+7k1$u^ z=vUszf)F0u91sLQ3T;CCAK;t5>}jtbri!cZ0B z&%~XKJk|zQ2Fu7$BmU+{M%WYF8H@xwhwTU#;ddBj=Ig8`<|PIL;TSPG+$~fV>>ZjB z<`4{E!}c*wF@>z3nd=!=ECLgVRpAdpF`;Fljp0-R^*gqJv4HuMIfpreQH&9=JMpjZ z$UjhTyuzrkg%#F+fW+CGu!bcL-VRL9#$Q?3<$D#P2FbTuM7|OIWFvcNt zdz(cFk;3XwK{zh*KFYrdYrrot*v#J;W%wG50X`-AMy7|8!*jz!BI^)dg#Ctp%J_@1 zl<^b(9)^Qm#QeyC@bvHx;iZv71cWoN&+tKvwTu@TALCFrYBvOfOk#{0{Bl!di5-VM~g5KC6>^!y`>xBITBJdqpMXV*}6JHap#2ko$oj{CD!!Xxkz;x7af!F;d;%mA;0 zbQE6$Z^JY29J~l0Llg2x1u{TqG%5!q0rd4Bc%cJYp$mFYZVdT>S^}}+=!kriXViHF zGX6e?e_taY6NHdk5#$IxjzY*!^eYjnocbhrz~5~2IRi!E|3*oKJn#6X##7nI+>{1d z6{U}4@A$_5=AhO8w=onGnT;Gpvr?K!wg1#Wjv}v8>S(ncE1-F(N=e55>l*DG?Ifib z2Vuwt0muPCS<w#vZ#>0QtN9LsGm1L$kqw`L66NOOx zq}mXA)2hj1N*&2ezv#~G*gGU^#}TAYRCb!5^1Y*aD&oIYO3xOViRxdHn;uWCGpaJm zg(yN*M^#2EqFAUopx7u@dKJ(&!* z+@w^Jl}BIE8YoVZH`)!9BheY8_ZnJfG$vXbH9Fdj)cnwOkh2`EiaLv`p^xaf?$|5Q z9h}|;sQ;t&km{%zqY&BwN=tN|k|^CNR1cHRP&H9bQ7%M%Adje>D0+?ZhFS|9=a5<_ zv~y7=ddEPI4}bT2bWM?CI(8g2Pf-U+y;1d)pB=~0S7`U5UQ@eZ$C_weWY5rUQSlx7 zl}4hf=#C>1x@TxKy64jD)GS2Ls0exojPCU02ud~SFEwlQ|1?55PL86xFS-*^eM07^ z)(`DH=}y!Yx|^teAg@z2=o8O|maYE^4Qt=9rG9s-&u+ z*A2Z>(eq4=q5O+FK%J9bQsc;IT5HD{r5x&bf21lPtDiN%Er=A<5J3Mtx zuQAd;@ Date: Wed, 9 Jul 2025 15:42:16 -0500 Subject: [PATCH 2/4] remove commented out code --- adafruit_color_terminal.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/adafruit_color_terminal.py b/adafruit_color_terminal.py index 42701df..04ba1a4 100644 --- a/adafruit_color_terminal.py +++ b/adafruit_color_terminal.py @@ -219,8 +219,6 @@ def write(self, s): ): print("playing beep") self.audio_interface.play(self.beep_wave) - # while self.audio_interface.playing: - # pass return idx = 0 From 48cc56aed52171de7a48401eee84d798880bee9b Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 9 Jul 2025 15:43:40 -0500 Subject: [PATCH 3/4] revert unintended staticmethod change --- adafruit_color_terminal.py | 5 +++-- ruff.toml | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_color_terminal.py b/adafruit_color_terminal.py index 04ba1a4..17c3113 100644 --- a/adafruit_color_terminal.py +++ b/adafruit_color_terminal.py @@ -117,7 +117,8 @@ def __init__( beep_wave_file = open(bell_audio_file, "rb") self.beep_wave = WaveFile(beep_wave_file) - def parse_ansi_colors(self, text): + @staticmethod + def parse_ansi_colors(text): """ Parse ANSI color escape codes from a string. @@ -205,7 +206,7 @@ def write(self, s): :param s: The string to write. """ - clean_message, color_map = self.parse_ansi_colors(s) + clean_message, color_map = ColorTerminal.parse_ansi_colors(s) ordered_color_change_indexes = sorted(color_map.keys()) cur_change_index = 0 diff --git a/ruff.toml b/ruff.toml index fd4288d..3c0f2b2 100644 --- a/ruff.toml +++ b/ruff.toml @@ -94,7 +94,6 @@ ignore = [ "PLW1514", # unspecified-encoding "PLR0913", # too many args "PLR0917", # too many positional args - "PLR6301", # method could be function ] From ffc1a996230f4b87d2326c25d209a415015cb8b3 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 9 Jul 2025 16:01:58 -0500 Subject: [PATCH 4/4] fix docs build --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index e38c932..ecd67bd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -autodoc_mock_imports = ["terminalio", "tilepalettemapper", "displayio"] +autodoc_mock_imports = ["terminalio", "tilepalettemapper", "displayio", "audiocore"] autodoc_preserve_defaults = True pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy