Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions system/jsonreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ inline unsigned OptionalUInt(const Object &parent, const char *name,
return iter == parent.end() ? default_value : ToNum(*iter).AsUInt();
}

inline int OptionalInt(const Object &parent, const char *name,
int default_value) {
const Object::const_iterator iter = parent.find(name);
return iter == parent.end() ? default_value : ToNum(*iter).AsInt();
}

inline double OptionalDouble(const Object &parent, const char *name,
double default_value) {
const Object::const_iterator iter = parent.find(name);
Expand Down
8 changes: 8 additions & 0 deletions system/jsonwriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ class JsonWriter {
Number(number);
}

template <typename T>
void OptionalNumber(const char* name, T number, T default_value = T(0)) {
if (number != default_value) {
Name(name);
Number(number);
}
}

void Number(double number) { NumberGeneric(number); }

void Number(int number) { IntegerNumber(number); }
Expand Down
36 changes: 18 additions & 18 deletions system/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ void ParseFixtureTypes(const json::Array &node, Management &management) {

DmxChannel ParseDmxChannel(const Object &node) {
DmxChannel channel;
channel.SetUniverse(ToNum(node["universe"]).AsInt());
channel.SetChannel(ToNum(node["channel"]).AsInt());
channel.SetUniverse(OptionalUInt(node, "universe", 0));
channel.SetChannel(ToNum(node["channel"]).AsUInt());
return channel;
}

Expand Down Expand Up @@ -305,9 +305,9 @@ void ParsePresetCollection(const Object &node, Management &management) {
const Array &values = ToArr(node["values"]);
for (const Node &value : values) {
const Object &v = ToObj(value);
Folder &folder = *management.Folders()[ToNum(v["folder"]).AsSize()];
Folder &folder = *management.Folders()[OptionalSize(v, "folder", 0)];
FolderObject &obj = folder.GetChild(ToStr(v["controllable-ref"]));
const size_t inputIndex = ToNum(v["input-index"]).AsSize();
const size_t inputIndex = OptionalSize(v, "input-index", 0);
Controllable *controllable = dynamic_cast<Controllable *>(&obj);
if (controllable == nullptr)
throw std::runtime_error(
Expand All @@ -325,8 +325,8 @@ void ParseSequence(const Object &node, Sequence &sequence,
const Array &inputs = ToArr(node["inputs"]);
for (Node &item_node : inputs) {
const Object &item = ToObj(item_node);
size_t input = ToNum(item["input-index"]).AsSize();
size_t folderId = ToNum(item["folder"]).AsSize();
size_t input = OptionalSize(item, "input-index", 0);
size_t folderId = OptionalSize(item, "folder", 0);
Controllable &c = dynamic_cast<Controllable &>(
management.Folders()[folderId]->GetChild(ToStr(item["name"])));
sequence.Add(c, input);
Expand Down Expand Up @@ -419,8 +419,8 @@ void ParseEffect(const Object &node, Management &management) {
for (const Node &item : connections) {
const Object &c_node = ToObj(item);
const std::string &cName = ToStr(c_node["name"]);
const size_t cInputIndex = ToNum(c_node["input-index"]).AsSize();
const size_t folderId = ToNum(c_node["folder"]).AsSize();
const size_t cInputIndex = OptionalSize(c_node, "input-index", 0);
const size_t folderId = OptionalSize(c_node, "folder", 0);
Folder *folder = management.Folders()[folderId].Get();
effect.AddConnection(dynamic_cast<Controllable &>(folder->GetChild(cName)),
cInputIndex);
Expand All @@ -435,7 +435,7 @@ KeySceneItem &ParseKeySceneItem(const Object &node, Scene &scene) {

ControlSceneItem &ParseControlSceneItem(const Object &node, Scene &scene,
Management &management) {
const size_t folderId = ToNum(node["folder"]).AsSize();
const size_t folderId = OptionalSize(node, "folder", 0);
Folder *folder = management.Folders()[folderId].Get();
Controllable &controllable = static_cast<Controllable &>(
folder->GetChild(ToStr(node["controllable-ref"])));
Expand Down Expand Up @@ -500,21 +500,21 @@ void ParseControls(const Array &node, Management &management) {

SingleSourceValue ParseSingleSourceValue(const Object &object) {
SingleSourceValue result;
result.SetValue(ControlValue(ToNum(object["value"]).AsUInt()));
result.SetTargetValue(ToNum(object["target-value"]).AsUInt());
result.SetFadeSpeed(ToNum(object["fade-speed"]).AsDouble());
result.SetValue(ControlValue(OptionalUInt(object, "value", 0)));
result.SetTargetValue(OptionalUInt(object, "target-value", 0));
result.SetFadeSpeed(OptionalUInt(object, "fade-speed", 0.0));
return result;
}

void ParseSourceValues(const Array &node, Management &management) {
for (const Node &element : node) {
const Object &object = ToObj(element);
size_t folderId = ToNum(object["folder"]).AsSize();
size_t folderId = OptionalSize(object, "folder", 0);
const std::string name = ToStr(object["controllable-ref"]);
Folder *folder = management.Folders()[folderId].Get();
Controllable &controllable =
dynamic_cast<Controllable &>(folder->GetChild(name));
const size_t inputIndex = ToNum(object["input-index"]).AsSize();
const size_t inputIndex = OptionalSize(object, "input-index", 0);
SourceValue &value = management.AddSourceValue(controllable, inputIndex);
value.A() = ParseSingleSourceValue(ToObj(object["a"]));
value.B() = ParseSingleSourceValue(ToObj(object["b"]));
Expand All @@ -525,8 +525,8 @@ void ParseGuiPresetRef(const Object &node, gui::FaderSetState &fader,
Management &management) {
if (node.contains("name")) {
// Old way of storing inputs ; support to be removed at a later time
const size_t input = ToNum(node["input-index"]).AsSize();
const size_t folder_id = ToNum(node["folder"]).AsSize();
const size_t input = OptionalSize(node, "input-index", 0);
const size_t folder_id = OptionalSize(node, "folder", 0);
const std::string name = ToStr(node["name"]);
Folder *folder = management.Folders()[folder_id].Get();
Controllable &controllable =
Expand All @@ -540,8 +540,8 @@ void ParseGuiPresetRef(const Object &node, gui::FaderSetState &fader,
for (const Node &source_value_item : source_value_node) {
const Object &object = ToObj(source_value_item);
if (object.contains("name")) {
const size_t input = ToNum(object["input-index"]).AsSize();
const size_t folder_id = ToNum(object["folder"]).AsSize();
const size_t input = OptionalSize(object, "input-index", 0);
const size_t folder_id = OptionalSize(object, "folder", 0);
const std::string name = ToStr(object["name"]);
Folder *folder = management.Folders()[folder_id].Get();
Controllable &controllable =
Expand Down
2 changes: 2 additions & 0 deletions system/timepattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class TimePattern {

constexpr TimePattern() = default;

bool operator==(const TimePattern& rhs) const = default;

TimePattern(const std::string& date_time_str) {
SetDate(date_time_str);
SetTime(date_time_str.substr(11));
Expand Down
105 changes: 60 additions & 45 deletions system/writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ void writeFolderAttributes(WriteState &state, const FolderObject &obj) {
void writeDmxChannel(WriteState &state, const DmxChannel &dmxChannel,
const char *name) {
state.writer.StartObject(name);
state.writer.Number("universe", dmxChannel.Universe());
if (dmxChannel.Universe() != 0)
state.writer.Number("universe", dmxChannel.Universe());
state.writer.Number("channel", dmxChannel.Channel());
state.writer.EndObject();
}
Expand Down Expand Up @@ -248,19 +249,23 @@ void writeFixtureType(WriteState &state, const FixtureType &fixture_type) {

void writeSingleSourceValue(WriteState &state,
const SingleSourceValue &singleSourceValue) {
state.writer.Number("value", singleSourceValue.Value().UInt());
state.writer.Number("target-value", singleSourceValue.TargetValue());
state.writer.Number("fade-speed", singleSourceValue.FadeSpeed());
if (singleSourceValue.Value())
state.writer.Number("value", singleSourceValue.Value().UInt());
if (singleSourceValue.TargetValue())
state.writer.Number("target-value", singleSourceValue.TargetValue());
if (singleSourceValue.FadeSpeed() != 0.0)
state.writer.Number("fade-speed", singleSourceValue.FadeSpeed());
}

void writeSourceValue(WriteState &state, const SourceValue &sourceValue) {
writeControllable(state, sourceValue.GetControllable());

state.writer.StartObject();
state.writer.String("controllable-ref", sourceValue.GetControllable().Name());
state.writer.Number("input-index", sourceValue.InputIndex());
state.writer.Number("folder",
state.folderIds[&sourceValue.GetControllable().Parent()]);
if (sourceValue.InputIndex())
state.writer.Number("input-index", sourceValue.InputIndex());
state.writer.OptionalNumber(
"folder", state.folderIds[&sourceValue.GetControllable().Parent()]);
state.writer.StartObject("a");
writeSingleSourceValue(state, sourceValue.A());
state.writer.EndObject();
Expand All @@ -275,9 +280,10 @@ void writePresetValue(WriteState &state, const PresetValue &presetValue) {

state.writer.StartObject();
state.writer.String("controllable-ref", presetValue.GetControllable().Name());
state.writer.Number("input-index", presetValue.InputIndex());
state.writer.Number("folder",
state.folderIds[&presetValue.GetControllable().Parent()]);
if (presetValue.InputIndex())
state.writer.Number("input-index", presetValue.InputIndex());
state.writer.OptionalNumber(
"folder", state.folderIds[&presetValue.GetControllable().Parent()]);
state.writer.Number("value", presetValue.Value().UInt());
state.writer.EndObject();
}
Expand Down Expand Up @@ -338,9 +344,10 @@ void writeSequence(WriteState &state, const Sequence &sequence) {
state.writer.StartArray("inputs");
for (const Input &input : sequence.List()) {
state.writer.StartObject();
state.writer.Number("input-index", input.InputIndex());
state.writer.Number("folder",
state.folderIds[&input.GetControllable()->Parent()]);
if (input.InputIndex())
state.writer.Number("input-index", input.InputIndex());
state.writer.OptionalNumber(
"folder", state.folderIds[&input.GetControllable()->Parent()]);
state.writer.String("name", input.GetControllable()->Name());
state.writer.EndObject();
}
Expand Down Expand Up @@ -396,44 +403,51 @@ void writeEffect(WriteState &state, const Effect &effect) {
state.writer.String("effect_type", EffectTypeToName(effect.GetType()));
std::unique_ptr<PropertySet> ps = PropertySet::Make(effect);

std::unique_ptr<Effect> default_effect = Effect::Make(effect.GetType());

// the number and name of the effect controls are implied from the
// effect type, so do not require to be stored.

state.writer.StartArray("properties");
for (const Property &p : *ps) {
state.writer.StartObject();
state.writer.String("name", p.Name());
switch (p.GetType()) {
case PropertyType::Choice:
state.writer.String("value", ps->GetChoice(p));
break;
case PropertyType::ControlValue:
state.writer.Number("value", ps->GetControlValue(p));
break;
case PropertyType::Duration:
state.writer.Number("value", ps->GetDuration(p));
break;
case PropertyType::Boolean:
state.writer.Boolean("value", ps->GetBool(p));
break;
case PropertyType::Integer:
state.writer.Number("value", ps->GetInteger(p));
break;
case PropertyType::TimePattern:
state.writer.String("value", ToString(ps->GetTimePattern(p)));
break;
case PropertyType::Transition:
writeTransition(state, ps->GetTransition(p), "value");
break;
const bool has_default_value =
ps->EqualPropertyValues(p, *default_effect);
if (!has_default_value) {
state.writer.StartObject();
state.writer.String("name", p.Name());
switch (p.GetType()) {
case PropertyType::Choice:
state.writer.String("value", ps->GetChoice(p));
break;
case PropertyType::ControlValue:
state.writer.Number("value", ps->GetControlValue(p));
break;
case PropertyType::Duration:
state.writer.Number("value", ps->GetDuration(p));
break;
case PropertyType::Boolean:
state.writer.Boolean("value", ps->GetBool(p));
break;
case PropertyType::Integer:
state.writer.Number("value", ps->GetInteger(p));
break;
case PropertyType::TimePattern:
state.writer.String("value", ToString(ps->GetTimePattern(p)));
break;
case PropertyType::Transition:
writeTransition(state, ps->GetTransition(p), "value");
break;
}
state.writer.EndObject();
}
state.writer.EndObject();
}
state.writer.EndArray(); // properties
state.writer.StartArray("connections");
for (const std::pair<Controllable *, size_t> &c : effect.Connections()) {
state.writer.StartObject();
state.writer.Number("input-index", c.second);
state.writer.Number("folder", state.folderIds[&c.first->Parent()]);
if (c.second) state.writer.Number("input-index", c.second);
state.writer.OptionalNumber("folder",
state.folderIds[&c.first->Parent()]);
state.writer.String("name", c.first->Name());
state.writer.EndObject();
}
Expand All @@ -453,8 +467,8 @@ void writeControlSceneItem(WriteState &state, const ControlSceneItem &item) {
state.writer.Number("start-value", item.StartValue().UInt());
state.writer.Number("end-value", item.EndValue().UInt());
state.writer.String("controllable-ref", item.GetControllable().Name());
state.writer.Number("folder",
state.folderIds[&item.GetControllable().Parent()]);
state.writer.OptionalNumber(
"folder", state.folderIds[&item.GetControllable().Parent()]);
}

void writeBlackoutSceneItem(WriteState &state, const BlackoutSceneItem &item) {
Expand Down Expand Up @@ -552,10 +566,11 @@ void writeFaderState(WriteState &state, const gui::FaderState &fader) {
for (SourceValue *source : sources) {
state.writer.StartObject();
if (source != nullptr) {
state.writer.Number("folder",
state.folderIds[&source->GetControllable().Parent()]);
state.writer.OptionalNumber(
"folder", state.folderIds[&source->GetControllable().Parent()]);
state.writer.String("name", source->GetControllable().Name());
state.writer.Number("input-index", source->InputIndex());
if (source->InputIndex())
state.writer.Number("input-index", source->InputIndex());
}
state.writer.EndObject();
}
Expand Down
31 changes: 29 additions & 2 deletions theatre/properties/propertyset.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "propertyset.h"

#include <cassert>

#include "audioleveleffectps.h"
#include "colorcontroleffectps.h"
#include "colortemperatureeffectps.h"
Expand Down Expand Up @@ -69,8 +71,7 @@ std::unique_ptr<PropertySet> PropertySet::Make(FolderObject &object) {

void PropertySet::AssignProperty(const Property &to, const Property &from,
const PropertySet &fromSet) {
if (from.type_ != to.type_)
throw std::runtime_error("Copying different types");
assert(from.type_ == to.type_);
switch (from.type_) {
case PropertyType::Boolean:
SetBool(to, fromSet.GetBool(from));
Expand All @@ -96,4 +97,30 @@ void PropertySet::AssignProperty(const Property &to, const Property &from,
}
}

bool PropertySet::EqualPropertyValues(const Property &property,
const Effect &rhs) {
assert(dynamic_cast<Effect *>(_object));
const Effect &effect = static_cast<const Effect &>(*_object);
assert(effect.GetType() == rhs.GetType());
switch (property.type_) {
case PropertyType::Boolean:
return GetBool(property) == getBool(rhs, property.set_index_);
case PropertyType::Choice:
return GetChoice(property) == getChoice(rhs, property.set_index_);
case PropertyType::ControlValue:
return GetControlValue(property) ==
getControlValue(rhs, property.set_index_);
case PropertyType::Duration:
return GetDuration(property) == getDuration(rhs, property.set_index_);
case PropertyType::Integer:
return GetInteger(property) == getInteger(rhs, property.set_index_);
case PropertyType::TimePattern:
return GetTimePattern(property) ==
getTimePattern(rhs, property.set_index_);
case PropertyType::Transition:
return GetTransition(property) == getTransition(rhs, property.set_index_);
}
return false;
}

} // namespace glight::theatre
6 changes: 6 additions & 0 deletions theatre/properties/propertyset.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class TimePattern;

namespace glight::theatre {

/**
* A property set describes the properties of an object, and knows how to
* get and set the values. It also keeps a pointer to the object itself.
*/
class PropertySet {
public:
using iterator = std::vector<Property>::iterator;
Expand Down Expand Up @@ -111,6 +115,8 @@ class PropertySet {
void AssignProperty(const Property &to, const Property &from,
const PropertySet &fromSet);

bool EqualPropertyValues(const Property &property, const Effect &rhs);

protected:
/**
* Set the property
Expand Down
2 changes: 2 additions & 0 deletions theatre/transition.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class Transition {
constexpr Transition(double length_in_ms, TransitionType type) noexcept
: length_in_ms_(length_in_ms), type_(type) {}

constexpr bool operator==(const Transition &rhs) const = default;

constexpr TransitionType Type() const { return type_; }
void SetType(TransitionType type) { type_ = type; }

Expand Down