1 /*
2 * LadspaControl.cpp - model for controlling a LADSPA port
3 *
4 * Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
5 * Copyright (c) 2006-2008 Danny McRae <khjklujn/at/users.sourceforge.net>
6 *
7 * This file is part of LMMS - https://lmms.io
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program (see COPYING); if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA.
23 *
24 */
25
26 #include <cstdio>
27
28 #include "LadspaControl.h"
29 #include "LadspaBase.h"
30
31
LadspaControl(Model * _parent,port_desc_t * _port,bool _link)32 LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port,
33 bool _link ) :
34 Model( _parent ),
35 m_link( _link ),
36 m_port( _port ),
37 m_linkEnabledModel( _link, this, tr( "Link channels" ) ),
38 m_toggledModel( false, this, m_port->name ),
39 m_knobModel( 0, 0, 0, 1, this, m_port->name ),
40 m_tempoSyncKnobModel( 0, 0, 0, 1, m_port->max, this, m_port->name )
41 {
42 if( m_link )
43 {
44 connect( &m_linkEnabledModel, SIGNAL( dataChanged() ),
45 this, SLOT( linkStateChanged() ),
46 Qt::DirectConnection );
47 }
48
49 switch( m_port->data_type )
50 {
51 case TOGGLED:
52 connect( &m_toggledModel, SIGNAL( dataChanged() ),
53 this, SLOT( ledChanged() ) );
54 if( m_port->def == 1.0f )
55 {
56 m_toggledModel.setValue( true );
57 }
58 // TODO: careful: we must prevent saved scales
59 m_toggledModel.setScaleLogarithmic( m_port->suggests_logscale );
60 break;
61
62 case INTEGER:
63 m_knobModel.setRange( static_cast<int>( m_port->max ),
64 static_cast<int>( m_port->min ),
65 1 + static_cast<int>( m_port->max -
66 m_port->min ) / 400 );
67 m_knobModel.setInitValue(
68 static_cast<int>( m_port->def ) );
69 connect( &m_knobModel, SIGNAL( dataChanged() ),
70 this, SLOT( knobChanged() ) );
71 // TODO: careful: we must prevent saved scales
72 m_knobModel.setScaleLogarithmic( m_port->suggests_logscale );
73 break;
74
75 case FLOATING:
76 m_knobModel.setRange( m_port->min, m_port->max,
77 ( m_port->max - m_port->min )
78 / ( m_port->name.toUpper() == "GAIN"
79 && m_port->max == 10.0f ? 4000.0f :
80 ( m_port->suggests_logscale ? 8000.0f : 800.0f ) ) );
81 m_knobModel.setInitValue( m_port->def );
82 connect( &m_knobModel, SIGNAL( dataChanged() ),
83 this, SLOT( knobChanged() ) );
84 // TODO: careful: we must prevent saved scales
85 m_knobModel.setScaleLogarithmic( m_port->suggests_logscale );
86 break;
87
88 case TIME:
89 m_tempoSyncKnobModel.setRange( m_port->min, m_port->max,
90 ( m_port->max -
91 m_port->min ) / 800.0f );
92 m_tempoSyncKnobModel.setInitValue( m_port->def );
93 connect( &m_tempoSyncKnobModel, SIGNAL( dataChanged() ),
94 this, SLOT( tempoKnobChanged() ) );
95 // TODO: careful: we must prevent saved scales
96 m_tempoSyncKnobModel.setScaleLogarithmic( m_port->suggests_logscale );
97 break;
98
99 default:
100 break;
101 }
102 }
103
104
105
106
~LadspaControl()107 LadspaControl::~LadspaControl()
108 {
109 }
110
111
112
113
value()114 LADSPA_Data LadspaControl::value()
115 {
116 switch( m_port->data_type )
117 {
118 case TOGGLED:
119 return static_cast<LADSPA_Data>( m_toggledModel.value() );
120 case INTEGER:
121 case FLOATING:
122 return static_cast<LADSPA_Data>( m_knobModel.value() );
123 case TIME:
124 return static_cast<LADSPA_Data>( m_tempoSyncKnobModel.value() );
125 default:
126 qWarning( "LadspaControl::value(): BAD BAD BAD\n" );
127 break;
128 }
129
130 return 0;
131 }
132
133
valueBuffer()134 ValueBuffer * LadspaControl::valueBuffer()
135 {
136 switch( m_port->data_type )
137 {
138 case TOGGLED:
139 case INTEGER:
140 return NULL;
141 case FLOATING:
142 return m_knobModel.valueBuffer();
143 case TIME:
144 return m_tempoSyncKnobModel.valueBuffer();
145 default:
146 qWarning( "LadspaControl::valueBuffer(): BAD BAD BAD\n" );
147 break;
148 }
149
150 return NULL;
151 }
152
153
154
setValue(LADSPA_Data _value)155 void LadspaControl::setValue( LADSPA_Data _value )
156 {
157 switch( m_port->data_type )
158 {
159 case TOGGLED:
160 m_toggledModel.setValue( static_cast<bool>( _value ) );
161 break;
162 case INTEGER:
163 m_knobModel.setValue( static_cast<int>( _value ) );
164 break;
165 case FLOATING:
166 m_knobModel.setValue( static_cast<float>( _value ) );
167 break;
168 case TIME:
169 m_tempoSyncKnobModel.setValue( static_cast<float>(
170 _value ) );
171 break;
172 default:
173 printf("LadspaControl::setValue BAD BAD BAD\n");
174 break;
175 }
176 }
177
178
179
180
saveSettings(QDomDocument & doc,QDomElement & parent,const QString & name)181 void LadspaControl::saveSettings( QDomDocument& doc,
182 QDomElement& parent,
183 const QString& name )
184 {
185 QDomElement e = doc.createElement( name );
186
187 if( m_link )
188 {
189 m_linkEnabledModel.saveSettings( doc, e, "link" );
190 }
191 switch( m_port->data_type )
192 {
193 case TOGGLED:
194 m_toggledModel.saveSettings( doc, e, "data" );
195 break;
196 case INTEGER:
197 case FLOATING:
198 m_knobModel.saveSettings( doc, e, "data" );
199 break;
200 case TIME:
201 m_tempoSyncKnobModel.saveSettings( doc, e, "data" );
202 break;
203 default:
204 printf("LadspaControl::saveSettings BAD BAD BAD\n");
205 break;
206 }
207
208 parent.appendChild( e );
209 }
210
211
212
213
loadSettings(const QDomElement & parent,const QString & name)214 void LadspaControl::loadSettings( const QDomElement& parent, const QString& name )
215 {
216 QString dataModelName = "data";
217 QString linkModelName = "link";
218 QDomElement e = parent.namedItem( name ).toElement();
219
220 // COMPAT < 1.0.0: detect old data format where there's either no dedicated sub
221 // element or there's a direct sub element with automation link information
222 if( e.isNull() || e.hasAttribute( "id" ) )
223 {
224 dataModelName = name;
225 linkModelName = name + "link";
226 e = parent;
227 }
228
229 if( m_link )
230 {
231 m_linkEnabledModel.loadSettings( e, linkModelName );
232 }
233
234 switch( m_port->data_type )
235 {
236 case TOGGLED:
237 m_toggledModel.loadSettings( e, dataModelName );
238 break;
239 case INTEGER:
240 case FLOATING:
241 m_knobModel.loadSettings( e, dataModelName );
242 break;
243 case TIME:
244 m_tempoSyncKnobModel.loadSettings( e, dataModelName );
245 break;
246 default:
247 printf("LadspaControl::loadSettings BAD BAD BAD\n");
248 break;
249 }
250 }
251
252
253
254
linkControls(LadspaControl * _control)255 void LadspaControl::linkControls( LadspaControl * _control )
256 {
257 switch( m_port->data_type )
258 {
259 case TOGGLED:
260 BoolModel::linkModels( &m_toggledModel, _control->toggledModel() );
261 break;
262 case INTEGER:
263 case FLOATING:
264 FloatModel::linkModels( &m_knobModel, _control->knobModel() );
265 break;
266 case TIME:
267 TempoSyncKnobModel::linkModels( &m_tempoSyncKnobModel,
268 _control->tempoSyncKnobModel() );
269 break;
270 default:
271 break;
272 }
273 }
274
275
276
277
ledChanged()278 void LadspaControl::ledChanged()
279 {
280 emit changed( m_port->port_id, static_cast<LADSPA_Data>(
281 m_toggledModel.value() ) );
282 }
283
284
285
286
knobChanged()287 void LadspaControl::knobChanged()
288 {
289 emit changed( m_port->port_id, static_cast<LADSPA_Data>(
290 m_knobModel.value() ) );
291 }
292
293
294
295
tempoKnobChanged()296 void LadspaControl::tempoKnobChanged()
297 {
298 emit changed( m_port->port_id, static_cast<LADSPA_Data>(
299 m_tempoSyncKnobModel.value() ) );
300 }
301
302
303
304
unlinkControls(LadspaControl * _control)305 void LadspaControl::unlinkControls( LadspaControl * _control )
306 {
307 switch( m_port->data_type )
308 {
309 case TOGGLED:
310 BoolModel::unlinkModels( &m_toggledModel, _control->toggledModel() );
311 break;
312 case INTEGER:
313 case FLOATING:
314 FloatModel::unlinkModels( &m_knobModel, _control->knobModel() );
315 break;
316 case TIME:
317 TempoSyncKnobModel::unlinkModels( &m_tempoSyncKnobModel,
318 _control->tempoSyncKnobModel() );
319 break;
320 default:
321 break;
322 }
323 }
324
325
326
327
linkStateChanged()328 void LadspaControl::linkStateChanged()
329 {
330 emit linkChanged( m_port->control_id, m_linkEnabledModel.value() );
331 }
332
333
334
335
setLink(bool _state)336 void LadspaControl::setLink( bool _state )
337 {
338 m_linkEnabledModel.setValue( _state );
339 }
340
341
342
343
344