pw-cli: Work without readline too

Build and install pw-cli using getline() (standardized in POSIX.1-2008)
if readline is not found.
This commit is contained in:
Jonas Holmberg 2022-06-15 16:00:22 +02:00
parent b9fa0e6f28
commit 671fc51d27
3 changed files with 41 additions and 12 deletions

View File

@ -266,6 +266,7 @@ if not readline_dep.found()
endif
summary({'readline (for pw-cli)': readline_dep.found()}, bool_yn: true, section: 'Misc dependencies')
cdata.set('HAVE_READLINE', readline_dep.found())
ncurses_dep = dependency('ncursesw', required : false)
sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile'))
summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain')

View File

@ -17,13 +17,11 @@ foreach t : tools_sources
)
endforeach
if readline_dep.found()
executable('pw-cli',
'pw-cli.c',
install: true,
dependencies: [pipewire_dep, readline_dep]
)
endif
executable('pw-cli',
'pw-cli.c',
install: true,
dependencies: [pipewire_dep, readline_dep]
)
if ncurses_dep.found()
executable('pw-top',

View File

@ -22,6 +22,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
@ -33,8 +35,10 @@
#endif
#include <getopt.h>
#include <fnmatch.h>
#ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#include <locale.h>
#if !defined(FNM_EXTMATCH)
@ -307,7 +311,12 @@ static void on_core_info(void *_data, const struct pw_core_info *info)
static void set_prompt(struct remote_data *rd)
{
snprintf(prompt, sizeof(prompt), "%s>> ", rd->name);
#ifdef HAVE_READLINE
rl_set_prompt(prompt);
#else
printf("%s", prompt);
fflush(stdout);
#endif
}
static void on_core_done(void *_data, uint32_t id, int seq)
@ -3040,18 +3049,20 @@ static bool parse(struct data *data, char *buf, char **error)
}
/* We need a global variable, readline doesn't have a closure arg */
static struct data *readline_dataptr;
static struct data *input_dataptr;
static void readline_process_line(char *line)
static void input_process_line(char *line)
{
struct data *d = readline_dataptr;
struct data *d = input_dataptr;
char *error;
if (!line)
line = strdup("quit");
if (line[0] != '\0') {
#ifdef HAVE_READLINE
add_history(line);
#endif
if (!parse(d, line, &error)) {
fprintf(stderr, "Error: \"%s\"\n", error);
free(error);
@ -3065,8 +3076,21 @@ static void do_input(void *data, int fd, uint32_t mask)
struct data *d = data;
if (mask & SPA_IO_IN) {
readline_dataptr = d;
input_dataptr = d;
#ifdef HAVE_READLINE
rl_callback_read_char();
#else
{
char *line = NULL;
size_t s = 0;
if (getline(&line, &s, stdin) < 0) {
free(line);
line = NULL;
}
input_process_line(line);
}
#endif
if (d->current == NULL)
pw_main_loop_quit(d->loop);
@ -3078,6 +3102,7 @@ static void do_input(void *data, int fd, uint32_t mask)
}
}
#ifdef HAVE_READLINE
static char *
readline_match_command(const char *text, int state)
{
@ -3119,13 +3144,14 @@ readline_command_completion(const char *text, int start, int end)
static void readline_init()
{
rl_attempted_completion_function = readline_command_completion;
rl_callback_handler_install(">> ", readline_process_line);
rl_callback_handler_install(">> ", input_process_line);
}
static void readline_cleanup()
{
rl_callback_handler_remove();
}
#endif
static void do_quit_on_signal(void *data, int signal_number)
{
@ -3232,13 +3258,17 @@ int main(int argc, char *argv[])
printf("Welcome to PipeWire version %s. Type 'help' for usage.\n",
pw_get_library_version());
#ifdef HAVE_READLINE
readline_init();
#endif
pw_loop_add_io(l, STDIN_FILENO, SPA_IO_IN|SPA_IO_HUP, false, do_input, &data);
pw_main_loop_run(data.loop);
#ifdef HAVE_READLINE
readline_cleanup();
#endif
} else {
char buf[4096], *p, *error;