Bonjour Nal,
Entrons tout de suite dans le vif du sujet : j'ai Ă©crit un Taptempo en Zig.
Il ne gÚre aucun argument, n'a aucune fonctionnalité marrante, mais il fonctionne.
Il suffit d'appuyer sur une touche pour l'activer, puis d'appuyer en cadence jusqu'Ă cinq fois. On peut arrĂȘter l'enregistrement en appuyant sur la touche q, qui permet aussi de quitter le programme.
Le voici donc ci-dessous :
// taptempo.zig
//
//! Copyright 2023 alberic89 <alberic89@gmx.com>
//!
//! This program is free software; you can redistribute it and/or modify
//! it under the terms of the GNU General Public License as published by
//! the Free Software Foundation; either version 3 of the License, or
//! (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program. If not, see <https://www.gnu.org/licenses/>.âŻ
//!
//! Compilé avec succÚs avec zig 0.11.0-dev.4406+d370005d3 (2 août 2023)
//! Retouvez le code source Ă <https://github.com/alberic89/taptempo-zig>
//
// Pour compiler :
// ```bash
// zig build-exe taptempo.zig
// ```
// Sur une idée de François Mazen
// https://linuxfr.org/users/mzf/journaux/un-tap-tempo-en-ligne-de-commande
//
// Merci Ă Leon Henrik Plickat pour son exemple d'application zig "Uncooked"
// https://zig.news/lhp/want-to-create-a-tui-application-the-basics-of-uncooked-terminal-io-17gm
//
const std = @import("std");
const stdout = std.io.getStdOut().writer();
const fs = std.fs;
const os = std.os;
const time = std.time;
/// Cette fonction va capturer et calculer le tempo de la frappe au clavier.
/// Peut retourner une erreur.
pub fn captureTempo(tty: fs.File) !void {
// On enregistre 5 frappes
var tap: [5]?i64 = [5]?i64{null, null, null, null, null};
try stdout.print("Capture du tempo", .{});
for (tap, 0..) |_, index| {
var buffer: [1]u8 = undefined;
_ = try tty.read(&buffer);
// Si la touche q est pressĂ©e, on arrĂȘte d'enregistrer la frappe
if (buffer[0] == 'q') {
break;
} else {
// La précision d'enregistrement est *au maximum* de l'ordre
// de la milliseconde, mais peut ĂȘtre plus faible en fonction
// du matériel et de l'OS
tap[index] = time.milliTimestamp();
try stdout.print(".", .{});
}
}
try stdout.print(" Terminé.\n", .{});
var ecart: [4]?i64 = [4]?i64{null, null, null, null};
// On calcule l'Ă©cart entre les frappes, en prĂ©voyant le cas oĂč il
// n'y a pas eu 5 frappes
for (tap[1..], 0..) |ftime, index| {
if (ftime != null) {
ecart[index] = ftime.? - tap[index].?;
}
}
var ecart_moy: ?f64 = null;
// On calcule l'Ă©cart moyen
for (ecart) |inter| {
if (inter != null) {
if (ecart_moy != null) {
var inter_f: f64 = @floatFromInt(inter.?);
ecart_moy = ( ecart_moy.? + inter_f ) / 2;
} else {
ecart_moy = @floatFromInt(inter.?);
}
}
}
// Si il y a eu moins de 2 frappes, on ne peut pas calculer le tempo
if (ecart_moy == null) {
try stdout.print("Tu n'as pas le rythme dans la peau !\n", .{});
return;
}
// Le tempo est donné avec un entier en battements par minute
var bpm: u64 = @intFromFloat((60 * time.ms_per_s) / ecart_moy.?);
try stdout.print("Tempo : {} bpm\n", .{bpm});
return;
}
pub fn main() !void {
// On récupÚre la sortie standart
var tty = try fs.cwd().openFile("/dev/tty", .{ .mode = .read_write });
defer tty.close();
// On enregistre l'Ă©tat du terminal
const original = try os.tcgetattr(tty.handle);
var raw = original;
// On active un certain nombre de paramĂštres :
// ECHO: Le terminal n'affiche plus les touches pressées.
// ICANON: Désactive le mode d'entrée canonique ("cooked").
// Permet de lire l'entrée byte-par-byte au lieu de
// ligne-par-ligne.
raw.lflag &= ~@as(
os.linux.tcflag_t,
os.linux.ECHO | os.linux.ICANON,
);
// BRKINT: DĂ©sactive la conversion de l'envoi de SIGNINT en cas de crash.
// N'as normalement pas d'effet sur les systĂšmes modernes.
// INPCK: Désactive le contrÎle de la parité.
// N'as normalement pas d'effet sur les systĂšmes modernes.
// ISTRIP: DĂ©sactive la suppression du 8Ăšme bit des caractĂšres.
// N'as normalement pas d'effet sur les systĂšmes modernes.
raw.iflag &= ~@as(
os.linux.tcflag_t,
os.linux.BRKINT | os.linux.INPCK | os.linux.ISTRIP,
);
// On met la taille des caractĂšres Ă 8 bits.
// N'as normalement pas d'effet sur les systĂšmes modernes.
raw.cflag |= os.system.CS8;
raw.cc[os.system.V.TIME] = 0;
raw.cc[os.system.V.MIN] = 1;
// Applique les changements
try os.tcsetattr(tty.handle, .FLUSH, raw);
try stdout.print(
"Bienvenue dans Taptempo !\nPour commencer, appuyez sur une touche.\n(q pour arrĂȘter)\n",
.{});
while (true) {
var buffer: [1]u8 = undefined;
_ = try tty.read(&buffer);
if (buffer[0] == 'q') {
break;
} else {
try captureTempo(tty);
}
}
try stdout.print("Au revoir !\n", .{});
// Restaure l'Ă©tat original du terminal
try os.tcsetattr(tty.handle, .FLUSH, original);
return;
}
Pour ceux que le cÎté technique intéresse, voici quelques détails :
- certaines fonctionnalités du terminal sont désactivées pour pouvoir intercepter correctement la frappe au clavier,
- la précision est de l'ordre de la milliseconde, mais le résultat affiché est le produit d'une conversion un peu bourine des bpm en un entier,
- il n'y a aucune dépendance externe mis à part la bibliothÚque standard.
Des exécutables pour x86_64 et aarch64 sont disponibles sur la page des releases du dépÎt GitHub.
Si vous voulez en apprendre plus sur Zig, sachez qu'une dĂ©pĂȘche sur le sujet est en cours de rĂ©daction.
# Qu'est-ce que TapTempo
PostĂ©Â par Gof (site web personnel) . ĂvaluĂ©Â Ă Â 2.
Pour les nouveaux venus sur ce site, pourriez-vous expliquer ce qu'est exactement le TapTempo ? Merci d'avance !
[^] # Re: Qu'est-ce que TapTempo
PostĂ©Â par Ysabeau 𧶠(site web personnel, Mastodon) . ĂvaluĂ©Â Ă Â 4.
Il y a toute une page du wiki dessus. Je cite :
Il a été porté dans une foultitude de langages.
«âŻTak ne veut pas quÊŒon pense Ă lui, il veut quÊŒon penseâŻÂ», Terry Pratchett, DĂ©raillĂ©.
# Non mais ...
PostĂ©Â par Colin Pitrat (site web personnel) . ĂvaluĂ©Â Ă Â 4.
C'est qui ce zig qui a 3 ans de retard?!
# quelques remarques
PostĂ©Â par reno . ĂvaluĂ©Â Ă Â 3. DerniĂšre modification le 07 aoĂ»t 2023 Ă 15:36.
Merci pour ce début de tutoriel
Suivre le flux des commentaires
Note : les commentaires appartiennent Ă celles et ceux qui les ont postĂ©s. Nous nâen sommes pas responsables.