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 endif
summary({'readline (for pw-cli)': readline_dep.found()}, bool_yn: true, section: 'Misc dependencies') 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) ncurses_dep = dependency('ncursesw', required : false)
sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile')) 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') 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 endforeach
if readline_dep.found() executable('pw-cli',
executable('pw-cli', 'pw-cli.c',
'pw-cli.c', install: true,
install: true, dependencies: [pipewire_dep, readline_dep]
dependencies: [pipewire_dep, readline_dep] )
)
endif
if ncurses_dep.found() if ncurses_dep.found()
executable('pw-top', executable('pw-top',

View File

@ -22,6 +22,8 @@
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
*/ */
#include "config.h"
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@ -33,8 +35,10 @@
#endif #endif
#include <getopt.h> #include <getopt.h>
#include <fnmatch.h> #include <fnmatch.h>
#ifdef HAVE_READLINE
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#endif
#include <locale.h> #include <locale.h>
#if !defined(FNM_EXTMATCH) #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) static void set_prompt(struct remote_data *rd)
{ {
snprintf(prompt, sizeof(prompt), "%s>> ", rd->name); snprintf(prompt, sizeof(prompt), "%s>> ", rd->name);
#ifdef HAVE_READLINE
rl_set_prompt(prompt); rl_set_prompt(prompt);
#else
printf("%s", prompt);
fflush(stdout);
#endif
} }
static void on_core_done(void *_data, uint32_t id, int seq) 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 */ /* 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; char *error;
if (!line) if (!line)
line = strdup("quit"); line = strdup("quit");
if (line[0] != '\0') { if (line[0] != '\0') {
#ifdef HAVE_READLINE
add_history(line); add_history(line);
#endif
if (!parse(d, line, &error)) { if (!parse(d, line, &error)) {
fprintf(stderr, "Error: \"%s\"\n", error); fprintf(stderr, "Error: \"%s\"\n", error);
free(error); free(error);
@ -3065,8 +3076,21 @@ static void do_input(void *data, int fd, uint32_t mask)
struct data *d = data; struct data *d = data;
if (mask & SPA_IO_IN) { if (mask & SPA_IO_IN) {
readline_dataptr = d; input_dataptr = d;
#ifdef HAVE_READLINE
rl_callback_read_char(); 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) if (d->current == NULL)
pw_main_loop_quit(d->loop); 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 * static char *
readline_match_command(const char *text, int state) 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() static void readline_init()
{ {
rl_attempted_completion_function = readline_command_completion; 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() static void readline_cleanup()
{ {
rl_callback_handler_remove(); rl_callback_handler_remove();
} }
#endif
static void do_quit_on_signal(void *data, int signal_number) 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", printf("Welcome to PipeWire version %s. Type 'help' for usage.\n",
pw_get_library_version()); pw_get_library_version());
#ifdef HAVE_READLINE
readline_init(); readline_init();
#endif
pw_loop_add_io(l, STDIN_FILENO, SPA_IO_IN|SPA_IO_HUP, false, do_input, &data); pw_loop_add_io(l, STDIN_FILENO, SPA_IO_IN|SPA_IO_HUP, false, do_input, &data);
pw_main_loop_run(data.loop); pw_main_loop_run(data.loop);
#ifdef HAVE_READLINE
readline_cleanup(); readline_cleanup();
#endif
} else { } else {
char buf[4096], *p, *error; char buf[4096], *p, *error;