Makefile: install-doc: install manpage links for each command
[ng-jackspa.git] / qjackspa.cpp
blobdf9f6dddd2c8a45a5916cac672ca88a6bbda6511
1 // qjackspa.cpp - simple Qt4 LADSPA host for the Jack Audio Connection Kit
2 // Copyright © 2013 Géraud Meyer <graud@gmx.com>
3 //
4 // This file is part of ng-jackspa.
5 //
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.
9 //
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/>.
18 #include <iostream>
19 #include <exception>
20 #include "qjackspa.h"
22 #define PROGRAM_NAME "qjackspa"
23 #include "interface.c"
24 #define PROGRAM_DESCRIPTION_EXTRA PROGRAM_NAME " also accepts standard Qt options.\n\n"
26 int main(int argc, char *argv[])
28 QApplication app(argc, argv);
30 /* Command line options */
31 GError *error = NULL;
32 GOptionContext *context = interface_context();
33 g_option_context_set_description( context, g_strconcat
34 ( PROGRAM_DESCRIPTION_EXTRA,
35 g_option_context_get_description(context), NULL ) );
36 if (!g_option_context_parse(context, &argc, &argv, &error)) {
37 QMessageBox::critical
38 ( 0, QString(PACKAGE_NAME " error"),
39 QString("Option parsing failed"), QMessageBox::Ok );
40 std::cerr << "option parsing failed: " << error->message << std::endl;
41 return -1;
44 /* Main window */
45 QScrollArea window;
47 /* Initialise jackspa */
48 state_t state;
49 if (!jackspa_init(&state, argc, argv)) {
50 if (verbose)
51 QMessageBox::critical
52 ( 0, QString(PACKAGE_NAME " error"),
53 QString("Cannot initialise jackspa"), QMessageBox::Ok );
54 return 1;
57 try
60 /* Main layout */
61 window.setWidget(new QWidget);
62 QVBoxLayout *slider_box = new QVBoxLayout(window.widget());
64 /* Title bar */
65 QPushButton *button;
66 QPushButton *toggle;
68 QGridLayout *title = 0;
69 slider_box->addLayout(title = new QGridLayout);
70 title->addWidget(button = new QPushButton("&Def"), 0, 0);
71 title->addWidget(toggle = new QPushButton("&Xch"), 1, 0);
72 QLabel *label = 0;
73 title->addWidget(label = new QLabel(state.descriptor->Name), 0, 1, 2, 1);
75 button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
76 toggle->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
77 label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
78 title->setHorizontalSpacing(4);
79 title->setVerticalSpacing(2);
81 /* Initialise the controls */
82 for (unsigned long p = 0, c = 0; p < state.descriptor->PortCount; p++)
83 if ( LADSPA_IS_PORT_INPUT(state.descriptor->PortDescriptors[p]) &&
84 LADSPA_IS_PORT_CONTROL(state.descriptor->PortDescriptors[p]) )
86 ControlLayout *control = 0;
87 slider_box->addLayout(control = new ControlLayout(&state, p, c++));
88 QObject::connect( button, SIGNAL(clicked()),
89 control, SLOT(on_button_pressed()) );
90 QObject::connect( toggle, SIGNAL(clicked()),
91 control, SLOT(exchange_control()) );
94 /* Main layout */
95 slider_box->setContentsMargins(1, 1, 1, 1);
96 slider_box->setSpacing(8);
97 window.setWidgetResizable(true);
98 window.frameSize().setWidth(400);
99 window.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
100 window.setWindowTitle
101 ((*new QString(PROGRAM_NAME "_")).append(state.descriptor->Label));
102 window.show();
105 catch(std::exception const &e)
107 QMessageBox::critical
108 ( 0, QString(PROGRAM_NAME),
109 QString("Exception failure while initialising the Qt interface:\n").
110 append(e.what()),
111 QMessageBox::Ok );
112 throw(e);
115 int rc = app.exec();
117 jackspa_fini(&state);
118 return rc;
121 ControlLayout::ControlLayout(state_t *state, unsigned long port,
122 unsigned long ctrl, QWidget *parent) :
123 QGridLayout(parent),
124 button("Def"),
125 slider(Qt::Horizontal)
127 control_init(&control, state, port, ctrl);
128 label.setText(control.name);
129 number.setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);
130 number.setAccelerated(true);
131 number.setDecimals(4);
132 number.setRange( static_cast<double>(control.min),
133 static_cast<double>(control.max) );
134 number.setSingleStep(static_cast<double>(control.inc.fine));
135 slider.setTracking(false);
136 slider.setRange(0, 5000);
137 slider.setSingleStep
138 (5000 / nearbyintf((control.max - control.min) / control.inc.fine));
139 slider.setPageStep
140 (5000 / nearbyintf((control.max - control.min) / control.inc.coarse));
141 if (control.type == JACKSPA_INT || control.type == JACKSPA_TOGGLE) {
142 number.setDecimals(0);
143 slider.setRange(0, nearbyintf(control.max - control.min));
144 slider.setSingleStep(1);
145 slider.setPageStep(2);
146 slider.setTickInterval(1);
147 slider.setTickPosition(QSlider::TicksLeft);
150 /* Setup the widgets' state */
151 number.setValue(static_cast<double>(*control.val));
152 on_number_changed();
154 /* Layout the widgets */
155 setHorizontalSpacing(4);
156 setVerticalSpacing(2);
157 addWidget(&button, 0, 0);
158 addWidget(&number, 1, 0);
159 addWidget(&label, 0, 2);
160 addWidget(&slider, 1, 2);
161 button.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
162 label.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
163 slider.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
165 /* Signal connections */
166 QObject::connect( &number, SIGNAL(valueChanged(double)),
167 this, SLOT(on_number_changed()) );
168 QObject::connect( &slider, SIGNAL(valueChanged(int)),
169 this, SLOT(on_slider_changed()) );
170 QObject::connect( &button, SIGNAL(clicked()),
171 this, SLOT(on_button_pressed()) );
174 ControlLayout::~ControlLayout()
176 control_fini(&control);
179 void ControlLayout::on_number_changed()
181 *control.val = static_cast<LADSPA_Data>(number.value());
182 set_slider(static_cast<LADSPA_Data>(number.value()));
185 void ControlLayout::on_slider_changed()
187 int num_pos = slider.maximum() - slider.minimum();
188 LADSPA_Data val = control.min +
189 static_cast<LADSPA_Data>(slider.value()) /
190 static_cast<LADSPA_Data>(num_pos) *
191 (control.max - control.min);
193 *control.val = val;
194 number.setValue(static_cast<double>(val));
197 void ControlLayout::on_button_pressed()
199 if (control.def) {
200 *control.val = *control.def;
201 number.setValue(static_cast<double>(*control.def));
202 set_slider(*control.def);
206 void ControlLayout::exchange_control()
208 control_exchange(&control);
209 set_slider(*control.val);
212 void ControlLayout::set_slider(LADSPA_Data val)
214 int num_pos = slider.maximum() - slider.minimum();
216 slider.setValue( static_cast<int>( lrintf
217 ( ((val - control.min) * static_cast<LADSPA_Data>(num_pos)) /
218 (control.max - control.min) ) ) );
219 // setValue() will not emit valueChanged() if it is being set to its
220 // current value