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
)) {
52 ( 0, QString(PACKAGE_NAME
" error"),
53 QString("Cannot initialise jackspa"), QMessageBox::Ok
);
61 window
.setWidget(new QWidget
);
62 QVBoxLayout
*slider_box
= new QVBoxLayout(window
.widget());
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);
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()) );
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
));
105 catch(std::exception
const &e
)
107 QMessageBox::critical
108 ( 0, QString(PROGRAM_NAME
),
109 QString("Exception failure while initialising the Qt interface:\n").
117 jackspa_fini(&state
);
121 ControlLayout::ControlLayout(state_t
*state
, unsigned long port
,
122 unsigned long ctrl
, QWidget
*parent
) :
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);
138 (5000 / nearbyintf((control
.max
- control
.min
) / control
.inc
.fine
));
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
));
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
);
194 number
.setValue(static_cast<double>(val
));
197 void ControlLayout::on_button_pressed()
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