From 98bf08bdcf2edd9d397f32650a8bfe62186fbecf Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sun, 9 Feb 2014 11:50:07 +0100 Subject: baresip 0.4.10 --- modules/stdio/module.mk | 11 +++ modules/stdio/stdio.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 modules/stdio/module.mk create mode 100644 modules/stdio/stdio.c (limited to 'modules/stdio') diff --git a/modules/stdio/module.mk b/modules/stdio/module.mk new file mode 100644 index 0000000..4c52b28 --- /dev/null +++ b/modules/stdio/module.mk @@ -0,0 +1,11 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := stdio +$(MOD)_SRCS += stdio.c +$(MOD)_LFLAGS += + +include mk/mod.mk diff --git a/modules/stdio/stdio.c b/modules/stdio/stdio.c new file mode 100644 index 0000000..bfdc9e7 --- /dev/null +++ b/modules/stdio/stdio.c @@ -0,0 +1,182 @@ +/** + * @file stdio.c Standard Input/Output UI module + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include +#include +#include +#include +#include + + +/** Local constants */ +enum { + RELEASE_VAL = 250 /**< Key release value in [ms] */ +}; + +struct ui_st { + struct ui *ui; /* base class */ + struct tmr tmr; + struct termios term; + bool term_set; + ui_input_h *h; + void *arg; +}; + + +/* We only allow one instance */ +static struct ui_st *_ui; +static struct ui *stdio; + + +static void ui_destructor(void *arg) +{ + struct ui_st *st = arg; + + fd_close(STDIN_FILENO); + + if (st->term_set) + tcsetattr(STDIN_FILENO, TCSANOW, &st->term); + + tmr_cancel(&st->tmr); + mem_deref(st->ui); + + _ui = NULL; +} + + +static int print_handler(const char *p, size_t size, void *arg) +{ + (void)arg; + + return 1 == fwrite(p, size, 1, stderr) ? 0 : ENOMEM; +} + + +static void report_key(struct ui_st *ui, char key) +{ + struct re_printf pf; + + pf.vph = print_handler; + + if (ui->h) + ui->h(key, &pf, ui->arg); +} + + +static void timeout(void *arg) +{ + struct ui_st *st = arg; + + /* Emulate key-release */ + report_key(st, 0x00); +} + + +static void ui_fd_handler(int flags, void *arg) +{ + struct ui_st *st = arg; + char key; + (void)flags; + + if (1 != read(STDIN_FILENO, &key, 1)) { + return; + } + + tmr_start(&st->tmr, RELEASE_VAL, timeout, st); + report_key(st, key); +} + + +static int term_setup(struct ui_st *st) +{ + struct termios now; + + if (tcgetattr(STDIN_FILENO, &st->term) < 0) + return errno; + + now = st->term; + + now.c_lflag |= ISIG; + now.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); + + /* required on Solaris */ + now.c_cc[VMIN] = 1; + now.c_cc[VTIME] = 0; + + if (tcsetattr(STDIN_FILENO, TCSANOW, &now) < 0) + return errno; + + st->term_set = true; + + return 0; +} + + +static int ui_alloc(struct ui_st **stp, struct ui_prm *prm, + ui_input_h *ih, void *arg) +{ + struct ui_st *st; + int err; + + (void)prm; + + if (!stp) + return EINVAL; + + if (_ui) { + *stp = mem_ref(_ui); + return 0; + } + + st = mem_zalloc(sizeof(*st), ui_destructor); + if (!st) + return ENOMEM; + + st->ui = mem_ref(stdio); + tmr_init(&st->tmr); + + err = fd_listen(STDIN_FILENO, FD_READ, ui_fd_handler, st); + if (err) + goto out; + + err = term_setup(st); + if (err) { + info("stdio: could not setup terminal: %m\n", err); + err = 0; + } + + st->h = ih; + st->arg = arg; + + out: + if (err) + mem_deref(st); + else + *stp = _ui = st; + + return err; +} + + +static int module_init(void) +{ + return ui_register(&stdio, "stdio", ui_alloc, NULL); +} + + +static int module_close(void) +{ + stdio = mem_deref(stdio); + return 0; +} + + +const struct mod_export DECL_EXPORTS(stdio) = { + "stdio", + "ui", + module_init, + module_close +}; -- cgit v1.2.3