1 // qsamplerDevice.h
2 //
3 /****************************************************************************
4    Copyright (C) 2004-2020, rncbc aka Rui Nuno Capela. All rights reserved.
5    Copyright (C) 2007, 2008 Christian Schoenebeck
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License
9    as published by the Free Software Foundation; either version 2
10    of the License, or (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License along
18    with this program; if not, write to the Free Software Foundation, Inc.,
19    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 
21 *****************************************************************************/
22 
23 #ifndef __qsamplerDevice_h
24 #define __qsamplerDevice_h
25 
26 #include <QListWidget>
27 #include <QListWidgetItem>
28 #include <QTreeWidgetItem>
29 #include <QTableWidget>
30 #include <QTableWidgetItem>
31 #include <QAbstractTableModel>
32 #include <QItemDelegate>
33 #include <QFontMetrics>
34 #include <QModelIndex>
35 #include <QSize>
36 #include <QList>
37 #include <set>
38 
39 #include <lscp/client.h>
40 #include <lscp/device.h>
41 
42 #include "qsamplerOptions.h"
43 
44 namespace QSampler {
45 
46 class DevicePort;
47 
48 // Special QListViewItem::rtti() unique return value.
49 #define	QSAMPLER_DEVICE_ITEM    1001
50 
51 
52 //-------------------------------------------------------------------------
53 // QSampler::DeviceParam - MIDI/Audio Device parameter structure.
54 //
55 
56 class DeviceParam
57 {
58 public:
59 
60 	// Constructor.
61 	DeviceParam(lscp_param_info_t *pParamInfo = nullptr,
62 		const char *pszValue = nullptr);
63 
64 	// Initializer.
65 	void setParam(lscp_param_info_t *pParamInfo,
66 		const char *pszValue = nullptr);
67 
68 	// Info structure field members.
69 	lscp_type_t	type;
70 	QString 	description;
71 	bool    	mandatory;
72 	bool    	fix;
73 	bool    	multiplicity;
74 	QStringList depends;
75 	QString 	defaultv;
76 	QString 	range_min;
77 	QString 	range_max;
78 	QStringList possibilities;
79 	// The current parameter value.
80 	QString 	value;
81 };
82 
83 // Typedef'd parameter QMap.
84 typedef QMap<QString, DeviceParam> DeviceParamMap;
85 
86 // Typedef'd device port/channels QList.
87 typedef QList<DevicePort *> DevicePortList;
88 
89 
90 //-------------------------------------------------------------------------
91 // QSampler::Device - MIDI/Audio Device structure.
92 //
93 
94 class Device
95 {
96 public:
97 
98 	// We use the same class for MIDI and audio device management
99 	enum DeviceType { None, Midi, Audio };
100 
101 	// Constructor.
102 	Device(DeviceType deviceType, int iDeviceID = -1);
103 	// Copy constructor.
104 	Device(const Device& device);
105 
106 	// Default destructor.
107 	~Device();
108 
109 	// Initializer.
110 	void setDevice(DeviceType deviceType, int iDeviceID = -1);
111 
112 	// Driver name initializer.
113 	void setDriver(const QString& sDriverName);
114 
115 	// Device property accessors.
116 	int            deviceID() const;
117 	DeviceType     deviceType() const;
118 	const QString& deviceTypeName() const;
119 	const QString& driverName() const;
120 
121 	// Special device name formatter.
122 	QString deviceName() const;
123 
124 	// Set the proper device parameter value.
125 	bool setParam (const QString& sParam, const QString& sValue);
126 
127 	// Device parameters accessor.
128 	const DeviceParamMap& params() const;
129 
130 	// Device port/channel list accessor.
131 	DevicePortList& ports();
132 
133 	// Device parameter dependency list refreshner.
134 	int refreshParams();
135 	// Device port/channel list refreshner.
136 	int refreshPorts();
137 	// Refresh/set dependencies given that some parameter has changed.
138 	int refreshDepends(const QString& sParam);
139 
140 	// Create/destroy device methods.
141 	bool createDevice();
142 	bool deleteDevice();
143 
144 	// Message logging methods (brainlessly mapped to main form's).
145 	void appendMessages       (const QString& s) const;
146 	void appendMessagesColor  (const QString& s, const QColor& rgb) const;
147 	void appendMessagesText   (const QString& s) const;
148 	void appendMessagesError  (const QString& s) const;
149 	void appendMessagesClient (const QString& s) const;
150 
151 	// Device ids enumerator.
152 	static int *getDevices(lscp_client_t *pClient,
153 		DeviceType deviceType);
154 	static std::set<int> getDeviceIDs(lscp_client_t *pClient,
155 		DeviceType deviceType);
156 
157 	// Driver names enumerator.
158 	static QStringList getDrivers(lscp_client_t *pClient,
159 		DeviceType deviceType);
160 
161 private:
162 
163 	// Refresh/set given parameter based on driver supplied dependencies.
164 	int refreshParam(const QString& sParam);
165 
166 	// Instance variables.
167 	int        m_iDeviceID;
168 	DeviceType m_deviceType;
169 	QString    m_sDeviceType;
170 	QString    m_sDriverName;
171 	QString    m_sDeviceName;
172 
173 	// Device parameter list.
174 	DeviceParamMap m_params;
175 
176 	// Device port/channel list.
177 	DevicePortList m_ports;
178 };
179 
180 
181 //-------------------------------------------------------------------------
182 // QSampler::DevicePort - MIDI/Audio Device port/channel structure.
183 //
184 
185 class DevicePort
186 {
187 public:
188 
189 	// Constructor.
190 	DevicePort(Device& device, int iPortID);
191 	// Default destructor.
192 	~DevicePort();
193 
194 	// Initializer.
195 	void setDevicePort(int iPortID);
196 
197 	// Device port property accessors.
198 	int            portID()   const;
199 	const QString& portName() const;
200 
201 	// Device port parameters accessor.
202 	const DeviceParamMap& params() const;
203 
204 	// Set the proper device port/channel parameter value.
205 	bool setParam (const QString& sParam, const QString& sValue);
206 
207 private:
208 
209 	// Device reference.
210 	Device& m_device;
211 
212 	// Instance variables.
213 	int     m_iPortID;
214 	QString m_sPortName;
215 
216 	// Device port parameter list.
217 	DeviceParamMap m_params;
218 };
219 
220 
221 //-------------------------------------------------------------------------
222 // QSampler::DeviceItem - QTreeWidget device item.
223 //
224 
225 class DeviceItem : public QTreeWidgetItem
226 {
227 public:
228 
229 	// Constructors.
230 	DeviceItem(QTreeWidget *pTreeWidget,
231 		Device::DeviceType deviceType);
232 	DeviceItem(QTreeWidgetItem *pItem,
233 		Device::DeviceType deviceType, int iDeviceID);
234 
235 	// Default destructor.
236 	~DeviceItem();
237 
238 	// Instance accessors.
239 	Device& device();
240 
241 private:
242 
243 	// Instance variables.
244 	Device m_device;
245 };
246 
247 
248 struct DeviceParameterRow {
249 	QString     name;
250 	DeviceParam param;
251 	bool        alive; // whether these params refer to an existing device
252 	                   // or for a device that is yet to be created
253 };
254 
255 
256 //-------------------------------------------------------------------------
257 // QSampler::AbstractDeviceParamModel - data model base class for device parameters
258 //
259 
260 class AbstractDeviceParamModel : public QAbstractTableModel
261 {
262 	Q_OBJECT
263 
264 public:
265 
266 	AbstractDeviceParamModel(QObject *pParent = nullptr);
267 
268 	// Overridden methods from subclass(es)
269 	int rowCount(const QModelIndex& parent = QModelIndex()) const;
270 	int columnCount(const QModelIndex& parent = QModelIndex() ) const;
271 	QVariant headerData(int section,
272 		Qt::Orientation orientation, int role = Qt::DisplayRole) const;
273 	Qt::ItemFlags flags(const QModelIndex& index) const;
274 
275 	virtual void clear();
276 
277 	void refresh(const DeviceParamMap* params, bool bEditable);
278 
279 protected:
280 
281 	const DeviceParamMap *m_pParams;
282 	bool m_bEditable;
283 };
284 
285 
286 //-------------------------------------------------------------------------
287 // QSampler::DeviceParamModel - data model for device parameters
288 //                              (used for QTableView)
289 
290 class DeviceParamModel : public AbstractDeviceParamModel
291 {
292 	Q_OBJECT
293 
294 public:
295 
296 	DeviceParamModel(QObject *pParent = nullptr);
297 
298 	// Overridden methods from subclass(es)
299 	QVariant data(const QModelIndex &index, int role) const;
300 	bool setData(const QModelIndex& index,
301 		const QVariant& value, int role = Qt::EditRole);
302 
303 	void clear();
304 
305 public slots:
306 
307 	void refresh(Device* pDevice, bool bEditable);
308 
309 private:
310 
311 	Device *m_pDevice;
312 };
313 
314 
315 //-------------------------------------------------------------------------
316 // QSampler::PortParamModel - data model for port parameters
317 //                            (used for QTableView)
318 
319 class PortParamModel : public AbstractDeviceParamModel
320 {
321 	Q_OBJECT
322 
323 public:
324 
325 	PortParamModel(QObject *pParent = 0);
326 
327 	// overridden methods from subclass(es)
328 	QVariant data(const QModelIndex &index, int role) const;
329 	bool setData(const QModelIndex& index,
330 		const QVariant& value, int role = Qt::EditRole);
331 
332 	void clear();
333 
334 public slots:
335 
336 	void refresh(DevicePort* pPort, bool bEditable);
337 
338 private:
339 
340 	DevicePort* m_pPort;
341 };
342 
343 
344 //-------------------------------------------------------------------------
345 // QSampler::DeviceParamDelegate - table cell renderer for device/port parameters
346 //
347 
348 class DeviceParamDelegate : public QItemDelegate
349 {
350 	Q_OBJECT
351 
352 public:
353 
354 	DeviceParamDelegate(QObject *pParent = nullptr);
355 
356 	QWidget* createEditor(QWidget *pParent,
357 		const QStyleOptionViewItem& option, const QModelIndex& index) const;
358 	void setEditorData(QWidget *pEditor, const QModelIndex& index) const;
359 	void setModelData(QWidget *pEditor, QAbstractItemModel *pModel,
360 		const QModelIndex& index) const;
361 	void updateEditorGeometry(QWidget* pEditor,
362 		const QStyleOptionViewItem& option, const QModelIndex& index) const;
363 };
364 
365 } // namespace QSampler
366 
367 // so we can use it i.e. through QVariant
368 Q_DECLARE_METATYPE(QSampler::DeviceParameterRow)
369 
370 #endif  // __qsamplerDevice_h
371 
372 
373 // end of qsamplerDevice.h
374