1 /* jackspa-cli.c - simple CLI LADSPA host for the Jack Audio Connection Kit
2 * Copyright © 2013 Géraud Meyer <graud@gmx.com>
4 * This file is part of ng-jackspa.
6 * ng-jackspa is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License version 2 as published by the
8 * Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with ng-jackspa. If not, see <http://www.gnu.org/licenses/>.
27 #define PROGRAM_NAME "jackspa-cli"
28 #include "interface.c"
30 #define NOTIF_BACKGROUND "continuing to run in the background"
32 volatile sig_atomic_t stop_signaled
= 0;
34 static void stop_handler(int s
)
39 static int tty
= -1; /* controlling terminal or -1 */
41 static void background_handler(int s
)
45 /* setup a child that will stop us then wake us up */
48 /* error, use the default handler */
49 signal(SIGTSTP
, SIG_DFL
);
53 if (tty
>= 0 && verbose
)
54 write( STDOUT_FILENO
, PROGRAM_NAME
": " NOTIF_BACKGROUND
"\n",
55 sizeof(PROGRAM_NAME
)-1 + 2 + sizeof(NOTIF_BACKGROUND
)-1 + 1 );
56 /* make sure the parent is not in the foreground (or has no ctty) */
57 for (i
= 1; tcgetpgrp(tty
) == getpgid(getppid()); i
<<= 1) {
58 kill(getppid(), SIGSTOP
); /* let the shell regain control of the tty */
59 usleep(i
), kill(getppid(), SIGCONT
);
65 volatile sig_atomic_t print_signaled
= 0;
67 static void printcontrols_handler(int s
)
72 void printcontrols_async(unsigned long c
, controls_t controls
)
74 if (!print_signaled
) return;
76 for (; c
; c
--, controls
++)
77 printf("%e\t# %s\n", *(*controls
)->val
, (*controls
)->name
);
81 int main(int argc
, char *argv
[])
85 tty
= open("/dev/tty", O_NOCTTY
);
90 rc
= !sigemptyset(&act
.sa_mask
);
92 /* SIGINT handler to exit gracefully */
93 act
.sa_handler
= stop_handler
;
94 rc
= !sigaction(SIGINT
, &act
, NULL
) && rc
;
95 /* SIGTTIN handler to avoid being stopped */
96 act
.sa_handler
= SIG_IGN
;
97 rc
= !sigaction(SIGTTIN
, &act
, NULL
) && rc
;
98 /* SIGTSTP handler to go into the background */
99 act
.sa_handler
= background_handler
;
100 rc
= !sigaction(SIGTSTP
, &act
, NULL
) && rc
;
101 /* SIGCHLD handler to avoid a child to become defunct */
102 act
.sa_handler
= SIG_IGN
;
103 rc
= !sigaction(SIGCHLD
, &act
, NULL
) && rc
;
104 /* SIGUSR1 to print the active values */
105 act
.sa_handler
= printcontrols_handler
;
106 rc
= !sigaction(SIGUSR1
, &act
, NULL
) && rc
;
109 fputs(PROGRAM_NAME
": error while setting up the signal handlers\n", stderr
);
111 /* Command line options */
112 GOptionContext
*context
= interface_context();
113 GError
*error
= NULL
;
114 if (!g_option_context_parse(context
, &argc
, &argv
, &error
))
115 return (fprintf(stderr
, "option parsing failed: %s\n", error
->message
), -1);
117 /* Initialize jackspa */
119 if (!jackspa_init(&state
, argc
, argv
))
122 /* Initialize the controls with the requested values */
125 if (control_buildall(&c
, &controls
, &state
))
129 if (!isatty(fileno(stdin
)))
130 while (!stop_signaled
) {
131 printcontrols_async(c
, controls
);
135 while (!stop_signaled
&& !feof(stdin
)) {
136 printcontrols_async(c
, controls
);
137 if (getpgrp() == tcgetpgrp(STDIN_FILENO
))
138 /* we are in the foreground process group */
143 control_cleanupall(c
, &controls
);
144 jackspa_fini(&state
);