njackspa: [bug] fix the fields' widths
[ng-jackspa.git] / jackspa-cli.c
blob02836da7806de854ef0f41970be3d5e61fca2d20
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"
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)
36 stop_signaled = 1;
39 static int tty = -1; /* controlling terminal or -1 */
41 static void background_handler(int s)
43 int i;
45 /* setup a child that will stop us then wake us up */
46 i = fork();
47 if (i < 0) {
48 /* error, use the default handler */
49 signal(SIGTSTP, SIG_DFL);
50 kill(0, SIGTSTP);
52 else if (i == 0) {
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);
61 _exit(0);
65 int main(int argc, char *argv[])
67 int rc = 0;
69 tty = open("/dev/tty", O_NOCTTY);
71 /* Signals */
72 struct sigaction act;
73 act.sa_flags = 0;
74 rc = !sigemptyset(&act.sa_mask);
75 if (rc) {
76 /* SIGINT handler to exit gracefully */
77 act.sa_handler = stop_handler;
78 rc = !sigaction(SIGINT, &act, NULL) && rc;
79 /* SIGTTIN handler to avoid being stopped */
80 act.sa_handler = SIG_IGN;
81 rc = !sigaction(SIGTTIN, &act, NULL) && rc;
82 /* SIGTSTP handler to go into the background */
83 act.sa_handler = background_handler;
84 rc = !sigaction(SIGTSTP, &act, NULL) && rc;
85 /* SIGCHLD handler to avoid a child to become defunct */
86 act.sa_handler = SIG_IGN;
87 rc = !sigaction(SIGCHLD, &act, NULL) && rc;
89 if (!rc)
90 fputs(PROGRAM_NAME ": error while setting up the signal handlers\n", stderr);
92 /* Command line options */
93 GOptionContext *context = interface_context();
94 GError *error = NULL;
95 if (!g_option_context_parse(context, &argc, &argv, &error))
96 return (fprintf(stderr, "option parsing failed: %s\n", error->message), -1);
98 /* Initialize jackspa */
99 state_t state;
100 if (!jackspa_init(&state, argc, argv))
101 return 1;
103 /* Set the default values */
104 unsigned long c;
105 controls_t controls;
106 if (control_buildall(&c, &controls, &state))
107 return 2;
109 /* Wait */
110 if (!isatty(fileno(stdin)))
111 while (!stop_signaled) sleep(-1);
112 else
113 while (!stop_signaled && !feof(stdin))
114 if (getpgrp() == tcgetpgrp(STDIN_FILENO))
115 /* we are in the foreground process group */
116 getchar();
117 else usleep(100000);
119 control_cleanupall(c, &controls);
121 return 0;