| Chris@58 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@0 | 2 | 
| Chris@0 | 3 /* | 
| Chris@59 | 4     Sonic Visualiser | 
| Chris@59 | 5     An audio file viewer and annotation editor. | 
| Chris@59 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@59 | 7     This file copyright 2006 Chris Cannam. | 
| Chris@0 | 8 | 
| Chris@59 | 9     This program is free software; you can redistribute it and/or | 
| Chris@59 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@59 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@59 | 12     License, or (at your option) any later version.  See the file | 
| Chris@59 | 13     COPYING included with this distribution for more information. | 
| Chris@0 | 14 */ | 
| Chris@0 | 15 | 
| Chris@0 | 16 #include "PropertyBox.h" | 
| Chris@63 | 17 #include "PluginParameterDialog.h" | 
| Chris@0 | 18 | 
| Chris@0 | 19 #include "base/PropertyContainer.h" | 
| Chris@33 | 20 #include "base/PlayParameters.h" | 
| Chris@33 | 21 #include "base/Layer.h" | 
| Chris@0 | 22 | 
| Chris@63 | 23 #include "plugin/RealTimePluginFactory.h" | 
| Chris@63 | 24 #include "plugin/RealTimePluginInstance.h" | 
| Chris@71 | 25 #include "plugin/PluginXml.h" | 
| Chris@63 | 26 | 
| Chris@0 | 27 #include "AudioDial.h" | 
| Chris@33 | 28 #include "LEDButton.h" | 
| Chris@0 | 29 | 
| Chris@0 | 30 #include <QGridLayout> | 
| Chris@0 | 31 #include <QHBoxLayout> | 
| Chris@33 | 32 #include <QVBoxLayout> | 
| Chris@0 | 33 #include <QCheckBox> | 
| Chris@0 | 34 #include <QComboBox> | 
| Chris@63 | 35 #include <QPushButton> | 
| Chris@0 | 36 #include <QLabel> | 
| Chris@33 | 37 #include <QFrame> | 
| Chris@0 | 38 | 
| Chris@0 | 39 #include <cassert> | 
| Chris@0 | 40 #include <iostream> | 
| Martin@46 | 41 #include <cmath> | 
| Chris@0 | 42 | 
| Chris@0 | 43 //#define DEBUG_PROPERTY_BOX 1 | 
| Chris@0 | 44 | 
| Chris@0 | 45 PropertyBox::PropertyBox(PropertyContainer *container) : | 
| Chris@0 | 46     m_container(container) | 
| Chris@0 | 47 { | 
| Chris@0 | 48 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 49     std::cerr << "PropertyBox[" << this << "(\"" << | 
| Chris@0 | 50 	container->getPropertyContainerName().toStdString() << "\")]::PropertyBox" << std::endl; | 
| Chris@0 | 51 #endif | 
| Chris@0 | 52 | 
| Chris@34 | 53     m_mainBox = new QVBoxLayout; | 
| Chris@34 | 54     setLayout(m_mainBox); | 
| Chris@33 | 55 | 
| Chris@34 | 56     m_mainWidget = new QWidget; | 
| Chris@34 | 57     m_mainBox->addWidget(m_mainWidget); | 
| Chris@34 | 58     m_mainBox->insertStretch(1, 10); | 
| Chris@33 | 59 | 
| Chris@34 | 60     m_viewPlayFrame = 0; | 
| Chris@34 | 61     populateViewPlayFrame(); | 
| Chris@33 | 62 | 
| Chris@0 | 63     m_layout = new QGridLayout; | 
| Chris@34 | 64     m_layout->setMargin(0); | 
| Chris@33 | 65     m_mainWidget->setLayout(m_layout); | 
| Chris@0 | 66 | 
| Chris@34 | 67     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@0 | 68 | 
| Chris@0 | 69     blockSignals(true); | 
| Chris@0 | 70 | 
| Chris@0 | 71     size_t i; | 
| Chris@0 | 72 | 
| Chris@0 | 73     for (i = 0; i < properties.size(); ++i) { | 
| Chris@0 | 74 	updatePropertyEditor(properties[i]); | 
| Chris@0 | 75     } | 
| Chris@0 | 76 | 
| Chris@0 | 77     blockSignals(false); | 
| Chris@0 | 78 | 
| Chris@0 | 79     m_layout->setRowStretch(m_layout->rowCount(), 10); | 
| Chris@0 | 80 | 
| Chris@0 | 81 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 82     std::cerr << "PropertyBox[" << this << "]::PropertyBox returning" << std::endl; | 
| Chris@0 | 83 #endif | 
| Chris@0 | 84 } | 
| Chris@0 | 85 | 
| Chris@0 | 86 PropertyBox::~PropertyBox() | 
| Chris@0 | 87 { | 
| Chris@0 | 88 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@33 | 89     std::cerr << "PropertyBox[" << this << "]::~PropertyBox" << std::endl; | 
| Chris@0 | 90 #endif | 
| Chris@0 | 91 } | 
| Chris@0 | 92 | 
| Chris@0 | 93 void | 
| Chris@34 | 94 PropertyBox::populateViewPlayFrame() | 
| Chris@33 | 95 { | 
| Chris@36 | 96 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@34 | 97     std::cerr << "PropertyBox(" << m_container << ")::populateViewPlayFrame" << std::endl; | 
| Chris@36 | 98 #endif | 
| Chris@34 | 99 | 
| Chris@34 | 100     if (m_viewPlayFrame) { | 
| Chris@34 | 101 	delete m_viewPlayFrame; | 
| Chris@34 | 102 	m_viewPlayFrame = 0; | 
| Chris@34 | 103     } | 
| Chris@34 | 104 | 
| Chris@34 | 105     if (!m_container) return; | 
| Chris@34 | 106 | 
| Chris@34 | 107     Layer *layer = dynamic_cast<Layer *>(m_container); | 
| Chris@34 | 108     if (layer) { | 
| Chris@34 | 109 	connect(layer, SIGNAL(modelReplaced()), | 
| Chris@34 | 110 		this, SLOT(populateViewPlayFrame())); | 
| Chris@34 | 111     } | 
| Chris@34 | 112 | 
| Chris@34 | 113     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@33 | 114     if (!params && !layer) return; | 
| Chris@33 | 115 | 
| Chris@34 | 116     m_viewPlayFrame = new QFrame; | 
| Chris@34 | 117     m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); | 
| Chris@34 | 118     m_mainBox->addWidget(m_viewPlayFrame); | 
| Chris@34 | 119 | 
| Chris@34 | 120     QHBoxLayout *layout = new QHBoxLayout; | 
| Chris@34 | 121     m_viewPlayFrame->setLayout(layout); | 
| Chris@34 | 122 | 
| Chris@34 | 123     layout->setMargin(layout->margin() / 2); | 
| Chris@34 | 124 | 
| Chris@36 | 125 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@34 | 126     std::cerr << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName().toStdString() << ") params " << params << std::endl; | 
| Chris@36 | 127 #endif | 
| Chris@36 | 128 | 
| Chris@33 | 129     if (layer) { | 
| Chris@34 | 130 	QLabel *showLabel = new QLabel(tr("Show")); | 
| Chris@34 | 131 	layout->addWidget(showLabel); | 
| Chris@34 | 132 	layout->setAlignment(showLabel, Qt::AlignVCenter); | 
| Chris@34 | 133 | 
| Chris@33 | 134 	LEDButton *showButton = new LEDButton(Qt::blue); | 
| Chris@33 | 135 	layout->addWidget(showButton); | 
| Chris@47 | 136 	connect(showButton, SIGNAL(stateChanged(bool)), | 
| Chris@47 | 137 		this, SIGNAL(showLayer(bool))); | 
| Chris@34 | 138 	layout->setAlignment(showButton, Qt::AlignVCenter); | 
| Chris@33 | 139     } | 
| Chris@33 | 140 | 
| Chris@33 | 141     if (params) { | 
| Chris@34 | 142 | 
| Chris@34 | 143 	QLabel *playLabel = new QLabel(tr("Play")); | 
| Chris@34 | 144 	layout->addWidget(playLabel); | 
| Chris@34 | 145 	layout->setAlignment(playLabel, Qt::AlignVCenter); | 
| Chris@34 | 146 | 
| Chris@33 | 147 	LEDButton *playButton = new LEDButton(Qt::darkGreen); | 
| Chris@33 | 148 	layout->addWidget(playButton); | 
| Chris@33 | 149 	connect(playButton, SIGNAL(stateChanged(bool)), | 
| Chris@33 | 150 		params, SLOT(setPlayAudible(bool))); | 
| Chris@34 | 151 	connect(params, SIGNAL(playAudibleChanged(bool)), | 
| Chris@34 | 152 		playButton, SLOT(setState(bool))); | 
| Chris@34 | 153 	layout->setAlignment(playButton, Qt::AlignVCenter); | 
| Chris@34 | 154 | 
| Chris@34 | 155 	layout->insertStretch(-1, 10); | 
| Chris@34 | 156 | 
| Chris@63 | 157         if (params->getPlayPluginId() != "") { | 
| Chris@64 | 158             QPushButton *pluginButton = new QPushButton(QIcon(":icons/faders.png"), ""); | 
| Chris@64 | 159             pluginButton->setFixedWidth(24); | 
| Chris@64 | 160             pluginButton->setFixedHeight(24); | 
| Chris@63 | 161             layout->addWidget(pluginButton); | 
| Chris@63 | 162             connect(pluginButton, SIGNAL(clicked()), | 
| Chris@63 | 163                     this, SLOT(editPlugin())); | 
| Chris@63 | 164         } | 
| Chris@63 | 165 | 
| Chris@34 | 166 	AudioDial *gainDial = new AudioDial; | 
| Chris@34 | 167 	layout->addWidget(gainDial); | 
| Chris@34 | 168 	gainDial->setMeterColor(Qt::darkRed); | 
| Chris@34 | 169 	gainDial->setMinimum(-50); | 
| Chris@34 | 170 	gainDial->setMaximum(50); | 
| Chris@34 | 171 	gainDial->setPageStep(1); | 
| Chris@34 | 172 	gainDial->setFixedWidth(24); | 
| Chris@34 | 173 	gainDial->setFixedHeight(24); | 
| Chris@34 | 174 	gainDial->setNotchesVisible(false); | 
| Chris@57 | 175 	gainDial->setToolTip(tr("Playback Level")); | 
| Chris@34 | 176 	gainDial->setDefaultValue(0); | 
| Chris@34 | 177 	connect(gainDial, SIGNAL(valueChanged(int)), | 
| Chris@34 | 178 		this, SLOT(playGainDialChanged(int))); | 
| Chris@34 | 179 	connect(params, SIGNAL(playGainChanged(float)), | 
| Chris@34 | 180 		this, SLOT(playGainChanged(float))); | 
| Chris@34 | 181 	connect(this, SIGNAL(changePlayGain(float)), | 
| Chris@34 | 182 		params, SLOT(setPlayGain(float))); | 
| Chris@34 | 183 	connect(this, SIGNAL(changePlayGainDial(int)), | 
| Chris@34 | 184 		gainDial, SLOT(setValue(int))); | 
| Chris@34 | 185 	layout->setAlignment(gainDial, Qt::AlignVCenter); | 
| Chris@34 | 186 | 
| Chris@34 | 187 	AudioDial *panDial = new AudioDial; | 
| Chris@34 | 188 	layout->addWidget(panDial); | 
| Chris@34 | 189 	panDial->setMeterColor(Qt::darkGreen); | 
| Chris@34 | 190 	panDial->setMinimum(-50); | 
| Chris@34 | 191 	panDial->setMaximum(50); | 
| Chris@34 | 192 	panDial->setPageStep(1); | 
| Chris@34 | 193 	panDial->setFixedWidth(24); | 
| Chris@34 | 194 	panDial->setFixedHeight(24); | 
| Chris@34 | 195 	panDial->setNotchesVisible(false); | 
| Chris@57 | 196 	panDial->setToolTip(tr("Playback Pan / Balance")); | 
| Chris@34 | 197 	panDial->setDefaultValue(0); | 
| Chris@34 | 198 	connect(panDial, SIGNAL(valueChanged(int)), | 
| Chris@34 | 199 		this, SLOT(playPanDialChanged(int))); | 
| Chris@34 | 200 	connect(params, SIGNAL(playPanChanged(float)), | 
| Chris@34 | 201 		this, SLOT(playPanChanged(float))); | 
| Chris@34 | 202 	connect(this, SIGNAL(changePlayPan(float)), | 
| Chris@34 | 203 		params, SLOT(setPlayPan(float))); | 
| Chris@34 | 204 	connect(this, SIGNAL(changePlayPanDial(int)), | 
| Chris@34 | 205 		panDial, SLOT(setValue(int))); | 
| Chris@34 | 206 	layout->setAlignment(panDial, Qt::AlignVCenter); | 
| Chris@34 | 207 | 
| Chris@34 | 208     } else { | 
| Chris@34 | 209 | 
| Chris@34 | 210 	layout->insertStretch(-1, 10); | 
| Chris@33 | 211     } | 
| Chris@33 | 212 } | 
| Chris@33 | 213 | 
| Chris@33 | 214 void | 
| Chris@0 | 215 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name) | 
| Chris@0 | 216 { | 
| Chris@0 | 217     PropertyContainer::PropertyType type = m_container->getPropertyType(name); | 
| Chris@0 | 218     int row = m_layout->rowCount(); | 
| Chris@0 | 219 | 
| Chris@0 | 220     int min = 0, max = 0, value = 0; | 
| Chris@0 | 221     value = m_container->getPropertyRangeAndValue(name, &min, &max); | 
| Chris@0 | 222 | 
| Chris@0 | 223     bool have = (m_propertyControllers.find(name) != | 
| Chris@0 | 224 		 m_propertyControllers.end()); | 
| Chris@0 | 225 | 
| Chris@0 | 226     QString groupName = m_container->getPropertyGroupName(name); | 
| Chris@87 | 227     QString propertyLabel = m_container->getPropertyLabel(name); | 
| Chris@0 | 228 | 
| Chris@0 | 229 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 230     std::cerr << "PropertyBox[" << this | 
| Chris@0 | 231 	      << "(\"" << m_container->getPropertyContainerName().toStdString() | 
| Chris@0 | 232 	      << "\")]"; | 
| Chris@0 | 233     std::cerr << "::updatePropertyEditor(\"" << name.toStdString() << "\"):"; | 
| Chris@0 | 234     std::cerr << " value " << value << ", have " << have << ", group \"" | 
| Chris@0 | 235 	      << groupName.toStdString() << "\"" << std::endl; | 
| Chris@0 | 236 #endif | 
| Chris@0 | 237 | 
| Chris@0 | 238     bool inGroup = (groupName != QString()); | 
| Chris@0 | 239 | 
| Chris@0 | 240     if (!have) { | 
| Chris@0 | 241 	if (inGroup) { | 
| Chris@0 | 242 	    if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { | 
| Chris@0 | 243 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 244 		std::cerr << "PropertyBox: adding label \"" << groupName.toStdString() << "\" and frame for group for \"" << name.toStdString() << "\"" << std::endl; | 
| Chris@0 | 245 #endif | 
| Chris@33 | 246 		m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0); | 
| Chris@33 | 247 		QFrame *frame = new QFrame(m_mainWidget); | 
| Chris@0 | 248 		m_layout->addWidget(frame, row, 1, 1, 2); | 
| Chris@0 | 249 		m_groupLayouts[groupName] = new QHBoxLayout; | 
| Chris@0 | 250 		m_groupLayouts[groupName]->setMargin(0); | 
| Chris@0 | 251 		frame->setLayout(m_groupLayouts[groupName]); | 
| Chris@0 | 252 	    } | 
| Chris@0 | 253 	} else { | 
| Chris@0 | 254 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@87 | 255 	    std::cerr << "PropertyBox: adding label \"" << propertyLabel.toStdString() << "\"" << std::endl; | 
| Chris@0 | 256 #endif | 
| Chris@87 | 257 	    m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0); | 
| Chris@0 | 258 	} | 
| Chris@0 | 259     } | 
| Chris@0 | 260 | 
| Chris@0 | 261     switch (type) { | 
| Chris@0 | 262 | 
| Chris@0 | 263     case PropertyContainer::ToggleProperty: | 
| Chris@0 | 264     { | 
| Chris@0 | 265 	QCheckBox *cb; | 
| Chris@0 | 266 | 
| Chris@0 | 267 	if (have) { | 
| Chris@0 | 268 	    cb = dynamic_cast<QCheckBox *>(m_propertyControllers[name]); | 
| Chris@0 | 269 	    assert(cb); | 
| Chris@0 | 270 	} else { | 
| Chris@0 | 271 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 272 	    std::cerr << "PropertyBox: creating new checkbox" << std::endl; | 
| Chris@0 | 273 #endif | 
| Chris@0 | 274 	    cb = new QCheckBox(); | 
| Chris@0 | 275 	    cb->setObjectName(name); | 
| Chris@0 | 276 	    connect(cb, SIGNAL(stateChanged(int)), | 
| Chris@0 | 277 		    this, SLOT(propertyControllerChanged(int))); | 
| Chris@0 | 278 	    if (inGroup) { | 
| Chris@0 | 279 		cb->setToolTip(name); | 
| Chris@0 | 280 		m_groupLayouts[groupName]->addWidget(cb); | 
| Chris@0 | 281 	    } else { | 
| Chris@0 | 282 		m_layout->addWidget(cb, row, 1, 1, 2); | 
| Chris@0 | 283 	    } | 
| Chris@0 | 284 	    m_propertyControllers[name] = cb; | 
| Chris@0 | 285 	} | 
| Chris@0 | 286 | 
| Chris@55 | 287 	if (cb->isChecked() != (value > 0)) { | 
| Chris@55 | 288 	    cb->blockSignals(true); | 
| Chris@55 | 289 	    cb->setChecked(value > 0); | 
| Chris@55 | 290 	    cb->blockSignals(false); | 
| Chris@55 | 291 	} | 
| Chris@0 | 292 	break; | 
| Chris@0 | 293     } | 
| Chris@0 | 294 | 
| Chris@0 | 295     case PropertyContainer::RangeProperty: | 
| Chris@0 | 296     { | 
| Chris@0 | 297 	AudioDial *dial; | 
| Chris@0 | 298 | 
| Chris@0 | 299 	if (have) { | 
| Chris@0 | 300 	    dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]); | 
| Chris@0 | 301 	    assert(dial); | 
| Chris@0 | 302 	} else { | 
| Chris@0 | 303 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 304 	    std::cerr << "PropertyBox: creating new dial" << std::endl; | 
| Chris@0 | 305 #endif | 
| Chris@0 | 306 	    dial = new AudioDial(); | 
| Chris@0 | 307 	    dial->setObjectName(name); | 
| Chris@0 | 308 	    dial->setMinimum(min); | 
| Chris@0 | 309 	    dial->setMaximum(max); | 
| Chris@0 | 310 	    dial->setPageStep(1); | 
| Chris@34 | 311 	    dial->setNotchesVisible((max - min) <= 12); | 
| Chris@34 | 312 	    dial->setDefaultValue(value); | 
| Chris@0 | 313 	    connect(dial, SIGNAL(valueChanged(int)), | 
| Chris@0 | 314 		    this, SLOT(propertyControllerChanged(int))); | 
| Chris@0 | 315 | 
| Chris@0 | 316 	    if (inGroup) { | 
| Chris@0 | 317 		dial->setFixedWidth(24); | 
| Chris@0 | 318 		dial->setFixedHeight(24); | 
| Chris@0 | 319 		dial->setToolTip(name); | 
| Chris@0 | 320 		m_groupLayouts[groupName]->addWidget(dial); | 
| Chris@0 | 321 	    } else { | 
| Chris@0 | 322 		dial->setFixedWidth(32); | 
| Chris@0 | 323 		dial->setFixedHeight(32); | 
| Chris@0 | 324 		m_layout->addWidget(dial, row, 1); | 
| Chris@33 | 325 		QLabel *label = new QLabel(m_mainWidget); | 
| Chris@0 | 326 		connect(dial, SIGNAL(valueChanged(int)), | 
| Chris@0 | 327 			label, SLOT(setNum(int))); | 
| Chris@0 | 328 		label->setNum(value); | 
| Chris@0 | 329 		m_layout->addWidget(label, row, 2); | 
| Chris@0 | 330 	    } | 
| Chris@0 | 331 | 
| Chris@0 | 332 	    m_propertyControllers[name] = dial; | 
| Chris@0 | 333 	} | 
| Chris@0 | 334 | 
| Chris@55 | 335 	if (dial->value() != value) { | 
| Chris@55 | 336 	    dial->blockSignals(true); | 
| Chris@55 | 337 	    dial->setValue(value); | 
| Chris@55 | 338 	    dial->blockSignals(false); | 
| Chris@55 | 339 	} | 
| Chris@0 | 340 	break; | 
| Chris@0 | 341     } | 
| Chris@0 | 342 | 
| Chris@0 | 343     case PropertyContainer::ValueProperty: | 
| Chris@0 | 344     { | 
| Chris@0 | 345 	QComboBox *cb; | 
| Chris@0 | 346 | 
| Chris@0 | 347 	if (have) { | 
| Chris@0 | 348 	    cb = dynamic_cast<QComboBox *>(m_propertyControllers[name]); | 
| Chris@0 | 349 	    assert(cb); | 
| Chris@0 | 350 	} else { | 
| Chris@0 | 351 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@0 | 352 	    std::cerr << "PropertyBox: creating new combobox" << std::endl; | 
| Chris@0 | 353 #endif | 
| Chris@0 | 354 | 
| Chris@0 | 355 	    cb = new QComboBox(); | 
| Chris@0 | 356 	    cb->setObjectName(name); | 
| Chris@0 | 357 	    for (int i = min; i <= max; ++i) { | 
| Chris@0 | 358 		cb->addItem(m_container->getPropertyValueLabel(name, i)); | 
| Chris@0 | 359 	    } | 
| Chris@0 | 360 	    connect(cb, SIGNAL(activated(int)), | 
| Chris@0 | 361 		    this, SLOT(propertyControllerChanged(int))); | 
| Chris@0 | 362 	    if (inGroup) { | 
| Chris@0 | 363 		cb->setToolTip(name); | 
| Chris@0 | 364 		m_groupLayouts[groupName]->addWidget(cb); | 
| Chris@0 | 365 	    } else { | 
| Chris@0 | 366 		m_layout->addWidget(cb, row, 1, 1, 2); | 
| Chris@0 | 367 	    } | 
| Chris@0 | 368 	    m_propertyControllers[name] = cb; | 
| Chris@0 | 369 	} | 
| Chris@0 | 370 | 
| Chris@55 | 371 	if (cb->currentIndex() != value) { | 
| Chris@55 | 372 	    cb->blockSignals(true); | 
| Chris@55 | 373 	    cb->setCurrentIndex(value); | 
| Chris@55 | 374 	    cb->blockSignals(false); | 
| Chris@55 | 375 	} | 
| Chris@0 | 376 | 
| Chris@0 | 377 #ifdef Q_WS_MAC | 
| Chris@0 | 378 	// Crashes on startup without this, for some reason | 
| Chris@0 | 379 	cb->setMinimumSize(QSize(10, 10)); | 
| Chris@0 | 380 #endif | 
| Chris@0 | 381 | 
| Chris@0 | 382 	break; | 
| Chris@0 | 383     } | 
| Chris@0 | 384 | 
| Chris@0 | 385     default: | 
| Chris@0 | 386 	break; | 
| Chris@0 | 387     } | 
| Chris@0 | 388 } | 
| Chris@0 | 389 | 
| Chris@0 | 390 void | 
| Chris@0 | 391 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc) | 
| Chris@0 | 392 { | 
| Chris@0 | 393     if (pc != m_container) return; | 
| Chris@0 | 394 | 
| Chris@55 | 395 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@55 | 396     std::cerr << "PropertyBox::propertyContainerPropertyChanged" << std::endl; | 
| Chris@55 | 397 #endif | 
| Chris@55 | 398 | 
| Chris@0 | 399     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@0 | 400     size_t i; | 
| Chris@0 | 401 | 
| Chris@0 | 402     blockSignals(true); | 
| Chris@0 | 403 | 
| Chris@0 | 404     for (i = 0; i < properties.size(); ++i) { | 
| Chris@0 | 405 	updatePropertyEditor(properties[i]); | 
| Chris@0 | 406     } | 
| Chris@0 | 407 | 
| Chris@0 | 408     blockSignals(false); | 
| Chris@0 | 409 } | 
| Chris@0 | 410 | 
| Chris@0 | 411 void | 
| Chris@0 | 412 PropertyBox::propertyControllerChanged(int value) | 
| Chris@0 | 413 { | 
| Chris@0 | 414     QObject *obj = sender(); | 
| Chris@0 | 415     QString name = obj->objectName(); | 
| Chris@0 | 416 | 
| Chris@34 | 417 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@33 | 418     std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString() | 
| Chris@33 | 419 	      << ", " << value << ")" << std::endl; | 
| Chris@34 | 420 #endif | 
| Chris@0 | 421 | 
| Chris@0 | 422     PropertyContainer::PropertyType type = m_container->getPropertyType(name); | 
| Chris@0 | 423 | 
| Chris@0 | 424     if (type != PropertyContainer::InvalidProperty) { | 
| Chris@55 | 425 	m_container->setPropertyWithCommand(name, value); | 
| Chris@0 | 426     } | 
| Chris@0 | 427 | 
| Chris@0 | 428     if (type == PropertyContainer::RangeProperty) { | 
| Chris@0 | 429 	AudioDial *dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]); | 
| Chris@0 | 430 	if (dial) { | 
| Chris@0 | 431 	    dial->setToolTip(QString("%1: %2").arg(name).arg(value)); | 
| Chris@0 | 432 	    //!!! unfortunately this doesn't update an already-visible tooltip | 
| Chris@0 | 433 	} | 
| Chris@0 | 434     } | 
| Chris@0 | 435 } | 
| Chris@0 | 436 | 
| Chris@34 | 437 void | 
| Chris@34 | 438 PropertyBox::playGainChanged(float gain) | 
| Chris@34 | 439 { | 
| Chris@34 | 440     int dialValue = lrint(log10(gain) * 20.0); | 
| Chris@34 | 441     if (dialValue < -50) dialValue = -50; | 
| Chris@34 | 442     if (dialValue >  50) dialValue =  50; | 
| Chris@34 | 443     emit changePlayGainDial(dialValue); | 
| Chris@34 | 444 } | 
| Chris@34 | 445 | 
| Chris@34 | 446 void | 
| Chris@34 | 447 PropertyBox::playGainDialChanged(int dialValue) | 
| Chris@34 | 448 { | 
| Chris@34 | 449     float gain = pow(10, float(dialValue) / 20.0); | 
| Chris@34 | 450     emit changePlayGain(gain); | 
| Chris@34 | 451 } | 
| Chris@34 | 452 | 
| Chris@34 | 453 void | 
| Chris@34 | 454 PropertyBox::playPanChanged(float pan) | 
| Chris@34 | 455 { | 
| Chris@34 | 456     int dialValue = lrint(pan * 50.0); | 
| Chris@34 | 457     if (dialValue < -50) dialValue = -50; | 
| Chris@34 | 458     if (dialValue >  50) dialValue =  50; | 
| Chris@34 | 459     emit changePlayPanDial(dialValue); | 
| Chris@34 | 460 } | 
| Chris@34 | 461 | 
| Chris@34 | 462 void | 
| Chris@34 | 463 PropertyBox::playPanDialChanged(int dialValue) | 
| Chris@34 | 464 { | 
| Chris@34 | 465     float pan = float(dialValue) / 50.0; | 
| Chris@34 | 466     if (pan < -1.0) pan = -1.0; | 
| Chris@34 | 467     if (pan >  1.0) pan =  1.0; | 
| Chris@34 | 468     emit changePlayPan(pan); | 
| Chris@34 | 469 } | 
| Chris@0 | 470 | 
| Chris@63 | 471 void | 
| Chris@63 | 472 PropertyBox::editPlugin() | 
| Chris@63 | 473 { | 
| Chris@63 | 474     //!!! should probably just emit and let something else do this | 
| Chris@63 | 475 | 
| Chris@63 | 476     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@63 | 477     if (!params) return; | 
| Chris@63 | 478 | 
| Chris@63 | 479     QString pluginId = params->getPlayPluginId(); | 
| Chris@63 | 480     QString configurationXml = params->getPlayPluginConfiguration(); | 
| Chris@63 | 481 | 
| Chris@63 | 482     RealTimePluginFactory *factory = | 
| Chris@63 | 483 	RealTimePluginFactory::instanceFor(pluginId); | 
| Chris@63 | 484     if (!factory) return; | 
| Chris@63 | 485 | 
| Chris@63 | 486     RealTimePluginInstance *instance = | 
| Chris@63 | 487         factory->instantiatePlugin(pluginId, 0, 0, 48000, 1024, 1); | 
| Chris@63 | 488     if (!instance) return; | 
| Chris@63 | 489 | 
| Chris@71 | 490     PluginXml(instance).setParametersFromXml(configurationXml); | 
| Chris@63 | 491 | 
| Chris@69 | 492     PluginParameterDialog *dialog = new PluginParameterDialog(instance, -1, -1, -1); | 
| Chris@64 | 493     connect(dialog, SIGNAL(pluginConfigurationChanged(QString)), | 
| Chris@64 | 494             this, SLOT(pluginConfigurationChanged(QString))); | 
| Chris@64 | 495 | 
| Chris@63 | 496     if (dialog->exec() == QDialog::Accepted) { | 
| Chris@71 | 497         params->setPlayPluginConfiguration(PluginXml(instance).toXmlString()); | 
| Chris@64 | 498     } else { | 
| Chris@64 | 499         // restore in case we mucked about with the configuration | 
| Chris@64 | 500         // as a consequence of signals from the dialog | 
| Chris@64 | 501         params->setPlayPluginConfiguration(configurationXml); | 
| Chris@63 | 502     } | 
| Chris@63 | 503 | 
| Chris@63 | 504     delete dialog; | 
| Chris@63 | 505     delete instance; | 
| Chris@63 | 506 } | 
| Chris@63 | 507 | 
| Chris@64 | 508 void | 
| Chris@64 | 509 PropertyBox::pluginConfigurationChanged(QString configurationXml) | 
| Chris@64 | 510 { | 
| Chris@64 | 511     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@64 | 512     if (!params) return; | 
| Chris@64 | 513 | 
| Chris@64 | 514     params->setPlayPluginConfiguration(configurationXml); | 
| Chris@64 | 515 } | 
| Chris@64 | 516 | 
| Chris@64 | 517 | 
| Chris@64 | 518 | 
| Chris@0 | 519 #ifdef INCLUDE_MOCFILES | 
| Chris@0 | 520 #include "PropertyBox.moc.cpp" | 
| Chris@0 | 521 #endif | 
| Chris@0 | 522 |