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