1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21 */
22
23 //==============================================================================
24 /** These can be useful when debugging the topology. */
25
26 #ifndef LOG_BLOCKS_CONNECTIVITY
27 #define LOG_BLOCKS_CONNECTIVITY 0
28 #endif
29
30 #ifndef LOG_BLOCKS_PINGS
31 #define LOG_BLOCKS_PINGS 0
32 #endif
33
34 #ifndef DUMP_BANDWIDTH_STATS
35 #define DUMP_BANDWIDTH_STATS 0
36 #endif
37
38 #ifndef DUMP_TOPOLOGY
39 #define DUMP_TOPOLOGY 0
40 #endif
41
42 #define TOPOLOGY_LOG(text) \
43 JUCE_BLOCK_WITH_FORCED_SEMICOLON (juce::String buf ("Topology Src: "); \
44 juce::Logger::outputDebugString (buf << text);)
45
46 #if LOG_BLOCKS_CONNECTIVITY
47 #define LOG_CONNECTIVITY(text) TOPOLOGY_LOG(text)
48 #else
49 #define LOG_CONNECTIVITY(text)
50 #endif
51
52 #if LOG_BLOCKS_PINGS
53 #define LOG_PING(text) TOPOLOGY_LOG(text)
54 #else
55 #define LOG_PING(text)
56 #endif
57
58 #if DUMP_BANDWIDTH_STATS
59 #include "internal/juce_BandwidthStatsLogger.cpp"
60 #endif
61
62 #include "internal/juce_MidiDeviceConnection.cpp"
63 #include "internal/juce_MIDIDeviceDetector.cpp"
64 #include "internal/juce_DeviceInfo.cpp"
65 #include "internal/juce_DepreciatedVersionReader.cpp"
66 #include "internal/juce_BlockSerialReader.cpp"
67 #include "internal/juce_ConnectedDeviceGroup.cpp"
68 #include "internal/juce_BlockImplementation.cpp"
69 #include "internal/juce_Detector.cpp"
70 #include "internal/juce_DetectorHolder.cpp"
71
72 namespace juce
73 {
74
75 //==============================================================================
PhysicalTopologySource(bool startDetached)76 PhysicalTopologySource::PhysicalTopologySource (bool startDetached)
77 {
78 if (! startDetached)
79 setActive (true);
80 }
81
PhysicalTopologySource(DeviceDetector & detectorToUse,bool startDetached)82 PhysicalTopologySource::PhysicalTopologySource (DeviceDetector& detectorToUse, bool startDetached)
83 : customDetector (&detectorToUse)
84 {
85 if (! startDetached)
86 setActive (true);
87 }
88
~PhysicalTopologySource()89 PhysicalTopologySource::~PhysicalTopologySource()
90 {
91 setActive (false);
92 }
93
setActive(bool shouldBeActive)94 void PhysicalTopologySource::setActive (bool shouldBeActive)
95 {
96 JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
97
98 if (isActive() == shouldBeActive)
99 return;
100
101 if (shouldBeActive)
102 {
103 if (customDetector == nullptr)
104 detector = std::make_unique<DetectorHolder>(*this);
105 else
106 detector = std::make_unique<DetectorHolder>(*this, *customDetector);
107
108 detector->detector->activeTopologySources.add (this);
109 }
110 else
111 {
112 detector->detector->detach (this);
113 detector.reset();
114 }
115
116 listeners.call ([] (TopologySource::Listener& l){ l.topologyChanged(); });
117 }
118
isActive() const119 bool PhysicalTopologySource::isActive() const
120 {
121 return detector != nullptr;
122 }
123
isLockedFromOutside() const124 bool PhysicalTopologySource::isLockedFromOutside() const
125 {
126 if (detector != nullptr && detector->detector != nullptr)
127 return detector->detector->deviceDetector.isLockedFromOutside();
128
129 return false;
130 }
131
getCurrentTopology() const132 BlockTopology PhysicalTopologySource::getCurrentTopology() const
133 {
134 JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED // This method must only be called from the message thread!
135
136 if (detector != nullptr)
137 return detector->detector->currentTopology;
138
139 return {};
140 }
141
cancelAllActiveTouches()142 void PhysicalTopologySource::cancelAllActiveTouches() noexcept
143 {
144 if (detector != nullptr)
145 detector->detector->cancelAllActiveTouches();
146 }
147
hasOwnServiceTimer() const148 bool PhysicalTopologySource::hasOwnServiceTimer() const { return false; }
handleTimerTick()149 void PhysicalTopologySource::handleTimerTick()
150 {
151 if (detector != nullptr)
152 detector->handleTimerTick();
153 }
154
DeviceConnection()155 PhysicalTopologySource::DeviceConnection::DeviceConnection() {}
~DeviceConnection()156 PhysicalTopologySource::DeviceConnection::~DeviceConnection() {}
157
DeviceDetector()158 PhysicalTopologySource::DeviceDetector::DeviceDetector() {}
~DeviceDetector()159 PhysicalTopologySource::DeviceDetector::~DeviceDetector() {}
160
getStandardLittleFootFunctions()161 const char* const* PhysicalTopologySource::getStandardLittleFootFunctions() noexcept
162 {
163 return BlocksProtocol::ledProgramLittleFootFunctions;
164 }
165
166 template <typename ListType>
collectionsMatch(const ListType & list1,const ListType & list2)167 static bool collectionsMatch (const ListType& list1, const ListType& list2) noexcept
168 {
169 if (list1.size() != list2.size())
170 return false;
171
172 for (auto&& b : list1)
173 if (! list2.contains (b))
174 return false;
175
176 return true;
177 }
178
operator ==(const BlockTopology & other) const179 bool BlockTopology::operator== (const BlockTopology& other) const noexcept
180 {
181 return collectionsMatch (connections, other.connections) && collectionsMatch (blocks, other.blocks);
182 }
183
operator !=(const BlockTopology & other) const184 bool BlockTopology::operator!= (const BlockTopology& other) const noexcept
185 {
186 return ! operator== (other);
187 }
188
operator ==(const BlockDeviceConnection & other) const189 bool BlockDeviceConnection::operator== (const BlockDeviceConnection& other) const noexcept
190 {
191 return (device1 == other.device1 && device2 == other.device2
192 && connectionPortOnDevice1 == other.connectionPortOnDevice1
193 && connectionPortOnDevice2 == other.connectionPortOnDevice2)
194 || (device1 == other.device2 && device2 == other.device1
195 && connectionPortOnDevice1 == other.connectionPortOnDevice2
196 && connectionPortOnDevice2 == other.connectionPortOnDevice1);
197 }
198
operator !=(const BlockDeviceConnection & other) const199 bool BlockDeviceConnection::operator!= (const BlockDeviceConnection& other) const noexcept
200 {
201 return ! operator== (other);
202 }
203
204 } // namespace juce
205