DeviceInterface.hpp
1 #pragma once
2 #include <Device/Node/DeviceNode.hpp>
3 #include <Device/Protocol/DeviceSettings.hpp>
4 
5 #include <ossia/detail/callback_container.hpp>
6 #include <ossia/network/base/value_callback.hpp>
7 
8 #include <ossia-qt/device_metatype.hpp>
9 
10 #include <nano_signal_slot.hpp>
11 #include <score_lib_device_export.h>
12 
13 #include <verdigris>
14 class QMenu;
15 namespace score
16 {
17 struct DocumentContext;
18 }
19 namespace ossia
20 {
21 class value;
22 }
23 
24 namespace ossia::net
25 {
26 class node_base;
27 class parameter_base;
28 class device_base;
29 struct network_context;
30 using network_context_ptr = std::shared_ptr<network_context>;
31 }
32 namespace State
33 {
34 struct Message;
35 }
36 namespace Device
37 {
38 struct FullAddressSettings;
39 
40 struct SCORE_LIB_DEVICE_EXPORT DeviceCapas
41 {
42  bool canAddNode{true};
43  bool canRemoveNode{true};
44  bool canRenameNode{true};
45  bool canSetProperties{true};
46  bool canDisconnect{true};
47  bool canRefreshValue{true};
48  bool canRefreshTree{false};
49  bool asyncConnect{false};
50  bool canListen{true};
51  bool canSerialize{true};
52  bool canLearn{false};
53  bool hasCallbacks{true};
54 };
55 
56 enum DeviceLogging : int8_t
57 {
58  LogNothing,
59  LogUnfolded,
60  LogEverything
61 };
62 
63 class SCORE_LIB_DEVICE_EXPORT DeviceInterface
64  : public QObject
65  , public Nano::Observer
66 {
67  W_OBJECT(DeviceInterface)
68 
69 public:
71  virtual ~DeviceInterface();
72 
73  const Device::DeviceSettings& settings() const noexcept;
74  const QString& name() const noexcept;
75 
76  virtual void addNode(const Device::Node& n);
77 
78  DeviceCapas capabilities() const noexcept;
79  virtual DeviceResources usedResources() const noexcept;
80 
81  virtual void disconnect();
82  virtual bool reconnect() = 0;
83  virtual void recreate(const Device::Node&); // Argument is the node of the
84  // device, used for recreation
85  virtual bool connected() const;
86 
87  void updateSettings(const Device::DeviceSettings&);
88 
89  // Asks, and returns all the new addresses if the device can refresh itself
90  // Minuit-like.
91  // The addresses are not applied to the device, they have to be via a
92  // command!
93  virtual Device::Node refresh();
94  std::optional<ossia::value> refresh(const State::Address&);
95  void request(const Device::Node&);
96  void setListening(const State::Address&, bool);
97  void addToListening(const std::vector<State::Address>&);
98  std::vector<State::Address> listening() const;
99 
100  virtual void addAddress(const Device::FullAddressSettings&);
101  virtual void updateAddress(
102  const State::Address& currentAddr, const Device::FullAddressSettings& newAddr);
103  void removeNode(const State::Address&);
104 
105  void sendMessage(const State::Address& addr, const ossia::value& v);
106 
107  // Make a node from an inside path, if it has been added for instance.
108  Device::Node getNode(const State::Address&) const;
109  Device::Node getNodeWithoutChildren(const State::Address&) const;
110 
111  bool isLogging() const;
112  void setLogging(DeviceLogging);
113 
114  virtual ossia::net::device_base* getDevice() const = 0;
115 
116  virtual bool isLearning() const;
117  virtual void setLearning(bool);
118 
119  virtual QMimeData* mimeData() const;
120  virtual void setupContextMenu(QMenu&) const;
121 
122  void nodeCreated(const ossia::net::node_base&);
123  void nodeRemoving(const ossia::net::node_base&);
124  void nodeRenamed(const ossia::net::node_base&, std::string);
125  void addressCreated(const ossia::net::parameter_base&);
126  void addressUpdated(const ossia::net::node_base&, ossia::string_view key);
127  void addressRemoved(const ossia::net::parameter_base& addr);
128 
129  Nano::Signal<void(const State::Address&, const ossia::value&)> valueUpdated;
130 
131 public:
132  // These signals are emitted if a device changes from the inside
133  void pathAdded(const State::Address& arg_1)
134  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, pathAdded, arg_1)
135  void pathUpdated(
136  const State::Address& arg_1, // current address
137  const Device::AddressSettings& arg_2)
138  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, pathUpdated, arg_1, arg_2) // new data
139  void pathRemoved(const State::Address& arg_1)
140  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, pathRemoved, arg_1)
141 
142  // In case the whole namespace changed?
143  void namespaceUpdated() E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, namespaceUpdated)
144 
145  // In case the device changed
146  void deviceChanged(ossia::net::device_base* old_dev, ossia::net::device_base* new_dev)
147  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, deviceChanged, old_dev, new_dev)
148 
149  /* If logging is enabled, these two signals may be sent
150  * when something happens */
151  void logInbound(const QString& arg_1) const
152  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, logInbound, arg_1)
153  void logOutbound(const QString& arg_1) const
154  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, logOutbound, arg_1)
155 
156  void connectionChanged(bool arg_1) const
157  E_SIGNAL(SCORE_LIB_DEVICE_EXPORT, connectionChanged, arg_1)
158 
159 protected:
160  Device::DeviceSettings m_settings;
161  DeviceCapas m_capas;
162 
163  using callback_pair = std::pair<
164  ossia::net::parameter_base*,
165  ossia::callback_container<ossia::value_callback>::iterator>;
166  score::hash_map<State::Address, callback_pair> m_callbacks;
167 
168  void removeListening_impl(ossia::net::node_base& node, State::Address addr);
169  void removeListening_impl(
170  ossia::net::node_base& node, State::Address addr, std::vector<State::Address>&);
171  void renameListening_impl(const State::Address& parent, const QString& newName);
172  void setLogging_impl(DeviceLogging) const;
173  void enableCallbacks();
174  void disableCallbacks();
175 
176  // Refresh without handling callbacks
177  Device::Node simple_refresh();
178 
179 private:
180  DeviceLogging m_logging = DeviceLogging::LogNothing;
181  bool m_callbacksEnabled = false;
182 };
183 
184 class SCORE_LIB_DEVICE_EXPORT OwningDeviceInterface : public DeviceInterface
185 {
186 public:
187  ~OwningDeviceInterface() override;
188  void replaceDevice(ossia::net::device_base*);
189  void releaseDevice();
190 
191 protected:
192  void disconnect() override;
193 
194  using DeviceInterface::DeviceInterface;
195 
196  ossia::net::device_base* getDevice() const final override { return m_dev.get(); }
197 
198  std::unique_ptr<ossia::net::device_base> m_dev;
199  bool m_owned{true};
200 };
201 
202 SCORE_LIB_DEVICE_EXPORT ossia::net::node_base*
203 getNodeFromPath(const QStringList& path, ossia::net::device_base& dev);
204 
205 SCORE_LIB_DEVICE_EXPORT ossia::net::node_base*
206 createNodeFromPath(const QStringList& path, ossia::net::device_base& dev);
207 
208 SCORE_LIB_DEVICE_EXPORT Device::Node ToDeviceExplorer(const ossia::net::node_base& node);
209 
210 SCORE_LIB_DEVICE_EXPORT ossia::net::node_base*
211 findNodeFromPath(const Device::Node& path, ossia::net::device_base& dev);
212 
213 SCORE_LIB_DEVICE_EXPORT ossia::net::node_base*
214 findNodeFromPath(const QStringList& path, ossia::net::device_base& dev);
215 
216 SCORE_LIB_DEVICE_EXPORT
217 void releaseDevice(
218  ossia::net::network_context& ctx, std::unique_ptr<ossia::net::device_base> dev);
219 }
Definition: DeviceInterface.hpp:66
Definition: DeviceInterface.hpp:185
Manipulation of Devices from Qt.
Definition: AddressSettings.cpp:14
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Definition: AddressSettings.hpp:49
Definition: DeviceInterface.hpp:41
Definition: DeviceSettings.hpp:20
Definition: AddressSettings.hpp:62
The Address struct.
Definition: Address.hpp:58
The Message struct.
Definition: Message.hpp:15