qjackspa: add some spacing
[ng-jackspa.git] / jackspa-cli.c
blob13209f19c45e9006229772dfb9d603189c855dc5
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
13 * more details.
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/>.
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <signal.h>
23 #include <fcntl.h>
24 #include "jackspa.h"
25 #include "control.h"
27 #define PROGRAM_NAME "jackspa-cli"
29 #define NOTIF_BACKGROUND "continuing to run in the background"
31 volatile sig_atomic_t stop_signaled = 0;
33 static void stop_handler(int s)
35 stop_signaled = 1;
38 static int tty = -1; /* controlling terminal or -1 */
40 static void background_handler(int s)
42 int i;
44 /* setup a child that will stop us then wake us up */
45 i = fork();
46 if (i < 0) {
47 /* error, use the default handler */
48 signal(SIGTSTP, SIG_DFL);
49 kill(0, SIGTSTP);
51 else if (i == 0) {
52 if (tty >= 0)
53 write( STDOUT_FILENO, PROGRAM_NAME ": " NOTIF_BACKGROUND "\n",
54 sizeof(PROGRAM_NAME)-1 + 2 + sizeof(NOTIF_BACKGROUND)-1 + 1 );
55 /* make sure the parent is not in the foreground (or has no ctty) */
56 for (i = 1; tcgetpgrp(tty) == getpgid(getppid()); i <<= 1) {
57 kill(getppid(), SIGSTOP); /* let the shell regain control of the tty */
58 usleep(i), kill(getppid(), SIGCONT);
60 _exit(0);
64 int main(int argc, char *argv[])
66 int rc = 0;
68 tty = open("/dev/tty", O_NOCTTY);
70 /* Signals */
71 struct sigaction act;
72 act.sa_flags = 0;
73 rc = !sigemptyset(&act.sa_mask);
74 if (rc) {
75 /* SIGINT handler to exit gracefully */
76 act.sa_handler = stop_handler;
77 rc = !sigaction(SIGINT, &act, NULL) && rc;
78 /* SIGTTIN handler to avoid being stopped */
79 act.sa_handler = SIG_IGN;
80 rc = !sigaction(SIGTTIN, &act, NULL) && rc;
81 /* SIGTSTP handler to go into the background */
82 act.sa_handler = background_handler;
83 rc = !sigaction(SIGTSTP, &act, NULL) && rc;
84 /* SIGCHLD handler to avoid a child to become defunct */
85 act.sa_handler = SIG_IGN;
86 rc = !sigaction(SIGCHLD, &act, NULL) && rc;
88 if (!rc)
89 fputs(PROGRAM_NAME ": error while setting up the signal handlers\n", stderr);
91 /* Initialize jackspa */
92 state_t state;
93 if (!jackspa_init(&state, argc, argv))
94 return 1;
96 /* Set the default values */
97 unsigned long c;
98 controls_t controls;
99 if (control_buildall(&c, &controls, &state))
100 return 2;
102 /* Wait */
103 if (!isatty(fileno(stdin)))
104 while (!stop_signaled) sleep(-1);
105 else
106 while (!stop_signaled && !feof(stdin))
107 if (getpgrp() == tcgetpgrp(STDIN_FILENO))
108 /* we are in the foreground process group */
109 getchar();
110 else usleep(100000);
112 control_cleanupall(c, &controls);
114 return 0;