1 // qjackspa.cpp - simple Qt4 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/>.
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 */
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
)) {
38 ( 0, QString(PACKAGE_NAME
" error"),
39 QString("Option parsing failed"), QMessageBox::Ok
);
40 std::cerr
<< "option parsing failed: " << error
->message
<< std::endl
;
47 /* Initialise jackspa */
49 if (!jackspa_init(&state
, argc
, argv
)) {
51 ( 0, QString(PACKAGE_NAME
" error"),
52 QString("Cannot initialise jackspa"), QMessageBox::Ok
);
60 window
.setWidget(new QWidget
);
61 QVBoxLayout
*slider_box
= new QVBoxLayout(window
.widget());
67 QGridLayout
*title
= 0;
68 slider_box
->addLayout(title
= new QGridLayout
);
69 title
->addWidget(button
= new QPushButton("&Def"), 0, 0);
70 title
->addWidget(toggle
= new QPushButton("&Xch"), 1, 0);
72 title
->addWidget(label
= new QLabel(state
.descriptor
->Name
), 0, 1, 2, 1);
74 button
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
75 toggle
->setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
);
76 label
->setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
);
77 title
->setHorizontalSpacing(4);
78 title
->setVerticalSpacing(2);
80 /* Initialise the controls */
81 for (unsigned long p
= 0, c
= 0; p
< state
.descriptor
->PortCount
; p
++)
82 if ( LADSPA_IS_PORT_INPUT(state
.descriptor
->PortDescriptors
[p
]) &&
83 LADSPA_IS_PORT_CONTROL(state
.descriptor
->PortDescriptors
[p
]) )
85 ControlLayout
*control
= 0;
86 slider_box
->addLayout(control
= new ControlLayout(&state
, p
, c
++));
87 QObject::connect( button
, SIGNAL(clicked()),
88 control
, SLOT(on_button_pressed()) );
89 QObject::connect( toggle
, SIGNAL(clicked()),
90 control
, SLOT(exchange_control()) );
94 slider_box
->setContentsMargins(1, 1, 1, 1);
95 slider_box
->setSpacing(8);
96 window
.setWidgetResizable(true);
97 window
.frameSize().setWidth(400);
98 window
.setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Expanding
);
100 ((*new QString(PROGRAM_NAME
"_")).append(state
.descriptor
->Label
));
104 catch(std::exception
const &e
)
106 QMessageBox::critical
107 ( 0, QString(PROGRAM_NAME
),
108 QString("Exception failure while initialising the Qt interface:\n").
117 ControlLayout::ControlLayout(state_t
*state
, unsigned long port
,
118 unsigned long ctrl
, QWidget
*parent
) :
121 slider(Qt::Horizontal
)
123 control_init(&control
, state
, port
, ctrl
);
124 label
.setText(control
.name
);
125 number
.setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue
);
126 number
.setAccelerated(true);
127 number
.setDecimals(4);
128 number
.setRange( static_cast<double>(control
.min
),
129 static_cast<double>(control
.max
) );
130 number
.setSingleStep(static_cast<double>(control
.inc
.fine
));
131 slider
.setTracking(false);
132 slider
.setRange(0, 5000);
134 (5000 / nearbyintf((control
.max
- control
.min
) / control
.inc
.fine
));
136 (5000 / nearbyintf((control
.max
- control
.min
) / control
.inc
.coarse
));
137 if (control
.type
== JACKSPA_INT
|| control
.type
== JACKSPA_TOGGLE
) {
138 number
.setDecimals(0);
139 slider
.setRange(0, nearbyintf(control
.max
- control
.min
));
140 slider
.setSingleStep(1);
141 slider
.setPageStep(2);
142 slider
.setTickInterval(1);
143 slider
.setTickPosition(QSlider::TicksLeft
);
146 /* Setup the widgets' state */
147 number
.setValue(static_cast<double>(*control
.val
));
150 /* Layout the widgets */
151 setHorizontalSpacing(4);
152 setVerticalSpacing(2);
153 addWidget(&button
, 0, 0);
154 addWidget(&number
, 1, 0);
155 addWidget(&label
, 0, 2);
156 addWidget(&slider
, 1, 2);
157 button
.setSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Preferred
);
158 label
.setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
);
159 slider
.setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
);
161 /* Signal connections */
162 QObject::connect( &number
, SIGNAL(valueChanged(double)),
163 this, SLOT(on_number_changed()) );
164 QObject::connect( &slider
, SIGNAL(valueChanged(int)),
165 this, SLOT(on_slider_changed()) );
166 QObject::connect( &button
, SIGNAL(clicked()),
167 this, SLOT(on_button_pressed()) );
170 void ControlLayout::on_number_changed()
172 *control
.val
= static_cast<LADSPA_Data
>(number
.value());
173 set_slider(static_cast<LADSPA_Data
>(number
.value()));
176 void ControlLayout::on_slider_changed()
178 int num_pos
= slider
.maximum() - slider
.minimum();
179 LADSPA_Data val
= control
.min
+
180 static_cast<LADSPA_Data
>(slider
.value()) /
181 static_cast<LADSPA_Data
>(num_pos
) *
182 (control
.max
- control
.min
);
185 number
.setValue(static_cast<double>(val
));
188 void ControlLayout::on_button_pressed()
191 *control
.val
= *control
.def
;
192 number
.setValue(static_cast<double>(*control
.def
));
193 set_slider(*control
.def
);
197 void ControlLayout::exchange_control()
199 control_exchange(&control
);
200 set_slider(*control
.val
);
203 void ControlLayout::set_slider(LADSPA_Data val
)
205 int num_pos
= slider
.maximum() - slider
.minimum();
207 slider
.setValue( static_cast<int>( lrintf
208 ( ((val
- control
.min
) * static_cast<LADSPA_Data
>(num_pos
)) /
209 (control
.max
- control
.min
) ) ) );
210 // setValue() will not emit valueChanged() if it is being set to its