GCC Code Coverage Report


Directory: ./
File: channeloutput/ControlChannelOutput.cpp
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 48 49 98.0%
Functions: 8 8 100.0%
Branches: 50 94 53.2%

Line Branch Exec Source
1 /*
2 * This file is part of the Falcon Player (FPP) and is Copyright (C)
3 * 2013-2024 by the Falcon Player Developers.
4 *
5 * The Falcon Player (FPP) is free software, and is covered under
6 * multiple Open Source licenses. Please see the included 'LICENSES'
7 * file for descriptions of what files are covered by each license.
8 *
9 * This source file is covered under the GPL v2 as described in the
10 * included LICENSE.GPL file.
11 */
12
13 #include "fpp-pch.h"
14
15 #include "fpp-json.h"
16
17 #include "../log.h"
18
19 #include "../commands/Commands.h"
20 #include "../Sequence.h"
21
22 #include "ControlChannelOutput.h"
23
24 #include "Plugin.h"
25 class ControlChannelOutputPlugin : public FPPPlugins::Plugin, public FPPPlugins::ChannelOutputPlugin {
26 public:
27 3 ControlChannelOutputPlugin() :
28
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
9 FPPPlugins::Plugin("ControlChannelOutput") {
29 3 }
30 3 virtual ChannelOutput* createChannelOutput(unsigned int startChannel, unsigned int channelCount) override {
31
2/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6 return new ControlChannelOutput(startChannel, channelCount);
32 }
33 };
34
35 extern "C" {
36 3 FPPPlugins::Plugin* createPlugin() {
37
2/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6 return new ControlChannelOutputPlugin();
38 }
39 }
40
41 3 ControlChannelOutput::ControlChannelOutput(unsigned int startChannel, unsigned int channelCount) :
42 3 ChannelOutput(startChannel, channelCount) {
43 3 }
44 12 ControlChannelOutput::~ControlChannelOutput() {
45 12 }
46
47 3 int ControlChannelOutput::Init(Json::Value config) {
48
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (config.isMember("values")) {
49
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 for (int x = 0; x < config["values"].size(); x++) {
50
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 uint8_t v = config["values"][x]["value"].asUInt();
51
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 std::string p = config["values"][x]["preset"].asString();
52
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (p != "") {
53
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 presets[v].emplace_back(p);
54 }
55 2 }
56 }
57
58
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 return ChannelOutput::Init(config);
59 }
60
61 88 int ControlChannelOutput::SendData(unsigned char* channelData) {
62 88 uint8_t v = *channelData;
63
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 86 times.
88 if (v != lastValue) {
64 2 lastValue = v;
65
66
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 auto it = presets.find(v);
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (it == presets.end()) {
68 ✗ return 0;
69 }
70
71 // Make the value that fired the preset available to the preset's
72 // commands as %CHANNEL_VALUE% / %CHANNEL_VALUE255% / %CHANNEL_VALUE100%.
73 // Presets that don't reference the keywords are unaffected.
74 2 std::map<std::string, std::string> keywords;
75
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 keywords["CHANNEL_VALUE"] = std::to_string(v);
76
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 keywords["CHANNEL_VALUE255"] = std::to_string(v);
77
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 keywords["CHANNEL_VALUE100"] = std::to_string((v * 100 + 127) / 255);
78
79
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (auto& p : it->second) {
80
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (p != "") {
81
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 LogDebug(VB_COMMAND, "Control Channel %d (value %d) triggering preset \"%s\"\n", StartChannel(), v, p.c_str());
82 // Deferred to the main loop like FSEQ-triggered presets:
83 // SendData runs on the output thread holding outputThreadLock,
84 // so running the commands here stalled every output for as
85 // long as they took, and tied this thread to every lock a
86 // command can take.
87
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 sequence->queuePreset(p, std::map<std::string, std::string>(keywords));
88 }
89 }
90 2 }
91 88 return 0;
92 }
93
94 3 void ControlChannelOutput::DumpConfig(void) {
95 3 ChannelOutput::DumpConfig();
96
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 for (auto& p : presets) {
97
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::string v = " Value " + std::to_string(p.first) + ": ";
98
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (auto& a : p.second) {
99
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 v += " \"";
100
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 v += a;
101
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 v += "\"";
102 }
103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 LogDebug(VB_CHANNELOUT, "%s\n", v.c_str());
104 2 }
105 3 }
106