| /* |
| * libbrlapi - A library providing access to braille terminals for applications. |
| * |
| * Copyright (C) 2006-2023 by |
| * Samuel Thibault <Samuel.Thibault@ens-lyon.org> |
| * Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org> |
| * |
| * libbrlapi comes with ABSOLUTELY NO WARRANTY. |
| * |
| * This is free software, placed under the terms of the |
| * GNU Lesser General Public License, as published by the Free Software |
| * Foundation; either version 2.1 of the License, or (at your option) any |
| * later version. Please see the file LICENSE-LGPL for details. |
| * |
| * Web Page: http://brltty.app/ |
| * |
| * This software is maintained by Dave Mielke <dave@mielke.cc>. |
| */ |
| |
| package org.a11y.brlapi.clients; |
| |
| import java.io.InterruptedIOException; |
| import java.util.concurrent.TimeoutException; |
| import org.a11y.brlapi.*; |
| |
| public class EchoClient extends Client { |
| private boolean echoDriverKeys = false; |
| private boolean echoNames = false; |
| |
| public final static int MINIMUM_READ_COUNT = 1; |
| public final static int DEFAULT_READ_COUNT = 10; |
| |
| public final static String NO_TIMEOUT = "none"; |
| public final static int FOREVER_READ_TIMEOUT = 0; |
| public final static int MINIMUM_READ_TIMEOUT = 1; |
| public final static int DEFAULT_READ_TIMEOUT = 10; |
| |
| private int readCount = DEFAULT_READ_COUNT; |
| private final OperandUsage readCountUsage = new OperandUsage("read count") |
| .setDefault(readCount) |
| .setRangeMinimum(MINIMUM_READ_COUNT) |
| ; |
| |
| private int readTimeout = DEFAULT_READ_TIMEOUT; |
| private final OperandUsage readTimeoutUsage = new OperandUsage("read timeout") |
| .setDefault(readTimeout) |
| .setRangeMinimum(MINIMUM_READ_TIMEOUT) |
| .setRangeUnits("seconds") |
| .setRangeComment("readKeyWithTimeout is used") |
| .addWord(NO_TIMEOUT, FOREVER_READ_TIMEOUT, "readKey is used") |
| ; |
| |
| public EchoClient (String... arguments) { |
| super(arguments); |
| addRepeatingParameter("tty"); |
| |
| addOption("commands", |
| (operands) -> { |
| echoDriverKeys = false; |
| } |
| ); |
| |
| addOption("keys", |
| (operands) -> { |
| echoDriverKeys = true; |
| } |
| ); |
| |
| addOption("values", |
| (operands) -> { |
| echoNames = false; |
| } |
| ); |
| |
| addOption("names", |
| (operands) -> { |
| echoNames = true; |
| } |
| ); |
| |
| addOption("reads", |
| (operands) -> { |
| readCount = Parse.asInt( |
| readCountUsage.getOperandDescription(), |
| operands[0], MINIMUM_READ_COUNT |
| ); |
| }, |
| "count" |
| ); |
| |
| addOption("timeout", |
| (operands) -> { |
| String operand = operands[0]; |
| |
| if (Strings.isAbbreviation(NO_TIMEOUT, operand)) { |
| readTimeout = FOREVER_READ_TIMEOUT; |
| } else { |
| readTimeout = Parse.asInt( |
| readTimeoutUsage.getOperandDescription(), |
| operand, MINIMUM_READ_TIMEOUT |
| ); |
| } |
| }, |
| "seconds" |
| ); |
| } |
| |
| @Override |
| protected final void extendUsageSummary (StringBuilder usage) { |
| super.extendUsageSummary(usage); |
| |
| readCountUsage.appendTo(usage); |
| readTimeoutUsage.appendTo(usage); |
| } |
| |
| private int[] ttyPath = null; |
| |
| @Override |
| protected void processParameters (String[] parameters) |
| throws SyntaxException |
| { |
| int count = parameters.length; |
| ttyPath = new int[count]; |
| |
| for (int i=0; i<count; i+=1) { |
| ttyPath[i] = Parse.asInt("tty path component", parameters[i]); |
| } |
| } |
| |
| private final void show (Connection connection, String text) { |
| printf("%s\n", text); |
| connection.write(text, Constants.CURSOR_OFF); |
| } |
| |
| private final String toString (Connection connection, long code) { |
| if (echoDriverKeys) { |
| DriverKeycode keycode = new DriverKeycode(code); |
| String string = keycode.toString(); |
| |
| if (echoNames) { |
| String name = connection.getParameters().driverKeycodeName.get(keycode.getValue()); |
| |
| if ((name != null) && !name.isEmpty()) { |
| string += " Name:" + name; |
| } |
| } |
| |
| return string; |
| } else { |
| CommandKeycode keycode = new CommandKeycode(code); |
| if (!echoNames) return keycode.toString(); |
| |
| StringBuilder builder = new StringBuilder(); |
| builder.append(Keycode.toString(code)); |
| |
| { |
| String type = keycode.getTypeName(); |
| if (type != null) builder.append(" Type:").append(type); |
| } |
| |
| { |
| String command = keycode.getCommandName(); |
| if (command != null) builder.append(" Cmd:").append(command); |
| } |
| |
| { |
| int argument = keycode.getArgument(); |
| |
| if (argument > 0) { |
| builder.append( |
| String.format( |
| " Arg:%04X(%d)", argument, argument |
| ) |
| ); |
| } |
| } |
| |
| { |
| String[] flags = keycode.getFlagNames(); |
| |
| if (flags != null) { |
| int count = flags.length; |
| boolean first = true; |
| |
| for (int index=0; index<count; index+=1) { |
| String flag = flags[index]; |
| if (flag == null) continue; |
| if (flag.isEmpty()) continue; |
| |
| if (first) { |
| first = false; |
| builder.append(" Flg:"); |
| } else { |
| builder.append(','); |
| } |
| |
| builder.append(flag); |
| } |
| } |
| } |
| |
| return builder.toString(); |
| } |
| } |
| |
| @Override |
| protected final void runClient (Connection connection) throws ProgramException { |
| ttyMode( |
| connection, echoDriverKeys, |
| (con) -> { |
| show(con, |
| String.format( |
| "press keys (timeout is %d seconds)", readTimeout |
| ) |
| ); |
| |
| while (readCount-- > 0) { |
| long code; |
| |
| try { |
| if (readTimeout == FOREVER_READ_TIMEOUT) { |
| code = con.readKey(); |
| } else { |
| code = con.readKeyWithTimeout((readTimeout * 1000)); |
| } |
| } catch (InterruptedIOException exception) { |
| continue; |
| } catch (TimeoutException exception) { |
| break; |
| } |
| |
| show(con, toString(con, code)); |
| } |
| }, |
| ttyPath |
| ); |
| } |
| } |