Auteur/autrice : sdgadmin

0 AD

a28.0-1 segfaults in pyrogenesis with js128 128.14.0-1


https://gitea.wildfiregames.com/0ad/0ad/issues/8752


~
 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
TIMER TOTALS (7 clients)
-----------------------------------------------------
  xml_validation: 1540.54 kc (9x)
  tc_ShaderValidation: 625.284 kc (1x)
  tc_pool_alloc: 0 c (0x)
  tc_transform: 2108.61 kc (6x)
  tc_plain_transform: 2060.88 kc (6x)
  tc_dds_transform: 26.632 kc (14x)
  tc_png_decode: 23.257 Mc (2x)
-----------------------------------------------------

~ 14s
 0SDL_AUDIODRIVER=pulseaudio 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
TIMER TOTALS (7 clients)
-----------------------------------------------------
  xml_validation: 1420.79 kc (9x)
  tc_ShaderValidation: 653.906 kc (1x)
  tc_pool_alloc: 0 c (0x)
  tc_transform: 554.658 kc (5x)
  tc_plain_transform: 523.006 kc (5x)
  tc_dds_transform: 20.756 kc (11x)
  tc_png_decode: 5142.13 kc (2x)
-----------------------------------------------------

~ 10s
 SDL_AUDIODRIVER=pipewire 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
TIMER TOTALS (7 clients)
-----------------------------------------------------
  xml_validation: 1254.57 kc (9x)
  tc_ShaderValidation: 586.846 kc (1x)
  tc_pool_alloc: 0 c (0x)
  tc_transform: 564.752 kc (6x)
  tc_plain_transform: 525.228 kc (6x)
  tc_dds_transform: 26.358 kc (14x)
  tc_png_decode: 4981.47 kc (2x)
-----------------------------------------------------

~ 6s
 SDL_AUDIODRIVER=pipewire 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
TIMER TOTALS (7 clients)
-----------------------------------------------------
  xml_validation: 1284.66 kc (9x)
  tc_ShaderValidation: 622.394 kc (1x)
  tc_pool_alloc: 0 c (0x)
  tc_transform: 564.422 kc (5x)
  tc_plain_transform: 534.696 kc (5x)
  tc_dds_transform: 20 kc (11x)
  tc_png_decode: 5186.83 kc (2x)
-----------------------------------------------------



~ 9s
 SDL_AUDIODRIVER=pipewire 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
FILES| JSON data written to '/home/stefan/.config/0ad/config/matchsettings.json'
FILES| Replay written to '/home/stefan/.local/share/0ad/replays/0.28.0/2026-02-22_0002'
GAME STARTED, ALL INIT COMPLETE
/usr/bin/0ad : ligne 9 : 15050 Erreur de segmentation     (core dumped)"$pyrogenesis" "$@"

~ 1m 12s
 coredumpctl info 0ad
No coredumps found.

~
 coredumpctl gdb 0ad
No match found.

~
 systemctl --user stop pipewire pipewire-pulse wireplumber
Job for wireplumber.service canceled.
Job for pipewire.service canceled.

~
 SDL_AUDIODRIVER=pipewire 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
FILES| JSON data written to '/home/stefan/.config/0ad/config/matchsettings.json'
FILES| Replay written to '/home/stefan/.local/share/0ad/replays/0.28.0/2026-02-22_0003'
GAME STARTED, ALL INIT COMPLETE
/usr/bin/0ad : ligne 9 : 21023 Erreur de segmentation     (core dumped)"$pyrogenesis" "$@"

~ 3m 49s
 LIBGL_ALWAYS_SOFTWARE=1 0ad
FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
Sound: AlcInit success, using OpenAL Soft
FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
WARNING: You are using 'llvmpipe (LLVM 21.1.6, 256 bits)' graphics driver, expect very poor performance!
WARNING: If possible install a proper graphics driver for your hardware.
FILES| JSON data written to '/home/stefan/.config/0ad/config/matchsettings.json'
FILES| Replay written to '/home/stefan/.local/share/0ad/replays/0.28.0/2026-02-22_0004'
GAME STARTED, ALL INIT COMPLETE
FILES| Replay metadata written to '/home/stefan/.local/share/0ad/replays/0.28.0/2026-02-22_0004/metadata.json'
TIMER TOTALS (7 clients)
-----------------------------------------------------
  xml_validation: 149.972 Mc (214x)
  tc_ShaderValidation: 636.988 kc (1x)
  tc_pool_alloc: 0 c (0x)
  tc_transform: 14.4247 Mc (689x)
  tc_plain_transform: 7546.28 kc (689x)
  tc_dds_transform: 5834.04 kc (1638x)
  tc_png_decode: 145.786 Mc (164x)
-----------------------------------------------------

~ 6m 51s
 glxinfo | grep "OpenGL renderer"
OpenGL renderer string: Mesa Intel(R) Arc(tm) Graphics (MTL)

~
 
~
 lsof | grep snd
pipewire   1224                 stefan  mem       CHR              116,2                 952 /dev/snd/pcmC0D0p
pipewire   1224                 stefan   50u      CHR             116,11        0t0      966 /dev/snd/controlC0
pipewire   1224                 stefan   59u      CHR              116,1        0t0      544 /dev/snd/seq
pipewire   1224                 stefan   60u      CHR              116,1        0t0      544 /dev/snd/seq
pipewire   1224                 stefan   81u      CHR              116,2        0t0      952 /dev/snd/pcmC0D0p
pipewire   1224  1237 module-rt stefan  mem       CHR              116,2                 952 /dev/snd/pcmC0D0p
pipewire   1224  1237 module-rt stefan   50u      CHR             116,11        0t0      966 /dev/snd/controlC0
pipewire   1224  1237 module-rt stefan   59u      CHR              116,1        0t0      544 /dev/snd/seq
pipewire   1224  1237 module-rt stefan   60u      CHR              116,1        0t0      544 /dev/snd/seq
pipewire   1224  1237 module-rt stefan   81u      CHR              116,2        0t0      952 /dev/snd/pcmC0D0p
pipewire   1224  1240 data-loop stefan  mem       CHR              116,2                 952 /dev/snd/pcmC0D0p
pipewire   1224  1240 data-loop stefan   50u      CHR             116,11        0t0      966 /dev/snd/controlC0
pipewire   1224  1240 data-loop stefan   59u      CHR              116,1        0t0      544 /dev/snd/seq
pipewire   1224  1240 data-loop stefan   60u      CHR              116,1        0t0      544 /dev/snd/seq
pipewire   1224  1240 data-loop stefan   81u      CHR              116,2        0t0      952 /dev/snd/pcmC0D0p
kded6      1437                 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1439 QDBusConn stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1442 WaylandEv stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1443 WaylandEv stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1444 kded6:dis stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1445 kded6:sh0 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1453 pool-spaw stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1454 gmain     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1455 gdbus     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1459 dconf\x20 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1544 threaded- stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1576 KIO::Work stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
kded6      1437  1577 KIO::Work stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462                 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1475 QDBusConn stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1481 WaylandEv stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1482 WaylandEv stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1486 plasmas:d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1487 plasmashe stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1601 QQmlThrea stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1713 QSGRender stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1714 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1715 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1716 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1717 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1718 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1719 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1721 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  1722 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2111 QThread   stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2112 threaded- stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2222 QSGRender stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2232 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2233 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2258 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  2261 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4044 QSGRender stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4045 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4046 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4047 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4048 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4134 calculato stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4135 helprunne stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4136 krunner_a stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4137 krunner_b stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4138 krunner_k stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4139 krunner_p stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4140 krunner_r stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4141 krunner_s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4142 krunner_s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4143 krunner_s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4144 krunner_w stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4145 locations stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4146 krunner_c stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4147 krunner_c stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4148 krunner_d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4149 krunner_k stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4150 krunner_k stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4151 krunner_s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4152 org.kde.d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4155 unitconve stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4156 krunner_s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4157 krunner_p stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4158 krunner_k stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4159 krunner_p stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4160 QNetworkA stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4161 pool-spaw stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4162 gmain     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4163 gdbus     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4610 QSGRender stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4611 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4612 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4613 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  4614 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  5784 QSGRender stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  5785 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  5786 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  5787 plasma:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462  5788 plasmash: stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462 11715 KIO::Work stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462 11716 KIO::Work stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462 11717 KIO::Work stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462 21080 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
plasmashe  1462 21081 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836                 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836  1855 QDBusConn stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836  1860 WaylandEv stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836  1861 WaylandEv stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836  1868 konsole:d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836  1869 konsole:s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21004 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21005 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21006 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21007 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21008 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21009 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21010 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
konsole    1836 21011 Thread    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744                 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10747 AsyncSi~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10751 pool-spaw stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10752 gmain     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10754 [pango]   stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10755 gdbus     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10756 WaylandPr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10757 dconf\x20 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10758 glean.dis stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10760 IPC\x20I/ stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10761 Timer     stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10762 Netlink   stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10763 Socket    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10764 IPDL\x20B stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10770 HTML5\x20 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10771 StyleThre stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10772 StyleThre stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10773 StyleThre stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10774 StyleThre stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10775 StyleThre stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10780 JS\x20Wat stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10782 Cache2    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10783 Cookie    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10785 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10786 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10787 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10788 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10789 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10790 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10791 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10792 TaskCon~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10802 QuotaMana stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10804 Worker    stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10805 firefox:d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10806 firefox:s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10808 Softwar~c stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10809 Renderer  stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10810 WRWorker# stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10811 WRWorker# stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10812 WRWorker# stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10813 WRWorker# stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10814 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10815 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10816 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10817 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10818 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10819 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10820 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10821 WRWorkerL stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10822 WrGlyph~t stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10823 Composito stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10824 CanvasRen stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10825 firefox:d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10826 firefox:s stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10827 firefo:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10828 firefox:g stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10829 ImageIO   stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10830 Permissio stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10831 IPC\x20La stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10833 gly-globa stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10834 async-io  stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10866 SandboxRe stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10897 BgIOThr~P stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10903 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10904 TRR\x20Ba stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10905 DNS\x20Re stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10946 GMPThread stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10948 ImageBrid stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10950 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10951 ProcessHa stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10961 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10970 AudioIP~v stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10971 AudioIP~a stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10972 AudioIP~i stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 10993 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11000 WRScene~i stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11001 WRScene~d stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11002 WRRende~c stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11244 sqldb:e~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11266 sqldb:p~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11267 sqldb:c~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11268 sqldb:p~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11280 DNS\x20Re stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11281 RemoteLzy stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11283 sqldb:p~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11284 URL\x20Cl stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11286 sqldb:d~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11287 DOM\x20Wo stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11288 MemoryPol stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11289 DOM\x20Wo stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11290 DNS\x20Re stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11292 LS\x20Thr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11302 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11331 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11333 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11369 glean.mps stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11376 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11412 sqldb:p~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11413 sqldb:f~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11423 sqldb:c~l stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11427 sqldb:p~i stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11434 DNS\x20Re stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11435 Backgro~P stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11437 DOM\x20Wo stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11443 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11497 FSBroker1 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11802 firefo:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 11803 firefox:g stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 18055 StreamTra stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 20110 firefo:tr stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 20111 firefox:g stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 21431 StreamTra stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
firefox   10744 21513 Indexed~  stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)
wireplumb 20432                 stefan   25u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432                 stefan   26u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432                 stefan   27u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20439 module-rt stefan   25u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20439 module-rt stefan   26u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20439 module-rt stefan   27u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20440 gmain     stefan   25u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20440 gmain     stefan   26u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20440 gmain     stefan   27u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20442 pool-spaw stefan   25u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20442 pool-spaw stefan   26u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20442 pool-spaw stefan   27u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20445 gdbus     stefan   25u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20445 gdbus     stefan   26u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20445 gdbus     stefan   27u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20446 data-loop stefan   25u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20446 data-loop stefan   26u      CHR             116,11        0t0      966 /dev/snd/controlC0
wireplumb 20432 20446 data-loop stefan   27u      CHR             116,11        0t0      966 /dev/snd/controlC0
pactl     20455                 stefan  mem       REG               0,29             2585258 /usr/lib/libsndfile.so.1.0.37 (path dev=0,31)

~
 
  ~ 9s
   SDL_AUDIODRIVER=pipewire 0ad
  FILES| Main log written to '/home/stefan/.local/state/0ad/log/mainlog.html'
  FILES| Interesting log written to '/home/stefan/.local/state/0ad/log/interestinglog.html'
  Sound: AlcInit success, using OpenAL Soft
  FILES| Hardware details written to '/home/stefan/.local/state/0ad/log/system_info.txt'
  FILES| UserReport written to '/home/stefan/.local/state/0ad/log/userreport_hwdetect.txt'
  FILES| JSON data written to '/home/stefan/.config/0ad/config/matchsettings.json'
  FILES| Replay written to '/home/stefan/.local/share/0ad/replays/0.28.0/2026-02-22_0002'
  GAME STARTED, ALL INIT COMPLETE
  /usr/bin/0ad : ligne 9 : 15050 Erreur de segmentation     (core dumped)"$pyrogenesis" "$@"

  ~ 1m 12s
   

Coupures audio sur Intel Meteor Lake sous Linux

Abstract

Les laptops Intel Meteor Lake (Lenovo Yoga Pro 9, Legion, etc.) souffrent d’instabilités audio sévères sous Linux avec la pile SOF + SoundWire + TAS2781. Après une analyse approfondie du stack (SOF, SoundWire, tas2781-hda, runtime PM, non-idempotence), la cause racine a été identifiée : l’initialisation du DSP du TAS2781 est non idempotente et dépend du chargement correct de son firmware.

Sur les distributions qui livrent le firmware en .zst (Arch Linux, CachyOS, Fedora Rawhide…), le driver tas2781-hda ne décompresse pas automatiquement le fichier → le DSP reste muet → son pourri (aigus seulement, pas de basses).

Solution définitive : forcer le mode HDA legacy (dsp_driver=1) + décompression permanente du firmware TAS2781. Stabilité 100 % dès le premier boot, même après mises à jour.


1. Introduction

Les plateformes Meteor Lake ont abandonné le vieux HDA au profit de SOF + SoundWire. Sur papier, c’est plus moderne, plus économe, plus puissant. En pratique, sous Linux, c’est souvent instable : coupures, son dégradé, besoin de plusieurs reboots, etc.

Cet article documente le problème sur un Lenovo Yoga Pro 9 16IMH9 et propose la solution qui marche à tous les coups.


2. Matériel et environnement

  • Machine : Lenovo Yoga Pro 9 16IMH9 (Meteor Lake-P)
  • Amplificateur : Texas Instruments TAS2781 (via SoundWire + I²C)
  • Kernel : 6.12.68-2-cachyos-lts (et toutes les versions récentes concernées)
  • Audio stack : ALSA + PipeWire
  • Distribution : CachyOS (mais le bug existe aussi sur Arch, Fedora, etc.)

3. Analyse du problème (résumé des observations initiales)

  • Le son devient aléatoirement dégradé (aigus seulement, basses mortes, distorsion).
  • Un simple reboot ne suffit pas toujours → parfois 2 ou 3 reboots consécutifs sont nécessaires.
  • Le mode SOF (dsp_driver=0) est instable.
  • Le mode HDA legacy (dsp_driver=1) est parfaitement stable dès le premier boot.
  • Le driver tas2781-hda se lie correctement (bound i2c-TIAS2781:00), mais le DSP du TAS2781 n’a parfois jamais reçu son firmware.

4. La cause racine sur Arch/CachyOS (découverte finale)

Sur CachyOS (et Arch), linux-firmware fournit les blobs TAS2781 compressés en .zst :

text

/lib/firmware/ti/audio/tas2781/TAS2XXX2326.bin.zst

Le driver snd_hda_scodec_tas2781_i2c demande exactement TAS2XXX2326.bin (sans .zst). Le firmware loader du noyau ne décompresse pas automatiquement ce fichier dans ce contexte précis → le DSP du TAS2781 reste sans configuration → son pourri.

C’est pourquoi le problème disparaissait parfois après plusieurs reboots (hasard du timing de décompression ou de re-probe).


5. Solution définitive (valable sur toutes les distros utilisant .zst)

5.1 Forcer le mode HDA legacy (stable à 100 %)

fish

sudo tee /etc/modprobe.d/disable-sof.conf <<EOF
options snd_intel_dspcfg dsp_driver=1
EOF
sudo reboot

5.2 Décompresser le firmware TAS2781 une bonne fois pour toutes

fish

sudo zstd -d /lib/firmware/ti/audio/tas2781/TAS2XXX2326.bin.zst \
          -o /lib/firmware/TAS2XXX2326.bin

5.3 Rendre le fix permanent (même après pacman -Syu linux-firmware)

fish

# Script
sudo tee /usr/local/bin/fix-tas2781-firmware.fish <<'EOF'
#!/usr/bin/fish
set FW_SRC /lib/firmware/ti/audio/tas2781/TAS2XXX2326.bin.zst
set FW_DST /lib/firmware/TAS2XXX2326.bin

if test -f $FW_SRC; and not test -f $FW_DST
    echo "Décompression TAS2781 firmware..."
    sudo zstd -d $FW_SRC -o $FW_DST
    echo "OK → $FW_DST créé"
else
    echo "Firmware déjà OK"
end
EOF

sudo chmod +x /usr/local/bin/fix-tas2781-firmware.fish

fish

# Service systemd
sudo tee /etc/systemd/system/tas2781-firmware.service <<EOF
[Unit]
Description=Décompresse TAS2781 firmware (.zst → .bin)
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/fix-tas2781-firmware.fish
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now tas2781-firmware.service

Après ça, même après une mise à jour du firmware, le son reste parfait au prochain boot.


6. Que faire pour quand même avoir SOF à jour ?

Le bug SOF/SoundWire/TAS2781 est toujours présent upstream (non-idempotence + gestion d’énergie). En attendant un vrai fix dans le noyau, le mode HDA legacy est la seule solution stable aujourd’hui.


Conclusion

Le problème n’était pas un bug de SOF en lui-même, mais une combinaison fatale :

  • initialisation non idempotente du TAS2781
  • firmware fourni en .zst sur Arch/CachyOS
  • driver qui ne décompresse pas

Avec le mode HDA + le service de décompression, le son est maintenant parfaitement stable sur mon Yoga Pro 9, même après des dizaines de reboots/suspensions/mises à jour.

Merci à tous ceux qui ont signalé le même problème. Le workaround est maintenant documenté et reproductible.


Arnold II

Arnold II

La page de notation des fichiers DSK est grande ouverte… et nos zamis les bots n’ont évidemment pas résisté à l’envie de venir mettre leurs petites notes partout 🤖⭐

Résultat : je vais devoir ajouter une vraie gestion des utilisateurs et réserver l’édition des fichiers DSK aux humains dûment habilités (oui, vous, pas les robots).

Bonne nouvelle : tout ça existe déjà pour le projet Save, donc cela devrait pas me prendre trop temps à l’implémenter , par contre ce qui en prendra c’est la prise en charge d’autres machines 8 bits genre , l’ennemi de toujours le C64.

Save

Le projet Save Videos est une application web inspiré des plugins yt-dlp et X_Media_download pour permettre aux utilisateurs de sauvegarder, organiser et visualiser des vidéos provenant de plateformes comme YouTube et X (anciennement Twitter). Conçue avec un accent sur la simplicité d’utilisation et la sécurité, cette plateforme répond aux besoins des individus souhaitant archiver du contenu multimédia de manière fiable et privée.
L’application intègre des fonctionnalités avancées tout en respectant les principes de confidentialité et de protection des données. Ce résumé présente les fonctionnalités principales, les mesures de sécurité implémentées, ainsi que les perspectives d’évolution futures.

Fonctionnalités Actuelles

L’application offre un ensemble de fonctionnalités essentielles pour une gestion efficace des vidéos :

  • Inscription et Connexion Sécurisées : Les utilisateurs peuvent créer un compte avec un nom d’utilisateur, un email et un mot de passe haché. Une vérification par code de confirmation envoyé par email est requise pour activer le compte, garantissant l’authenticité des adresses fournies.
  • Ajout et Édition de Vidéos : Possibilité d’ajouter des vidéos via URL (YouTube ou X) ou téléversement local (formats MP4, AVI, MKV). Les catégories multiples (séparées par virgules), commentaires et miniatures sont supportés. Une option permet de copier localement les vidéos pour éviter la censure.
  • Visualisation et Gestion : Une page dédiée affiche les vidéos en mode inline (iframe pour YouTube, tag video pour locales). Les utilisateurs peuvent éditer, supprimer ou rendre publiques leurs vidéos. Un système de catégories facilite la navigation.
  • Téléchargement Sécurisé : Les vidéos locales sont servies via un script dédié qui vérifie les permissions, empêchant les accès non autorisés.
  • Support Multimédia : Intégration de miniatures automatiques pour YouTube/X, et analyse antivirus (ClamAV) pour les uploads.
  • Vidéo publique , apparaît sur la home page , vidéo privé n’apparaît que sur la page de son utilisateur
  • Importation par playlist youtube
  • Importation de toutes les vidéos publiques d’un user youtube

Ces fonctionnalités sont accessibles via une interface responsive, stylisée avec Tailwind CSS, assurant une expérience utilisateur fluide sur tous les appareils.

Mesures de Sécurité Mises en Place

La sécurité est au cœur du projet, avec des implémentations robustes pour protéger les données et prévenir les attaques courantes :

  • Protection contre les Attaques CSRF : Tous les formulaires (inscription, connexion, ajout/édition de vidéos) incluent un jeton CSRF généré dynamiquement et validé côté serveur.
  • CAPTCHA Open Source : Utilisation de Securimage pour empêcher les inscriptions et connexions automatisées par bots, sans dépendance à des services externes comme Google.
  • Vérification par Email : Les nouveaux comptes nécessitent une confirmation via un code à 6 chiffres envoyé par email, avec expiration après une heure.
  • Contrôle d’Accès aux Fichiers : Les vidéos uploadées ne sont plus accessibles directement ; un script PHP vérifie l’authentification et les permissions avant de servir le contenu.
  • Analyse Antivirus : Tous les fichiers téléversés sont scannés avec ClamAV avant stockage.
  • Hachage des Mots de Passe : Utilisation de `password_hash` pour stocker les mots de passe de manière sécurisée.
  • Validation des Entrées : Filtrage strict des URLs, emails et fichiers pour prévenir les injections et les uploads malveillants.

Ces mesures alignent l’application sur les standards OWASP, réduisant significativement les risques d’exploitation.

Fonctionnalités Futures Envisagées

Pour étendre les capacités de l’application et renforcer sa robustesse, plusieurs améliorations sont prévues :

  • Améliorations Cryptographiques : Stockage des secrets (comme les mots de passe de base de données) via variables d’environnement, et enforcement de HTTPS pour les sessions.
  • Rate Limiting : Limitation des tentatives de connexion/inscription pour contrer les attaques par force brute.
  • Gestion Avancée des Uploads : Vérification du type MIME réel et quotas de stockage par utilisateur.
  • Fonctionnalités Utilisateur : Recherche avancée des vidéos, partage sécurisé, et intégration de notifications par email pour les mises à jour.
  • Mises à Jour Automatisées : Système de monitoring des dépendances pour détecter et patcher les vulnérabilités.
  • Headers de Sécurité HTTP : Ajout de CSP, HSTS et X-Frame-Options pour prévenir les attaques comme le clickjacking.
  • Amélioration du design
  • Ajout d’autres plateformes
  • Extension pour firefox : qui permettra de capturer l’URL d’une vidéo sur YouTube ou X et de l’envoyer directement à ce serveur

Ces évolutions viseront à maintenir l’application à jour face aux menaces émergentes, tout en améliorant l’expérience utilisateur.

Conclusion

Le projet Save Videos représente une solution pratique et sécurisée pour l’archivage de vidéos, avec un focus sur la confidentialité et la facilité d’utilisation. Grâce aux fonctionnalités actuelles et aux mesures de sécurité robustes, il offre une base solide pour les utilisateurs. Les développements futurs renforceront encore sa résilience, en faisant un outil indispensable pour la gestion multimédia.

Visit Save.sdg.ynh.fr

Plugin wordpress yt-dlp

Suivant la taille de la vidéo a télécharger , cela peut prendre plus ou moins , beaucoup de temps ,
Le serveur est pour l’instant un Raspberry 4 qui n’est pas une bête de course .

Veuillez ne pas fermer la page , ce qui interromprait le téléchargement de la vidéo.

Liste non exhaustive des sites internet compatibles :

1. Plateformes Générales de Vidéos (YouTube et Concurrents)

  • YouTube (y compris YouTube Music, YouTube Shorts, et canaux privés)
  • Vimeo
  • Dailymotion
  • Vevo
  • Rutube

2. Réseaux Sociaux et Partage de Vidéos Courts

  • TikTok
  • Instagram (Reels, IGTV, Stories)
  • Facebook (vidéos, Reels, Watch)
  • Twitter/X (vidéos et GIFs)
  • Reddit (vidéos intégrées)
  • Snapchat
  • Twitch (VOD et clips)

3. Plateformes de Streaming Professionnel et TV

  • Netflix (contenu accessible sans DRM)
  • Hulu
  • Disney+
  • Amazon Prime Video
  • BBC iPlayer
  • ARTE.tv
  • Canal+ (France)
  • TF1 (France)
  • France Télévisions (Pluzz, etc.)

4. Sites Éducatifs et Documentaires

  • TED
  • Khan Academy
  • Coursera
  • edX
  • Udemy

5. Plateformes de Musique et Audio

  • SoundCloud
  • Bandcamp
  • Mixcloud
  • Spotify (podcasts et playlists limités)
  • Deezer

6. Autres Catégories (Jeux, Actualités, Adultes, etc.)

  • Twitch (jeux en direct)
  • CNN, Fox News, et autres chaînes d’actualités
  • Pornhub, XVideos, etc. (catégorie adulte)
  • NicoNico (Japon)
  • Bilibili (Chine)
  • IQIYI (Chine)

Notes Importantes :

La compatibilité peut varier en fonction des mises à jour des sites

Fichiers récemment téléchargés (disponibles temporairement)

  • Aucun fichier récent disponible.

X_dwndl.py

x_downdl.py , script python permettant de télécharger des videos poster sur t sur X.com

Extrayant l’ID du post à partir d’une URL.
Récupérant un « guest token » pour accéder à l’API sans compte.
Analysant les données du post pour identifier les images et vidéos.
Téléchargeant les fichiers en qualité optimale (images en original, vidéos avec le bitrate le plus élevé).

Blackjack

compter les cartes

  • Blackjack : le but est d’avoir une main plus proche de 21 que le croupier sans dépasser 21.
  • Chaque carte a une valeur dans le comptage :
    • Cartes basses (2 à 6) = +1
    • Cartes neutres (7 à 9) = 0
    • Cartes hautes (10, figures, as) = -1

  • Si le reste du paquet est riche en cartes hautes (10, as), le joueur a plus de chances de faire blackjack et de gagner.
  • Si le reste est riche en cartes basses, le croupier a un avantage plus important.

L’astuce : augmenter les mises quand le paquet est favorable, et miser peu quand il ne l’est pas.


import random
import logging
import tkinter as tk
from tkinter import messagebox
from tkinter import ttk
from collections import deque
import os
import sys
import argparse

# -------------------------
# Import optionnels
# -------------------------
# PIL (images de cartes)
try:
    from PIL import Image, ImageTk
    PIL_AVAILABLE = True
except Exception:
    PIL_AVAILABLE = False

# Matplotlib (graphique)
try:
    import matplotlib.pyplot as plt
    MATPLOTLIB_AVAILABLE = True
except Exception:
    MATPLOTLIB_AVAILABLE = False

# -------------------------
# Configuration du logging
# -------------------------
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
logger = logging.getLogger('BlackjackTrainer')

# Mode debug détaillé (comportement et prints supplémentaires)
DEBUG_MODE = False

# -------------------------
# Constantes et utilitaires
# -------------------------
RANKS = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
SUITS = ['S','H','D','C']

# Valeur blackjack nominale (A peut être 11 ou 1 selon l'ajustement)
VALUE_MAP = { 'A':11, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'J':10, 'Q':10, 'K':10 }

# Hi-Lo count mapping
HI_LO_MAP = { '2':1, '3':1, '4':1, '5':1, '6':1,
              '7':0, '8':0, '9':0,
              '10':-1, 'J':-1, 'Q':-1, 'K':-1, 'A':-1 }

# Nom du dossier d'images
CARD_IMAGE_DIR = 'cards'
CARD_IMAGE_SIZE = (72, 96)  # taille d'affichage (largeur, hauteur)

# Nombre max de slots (réduit pour éviter clipping)
MAX_CARD_SLOTS = 6

# -------------------------
# Fonctions utilitaires
# -------------------------

def build_shoe(num_decks):
    """Construit une 'shoe' (paquet multiple) sous forme deque de tuples (rank, suit)."""
    shoe = []
    for _ in range(num_decks):
        for s in SUITS:
            for r in RANKS:
                shoe.append((r, s))
    random.shuffle(shoe)
    return deque(shoe)


def card_value(card):
    """Retourne la valeur du rang (A=11 par défaut, on ajustera après)."""
    r, _ = card
    return VALUE_MAP[r]


def card_str(card):
    """Représentation texte d'une carte (ex: 'A♠')."""
    r, s = card
    suit_symbol = {'S':'','H':'','D':'','C':''}[s]
    return f"{r}{suit_symbol}"


def hi_lo_value(card):
    """Valeur Hi-Lo d'une carte donnée (int)."""
    r, _ = card
    return HI_LO_MAP[r]

# -------------------------
# Conseiller basique (Basic Strategy simplifiée)
# -------------------------

def basic_strategy_advice(player_hand, dealer_upcard):
    """
    Fournit un conseil simple: 'Hit' ou 'Stand' (et 'Double' si applicable).
    C'est une version simplifiée pour l'entraînement.
    """
    total = sum(card_value(c) for c in player_hand)
    aces = sum(1 for c in player_hand if c[0] == 'A')
    soft = False
    if aces and total <= 21:
        soft = True
    dealer_rank = dealer_upcard[0]
    dealer_val = 10 if dealer_rank in ['10','J','Q','K'] else (11 if dealer_rank=='A' else int(dealer_rank))

    if soft:
        if total >= 19:
            return 'Stand'
        if total == 18:
            if dealer_val in [9,10,11]:
                return 'Hit'
            return 'Stand'
        return 'Hit'
    else:
        if total >= 17:
            return 'Stand'
        if total <= 11:
            return 'Hit'
        if 12 <= total <= 16:
            if 2 <= dealer_val <= 6:
                return 'Stand'
            else:
                return 'Hit'
    return 'Hit'

# -------------------------
# Classe principale GUI
# -------------------------
class BlackjackTrainerGUI:
    def __init__(self, master, num_decks=6, base_bet=10):
        self.master = master
        master.title('Blackjack Trainer - Hi-Lo')

        # Paramètres
        self.num_decks = num_decks
        self.base_bet = base_bet
        self.player_money = 1000
        self.min_bet = base_bet
        self.max_bet = 10000
        self.debug = DEBUG_MODE

        # Delais configurables (ms)
        self.dealer_draw_delay_ms = 700
        self.initial_dealer_start_delay_ms = 150
        self.end_round_delay_ms = 200
        self.player_end_delay_ms = 800  # pour afficher la carte du joueur avant résolution

        # Shoe et compte
        self.shoe = build_shoe(self.num_decks)
        self.running_count = 0
        self.hands_played = 0
        self.history_money = [self.player_money]
        self.history_count = [self.running_count]

        # Chargement images si possible
        self.card_images = {}
        if PIL_AVAILABLE:
            self._load_card_images()
        else:
            logger.info('Pillow non disponible: affichage texte des cartes')

        # Construire UI
        self._build_ui()

        # Forcer une taille minimale pour éviter clipping des slots
        try:
            self.master.minsize(480, 260)
        except Exception:
            pass

        # Démarrer la première main
        self.new_round()

    # -------------------------
    # Chargement images
    # -------------------------
    def _load_card_images(self):
        dir_path = CARD_IMAGE_DIR
        if not os.path.isdir(dir_path):
            logger.warning(f"Dossier d'images '{dir_path}' introuvable. Utilisation du texte.")
            return
        loaded = 0
        for r in RANKS:
            for s in SUITS:
                fname = f"{r}{s}.png"
                path = os.path.join(dir_path, fname)
                if os.path.isfile(path):
                    try:
                        im = Image.open(path).convert('RGBA')
                        im = im.resize(CARD_IMAGE_SIZE, Image.LANCZOS)
                        self.card_images[(r,s)] = ImageTk.PhotoImage(im)
                        loaded += 1
                    except Exception as e:
                        logger.warning(f"Erreur chargement image {path}: {e}")
                else:
                    if self.debug:
                        logger.debug(f"Image non trouvée: {path}")
        logger.info(f"Images chargées: {loaded} cartes")

    # -------------------------
    # UI Builder
    # -------------------------
    def _build_ui(self):
        # Top info
        top = ttk.Frame(self.master, padding=8)
        top.pack(fill='x')

        self.info_var = tk.StringVar()
        info_label = ttk.Label(top, textvariable=self.info_var, font=('Courier', 11))
        info_label.pack(side='left', padx=6)

        # Buttons
        btn_frame = ttk.Frame(self.master, padding=6)
        btn_frame.pack(fill='x')

        self.hit_btn = ttk.Button(btn_frame, text='Hit', command=self.hit)
        self.stand_btn = ttk.Button(btn_frame, text='Stand', command=self.stand)
        self.new_btn = ttk.Button(btn_frame, text='Nouvelle main', command=self.new_round)
        if MATPLOTLIB_AVAILABLE:
            self.graph_btn = ttk.Button(btn_frame, text='Graphiques', command=self.show_graph)
        else:
            # bouton désactivé si matplotlib absent
            self.graph_btn = ttk.Button(btn_frame, text='Graphiques (requires matplotlib)', state='disabled', command=self._graph_unavailable)
        self.debug_btn = ttk.Button(btn_frame, text='Toggle Debug', command=self.toggle_debug)

        for w in (self.hit_btn, self.stand_btn, self.new_btn, self.graph_btn, self.debug_btn):
            w.pack(side='left', padx=4)

        # Board frames
        board = ttk.Frame(self.master, padding=6)
        board.pack(fill='both', expand=True)

        dealer_frame = ttk.LabelFrame(board, text='Croupier')
        dealer_frame.pack(fill='x', pady=4)
        # ici on crée des slots fixes pour le croupier
        self.dealer_canvas = ttk.Frame(dealer_frame)
        self.dealer_canvas.pack(fill='x', padx=6, pady=6)
        self.dealer_slots = []
        for _ in range(MAX_CARD_SLOTS):
            lbl = tk.Label(self.dealer_canvas, text='', borderwidth=1, relief='solid',
                           width=8, height=4, padx=6, pady=6, bg='white', fg='black', anchor='center')
            lbl.pack(side='left', padx=3)
            self.dealer_slots.append(lbl)

        player_frame = ttk.LabelFrame(board, text='Joueur')
        player_frame.pack(fill='x', pady=4)
        self.player_canvas = ttk.Frame(player_frame)
        self.player_canvas.pack(fill='x', padx=6, pady=6)
        self.player_slots = []
        for _ in range(MAX_CARD_SLOTS):
            lbl = tk.Label(self.player_canvas, text='', borderwidth=1, relief='solid',
                           width=8, height=4, padx=6, pady=6, bg='white', fg='black', anchor='center')
            lbl.pack(side='left', padx=3)
            self.player_slots.append(lbl)

        # Advice
        advice_frame = ttk.Frame(self.master, padding=6)
        advice_frame.pack(fill='x')
        self.advice_var = tk.StringVar()
        advice_label = ttk.Label(advice_frame, textvariable=self.advice_var, font=('Arial', 11, 'italic'))
        advice_label.pack(side='left')

        # Bet control
        bet_frame = ttk.Frame(self.master, padding=6)
        bet_frame.pack(fill='x')
        ttk.Label(bet_frame, text='Mise:').pack(side='left')
        self.bet_var = tk.IntVar(value=self.base_bet)
        self.bet_spin = ttk.Spinbox(bet_frame, from_=self.min_bet, to=self.max_bet, textvariable=self.bet_var, width=8)
        self.bet_spin.pack(side='left', padx=6)

    # -------------------------
    # Mécanique de jeu
    # -------------------------
    def _draw_from_shoe(self):
        """Tire une carte et gère le reshuffle quand la shoe est entamée."""
        # Remélanger si il reste moins de 25% de la shoe (paramètre configurable)
        if len(self.shoe) < int(0.25 * 52 * self.num_decks):
            logger.info('Reshuffle: pas assez de cartes, reshuffle')
            self.shoe = build_shoe(self.num_decks)
            self.running_count = 0
        card = self.shoe.popleft()
        # Mettre à jour running count
        self.running_count += hi_lo_value(card)
        if self.debug:
            logger.debug(f'Draw card: {card_str(card)} | hi-lo {hi_lo_value(card)} | running_count {self.running_count}')
        self.history_count.append(self.running_count)
        return card

    def _update_info(self):
        """Met à jour la barre d'information en haut (argent, compte, true count, total joueur)."""
        player_total = self._hand_value(self.player_hand) if hasattr(self, 'player_hand') else 0
        true_count = self._true_count()
        suggested_bet = self._suggest_bet()
        info_text = (f"Argent: {self.player_money}    "
                     f"Compte (running): {self.running_count}    "
                     f"True Count: {true_count:.2f}    "
                     f"Mise suggérée: {suggested_bet}    "
                     f"Main joueur: {player_total}")
        self.info_var.set(info_text)

    def _update_advice(self):
        """Met à jour le conseil de base affiché."""
        if hasattr(self, 'player_hand') and hasattr(self, 'dealer_hand') and len(self.dealer_hand) > 0:
            advice = basic_strategy_advice(self.player_hand, self.dealer_hand[0])
            self.advice_var.set(f"Conseil (basic): {advice}")
        else:
            self.advice_var.set("")

    def new_round(self):
        """Commence une nouvelle main: distribue deux cartes au joueur et au croupier."""
        # Réactiver contrôles (garantie)
        self._enable_controls()

        if self.player_money <= 0:
            messagebox.showwarning('Fin', "Vous n'avez plus d'argent. Fin de la session.")
            return

        # Distribution
        self.player_hand = [self._draw_from_shoe(), self._draw_from_shoe()]
        self.dealer_hand = [self._draw_from_shoe(), self._draw_from_shoe()]
        # récupérer la mise **courante** choisie par l'utilisateur
        self.current_bet = int(self.bet_var.get())
        self.hands_played += 1

        if self.debug:
            logger.debug(f'New round: player {self.player_hand}, dealer {self.dealer_hand}, bet {self.current_bet}')
            logger.debug(f'Dealer hand ranks: {[c[0] for c in self.dealer_hand]}')

        # Afficher la main du croupier avec la seconde carte cachée (placeholder)
        self._render_cards(hide_dealer_second=True)
        # Forcer le rendu immédiat de l'UI
        try:
            self.master.update_idletasks()
        except Exception:
            pass

        self._update_info()
        self._update_advice()

    def _render_cards(self, hide_dealer_second=False):
        """Met à jour les slots existants au lieu de recréer des widgets."""
        # Dealer
        for i in range(MAX_CARD_SLOTS):
            lbl = self.dealer_slots[i]
            if i < len(self.dealer_hand):
                # cas de la seconde carte cachée
                if i == 1 and hide_dealer_second:
                    lbl.config(text='[??]', image='', borderwidth=1, relief='solid', bg='white', fg='black')
                    lbl.image = None
                else:
                    card = self.dealer_hand[i]
                    if card in self.card_images:
                        lbl.config(image=self.card_images[card], text='', borderwidth=0, relief='flat', bg='white')
                        lbl.image = self.card_images[card]
                    else:
                        lbl.config(text=card_str(card), image='', borderwidth=1, relief='solid', bg='white', fg='black')
                        lbl.image = None
            else:
                # slot vide
                lbl.config(text='', image='', borderwidth=0, relief='flat', bg='white')
                lbl.image = None

        # Player
        for i in range(MAX_CARD_SLOTS):
            lbl = self.player_slots[i]
            if i < len(self.player_hand):
                card = self.player_hand[i]
                if card in self.card_images:
                    lbl.config(image=self.card_images[card], text='', borderwidth=0, relief='flat', bg='white')
                    lbl.image = self.card_images[card]
                else:
                    lbl.config(text=card_str(card), image='', borderwidth=1, relief='solid', bg='white', fg='black')
                    lbl.image = None
            else:
                lbl.config(text='', image='', borderwidth=0, relief='flat', bg='white')
                lbl.image = None

        # Debug: log what est affiché dans les slots
        if self.debug:
            try:
                dealer_texts = [self.dealer_slots[i].cget('text') for i in range(min(MAX_CARD_SLOTS, max(1, len(self.dealer_hand)+1)))]
                logger.debug(f"Rendering dealer slots (texts): {dealer_texts}")
            except Exception:
                pass

        # Forcer rafraîchissement UI
        try:
            self.master.update_idletasks()
        except Exception:
            pass

    def hit(self):
        """Le joueur tire une carte."""
        if not self._controls_enabled():
            return

        self.player_hand.append(self._draw_from_shoe())
        if self.debug:
            logger.debug(f'Player hits, hand now: {[card_str(c) for c in self.player_hand]}')
        total = self._hand_value(self.player_hand)

        # Toujours afficher la main complète
        self._render_cards(hide_dealer_second=True)
        self._update_info()
        self._update_advice()

        # Si la main est finie (21 ou bust), attendre un petit délai avant de résoudre pour que l'utilisateur voie la carte
        if total >= 21:
            self._disable_controls()
            self.master.after(self.player_end_delay_ms, self.resolve_round)

    def stand(self):
        """Le joueur reste: croupier joue selon règle (stand sur soft 17)."""
        self._render_cards(hide_dealer_second=False)
        self._update_info()
        self._disable_controls()
        self.master.after(self.initial_dealer_start_delay_ms, self._dealer_play)

    def _dealer_play(self):
        if self._hand_value(self.dealer_hand) < 17:
            self.dealer_hand.append(self._draw_from_shoe())
            if self.debug:
                logger.debug(f'Dealer draws: {card_str(self.dealer_hand[-1])}')
            self._render_cards(hide_dealer_second=False)
            self._update_info()
            self.master.after(self.dealer_draw_delay_ms, self._dealer_play)
        else:
            self.master.after(self.end_round_delay_ms, self._end_dealer_and_resolve)

    def _end_dealer_and_resolve(self):
        self._enable_controls()
        self.resolve_round()

    def resolve_round(self):
        player_total = self._hand_value(self.player_hand)
        dealer_total = self._hand_value(self.dealer_hand)
        bet = self.current_bet

        player_blackjack = (len(self.player_hand) == 2 and player_total == 21)
        dealer_blackjack = (len(self.dealer_hand) == 2 and dealer_total == 21)

        if player_blackjack and not dealer_blackjack:
            payout = int(1.5 * bet)
            self.player_money += payout
            result_text = f'Blackjack! Vous gagnez {payout}.'
        elif dealer_blackjack and not player_blackjack:
            self.player_money -= bet
            result_text = 'Le croupier a Blackjack. Vous perdez.'
        else:
            if player_total > 21:
                self.player_money -= bet
                result_text = 'Bust! Vous perdez.'
            elif dealer_total > 21 or player_total > dealer_total:
                self.player_money += bet
                result_text = 'Vous gagnez.'
            elif player_total == dealer_total:
                result_text = 'Push (égalité).'
            else:
                self.player_money -= bet
                result_text = 'Vous perdez.'

        self.history_money.append(self.player_money)

        message = (f"{result_text}\nArgent restant: {self.player_money}\n"
                   f"Compte running: {self.running_count} | True Count: {self._true_count():.2f}")
        messagebox.showinfo('Résultat', message)

        self.new_round()

    # -------------------------
    # Calculs & stratégies
    # -------------------------
    def _hand_value(self, hand):
        total = sum(card_value(c) for c in hand)
        aces = sum(1 for c in hand if c[0] == 'A')
        while total > 21 and aces:
            total -= 10
            aces -= 1
        return total

    def _true_count(self):
        decks_rem = max(1.0, len(self.shoe) / 52.0)
        return self.running_count / decks_rem

    def _suggest_bet(self):
        """Retourne la mise recommandée sans modifier la Spinbox de l'utilisateur."""
        tc = self._true_count()
        if tc <= 1:
            bet = self.base_bet
        else:
            level = int(tc)
            bet = min(self.player_money, self.base_bet * level)
        return bet

    # -------------------------
    # Contrôles utilitaires
    # -------------------------
    def _disable_controls(self):
        for w in (self.hit_btn, self.stand_btn, self.new_btn, self.graph_btn, self.debug_btn):
            try:
                w.state(['disabled'])
            except Exception:
                try:
                    w.config(state='disabled')
                except Exception:
                    pass
        try:
            self.bet_spin.config(state='disabled')
        except Exception:
            pass

    def _enable_controls(self):
        for w in (self.hit_btn, self.stand_btn, self.new_btn, self.graph_btn, self.debug_btn):
            try:
                w.state(['!disabled'])
            except Exception:
                try:
                    w.config(state='normal')
                except Exception:
                    pass
        try:
            self.bet_spin.config(state='normal')
        except Exception:
            pass

    def _controls_enabled(self):
        try:
            return 'disabled' not in self.hit_btn.state()
        except Exception:
            try:
                return self.hit_btn['state'] != 'disabled'
            except Exception:
                return True

    # -------------------------
    # Graphiques & utilitaires
    # -------------------------
    def show_graph(self):
        if not MATPLOTLIB_AVAILABLE:
            messagebox.showwarning('Graphiques indisponibles', 'matplotlib n\'est pas installé dans cet environnement.')
            return
        fig, ax1 = plt.subplots(figsize=(10,5))
        ax1.plot(self.history_money, label='Argent du joueur')
        ax1.set_xlabel('Mains jouées')
        ax1.set_ylabel('Argent')
        ax1.legend(loc='upper left')

        ax2 = ax1.twinx()
        ax2.plot(self.history_count, label='Running Count', linestyle='--')
        ax2.set_ylabel('Running Count')
        ax2.legend(loc='upper right')
        plt.title('Historique: Argent et Running Count')
        plt.grid(True)
        plt.show()

    def _graph_unavailable(self):
        messagebox.showinfo('Graphiques désactivés', 'La fonctionnalité de graphiques nécessite matplotlib.\nInstallez-le via "pip install matplotlib" si vous voulez activer cette fonction.')

    def toggle_debug(self):
        self.debug = not self.debug
        logger.setLevel(logging.DEBUG if self.debug else logging.INFO)
        logger.info(f'Debug mode set to {self.debug}')

# -------------------------
# Tests unitaires (non-GUI)
# -------------------------
def run_unit_tests():
    print('Running unit tests...')
    shoe = build_shoe(2)
    assert len(shoe) == 52 * 2, 'build_shoe: taille incorrecte'
    assert card_value(('A','S')) == 11
    assert card_value(('K','H')) == 10
    assert hi_lo_value(('2','C')) == 1
    assert hi_lo_value(('A','D')) == -1
    advice = basic_strategy_advice([('Q','H'),('4','D')], ('6','S'))
    assert advice == 'Stand', f'Expected Stand, got {advice}'
    advice2 = basic_strategy_advice([('A','H'),('6','D')], ('10','S'))
    assert advice2 == 'Hit', f'Expected Hit, got {advice2}'
    advice3 = basic_strategy_advice([('10','H'),('9','D')], ('7','C'))
    assert advice3 == 'Stand', f'Expected Stand, got {advice3}'
    print('All non-GUI tests passed.')

# -------------------------
# Main
# -------------------------
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Blackjack Trainer GUI')
    parser.add_argument('--test', action='store_true', help='Run non-GUI unit tests and exit')
    args = parser.parse_args()

    if args.test:
        run_unit_tests()
        sys.exit(0)

    try:
        root = tk.Tk()
    except Exception as e:
        print('Impossible de démarrer l\'interface graphique:', e)
        sys.exit(1)

    gui = BlackjackTrainerGUI(root, num_decks=6, base_bet=10)
    root.mainloop()

Thème : Superposition par Kaira. CopyLerft 2025