Add support for the bell "\a" character

Closes #39
This commit is contained in:
Leroy Hopson 2021-07-03 21:57:19 +07:00 committed by Leroy Hopson
parent 115521f645
commit 09dc080a2e
8 changed files with 98 additions and 0 deletions

View file

@ -158,6 +158,10 @@ There are three example scenes included in this project which you can study to l
- terminal.tscn - terminal.tscn
- asciicast.tscn - asciicast.tscn
## Credits
[bell.wav](/examples/bell.wav) by InspectorJ (<www.jshaw.co.uk>), downloaded from [freesound.org](https://freesound.org/people/InspectorJ/sounds/484344/), released under [CC-BY-3.0](https://creativecommons.org/licenses/by/3.0/).
## License ## License
If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license.

View file

@ -268,6 +268,11 @@ static int text_draw_cb(struct tsm_screen *con, uint64_t id, const uint32_t *ch,
return 0; return 0;
} }
static void bell_cb(tsm_vte *_vte, void *data) {
Terminal *terminal = static_cast<Terminal *>(data);
terminal->emit_signal("bell");
}
void Terminal::_register_methods() { void Terminal::_register_methods() {
register_method("_init", &Terminal::_init); register_method("_init", &Terminal::_init);
register_method("_ready", &Terminal::_ready); register_method("_ready", &Terminal::_ready);
@ -291,6 +296,7 @@ void Terminal::_register_methods() {
"event", GODOT_VARIANT_TYPE_OBJECT); "event", GODOT_VARIANT_TYPE_OBJECT);
register_signal<Terminal>("size_changed", "new_size", register_signal<Terminal>("size_changed", "new_size",
GODOT_VARIANT_TYPE_VECTOR2); GODOT_VARIANT_TYPE_VECTOR2);
register_signal<Terminal>("bell", Dictionary());
} }
Terminal::Terminal() {} Terminal::Terminal() {}
@ -310,6 +316,8 @@ void Terminal::_init() {
if (tsm_vte_new(&vte, screen, write_cb, this, NULL, NULL)) { if (tsm_vte_new(&vte, screen, write_cb, this, NULL, NULL)) {
ERR_PRINT("Error creating new tsm vte"); ERR_PRINT("Error creating new tsm vte");
} }
tsm_vte_set_bell_cb(vte, bell_cb, this);
} }
void Terminal::_ready() { update_theme(); } void Terminal::_ready() { update_theme(); }

View file

@ -6,6 +6,7 @@ const DefaultTheme = preload("../../themes/default.tres")
signal data_sent(data) signal data_sent(data)
signal key_pressed(data, event) signal key_pressed(data, event)
signal size_changed(new_size) signal size_changed(new_size)
signal bell
enum UpdateMode { enum UpdateMode {
DISABLED, DISABLED,
@ -62,6 +63,7 @@ func _ready():
_native_terminal.connect("data_sent", self, "_on_data_sent") _native_terminal.connect("data_sent", self, "_on_data_sent")
_native_terminal.connect("key_pressed", self, "_on_key_pressed") _native_terminal.connect("key_pressed", self, "_on_key_pressed")
_native_terminal.connect("size_changed", self, "_on_size_changed") _native_terminal.connect("size_changed", self, "_on_size_changed")
_native_terminal.connect("bell", self, "_on_bell")
_viewport.size = rect_size _viewport.size = rect_size
_viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS _viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS
@ -112,6 +114,10 @@ func _on_size_changed(new_size: Vector2):
emit_signal("size_changed", new_size) emit_signal("size_changed", new_size)
func _on_bell():
emit_signal("bell")
func _set_size_warning(value): func _set_size_warning(value):
if value: if value:
push_warning( push_warning(

BIN
examples/bell.wav Normal file

Binary file not shown.

21
examples/bell.wav.import Normal file
View file

@ -0,0 +1,21 @@
[remap]
importer="wav"
type="AudioStreamSample"
path="res://.import/bell.wav-90c86fbe33880ba47c154bebbc865497.sample"
[deps]
source_file="res://examples/bell.wav"
dest_files=[ "res://.import/bell.wav-90c86fbe33880ba47c154bebbc865497.sample" ]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop=false
compress/mode=0

View file

@ -2,6 +2,31 @@ extends GDXterm.Terminal
onready var pty = $PTY onready var pty = $PTY
var _next_bell := true
func _ready(): func _ready():
pty.fork(OS.get_environment("SHELL")) pty.fork(OS.get_environment("SHELL"))
func _on_Terminal_bell():
# Limit the rate at which bells can be rung in case the user does something crazy such as
# `while true; do echo -e "\a"; done`
# which causes a real mess if we keep adding AudioStreamPlayers.
if not _next_bell:
return
var player := AudioStreamPlayer.new()
player.stream = preload("../bell.wav")
player.autoplay = true
player.connect("finished", self, "_on_player_finished", [player])
add_child(player)
_next_bell = false
func _on_player_finished(player: AudioStreamPlayer):
player.queue_free()
func _on_Timer_timeout():
_next_bell = true

View file

@ -19,3 +19,10 @@ env = {
"COLORTERM": "truecolor", "COLORTERM": "truecolor",
"TERM": "xterm-256color" "TERM": "xterm-256color"
} }
[node name="Timer" type="Timer" parent="."]
wait_time = 0.1
autostart = true
[connection signal="bell" from="." to="." method="_on_Terminal_bell"]
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

View file

@ -0,0 +1,27 @@
extends WAT.Test
var term: GDXterm.Terminal
func pre():
term = GDXterm.Terminal.new()
term.rect_size = Vector2(400, 200)
add_child(term)
func post():
term.free()
func after():
term.free()
func test_bell() -> void:
term.write(char(7))
term.write(char(0x07))
term.write("\a")
term.write("\u0007")
term.write("'Ask not for whom the \a tolls; it tolls for thee' - John Donne")
yield(until_signal(term, "bell", 1), YIELD)
asserts.signal_was_emitted_x_times(term, "bell", 5)