Example #1
0
void MonitorGraphicsView::updateFixture(quint32 id)
{
    Fixture *fxi = m_doc->fixture(id);
    if (fxi == NULL || m_fixtures.contains(id) == false)
        return;

    const QLCFixtureMode *mode = fxi->fixtureMode();
    int width = 0;
    int height = 0;

    if (mode != 0)
    {
        width = mode->physical().width();
        height = mode->physical().height();
    }

    if (width == 0) width = 300;
    if (height == 0) height = 300;


    MonitorFixtureItem *item = m_fixtures[id];
    item->setSize(QSize((width * m_cellPixels) / m_unitValue, (height * m_cellPixels) / m_unitValue));

    item->setPos(realPositionToPixels(item->realPosition().x(), item->realPosition().y()));
}
void MonitorGraphicsView::updateFixture(quint32 id)
{
    Fixture *fxi = m_doc->fixture(id);
    if (fxi == NULL || m_fixtures.contains(id) == false)
        return;

    const QLCFixtureMode *mode = fxi->fixtureMode();
    int width = 0;
    int height = 0;

    if (mode != 0)
    {
        width = mode->physical().width();
        height = mode->physical().height();
    }

    if (fxi->isDimmer())
    {
        width = fxi->heads() * 200;
        height = 200;
    }
    else
    {
        if (width == 0) width = 300;
        if (height == 0) height = 300;
    }

    MonitorFixtureItem *item = m_fixtures[id];
    item->setSize(QSize((width * m_cellPixels) / m_unitValue, (height * m_cellPixels) / m_unitValue));

    qreal realX = m_xOffset + ((item->realPosition().x() * m_cellPixels) / m_unitValue);
    qreal realY = m_yOffset + ((item->realPosition().y() * m_cellPixels) / m_unitValue);

    item->setPos(realX, realY);
}
Example #3
0
void VCXYPadFixture::arm()
{
	Fixture* fxi = NULL;

	fxi = _app->doc()->fixture(m_fixture);
	if (fxi == NULL)
	{
		m_xLSB = KChannelInvalid;
		m_xMSB = KChannelInvalid;
		m_yLSB = KChannelInvalid;
		m_yMSB = KChannelInvalid;
	}
	else
	{
		const QLCFixtureMode* mode = NULL;
		QLCChannel* ch = NULL;

		/* If this fixture has no mode, it's a generic dimmer that
		   can't do pan&tilt anyway. */
		mode = fxi->fixtureMode();
		if (mode == NULL)
		{
			m_xLSB = KChannelInvalid;
			m_xMSB = KChannelInvalid;
			m_yLSB = KChannelInvalid;
			m_yMSB = KChannelInvalid;
			
			return;
		}

		/* Find exact channel numbers for MSB/LSB pan and tilt */
		for (t_channel i = 0; i < mode->channels().size(); i++)
		{
			ch = mode->channel(i);
			Q_ASSERT(ch != NULL);

			if (ch->group() == KQLCChannelGroupPan)
			{
				if (ch->controlByte() == 0)
					m_xMSB = fxi->universeAddress() + i;
				else if (ch->controlByte() == 1)
					m_xLSB = fxi->universeAddress() + i;
			}
			else if (ch->group() == KQLCChannelGroupTilt)
			{
				if (ch->controlByte() == 0)
					m_yMSB = fxi->universeAddress() + i;
				else if (ch->controlByte() == 1)
					m_yLSB = fxi->universeAddress() + i;
			}
		}
	}
}
Example #4
0
void Fixture_Test::loader()
{
    QBuffer buffer;
    buffer.open(QIODevice::WriteOnly | QIODevice::Text);
    QXmlStreamWriter xmlWriter(&buffer);

    xmlWriter.writeStartElement("Fixture");

    xmlWriter.writeTextElement("Channels", "18");
    xmlWriter.writeTextElement("Name", "Foobar");
    xmlWriter.writeTextElement("Universe", "3");
    xmlWriter.writeTextElement("Model", "Foobar");
    xmlWriter.writeTextElement("Mode", "Foobar");
    xmlWriter.writeTextElement("Manufacturer", "Foobar");
    xmlWriter.writeTextElement("ID", "42");
    xmlWriter.writeTextElement("Address", "21");

    xmlWriter.writeEndDocument();
    xmlWriter.setDevice(NULL);
    buffer.close();

    buffer.open(QIODevice::ReadOnly | QIODevice::Text);
    QXmlStreamReader xmlReader(&buffer);
    xmlReader.readNextStartElement();

    QVERIFY(m_doc != NULL);
    QVERIFY(m_doc->fixtures().size() == 0);

    QVERIFY(Fixture::loader(xmlReader, m_doc) == true);
    QVERIFY(m_doc->fixtures().size() == 1);
    QVERIFY(m_doc->fixture(0) == NULL); // No ID auto-assignment

    Fixture* fxi = m_doc->fixture(42);
    QVERIFY(fxi != NULL);
    QVERIFY(fxi->name() == "Foobar");
    QVERIFY(fxi->channels() == 18);
    QVERIFY(fxi->address() == 21);
    QVERIFY(fxi->universe() == 3);
    QVERIFY(fxi->fixtureDef() != NULL);
    QVERIFY(fxi->fixtureMode() != NULL);
}
Example #5
0
/*********************************************************************
 * Status
 *********************************************************************/
QString ChannelsGroup::status(Doc *doc) const
{
    QString info;

    QString title("<TR><TD CLASS='hilite' COLSPAN='3'><CENTER>%1</CENTER></TD></TR>");
    info += "<TABLE COLS='3' WIDTH='100%'>";

    // Fixture title
    info += title.arg(name());

    /********************************************************************
     * Channels
     ********************************************************************/

    // Title row
    info += QString("<TR><TD CLASS='subhi'>%1</TD>").arg(tr("Fixture"));
    info += QString("<TD CLASS='subhi'>%1</TD>").arg(tr("Channel"));
    info += QString("<TD CLASS='subhi'>%1</TD></TR>").arg(tr("Description"));

    foreach (SceneValue value, m_channels)
    {
        Fixture *fixture = doc->fixture(value.fxi);
        if (fixture == NULL)
            return QString();
        const QLCFixtureMode *mode = fixture->fixtureMode();
        QString chInfo("<TR><TD>%1</TD><TD>%2</TD><TD>%3</TD></TR>");
        if (mode != NULL)
        {
            info += chInfo.arg(fixture->name()).arg(value.channel + 1)
                    .arg(mode->channels().at(value.channel)->name());
        }
        else
        {
            info += chInfo.arg(fixture->name()).arg(value.channel + 1)
                    .arg(QString(tr("Channel %1")).arg(value.channel));
        }
    }
Example #6
0
void EFX::arm()
{
	class Scene* startScene = NULL;
	class Scene* stopScene = NULL;
	QLCFixtureMode* mode = NULL;
	QLCChannel* ch = NULL;
	int serialNumber = 0;
	Fixture* fxi = NULL;

	/* Initialization scene */
	if (m_startSceneID != KNoID && m_startSceneEnabled == true)
		startScene = static_cast <class Scene*>
			(_app->doc()->function(m_startSceneID));

	/* De-initialization scene */
	if (m_stopSceneID != KNoID && m_stopSceneEnabled == true)
		stopScene = static_cast <class Scene*>
			(_app->doc()->function(m_stopSceneID));

	QListIterator <EFXFixture*> it(m_fixtures);
	while (it.hasNext() == true)
	{
		EFXFixture* ef = it.next();
		Q_ASSERT(ef != NULL);

		ef->setSerialNumber(serialNumber++);
		ef->setStartScene(startScene);
		ef->setStopScene(stopScene);

		/* If fxi == NULL, the fixture has been destroyed */
		fxi = _app->doc()->fixture(ef->fixture());
		if (fxi == NULL)
			continue;

		/* If this fixture has no mode, it's a generic dimmer that
		   can't do pan&tilt anyway. */
		mode = fxi->fixtureMode();
		if (mode == NULL)
			continue;

		/* Find exact channel numbers for MSB/LSB pan and tilt */
		for (t_channel i = 0; i < mode->channels(); i++)
		{
			ch = mode->channel(i);
			Q_ASSERT(ch != NULL);

			if (ch->group() == KQLCChannelGroupPan)
			{
				if (ch->controlByte() == 0)
				{
					ef->setMsbPanChannel(
						fxi->universeAddress() + i);
				}
				else if (ch->controlByte() == 1)
				{
					ef->setLsbPanChannel(
						fxi->universeAddress() + i);
				}
			}
			else if (ch->group() == KQLCChannelGroupTilt)
			{
				if (ch->controlByte() == 0)
				{
					ef->setMsbTiltChannel(
						fxi->universeAddress() + i);
				}
				else if (ch->controlByte() == 1)
				{
					ef->setLsbTiltChannel(
						fxi->universeAddress() + i);
				}
			}
		}
	}

	/* Choose a point calculation function depending on the algorithm */
	if (m_algorithm == KCircleAlgorithmName)
		pointFunc = circlePoint;
	else if (m_algorithm == KEightAlgorithmName)
		pointFunc = eightPoint;
	else if (m_algorithm == KLineAlgorithmName)
		pointFunc = linePoint;
	else if (m_algorithm == KTriangleAlgorithmName)
		pointFunc = trianglePoint;
	else if (m_algorithm == KDiamondAlgorithmName)
		pointFunc = diamondPoint;
	else if (m_algorithm == KLissajousAlgorithmName)
		pointFunc = lissajousPoint;
	else
		pointFunc = NULL;
}
Example #7
0
void Fixture_Test::loader()
{
    QDomDocument doc;

    QDomElement root = doc.createElement("Fixture");
    doc.appendChild(root);

    QDomElement chs = doc.createElement("Channels");
    QDomText chsText = doc.createTextNode("18");
    chs.appendChild(chsText);
    root.appendChild(chs);

    QDomElement name = doc.createElement("Name");
    QDomText nameText = doc.createTextNode("Foobar");
    name.appendChild(nameText);
    root.appendChild(name);

    QDomElement uni = doc.createElement("Universe");
    QDomText uniText = doc.createTextNode("3");
    uni.appendChild(uniText);
    root.appendChild(uni);

    QDomElement model = doc.createElement("Model");
    QDomText modelText = doc.createTextNode("Foobar");
    model.appendChild(modelText);
    root.appendChild(model);

    QDomElement mode = doc.createElement("Mode");
    QDomText modeText = doc.createTextNode("Foobar");
    mode.appendChild(modeText);
    root.appendChild(mode);

    QDomElement type = doc.createElement("Manufacturer");
    QDomText typeText = doc.createTextNode("Foobar");
    type.appendChild(typeText);
    root.appendChild(type);

    QDomElement id = doc.createElement("ID");
    QDomText idText = doc.createTextNode("42");
    id.appendChild(idText);
    root.appendChild(id);

    QDomElement addr = doc.createElement("Address");
    QDomText addrText = doc.createTextNode("21");
    addr.appendChild(addrText);
    root.appendChild(addr);

    Doc* qlcdoc = new Doc(this, m_fixtureDefCache);
    QVERIFY(qlcdoc != NULL);
    QVERIFY(qlcdoc->fixtures() == 0);

    QVERIFY(Fixture::loader(&root, qlcdoc) == true);
    QVERIFY(qlcdoc->fixtures() == 1);
    QVERIFY(qlcdoc->fixture(0) == NULL); // No ID auto-assignment

    Fixture* fxi = qlcdoc->fixture(42);
    QVERIFY(fxi != NULL);
    QVERIFY(fxi->name() == "Foobar");
    QVERIFY(fxi->channels() == 18);
    QVERIFY(fxi->address() == 21);
    QVERIFY(fxi->universe() == 3);
    QVERIFY(fxi->fixtureDef() == NULL);
    QVERIFY(fxi->fixtureMode() == NULL);

    delete qlcdoc;
}
Example #8
0
void ConsoleChannel::init()
{
    Fixture* fxi = m_doc->fixture(m_fixture);
    //Q_ASSERT(fxi != NULL);

    new QVBoxLayout(this);
    layout()->setSpacing(0);
    layout()->setContentsMargins(0, 2, 0, 2);

    if (fxi != NULL)
    {
        m_presetButton = new QToolButton(this);
        m_presetButton->setStyle(AppUtil::saneStyle());
        layout()->addWidget(m_presetButton);
        layout()->setAlignment(m_presetButton, Qt::AlignHCenter);
        m_presetButton->setIconSize(QSize(32, 32));
        m_presetButton->setMinimumSize(QSize(32, 32));
        m_presetButton->setMaximumSize(QSize(32, 32));
        m_presetButton->setFocusPolicy(Qt::NoFocus);

        /* Create a menu only if channel has sophisticated contents */
        if (fxi->fixtureDef() != NULL && fxi->fixtureMode() != NULL)
            initMenu();
        else
            m_presetButton->setStyleSheet("QToolButton { border-image: url(:/intensity.png) 0 0 0 0 stretch stretch; }");
    }

    /* Value edit */
    m_spin = new QSpinBox(this);
    m_spin->setRange(0, UCHAR_MAX);
    m_spin->setValue(0);
    m_spin->setMinimumWidth(25);
    m_spin->setButtonSymbols(QAbstractSpinBox::NoButtons);
    m_spin->setStyle(AppUtil::saneStyle());
    layout()->addWidget(m_spin);
    m_spin->setAlignment(Qt::AlignCenter);
    m_spin->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
    layout()->setAlignment(m_spin, Qt::AlignHCenter);

    /* Value slider */
    m_slider = new ClickAndGoSlider(this);
    m_slider->setInvertedAppearance(false);
    m_slider->setRange(0, UCHAR_MAX);
    m_slider->setPageStep(1);
    m_slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    m_slider->setFocusPolicy(Qt::NoFocus);
    connect(m_slider, SIGNAL(controlClicked()),
            this, SLOT(slotControlClicked()));

    m_slider->setMinimumWidth(25);
    m_slider->setMaximumWidth(40);
    m_slider->setStyleSheet(
        "QSlider::groove:vertical { background: transparent; width: 32px; } "

        "QSlider::handle:vertical { "
        "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ddd, stop:0.45 #888, stop:0.50 #000, stop:0.55 #888, stop:1 #999);"
        "border: 1px solid #5c5c5c;"
        "border-radius: 4px; margin: 0 -1px; height: 20px; }"

        "QSlider::handle:vertical:hover {"
        "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #eee, stop:0.45 #999, stop:0.50 #ff0000, stop:0.55 #999, stop:1 #ccc);"
        "border: 1px solid #000; }"

        "QSlider::add-page:vertical { background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #78d, stop: 1 #97CDEC );"
        "border: 1px solid #5288A7; margin: 0 13px; }"

        "QSlider::sub-page:vertical { background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #888, stop: 1 #ddd );"
        "border: 1px solid #8E8A86; margin: 0 13px; }"

        "QSlider::handle:vertical:disabled { background: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ddd, stop:0.45 #888, stop:0.50 #444, stop:0.55 #888, stop:1 #999);"
        "border: 1px solid #666; }"
        );
    layout()->addWidget(m_slider);
    //layout()->setAlignment(m_slider, Qt::AlignHCenter);

    /* Channel number label */
    m_label = new QLabel(this);
    m_label->setMinimumWidth(25);
    m_label->setMaximumWidth(80);
    layout()->addWidget(m_label);
    m_label->setAlignment(Qt::AlignCenter);
    m_label->setText(QString::number(m_channel + 1));
    m_label->setFocusPolicy(Qt::NoFocus);
    m_label->setWordWrap(true);

    /* Set tooltip */
    if (fxi == NULL || fxi->isDimmer() == true)
    {
        setToolTip(tr("Intensity"));
    }
    else
    {
        const QLCChannel* ch = fxi->channel(m_channel);
        Q_ASSERT(ch != NULL);
        setToolTip(QString("%1").arg(ch->name()));
    }

    connect(m_spin, SIGNAL(valueChanged(int)), this, SLOT(slotSpinChanged(int)));
    connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(slotSliderChanged(int)));
    connect(this, SIGNAL(toggled(bool)), this, SLOT(slotChecked(bool)));
}
Example #9
0
File: efx.cpp Project: speakman/qlc
/**
 * Prepare this function for running. This is called when
 * the user sets the mode to Operate. Basically allocates everything
 * that is needed to run the function.
 */
void EFX::arm()
{
	class Scene* startScene = NULL;
	class Scene* stopScene = NULL;
	QLCFixtureMode* mode = NULL;
	QLCChannel* ch = NULL;
	t_fixture_id fxi_id = KNoID;
	Fixture* fxi = NULL;
	int channels = 0;
	int order = 0;

	m_channels = 0;

	/* Initialization scene */
	if (m_startSceneID != KNoID && m_startSceneEnabled == true)
	{
		startScene = static_cast <class Scene*>
			(_app->doc()->function(m_startSceneID));
		Q_ASSERT(startScene != NULL);
	}

	/* De-initialization scene */
	if (m_stopSceneID != KNoID && m_stopSceneEnabled == true)
	{
		stopScene = static_cast <class Scene*>
			(_app->doc()->function(m_stopSceneID));
		Q_ASSERT(stopScene != NULL);
	}

	QListIterator <t_function_id> it(m_fixtures);
	while (it.hasNext() == true)
	{
		fxi_id = it.next();
		Q_ASSERT(fxi_id != KNoID);

		EFXFixture ef(this, fxi_id, m_channels, order, m_direction,
			      startScene, stopScene);

		fxi = _app->doc()->fixture(fxi_id);
		Q_ASSERT(fxi != NULL);

		mode = fxi->fixtureMode();
		Q_ASSERT(mode != NULL);

		channels = 0;

		for (t_channel i = 0; i < mode->channels(); i++)
		{
			ch = mode->channel(i);
			Q_ASSERT(ch != NULL);

			if (ch->group() == KQLCChannelGroupPan)
			{
				if (ch->controlByte() == 0)
				{
					ef.setMsbPanChannel(
						fxi->universeAddress() + i);
					channels++;
				}
				else if (ch->controlByte() == 1)
				{
					ef.setLsbPanChannel(
						fxi->universeAddress() + i);
					channels++;
				}
			}
			else if (ch->group() == KQLCChannelGroupTilt)
			{
				if (ch->controlByte() == 0)
				{
					ef.setMsbTiltChannel(
						fxi->universeAddress() + i);
					channels++;
				}
				else if (ch->controlByte() == 1)
				{
					ef.setLsbTiltChannel(
						fxi->universeAddress() + i);
					channels++;
				}
			}
		}

		/* The fixture must have at least an LSB channel for 8bit
		   precision to get accepted into the EFX */
		if (ef.isValid() == true)
		{
			ef.updateSkipThreshold();
			m_runTimeData.append(ef);
			m_channels += channels;
			order++;
		}
	}

	/* Allocate space for channel data that is set to the eventbuffer */
	if (m_channelData == NULL)
		m_channelData = new unsigned int[m_channels];

	/* Allocate space for the event buffer, 1/2 seconds worth of events */
	if (m_eventBuffer == NULL)
		m_eventBuffer = new EventBuffer(m_channels, KFrequency >> 1);

	/* Choose a point calculation function depending on the algorithm */
	if (m_algorithm == KCircleAlgorithmName)
		pointFunc = circlePoint;
	else if (m_algorithm == KEightAlgorithmName)
		pointFunc = eightPoint;
	else if (m_algorithm == KLineAlgorithmName)
		pointFunc = linePoint;
	else if (m_algorithm == KTriangleAlgorithmName)
		pointFunc = trianglePoint;
	else if (m_algorithm == KDiamondAlgorithmName)
		pointFunc = diamondPoint;
	else if (m_algorithm == KLissajousAlgorithmName)
		pointFunc = lissajousPoint;
	else
		pointFunc = NULL;
}
Example #10
0
void MainView2D::createFixtureItem(quint32 fxID, quint16 headIndex, quint16 linkedIndex,
                                   QVector3D pos, bool mmCoords)
{
    if (isEnabled() == false)
        return;

    if (m_gridItem == NULL)
       initialize2DProperties();

    qDebug() << "[MainView2D] Creating fixture with ID" << fxID << headIndex << linkedIndex << "pos:" << pos;

    Fixture *fixture = m_doc->fixture(fxID);
    if (fixture == NULL)
        return;

    quint32 itemID = FixtureUtils::fixtureItemID(fxID, headIndex, linkedIndex);
    QLCFixtureMode *fxMode = fixture->fixtureMode();
    QQuickItem *newFixtureItem = qobject_cast<QQuickItem*>(fixtureComponent->create());
    quint32 itemFlags = m_monProps->fixtureFlags(fxID, headIndex, linkedIndex);

    newFixtureItem->setParentItem(m_gridItem);
    newFixtureItem->setProperty("itemID", itemID);

    if (itemFlags & MonitorProperties::HiddenFlag)
        newFixtureItem->setProperty("visible", false);

    if (fxMode != NULL && fixture->type() != QLCFixtureDef::Dimmer)
    {
        QLCPhysical phy = fxMode->physical();

        //qDebug() << "Current mode fixture heads:" << fxMode->heads().count();
        newFixtureItem->setProperty("headsNumber", fxMode->heads().count());

        if (fixture->channelNumber(QLCChannel::Pan, QLCChannel::MSB) != QLCChannel::invalid())
        {
            int panDeg = phy.focusPanMax();
            if (panDeg == 0) panDeg = 360;
            newFixtureItem->setProperty("panMaxDegrees", panDeg);
        }
        if (fixture->channelNumber(QLCChannel::Tilt, QLCChannel::MSB) != QLCChannel::invalid())
        {
            int tiltDeg = phy.focusTiltMax();
            if (tiltDeg == 0) tiltDeg = 270;
            newFixtureItem->setProperty("tiltMaxDegrees", tiltDeg);
        }
    }

    QPointF itemPos;
    QSizeF size = FixtureUtils::item2DDimension(fixture->type() == QLCFixtureDef::Dimmer ? NULL : fxMode,
                                                m_monProps->pointOfView());

    if (mmCoords == false && (pos.x() != 0 || pos.y() != 0))
    {
        float gridUnits = m_monProps->gridUnits() == MonitorProperties::Meters ? 1000.0 : 304.8;
        itemPos.setX((pos.x() * gridUnits) / m_cellPixels);
        itemPos.setY((pos.y() * gridUnits) / m_cellPixels);
    }

    if (m_monProps->containsItem(fxID, headIndex, linkedIndex))
    {
        itemPos = FixtureUtils::item2DPosition(m_monProps, m_monProps->pointOfView(), pos);
        newFixtureItem->setProperty("rotation",
                                    FixtureUtils::item2DRotation(m_monProps->pointOfView(),
                                                                 m_monProps->fixtureRotation(fxID, headIndex, linkedIndex)));
    }
    else
    {
        itemPos = FixtureUtils::available2DPosition(m_doc, m_monProps->pointOfView(),
                                                    QRectF(itemPos.x(), itemPos.y(), size.width(), size.height()));
        // add the new fixture to the Doc monitor properties
        QVector3D newPos = FixtureUtils::item3DPosition(m_monProps, itemPos, 1000.0);
        m_monProps->setFixturePosition(fxID, headIndex, linkedIndex, newPos);
        m_monProps->setFixtureFlags(fxID, headIndex, linkedIndex, 0);
        Tardis::instance()->enqueueAction(Tardis::FixtureSetPosition, itemID, QVariant(QVector3D(0, 0, 0)), QVariant(newPos));
    }

    newFixtureItem->setProperty("mmXPos", itemPos.x());
    newFixtureItem->setProperty("mmYPos", itemPos.y());
    newFixtureItem->setProperty("mmWidth", size.width());
    newFixtureItem->setProperty("mmHeight", size.height());
    newFixtureItem->setProperty("fixtureName", fixture->name());

    // and finally add the new item to the items map
    m_itemsMap[itemID] = newFixtureItem;

    QByteArray values;
    updateFixture(fixture, values);
}
Example #11
0
void EFX::arm()
{
    int serialNumber = 0;

    Doc* doc = qobject_cast <Doc*> (parent());
    Q_ASSERT(doc != NULL);

    QListIterator <EFXFixture*> it(m_fixtures);
    while (it.hasNext() == true)
    {
        EFXFixture* ef = it.next();
        Q_ASSERT(ef != NULL);

        ef->setSerialNumber(serialNumber++);

        /* If fxi == NULL, the fixture has been destroyed */
        Fixture* fxi = doc->fixture(ef->fixture());
        if (fxi == NULL)
            continue;

        /* If this fixture has no mode, it's a generic dimmer that
           can't do pan&tilt anyway. */
        const QLCFixtureMode* mode = fxi->fixtureMode();
        if (mode == NULL)
            continue;

        QList <quint32> intensityChannels;

        /* Find exact channel numbers for MSB/LSB pan and tilt */
        for (quint32 i = 0; i < quint32(mode->channels().size()); i++)
        {
            QLCChannel* ch = mode->channel(i);
            Q_ASSERT(ch != NULL);

            if (ch->group() == QLCChannel::Pan)
            {
                if (ch->controlByte() == QLCChannel::MSB)
                    ef->setMsbPanChannel(fxi->universeAddress() + i);
                else if (ch->controlByte() == QLCChannel::LSB)
                    ef->setLsbPanChannel(fxi->universeAddress() + i);
            }
            else if (ch->group() == QLCChannel::Tilt)
            {
                if (ch->controlByte() == QLCChannel::MSB)
                    ef->setMsbTiltChannel(fxi->universeAddress() + i);
                else if (ch->controlByte() == QLCChannel::LSB)
                    ef->setLsbTiltChannel(fxi->universeAddress() + i);
            }
            else if (ch->group() == QLCChannel::Intensity &&
                     ch->colour() == QLCChannel::NoColour) // Don't touch RGB/CMY channels
            {
                if (ch->searchCapability(/*D*/"immer", false) != NULL ||
                    ch->searchCapability(/*I*/"ntensity", false) != NULL)
                {
                    intensityChannels << (fxi->universeAddress() + i);
                }
            }
        }

        ef->setIntensityChannels(intensityChannels);
        ef->setFadeBus(fadeBusID());
    }

    Q_ASSERT(m_fader == NULL);
    m_fader = new GenericFader;

    resetElapsed();
}