Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoftpatchEditor #469

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
db575a0
added empty Softpatch Editor Window
offtools Mar 12, 2015
a81b4b6
*Softpatch Dialog (Fixture Tree, change Channels)
offtools Mar 13, 2015
5526bcb
*Softpatcheditor (works only on first universe for now, due bug in
offtools Mar 14, 2015
3150d30
*fix for crashing SimpleDesk crashing, when moving Fixture to different
offtools Mar 16, 2015
40eb3d7
cleanup, removed unused QTextStream
offtools Mar 16, 2015
6582f32
softpatch now works in all universes (cross universe patching is not
offtools Mar 16, 2015
a6389ee
softpatcheditor FIXME added
offtools Mar 16, 2015
e7d7d5d
fixed overlapping channel test
offtools Mar 16, 2015
b825276
added Channel Test Button, "preview" of the patched Channel
offtools Mar 16, 2015
fc2ffe7
SoftpatchEditor, fixed duplicate Search and View
offtools Mar 21, 2015
2140291
SoftpatchEditor: fixed init of count in hasDupliateChannels
offtools Mar 21, 2015
d580ca5
Update MonitorFixtures channels and values after Fixture was changed
offtools Mar 21, 2015
b156c62
Fix for occupied channels in Doc::m_addresses during softpatch
offtools Mar 22, 2015
cebfd70
*Test limited to Dimmer only Fixtures
offtools Mar 22, 2015
da72e6f
Merge remote-tracking branch 'upstream/master' into softpatch
offtools Mar 23, 2015
e26cba8
Softpatch now works on universe level, dumpOutput sends patched values
offtools Mar 26, 2015
7b9fc29
Merge remote-tracking branch 'upstream/master' into softpatch
offtools Mar 29, 2015
deae9fe
TODO
offtools Mar 29, 2015
99e51e6
Merge remote-tracking branch 'upstream/master' into softpatch
offtools Mar 30, 2015
d6716cb
Merge remote-tracking branch 'upstream/master' into softpatch
offtools Mar 30, 2015
8593c1d
Softpatch:
offtools Mar 30, 2015
af07800
reset Universe (otherwise channel values will stay after switching to
offtools Mar 31, 2015
51af831
fixed dimmer test
offtools Mar 31, 2015
ce158d9
proper reset of patchedValues
offtools Mar 31, 2015
597de64
removed one todo
offtools Mar 31, 2015
52e2796
SoftpatchEditor: added button to clear patch (for Fixtures, not the hole
offtools Mar 31, 2015
9200a6c
SoftpatchEditor/Universe - commented out some debug statements (too much
offtools Mar 31, 2015
35d2e11
reverting changes in fixturemanager (universe change of fixtures fix)…
offtools Apr 6, 2015
0c99d57
cleanup
offtools Apr 6, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion engine/src/doc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ bool Doc::addFixture(Fixture* fixture, quint32 id)
this, SLOT(slotFixtureChanged(quint32)));

/* Keep track of fixture addresses */
for (uint i = fixture->universeAddress();
for (quint32 i = fixture->universeAddress();
i < fixture->universeAddress() + fixture->channels(); i++)
{
m_addresses[i] = id;
Expand Down
4 changes: 3 additions & 1 deletion engine/src/inputoutputmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,10 @@ void InputOutputMap::dumpUniverses()
locker.relock();
}

const QByteArray patched = universe->patchedValues()->mid(0, universe->usedChannels());

// this is where QLC+ sends data to the output plugins
universe->dumpOutput(postGM);
universe->dumpOutput(patched);
}
}
}
Expand Down
192 changes: 187 additions & 5 deletions engine/src/universe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,15 @@ Universe::Universe(quint32 id, GrandMaster *gm, QObject *parent)
, m_hasChanged(false)
, m_preGMValues(new QByteArray(UNIVERSE_SIZE, char(0)))
, m_postGMValues(new QByteArray(UNIVERSE_SIZE, char(0)))
, m_patchedValues(new QByteArray(UNIVERSE_SIZE, char(0)))
, m_patchTable(UNIVERSE_SIZE)
, m_testDimmer(false)
{
m_relativeValues.fill(0, UNIVERSE_SIZE);
m_modifiers.fill(NULL, UNIVERSE_SIZE);

patchOneToOne();

m_name = QString("Universe %1").arg(id + 1);

connect(m_grandMaster, SIGNAL(valueChanged(uchar)),
Expand All @@ -64,13 +69,17 @@ Universe::~Universe()
{
delete m_preGMValues;
delete m_postGMValues;
delete m_patchedValues;
patchClear();
if (m_inputPatch != NULL)
delete m_inputPatch;
if (m_outputPatch != NULL)
delete m_outputPatch;
if (m_fbPatch != NULL)
delete m_fbPatch;

patchClear();

m_inputPatch = NULL;
m_outputPatch = NULL;
m_fbPatch = NULL;
Expand Down Expand Up @@ -197,6 +206,7 @@ void Universe::reset()
{
m_preGMValues->fill(0);
m_postGMValues->fill(0);
m_patchedValues->fill(0);
zeroRelativeValues();
m_modifiers.fill(NULL, UNIVERSE_SIZE);
m_passthrough = false;
Expand All @@ -209,6 +219,11 @@ void Universe::reset(int address, int range)
(*m_preGMValues)[i] = 0;
(*m_postGMValues)[i] = 0;
m_relativeValues[i] = 0;
qDebug() << Q_FUNC_INFO << " address: " << i << " patched channels: " << getPatchedChannels(i);
foreach (uint channel, getPatchedChannels(i))
{
(*m_patchedValues)[channel] = 0;
}
}
}

Expand All @@ -221,6 +236,7 @@ void Universe::zeroIntensityChannels()
(*m_preGMValues)[channel] = 0;
(*m_postGMValues)[channel] = 0;
m_relativeValues[channel] = 0;
(*m_patchedValues)[channel] = 0;
}
}

Expand Down Expand Up @@ -486,6 +502,111 @@ ChannelModifier *Universe::channelModifier(ushort channel)
return m_modifiers.at(channel);
}


/****************************************************************************
* Softpatch
****************************************************************************/

void Universe::patchClear()
{
for (uint i = 0; i < UNIVERSE_SIZE; i++)
{
m_patchTable[i].clear();
}
m_patchHash.clear();
}

void Universe::patchDimmer(uint dimmer, uint channel)
{
//qDebug() << Q_FUNC_INFO << " dimmer: " << dimmer << " channel: " << channel ;
if (dimmer < UNIVERSE_SIZE && channel < UNIVERSE_SIZE)
{
//qDebug() << Q_FUNC_INFO << " dimmer: " << dimmer << " channel: " << channel << " m_patchHash.contains(channel) = " << m_patchHash.contains(channel);
if (m_patchHash.contains(channel))
{
unPatchChannel(channel);
}

if (m_patchTable[dimmer].isEmpty() || !m_patchTable[dimmer].contains(channel))
{
m_patchHash.insert(channel, dimmer);
m_patchTable[dimmer].append(channel);
//qDebug() << Q_FUNC_INFO << " dimmer: " << dimmer << " channel: " << channel;
}
}
}

void Universe::unPatchChannel(uint channel)
{
if (channel < UNIVERSE_SIZE)
{
if (m_patchHash.contains(channel))
{
uint dimmer = m_patchHash[channel];
if (m_patchTable[dimmer].contains(channel))
{
int idx = m_patchTable[dimmer].indexOf(channel);
m_patchTable[dimmer].removeAt(idx);
m_patchHash.remove(channel);
qDebug() << Q_FUNC_INFO << " unpatch: " << channel << " from dimmer: " << dimmer;
}
else
qDebug() << Q_FUNC_INFO << " requested channel not found in dimmer";
}
}
}

void Universe::testDimmer(QList<uint> channels, bool on)
{
m_testDimmer = true;
foreach (uint channel, channels) {
write(channel, on ? uchar(255) : uchar(0));
}
m_testDimmer = false;
}

void Universe::patchOneToOne()
{
resetChanged();
patchClear();
for (uint i = 0; i < UNIVERSE_SIZE; i++)
patchDimmer(i, i);
}

const QList<uint> Universe::getPatchedChannels(uint dimmer) const
{
return m_patchTable[dimmer];
}

uint Universe::getPatchedDimmer(uint channel) const
{
Q_ASSERT(m_patchHash.contains(channel) == true);
return m_patchHash[channel];
}

void Universe::applyPatch(uint dimmer, uchar value)
{
if (!m_testDimmer)
{
foreach (uint channel, m_patchTable[dimmer]) {
if (channel >= m_usedChannels)
m_usedChannels = channel + 1;
(*m_patchedValues)[channel] = value;
}
}
else
{
// testDimmer bypasses the patch table
(*m_patchedValues)[dimmer] = value;
}
}

const QByteArray* Universe::patchedValues() const
{
return m_patchedValues;
}


/****************************************************************************
* Writing
****************************************************************************/
Expand Down Expand Up @@ -528,6 +649,8 @@ bool Universe::write(int channel, uchar value, bool forceLTP)
value = applyGM(channel, value);
(*m_postGMValues)[channel] = char(value);

applyPatch(channel, value);

return true;
}

Expand All @@ -552,11 +675,17 @@ bool Universe::writeRelative(int channel, uchar value)
value = applyGM(channel, value);
(*m_postGMValues)[channel] = char(value);

applyPatch(channel, value);

m_hasChanged = true;

return true;
}

/*********************************************************************
* Load & Save
*********************************************************************/

bool Universe::loadXML(const QDomElement &root, int index, InputOutputMap *ioMap)
{
if (root.tagName() != KXMLQLCUniverse)
Expand Down Expand Up @@ -616,17 +745,47 @@ bool Universe::loadXML(const QDomElement &root, int index, InputOutputMap *ioMap
output = tag.attribute(KXMLQLCUniverseFeedbackLine).toUInt();
ioMap->setOutputPatch(index, plugin, output, true);
}

else if (tag.tagName() == KXMLQLCUniversePatch)
{
/*
* TODO: load only non one to one dimmers (see save)
* patchOneToOne(); instead patchClear();
* just patch whats in the file (nothing if it was one to one)
*/

/* clear Patch */
patchClear();

/* Load Dimmers */
QDomNode dimmerNode = node.firstChildElement();
while (dimmerNode.isNull() == false)
{
QDomElement dimmerEl = dimmerNode.toElement();

if (dimmerEl.tagName() == KXMLQLCUniversePatchDimmer && dimmerEl.hasAttribute(KXMLQLCUniversePatchChannel))
{
uint dimmer = dimmerEl.attribute(KXMLQLCUniversePatchChannel).toUInt();
QString strvals = dimmerEl.text();
if (strvals.isEmpty() == false)
{
QStringList varray = strvals.split(",");
for (int i = 0; i < varray.count(); i++)
{
uint channel = QString(varray.at(i)).toUInt();
//unPatchDimmer(id);
patchDimmer(dimmer, channel);
}
}
}
dimmerNode = dimmerNode.nextSibling();
}
}
node = node.nextSibling();
}

return true;
}

/*********************************************************************
* Load & Save
*********************************************************************/

bool Universe::saveXML(QDomDocument *doc, QDomElement *wksp_root) const
{
Q_ASSERT(doc != NULL);
Expand Down Expand Up @@ -663,6 +822,29 @@ bool Universe::saveXML(QDomDocument *doc, QDomElement *wksp_root) const
root.appendChild(fbp);
}

QDomElement patch = doc->createElement(KXMLQLCUniversePatch);
for (int i = 0; i < UNIVERSE_SIZE; i++ ) {
QDomElement dimmer = doc->createElement(KXMLQLCUniversePatchDimmer);
dimmer.setAttribute(KXMLQLCUniversePatchChannel, i);
QList<uint> dim = getPatchedChannels(i);
/*
* TODO: save only non one to one dimmers
* condition: dim.size() == 1 && dim[0] == i
*/
QListIterator <uint> it(dim);
QString dimValues;
while (it.hasNext())
{
dimValues.append(QString("%1").arg(it.next()));
if(it.hasNext())
dimValues.append(",");
}
QDomText text = doc->createTextNode(dimValues);
dimmer.appendChild(text);
patch.appendChild(dimmer);
}
root.appendChild(patch);

// append universe element
wksp_root->appendChild(root);

Expand Down
Loading