Use 'fputs' instead of '(f)printf' to avoid -Wformat-security warnings
[jack_mixer.git] / src / jack_mix_box.c
blobf21afd0fe033268acfb984593e65ff4eae858b72
1 /*****************************************************************************
3 * This file is part of jack_mixer
5 * Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2009-2011 Frederic Peters <fpeters@0d.be>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *****************************************************************************/
24 * jack_mix_box is a most minimalistic jack mixer, a set of mono/sterero input
25 * channels, mixed to a single output channel, with the volume of the
26 * input channels controlled by MIDI control change (CC) codes.
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdbool.h>
34 #include <libintl.h>
35 #include <locale.h>
36 #include <getopt.h>
37 #include <signal.h>
38 #include <unistd.h>
39 #include "jack_mixer.h"
41 #define _(String) gettext(String)
43 jack_mixer_t mixer;
44 bool keepRunning = true;
46 void
47 usage()
49 const char* _usage = _(
50 "Usage: "
51 "jack_mix_box [-n <name>] [-p] [-s] [-v <dB>] MIDI_CC...\n"
52 "\n"
53 "-h|--help print this help message\n"
54 "-n|--name set JACK client name\n"
55 "-p|--pickup enable MIDI pickup mode (default: jump-to-value)\n"
56 "-s|--stereo make all input channels stereo with left+right input\n"
57 "-v|--volume initial volume gain in dBFS (default 0.0, i.e. unity gain)\n"
58 "\n"
59 "Each positional argument is interpreted as a MIDI Control Change number and\n"
60 "adds a mixer channel with one (mono) or left+right (stereo) inputs, whose\n"
61 "volume can be controlled via the given MIDI Control Change.\n"
62 "\n"
63 "Send SIGUSR1 to the process to have the current volumes reported per input\n"
64 "channel.\n\n");
65 fputs(_usage, stdout);
68 void
69 reportVolume(int sig)
71 (void)sig;
72 channels_volumes_read(mixer);
75 void
76 triggerShutDown(int sig)
78 (void)sig;
79 keepRunning = false;
82 int
83 main(int argc, char *argv[])
85 jack_mixer_scale_t scale;
86 jack_mixer_channel_t main_mix_channel;
87 char *jack_cli_name = NULL;
88 int channel_index;
89 bool bStereo = false;
90 enum midi_behavior_mode ePickup = Jump_To_Value;
91 double initialVolume = 0.0f; //in dbFS
92 char * localedir;
94 localedir = getenv("LOCALEDIR");
95 setlocale(LC_ALL, "");
96 bindtextdomain("jack_mixer", localedir != NULL ? localedir : LOCALEDIR);
97 textdomain("jack_mixer");
99 while (1) {
100 int c;
101 static struct option long_options[] =
103 {"name", required_argument, 0, 'n'},
104 {"help", no_argument, 0, 'h'},
105 {"pickup", no_argument, 0, 'p'},
106 {"stereo", no_argument, 0, 's'},
107 {"volume", required_argument, 0, 'v'},
108 {0, 0, 0, 0}
110 int option_index = 0;
112 c = getopt_long (argc, argv, "sphn:v:", long_options, &option_index);
113 if (c == -1)
114 break;
116 switch (c) {
117 case 'n':
118 jack_cli_name = strdup(optarg);
119 break;
120 case 's':
121 bStereo = true;
122 break;
123 case 'v':
124 initialVolume = strtod(optarg, NULL);
125 break;
126 case 'h':
127 usage();
128 exit(0);
129 break;
130 case 'p':
131 ePickup = Pick_Up;
132 break;
133 default:
134 fprintf(stderr, _("Unknown argument, aborting.\n"));
135 exit(1);
139 if (optind == argc) {
140 fputs(_("You must specify at least one input channel.\n"), stderr);
141 exit(1);
144 scale = scale_create();
145 scale_add_threshold(scale, -70.0, 0.0);
146 scale_add_threshold(scale, 0.0, 1.0);
147 scale_calculate_coefficients(scale);
149 if (jack_cli_name == NULL) {
150 jack_cli_name = strdup("jack_mix_box");
153 mixer = create(jack_cli_name, false);
154 if (mixer == NULL) {
155 fputs(jack_mixer_error_str(), stderr);
156 return -1;
158 main_mix_channel = add_output_channel(mixer, "MAIN", true, false);
159 channel_set_midi_scale(main_mix_channel, scale);
160 channel_volume_write(main_mix_channel, 0.0);
161 set_midi_behavior_mode(mixer, ePickup);
163 channel_index = 0;
164 while (optind < argc) {
165 char *channel_name;
166 jack_mixer_channel_t channel;
168 channel_index += 1;
169 channel_name = malloc(15);
170 if (snprintf(channel_name, 15, "Channel %d", channel_index) >= 15) {
171 free(channel_name);
172 abort();
174 channel = add_channel(mixer, channel_name, bStereo);
175 if (channel == NULL) {
176 fprintf(stderr, _("Failed to add channel %d, aborting.\n"), channel_index);
177 exit(1);
179 channel_set_volume_midi_cc(channel, atoi(argv[optind++]));
180 channel_set_midi_scale(channel, scale);
181 channel_volume_write(channel, initialVolume);
182 free(channel_name);
185 signal(SIGUSR1, reportVolume);
186 signal(SIGTERM, triggerShutDown);
187 signal(SIGHUP, triggerShutDown);
188 signal(SIGINT, triggerShutDown);
190 while (keepRunning) {
191 usleep(500u * 1000u); //500msec
194 remove_channels(mixer);
195 remove_output_channel(main_mix_channel);
196 destroy(mixer);
197 scale_destroy(scale);
198 free(jack_cli_name);
199 return 0;