Merge lp:~hile/mixxx/presetinfo into lp:~mixxxdevelopers/mixxx/trunk
- presetinfo
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 3228 |
Proposed branch: | lp:~hile/mixxx/presetinfo |
Merge into: | lp:~mixxxdevelopers/mixxx/trunk |
Diff against target: |
1143 lines (+660/-83) 15 files modified
mixxx/src/controllers/controller.cpp (+2/-0) mixxx/src/controllers/controller.h (+10/-0) mixxx/src/controllers/controllermanager.cpp (+36/-31) mixxx/src/controllers/controllermanager.h (+8/-1) mixxx/src/controllers/controllerpreset.h (+7/-0) mixxx/src/controllers/controllerpresetinfo.cpp (+232/-0) mixxx/src/controllers/controllerpresetinfo.h (+87/-0) mixxx/src/controllers/dlgprefcontroller.cpp (+64/-12) mixxx/src/controllers/dlgprefcontroller.h (+5/-1) mixxx/src/controllers/dlgprefcontrollerdlg.ui (+128/-38) mixxx/src/controllers/hid/hidcontroller.cpp (+64/-0) mixxx/src/controllers/hid/hidcontroller.h (+3/-0) mixxx/src/controllers/midi/midicontroller.cpp (+5/-0) mixxx/src/controllers/midi/midicontroller.h (+2/-0) mixxx/src/dlgpreferences.cpp (+7/-0) |
To merge this branch: | bzr merge lp:~hile/mixxx/presetinfo |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mixxx Development Team | Pending | ||
Review via email: mp+106001@code.launchpad.net |
Commit message
Description of the change
Patches for reading the info section from controller XML files, and using this information in the controller dialogs. Implements a presetInfo container and manager class, linked to ControllerManager.
Other minor details in the branch:
- added presetinfo product matching to controller, allows automatic mapping matching to controller
- implement controller ordering by name, use this in preferences
- added methods to process 'device category', for informational purposes only
- add a DeviceCategory field to controller preferences, show HID device info here. This helps choosing between keyboard and mice etc
- minor reformatting of the UI for controllers, adding description and making the text fields wrapped and static width
- 3166. By Ilkka Tuohela
-
Merged to trunk
- 3167. By Ilkka Tuohela
-
Merged latest mixxx trunk
- 3168. By Ilkka Tuohela
-
Merged changes from trunk
- 3169. By Ilkka Tuohela
-
Imported latest changes from trunk
Preview Diff
1 | === modified file 'mixxx/src/controllers/controller.cpp' |
2 | --- mixxx/src/controllers/controller.cpp 2012-05-26 23:32:16 +0000 |
3 | +++ mixxx/src/controllers/controller.cpp 2012-05-29 05:49:18 +0000 |
4 | @@ -22,6 +22,8 @@ |
5 | // Get --controllerDebug command line option |
6 | QStringList commandLineArgs = QApplication::arguments(); |
7 | m_bDebug = commandLineArgs.contains("--controllerDebug", Qt::CaseInsensitive); |
8 | + // Initialize device category to empty |
9 | + setDeviceCategory(""); |
10 | } |
11 | |
12 | Controller::~Controller() { |
13 | |
14 | === modified file 'mixxx/src/controllers/controller.h' |
15 | --- mixxx/src/controllers/controller.h 2012-05-26 23:19:28 +0000 |
16 | +++ mixxx/src/controllers/controller.h 2012-05-29 05:49:18 +0000 |
17 | @@ -54,6 +54,9 @@ |
18 | inline QString getName() const { |
19 | return m_sDeviceName; |
20 | } |
21 | + inline QString getCategory() const { |
22 | + return m_sDeviceCategory; |
23 | + } |
24 | inline bool debugging() const { |
25 | return m_bDebug; |
26 | } |
27 | @@ -62,6 +65,8 @@ |
28 | return m_bLearning; |
29 | } |
30 | |
31 | + virtual bool matchProductInfo(QHash <QString,QString > info) = 0; |
32 | + |
33 | signals: |
34 | void learnedMessage(QString message); |
35 | // Emitted when a new preset is loaded. pPreset is a /clone/ of the loaded |
36 | @@ -102,6 +107,9 @@ |
37 | inline void setDeviceName(QString deviceName) { |
38 | m_sDeviceName = deviceName; |
39 | } |
40 | + inline void setDeviceCategory(QString deviceCategory) { |
41 | + m_sDeviceCategory = deviceCategory; |
42 | + } |
43 | inline void setOutputDevice(bool outputDevice) { |
44 | m_bIsOutputDevice = outputDevice; |
45 | } |
46 | @@ -141,6 +149,8 @@ |
47 | |
48 | // Verbose and unique device name suitable for display. |
49 | QString m_sDeviceName; |
50 | + // Verbose and unique description of device type, defaults to empty |
51 | + QString m_sDeviceCategory; |
52 | // Flag indicating if this device supports output (receiving data from |
53 | // Mixxx) |
54 | bool m_bIsOutputDevice; |
55 | |
56 | === modified file 'mixxx/src/controllers/controllermanager.cpp' |
57 | --- mixxx/src/controllers/controllermanager.cpp 2012-05-01 14:45:33 +0000 |
58 | +++ mixxx/src/controllers/controllermanager.cpp 2012-05-29 05:49:18 +0000 |
59 | @@ -37,6 +37,10 @@ |
60 | return filename; |
61 | } |
62 | |
63 | +bool controllerCompare(Controller *a,Controller *b) { |
64 | + return a->getName() < b->getName(); |
65 | +} |
66 | + |
67 | ControllerManager::ControllerManager(ConfigObject<ConfigValue> * pConfig) : |
68 | QObject(), |
69 | m_pConfig(pConfig), |
70 | @@ -58,6 +62,9 @@ |
71 | QDir().mkpath(LOCAL_PRESETS_PATH); |
72 | } |
73 | |
74 | + // Initialize preset info parsers |
75 | + presetInfoManager = new PresetInfoEnumerator(m_pConfig); |
76 | + |
77 | // Instantiate all enumerators |
78 | m_enumerators.append(new PortMidiEnumerator()); |
79 | #ifdef __HSS1394__ |
80 | @@ -253,34 +260,6 @@ |
81 | } |
82 | } |
83 | |
84 | -QList<QString> ControllerManager::getPresetList(QString extension) { |
85 | - // Paths to search for controller presets |
86 | - QList<QString> controllerDirPaths; |
87 | - QString configPath = m_pConfig->getConfigPath(); |
88 | - controllerDirPaths.append(configPath.append("controllers/")); |
89 | - controllerDirPaths.append(LOCAL_PRESETS_PATH); |
90 | - |
91 | - // Should we also show the presets from USER_PRESETS_PATH? That could be |
92 | - // confusing. |
93 | - |
94 | - QList<QString> presets; |
95 | - foreach (QString dirPath, controllerDirPaths) { |
96 | - QDirIterator it(dirPath); |
97 | - while (it.hasNext()) { |
98 | - // Advance iterator. We get the filename from the next line. (It's a |
99 | - // bit weird.) |
100 | - it.next(); |
101 | - |
102 | - QString curPreset = it.fileName(); |
103 | - if (curPreset.endsWith(extension)) { |
104 | - curPreset.chop(QString(extension).length()); //chop off the extension |
105 | - presets.append(curPreset); |
106 | - } |
107 | - } |
108 | - } |
109 | - qSort(presets); |
110 | - return presets; |
111 | -} |
112 | |
113 | void ControllerManager::openController(Controller* pController) { |
114 | if (!pController) { |
115 | @@ -329,7 +308,6 @@ |
116 | return true; |
117 | } |
118 | |
119 | - |
120 | bool ControllerManager::loadPreset(Controller* pController, |
121 | const QString &filename, |
122 | const bool force) { |
123 | @@ -340,8 +318,18 @@ |
124 | return false; |
125 | } |
126 | |
127 | - QString filenameWithExt = filename + pController->presetExtension(); |
128 | - QString filepath = USER_PRESETS_PATH + filenameWithExt; |
129 | + // Handle case when filename is already valid full path to mapping |
130 | + // (coming from presetInfo.path) |
131 | + QString filenameWithExt; |
132 | + QString filepath; |
133 | + QFileInfo fileinfo(filename); |
134 | + if (fileinfo.isFile()) { |
135 | + filenameWithExt = fileinfo.baseName(); |
136 | + filepath = fileinfo.absoluteFilePath(); |
137 | + } else { |
138 | + filenameWithExt = filename + pController->presetExtension(); |
139 | + filepath = USER_PRESETS_PATH + filenameWithExt; |
140 | + } |
141 | |
142 | // If the file isn't present in the user's directory, check the local |
143 | // presets path. |
144 | @@ -374,6 +362,23 @@ |
145 | return true; |
146 | } |
147 | |
148 | +PresetInfoEnumerator* ControllerManager::getPresetInfoManager() { |
149 | + return presetInfoManager; |
150 | +} |
151 | + |
152 | +PresetInfo* ControllerManager::matchControllerPreset(Controller *controller) { |
153 | + QList<PresetInfo*> presets = presetInfoManager->getPresets(controller->presetExtension()); |
154 | + foreach (PresetInfo* preset, presets) { |
155 | + QList< QHash<QString,QString> > products = preset->getProducts(); |
156 | + for (int i=0;i<products.length();i++) { |
157 | + QHash <QString,QString> product = products[i]; |
158 | + if (controller->matchProductInfo(product)) |
159 | + return preset; |
160 | + } |
161 | + } |
162 | + return NULL; |
163 | +} |
164 | + |
165 | void ControllerManager::slotSavePresets(bool onlyActive) { |
166 | QList<Controller*> deviceList = getControllerList(false, true); |
167 | QSet<QString> filenames; |
168 | |
169 | === modified file 'mixxx/src/controllers/controllermanager.h' |
170 | --- mixxx/src/controllers/controllermanager.h 2012-04-28 04:12:06 +0000 |
171 | +++ mixxx/src/controllers/controllermanager.h 2012-05-29 05:49:18 +0000 |
172 | @@ -11,11 +11,15 @@ |
173 | #include "configobject.h" |
174 | #include "controllers/controllerenumerator.h" |
175 | #include "controllers/controllerpreset.h" |
176 | +#include "controllers/controllerpresetinfo.h" |
177 | |
178 | //Forward declaration(s) |
179 | class Controller; |
180 | class ControllerLearningEventFilter; |
181 | |
182 | +// Function to sort controllers by name |
183 | +bool controllerCompare(Controller *a,Controller *b); |
184 | + |
185 | /** Manages enumeration/operation/deletion of hardware controllers. */ |
186 | class ControllerManager : public QObject { |
187 | Q_OBJECT |
188 | @@ -25,7 +29,6 @@ |
189 | |
190 | QList<Controller*> getControllers() const; |
191 | QList<Controller*> getControllerList(bool outputDevices=true, bool inputDevices=true); |
192 | - QList<QString> getPresetList(QString extension); |
193 | ControllerLearningEventFilter* getControllerLearningEventFilter() const; |
194 | |
195 | // Prevent other parts of Mixxx from having to manually connect to our slots |
196 | @@ -47,6 +50,9 @@ |
197 | |
198 | // Writes out presets for currently connected input devices |
199 | void slotSavePresets(bool onlyActive=false); |
200 | + |
201 | + PresetInfo* matchControllerPreset(Controller *controller); |
202 | + PresetInfoEnumerator* getPresetInfoManager(); |
203 | |
204 | private slots: |
205 | // Open whatever controllers are selected in the preferences. This currently |
206 | @@ -76,6 +82,7 @@ |
207 | QList<ControllerEnumerator*> m_enumerators; |
208 | QList<Controller*> m_controllers; |
209 | QThread* m_pThread; |
210 | + PresetInfoEnumerator* presetInfoManager; |
211 | }; |
212 | |
213 | #endif // CONTROLLERMANAGER_H |
214 | |
215 | === modified file 'mixxx/src/controllers/controllerpreset.h' |
216 | --- mixxx/src/controllers/controllerpreset.h 2012-04-29 04:31:26 +0000 |
217 | +++ mixxx/src/controllers/controllerpreset.h 2012-05-29 05:49:18 +0000 |
218 | @@ -12,6 +12,7 @@ |
219 | #define CONTROLLERPRESET_H |
220 | |
221 | #include <QtCore> |
222 | +#include <QHash> |
223 | #include <QSharedPointer> |
224 | |
225 | class ControllerPresetVisitor; |
226 | @@ -87,6 +88,10 @@ |
227 | return m_mixxxVersion; |
228 | } |
229 | |
230 | + inline void addProductMatch(QHash<QString,QString> match) { |
231 | + m_productMatches.append(match); |
232 | + } |
233 | + |
234 | virtual void accept(ControllerPresetVisitor* visitor) const = 0; |
235 | virtual bool isMappable() const = 0; |
236 | |
237 | @@ -94,6 +99,8 @@ |
238 | // TODO(XXX) make private |
239 | QList<QString> scriptFileNames; |
240 | QList<QString> scriptFunctionPrefixes; |
241 | + // Optional list of controller device match details |
242 | + QList< QHash<QString,QString> > m_productMatches; |
243 | |
244 | private: |
245 | QString m_deviceId; |
246 | |
247 | === added file 'mixxx/src/controllers/controllerpresetinfo.cpp' |
248 | --- mixxx/src/controllers/controllerpresetinfo.cpp 1970-01-01 00:00:00 +0000 |
249 | +++ mixxx/src/controllers/controllerpresetinfo.cpp 2012-05-29 05:49:18 +0000 |
250 | @@ -0,0 +1,232 @@ |
251 | +/** |
252 | +* @file controllerpresetinfo.cpp |
253 | +* @author Ilkka Tuohela hile@iki.fi |
254 | +* @date Wed May 15 2012 |
255 | +* @brief Implement handling enumeration and parsing of preset info headers |
256 | +* |
257 | +* This class handles enumeration and parsing of controller XML description file |
258 | +* <info> header tags. It can be used to match controllers automatically or to |
259 | +* show details for a mapping. |
260 | +*/ |
261 | + |
262 | +#include "controllers/controllerpresetinfo.h" |
263 | + |
264 | +PresetInfo::PresetInfo(const QString preset_path) { |
265 | + // Parse <info> header section from a controller description XML file |
266 | + // Contents parsed by xml path: |
267 | + // info.name Mapping name, used for drop down menus in dialogs |
268 | + // info.author Mapping author |
269 | + // info.description Mapping description |
270 | + // info.devices.product List of device matches, specific to device type |
271 | + path = QFileInfo(preset_path).absoluteFilePath(); |
272 | + name = ""; |
273 | + author = ""; |
274 | + description = ""; |
275 | + |
276 | + QDomElement root = XmlParse::openXMLFile(path, "controller"); |
277 | + if (root.isNull()) { |
278 | + qDebug() << "ERROR parsing" << path; |
279 | + return; |
280 | + } |
281 | + QDomElement info = root.firstChildElement("info"); |
282 | + if (info.isNull()) { |
283 | + qDebug() << "MISSING <info> ELEMENT: " << path; |
284 | + return; |
285 | + } |
286 | + QDomElement dom_name = info.firstChildElement("name"); |
287 | + if (!dom_name.isNull()) name = dom_name.text(); |
288 | + |
289 | + QDomElement dom_author = info.firstChildElement("author"); |
290 | + if (!dom_author.isNull()) author = dom_author.text(); |
291 | + |
292 | + QDomElement dom_description = info.firstChildElement("description"); |
293 | + if (!dom_description.isNull()) description = dom_description.text(); |
294 | + |
295 | + QDomElement devices = info.firstChildElement("devices"); |
296 | + if (!devices.isNull()) { |
297 | + QDomElement product = devices.firstChildElement("product"); |
298 | + while (!product.isNull()) { |
299 | + QString protocol = product.attribute("protocol",""); |
300 | + if (protocol=="hid") { |
301 | + products.append(parseHIDProduct(product)); |
302 | + } else if (protocol=="midi") { |
303 | + qDebug("MIDI product info parsing not yet implemented"); |
304 | + //products.append(parseMIDIProduct(product); |
305 | + } else if (protocol=="osc") { |
306 | + qDebug("OSC product info parsing not yet implemented"); |
307 | + //products.append(parseOSCProduct(product); |
308 | + } else { |
309 | + qDebug("Product specification missing protocol attribute"); |
310 | + } |
311 | + product = product.nextSiblingElement("product"); |
312 | + } |
313 | + } |
314 | +} |
315 | + |
316 | +QHash<QString,QString> PresetInfo::parseHIDProduct(const QDomElement& element) const { |
317 | + // HID device <product> element parsing. Example of valid element: |
318 | + // <product protocol="hid" vendor_id="0x1" product_id="0x2" usage_page="0x3" usage="0x4" interface_number="0x3" /> |
319 | + // All numbers must be hex prefixed with 0x |
320 | + // Only vendor_id and product_id fields are required to map a device. |
321 | + // usage_page and usage are matched on OS/X and windows |
322 | + // interface_number is matched on linux, which does support usage_page/usage |
323 | + |
324 | + QHash<QString,QString> product; |
325 | + product.insert("procotol",element.attribute("protocol","")); |
326 | + product.insert("vendor_id",element.attribute("vendor_id","")); |
327 | + product.insert("product_id",element.attribute("product_id","")); |
328 | + product.insert("usage_page",element.attribute("usage_page","")); |
329 | + product.insert("usage",element.attribute("usage","")); |
330 | + product.insert("interface_number",element.attribute("interface_number","")); |
331 | + return product; |
332 | +} |
333 | + |
334 | +QHash<QString,QString> PresetInfo::parseMIDIProduct(const QDomElement& element) const { |
335 | + // TODO - implement parsing of MIDI attributes |
336 | + // When done, remember to fix switch() above to call this |
337 | + QHash<QString,QString> product; |
338 | + product.insert("procotol",element.attribute("protocol","")); |
339 | + return product; |
340 | +} |
341 | + |
342 | +QHash<QString,QString> PresetInfo::parseOSCProduct(const QDomElement& element) const { |
343 | + // TODO - implement parsing of OSC product attributes |
344 | + // When done, remember to fix switch() above to call this |
345 | + QHash<QString,QString> product; |
346 | + product.insert("procotol",element.attribute("protocol","")); |
347 | + return product; |
348 | +} |
349 | + |
350 | +PresetInfoEnumerator::PresetInfoEnumerator(ConfigObject<ConfigValue> *pConfig) |
351 | + : m_pConfig(pConfig) { |
352 | + |
353 | + QString configPath = m_pConfig->getConfigPath(); |
354 | + controllerDirPaths.append(configPath.append("controllers/")); |
355 | + controllerDirPaths.append(LOCAL_PRESETS_PATH); |
356 | + |
357 | + // Static list of supported default extensions, sorted by popularity |
358 | + fileExtensions.append(QString(".midi.xml")); |
359 | + fileExtensions.append(QString(".cntrlr.xml")); |
360 | + fileExtensions.append(QString(".hid.xml")); |
361 | + fileExtensions.append(QString(".osc.xml")); |
362 | + |
363 | + loadSupportedPresets(); |
364 | +} |
365 | + |
366 | +bool PresetInfoEnumerator::isValidExtension(const QString extension) { |
367 | + if (presetsByExtension.contains(extension)) |
368 | + return true; |
369 | + return false; |
370 | +} |
371 | + |
372 | +bool PresetInfoEnumerator::hasPresetInfo(const QString extension, const QString name) { |
373 | + // Check if preset info matching extension and preset name can be found |
374 | + if (!isValidExtension(extension)) |
375 | + return false; |
376 | + foreach (QString extension, presetsByExtension.keys()) { |
377 | + QMap <QString,PresetInfo*> presets = presetsByExtension[extension]; |
378 | + foreach (PresetInfo* preset, presets.values()) |
379 | + if (name==preset->getName()) |
380 | + return true; |
381 | + } |
382 | + return false; |
383 | +} |
384 | + |
385 | +bool PresetInfoEnumerator::hasPresetInfo(const QString path) { |
386 | + foreach (QString extension, presetsByExtension.keys()) { |
387 | + QMap <QString,PresetInfo*> presets = presetsByExtension[extension]; |
388 | + if (presets.contains(path)) |
389 | + return true; |
390 | + } |
391 | + return false; |
392 | +} |
393 | + |
394 | +PresetInfo* PresetInfoEnumerator::getPresetInfo(const QString extension, const QString name) { |
395 | + QList<PresetInfo*> extension_presets; |
396 | + if (!isValidExtension(extension)) |
397 | + return NULL; |
398 | + |
399 | + foreach (QString extension, presetsByExtension.keys()) { |
400 | + QMap <QString,PresetInfo*> presets = presetsByExtension[extension]; |
401 | + foreach (PresetInfo* preset, presets.values()) |
402 | + if (name==preset->getName()) |
403 | + return preset; |
404 | + } |
405 | + return NULL; |
406 | +} |
407 | + |
408 | +PresetInfo* PresetInfoEnumerator::getPresetInfo(const QString path) { |
409 | + // Lookup and return controller script preset info by script path |
410 | + // Return NULL if path is not found. |
411 | + foreach (QString extension, presetsByExtension.keys()) { |
412 | + QMap <QString,PresetInfo*> presets = presetsByExtension[extension]; |
413 | + if (presets.contains(path)) |
414 | + return presets[path]; |
415 | + } |
416 | + return NULL; |
417 | +} |
418 | + |
419 | +QList<PresetInfo*> PresetInfoEnumerator::getPresets(const QString extension) { |
420 | + // Return list of PresetInfo items matching extension |
421 | + // Returns empty list if no matching extension presets can be found |
422 | + QList <PresetInfo*> presets; |
423 | + if (presetsByExtension.contains(extension)) { |
424 | + presets = presetsByExtension[extension].values(); |
425 | + return presetsByExtension[extension].values(); |
426 | + } |
427 | + qDebug() << "Extension not registered to presetinfo" << extension; |
428 | + return presets; |
429 | +} |
430 | + |
431 | +void PresetInfoEnumerator::addExtension(const QString extension) { |
432 | + if (presetsByExtension.contains(extension)) |
433 | + return; |
434 | + QMap <QString,PresetInfo*> presets; |
435 | + presetsByExtension[extension] = presets; |
436 | +} |
437 | + |
438 | +void PresetInfoEnumerator::loadSupportedPresets() { |
439 | + |
440 | + foreach (QString dirPath, controllerDirPaths) { |
441 | + QDirIterator it(dirPath); |
442 | + while (it.hasNext()) { |
443 | + it.next(); |
444 | + const QString path = it.filePath(); |
445 | + foreach (QString extension, fileExtensions) { |
446 | + if (!path.endsWith(extension)) |
447 | + continue; |
448 | + if (!presetsByExtension.contains(extension)) { |
449 | + addExtension(extension); |
450 | + } |
451 | + PresetInfo* preset = new PresetInfo(path); |
452 | + presetsByExtension[extension][path] = preset; |
453 | + } |
454 | + } |
455 | + } |
456 | + |
457 | + foreach (QString extension, presetsByExtension.keys()) { |
458 | + QMap <QString,PresetInfo*> presets = presetsByExtension[extension]; |
459 | + qDebug() << "Extension" << extension << "total" << presets.keys().length() << "presets"; |
460 | + } |
461 | +} |
462 | + |
463 | +void PresetInfoEnumerator::updatePresets(const QString extension) { |
464 | + QMap <QString,PresetInfo*> presets; |
465 | + |
466 | + if (presetsByExtension.contains(extension)) |
467 | + presetsByExtension.remove(extension); |
468 | + |
469 | + foreach (QString dirPath, controllerDirPaths) { |
470 | + QDirIterator it(dirPath); |
471 | + while (it.hasNext()) { |
472 | + it.next(); |
473 | + const QString path = it.filePath(); |
474 | + if (!path.endsWith(extension)) |
475 | + continue; |
476 | + PresetInfo* preset = new PresetInfo(path); |
477 | + presets[path] = preset; |
478 | + } |
479 | + } |
480 | + |
481 | + presetsByExtension[extension] = presets; |
482 | +} |
483 | |
484 | === added file 'mixxx/src/controllers/controllerpresetinfo.h' |
485 | --- mixxx/src/controllers/controllerpresetinfo.h 1970-01-01 00:00:00 +0000 |
486 | +++ mixxx/src/controllers/controllerpresetinfo.h 2012-05-29 05:49:18 +0000 |
487 | @@ -0,0 +1,87 @@ |
488 | +/** |
489 | +* @file controllerpresetinfo.h |
490 | +* @author Ilkka Tuohela hile@iki.fi |
491 | +* @date Wed May 15 2012 |
492 | +* @brief Base class handling enumeration and parsing of preset info headers |
493 | +* |
494 | +* This class handles enumeration and parsing of controller XML description file |
495 | +* <info> header tags. It can be used to match controllers automatically or to |
496 | +* show details for a mapping. |
497 | +*/ |
498 | + |
499 | +#ifndef CONTROLLERPRESETINFO_H |
500 | +#define CONTROLLERPRESETINFO_H |
501 | + |
502 | +#include <QtGui> |
503 | +#include <QMap> |
504 | +#include <QHash> |
505 | + |
506 | +#include "xmlparse.h" |
507 | +#include "controllers/defs_controllers.h" |
508 | +#include "configobject.h" |
509 | + |
510 | +class PresetInfo { |
511 | + public: |
512 | + PresetInfo(const QString path); |
513 | + ~PresetInfo() {}; |
514 | + |
515 | + inline const QString getPath() { return path; }; |
516 | + |
517 | + inline const QString getName() { return name; }; |
518 | + inline const QString getDescription() { return description; }; |
519 | + inline const QString getAuthor() { return author; }; |
520 | + |
521 | + inline const QList< QHash<QString,QString> > getProducts() { return products; }; |
522 | + |
523 | + private: |
524 | + |
525 | + QHash<QString,QString> parseHIDProduct(const QDomElement& element) const; |
526 | + // Note - following are just stubs, not yet implemented |
527 | + QHash<QString,QString> parseMIDIProduct(const QDomElement& element) const; |
528 | + QHash<QString,QString> parseOSCProduct(const QDomElement& element) const; |
529 | + |
530 | + QString path; |
531 | + QString name; |
532 | + QString author; |
533 | + QString description; |
534 | + QList< QHash<QString,QString> > products; |
535 | +}; |
536 | + |
537 | +class PresetInfoEnumerator { |
538 | + public: |
539 | + PresetInfoEnumerator(ConfigObject<ConfigValue> *pConfig); |
540 | + virtual ~PresetInfoEnumerator() {}; |
541 | + |
542 | + bool isValidExtension(const QString extension); |
543 | + |
544 | + bool hasPresetInfo(const QString extension, const QString name); |
545 | + bool hasPresetInfo(const QString path); |
546 | + |
547 | + PresetInfo* getPresetInfo(const QString extension, const QString name); |
548 | + PresetInfo* getPresetInfo(const QString path); |
549 | + |
550 | + // Return cached list of presets for this extension |
551 | + QList <PresetInfo*> getPresets(const QString extension); |
552 | + |
553 | + // Updates presets matching given extension |
554 | + void updatePresets(const QString extension); |
555 | + |
556 | + protected: |
557 | + void addExtension(QString extension); |
558 | + void loadSupportedPresets(); |
559 | + |
560 | + private: |
561 | + |
562 | + QList <QString> fileExtensions; |
563 | + ConfigObject<ConfigValue>* m_pConfig; |
564 | + |
565 | + // List of paths for controller presets |
566 | + QList <QString> controllerDirPaths; |
567 | + |
568 | + // Cached presets by extension. Map format is: |
569 | + // [extension,[preset_path,preset]] |
570 | + QMap <QString, QMap<QString,PresetInfo*> > presetsByExtension; |
571 | + |
572 | +}; |
573 | + |
574 | +#endif |
575 | \ No newline at end of file |
576 | |
577 | === modified file 'mixxx/src/controllers/dlgprefcontroller.cpp' |
578 | --- mixxx/src/controllers/dlgprefcontroller.cpp 2012-04-29 04:31:26 +0000 |
579 | +++ mixxx/src/controllers/dlgprefcontroller.cpp 2012-05-29 05:49:18 +0000 |
580 | @@ -32,7 +32,9 @@ |
581 | m_ui.setupUi(this); |
582 | m_pLayout = m_ui.gridLayout_4; |
583 | const ControllerPresetPointer pPreset = controller->getPreset(); |
584 | + |
585 | m_ui.labelLoadedPreset->setText(presetShortName(pPreset)); |
586 | + m_ui.labelLoadedPresetDescription->setText(presetDescription(pPreset)); |
587 | |
588 | //m_pVerticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); |
589 | //m_pLayout->addItem(m_pVerticalSpacer, 4, 0, 1, 3); |
590 | @@ -42,21 +44,28 @@ |
591 | //setLayout(vLayout); |
592 | |
593 | m_ui.labelDeviceName->setText(m_pController->getName()); |
594 | + QString category = m_pController->getCategory(); |
595 | + if (category!="") { |
596 | + m_ui.labelDeviceCategory->setText(category); |
597 | + } else { |
598 | + m_ui.labelDeviceCategory->hide(); |
599 | + } |
600 | |
601 | connect(m_ui.comboBoxPreset, SIGNAL(activated(const QString&)), |
602 | this, SLOT(slotLoadPreset(const QString&))); |
603 | connect(m_ui.comboBoxPreset, SIGNAL(activated(const QString&)), |
604 | this, SLOT(slotDirty())); |
605 | |
606 | + // Connect if we wish to automatically set current mapping as autoload |
607 | + // connect(m_ui.comboBoxPreset, SIGNAL(currentIndexChanged(const QString&)), |
608 | + // this, SLOT(slotDirty())); |
609 | + |
610 | connect(this, SIGNAL(openController(Controller*)), |
611 | m_pControllerManager, SLOT(openController(Controller*))); |
612 | connect(this, SIGNAL(closeController(Controller*)), |
613 | m_pControllerManager, SLOT(closeController(Controller*))); |
614 | connect(this, SIGNAL(loadPreset(Controller*, QString, bool)), |
615 | m_pControllerManager, SLOT(loadPreset(Controller*, QString, bool))); |
616 | - |
617 | - // Load the list of presets into the presets combobox. |
618 | - enumeratePresets(); |
619 | } |
620 | |
621 | DlgPrefController::~DlgPrefController() { |
622 | @@ -78,6 +87,16 @@ |
623 | return presetName; |
624 | } |
625 | |
626 | +QString DlgPrefController::presetDescription(const ControllerPresetPointer pPreset) const { |
627 | + QString description = tr("No Description"); |
628 | + if (pPreset) { |
629 | + QString descr = pPreset->description(); |
630 | + if (description.length() > 0) |
631 | + description = descr; |
632 | + } |
633 | + return description; |
634 | +} |
635 | + |
636 | void DlgPrefController::addWidgetToLayout(QWidget* pWidget) { |
637 | // Remove the vertical spacer since we're adding stuff |
638 | //m_pLayout->removeItem(m_pVerticalSpacer); |
639 | @@ -91,18 +110,40 @@ |
640 | void DlgPrefController::enumeratePresets() { |
641 | m_ui.comboBoxPreset->clear(); |
642 | |
643 | + // qDebug() << "Enumerating presets for controller" << m_pController->getName(); |
644 | + |
645 | //Insert a dummy "..." item at the top to try to make it less confusing. |
646 | //(We don't want the first found file showing up as the default item |
647 | // when a user has their controller plugged in) |
648 | m_ui.comboBoxPreset->addItem("..."); |
649 | |
650 | + m_ui.comboBoxPreset->setInsertPolicy(QComboBox::InsertAlphabetically); |
651 | // Ask the controller manager for a list of applicable presets |
652 | - QList<QString> presetsList = |
653 | - m_pControllerManager->getPresetList(m_pController->presetExtension()); |
654 | - |
655 | - //Sort in alphabetical order |
656 | - qSort(presetsList); |
657 | - m_ui.comboBoxPreset->addItems(presetsList); |
658 | + PresetInfoEnumerator* pie = m_pControllerManager->getPresetInfoManager(); |
659 | + QList<PresetInfo*> presets = pie->getPresets(m_pController->presetExtension()); |
660 | + |
661 | + PresetInfo *match = NULL; |
662 | + int index = 1; |
663 | + foreach (PresetInfo* preset, presets) { |
664 | + // QVariant userdata = preset; |
665 | + m_ui.comboBoxPreset->addItem(preset->getName()); |
666 | + QList< QHash<QString,QString> > products = preset->getProducts(); |
667 | + for (int i=0;i<products.length();i++) { |
668 | + QHash <QString,QString> product = products[i]; |
669 | + if (m_pController->matchProductInfo(product)) { |
670 | + match = preset; |
671 | + break; |
672 | + } |
673 | + } |
674 | + index++; |
675 | + } |
676 | + |
677 | + // Jump to matching device in list if it was found. |
678 | + if (match!=NULL) { |
679 | + int index = m_ui.comboBoxPreset->findText(match->getName()); |
680 | + if (index!=-1) |
681 | + m_ui.comboBoxPreset->setCurrentIndex(index); |
682 | + } |
683 | } |
684 | |
685 | void DlgPrefController::slotUpdate() { |
686 | @@ -137,14 +178,25 @@ |
687 | } |
688 | |
689 | void DlgPrefController::slotLoadPreset(const QString &name) { |
690 | - if (name != "...") { |
691 | - emit(loadPreset(m_pController, name, true)); |
692 | - // It's applied on prefs close |
693 | + if (name=="...") |
694 | + return; |
695 | + |
696 | + // Lookup the name in preset from actual preset data |
697 | + PresetInfoEnumerator* presetmanager = m_pControllerManager->getPresetInfoManager(); |
698 | + PresetInfo* preset = presetmanager->getPresetInfo(m_pController->presetExtension(),name); |
699 | + if (preset==NULL) { |
700 | + qDebug() << "ERROR preset matching name not found: " << name; |
701 | + return; |
702 | } |
703 | + // qDebug() << "PRESET path" << preset->getPath(); |
704 | + |
705 | + // Applied on prefs close |
706 | + emit(loadPreset(m_pController, preset->getPath(), true)); |
707 | } |
708 | |
709 | void DlgPrefController::slotPresetLoaded(ControllerPresetPointer preset) { |
710 | m_ui.labelLoadedPreset->setText(presetShortName(preset)); |
711 | + m_ui.labelLoadedPresetDescription->setText(presetDescription(preset)); |
712 | } |
713 | |
714 | void DlgPrefController::slotDeviceState(int state) { |
715 | |
716 | === modified file 'mixxx/src/controllers/dlgprefcontroller.h' |
717 | --- mixxx/src/controllers/dlgprefcontroller.h 2012-04-29 04:31:26 +0000 |
718 | +++ mixxx/src/controllers/dlgprefcontroller.h 2012-05-29 05:49:18 +0000 |
719 | @@ -9,8 +9,10 @@ |
720 | #define DLGPREFCONTROLLER_H_ |
721 | |
722 | #include <QtGui> |
723 | +#include <QHash> |
724 | |
725 | #include "controllers/controllerpreset.h" |
726 | +#include "controllers/controllerpresetinfo.h" |
727 | #include "controllers/ui_dlgprefcontrollerdlg.h" |
728 | #include "configobject.h" |
729 | |
730 | @@ -36,6 +38,8 @@ |
731 | void slotLoadPreset(const QString &name); |
732 | // Mark that we need to apply the settings. |
733 | void slotDirty (); |
734 | + // Reload the mappings in the dropdown dialog |
735 | + void enumeratePresets(); |
736 | |
737 | signals: |
738 | void deviceStateChanged(DlgPrefController*, bool); |
739 | @@ -63,8 +67,8 @@ |
740 | |
741 | private: |
742 | QString presetShortName(const ControllerPresetPointer pPreset) const; |
743 | + QString presetDescription(const ControllerPresetPointer pPreset) const; |
744 | void savePreset(QString path); |
745 | - void enumeratePresets(); |
746 | |
747 | void enableDevice(); |
748 | void disableDevice(); |
749 | |
750 | === modified file 'mixxx/src/controllers/dlgprefcontrollerdlg.ui' |
751 | --- mixxx/src/controllers/dlgprefcontrollerdlg.ui 2012-04-29 04:34:22 +0000 |
752 | +++ mixxx/src/controllers/dlgprefcontrollerdlg.ui 2012-05-29 05:49:18 +0000 |
753 | @@ -57,7 +57,58 @@ |
754 | </property> |
755 | </widget> |
756 | </item> |
757 | - <item row="4" column="0"> |
758 | + <item row="5" column="0"> |
759 | + <widget class="QPushButton" name="pushButtonLearning"> |
760 | + <property name="enabled"> |
761 | + <bool>false</bool> |
762 | + </property> |
763 | + <property name="sizePolicy"> |
764 | + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
765 | + <horstretch>0</horstretch> |
766 | + <verstretch>0</verstretch> |
767 | + </sizepolicy> |
768 | + </property> |
769 | + <property name="maximumSize"> |
770 | + <size> |
771 | + <width>300</width> |
772 | + <height>16777215</height> |
773 | + </size> |
774 | + </property> |
775 | + <property name="toolTip"> |
776 | + <string>Click to start the Controller Learning wizard.</string> |
777 | + </property> |
778 | + <property name="text"> |
779 | + <string>Learning Wizard (MIDI Only)</string> |
780 | + </property> |
781 | + </widget> |
782 | + </item> |
783 | + <item row="5" column="1"> |
784 | + <spacer name="horizontalSpacer"> |
785 | + <property name="orientation"> |
786 | + <enum>Qt::Horizontal</enum> |
787 | + </property> |
788 | + <property name="sizeHint" stdset="0"> |
789 | + <size> |
790 | + <width>40</width> |
791 | + <height>20</height> |
792 | + </size> |
793 | + </property> |
794 | + </spacer> |
795 | + </item> |
796 | + <item row="7" column="0"> |
797 | + <spacer name="verticalSpacer"> |
798 | + <property name="orientation"> |
799 | + <enum>Qt::Vertical</enum> |
800 | + </property> |
801 | + <property name="sizeHint" stdset="0"> |
802 | + <size> |
803 | + <width>20</width> |
804 | + <height>40</height> |
805 | + </size> |
806 | + </property> |
807 | + </spacer> |
808 | + </item> |
809 | + <item row="4" column="0" colspan="2"> |
810 | <widget class="QGroupBox" name="groupBoxPresets"> |
811 | <property name="sizePolicy"> |
812 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
813 | @@ -65,6 +116,12 @@ |
814 | <verstretch>0</verstretch> |
815 | </sizepolicy> |
816 | </property> |
817 | + <property name="maximumSize"> |
818 | + <size> |
819 | + <width>550</width> |
820 | + <height>16777215</height> |
821 | + </size> |
822 | + </property> |
823 | <property name="title"> |
824 | <string/> |
825 | </property> |
826 | @@ -81,7 +138,7 @@ |
827 | <property name="margin"> |
828 | <number>0</number> |
829 | </property> |
830 | - <item row="1" column="2"> |
831 | + <item row="2" column="2"> |
832 | <widget class="QComboBox" name="comboBoxPreset"> |
833 | <property name="sizePolicy"> |
834 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
835 | @@ -97,8 +154,20 @@ |
836 | </property> |
837 | </widget> |
838 | </item> |
839 | - <item row="1" column="1"> |
840 | + <item row="2" column="1"> |
841 | <widget class="QLabel" name="label"> |
842 | + <property name="sizePolicy"> |
843 | + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> |
844 | + <horstretch>0</horstretch> |
845 | + <verstretch>0</verstretch> |
846 | + </sizepolicy> |
847 | + </property> |
848 | + <property name="maximumSize"> |
849 | + <size> |
850 | + <width>16777215</width> |
851 | + <height>16777215</height> |
852 | + </size> |
853 | + </property> |
854 | <property name="text"> |
855 | <string>Load Preset:</string> |
856 | </property> |
857 | @@ -113,7 +182,7 @@ |
858 | <item row="0" column="1"> |
859 | <widget class="QLabel" name="label_2"> |
860 | <property name="sizePolicy"> |
861 | - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
862 | + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> |
863 | <horstretch>0</horstretch> |
864 | <verstretch>0</verstretch> |
865 | </sizepolicy> |
866 | @@ -122,14 +191,14 @@ |
867 | <string>Loaded Preset:</string> |
868 | </property> |
869 | <property name="alignment"> |
870 | - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |
871 | + <set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set> |
872 | </property> |
873 | </widget> |
874 | </item> |
875 | <item row="0" column="2"> |
876 | <widget class="QLabel" name="labelLoadedPreset"> |
877 | <property name="sizePolicy"> |
878 | - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
879 | + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> |
880 | <horstretch>0</horstretch> |
881 | <verstretch>0</verstretch> |
882 | </sizepolicy> |
883 | @@ -137,50 +206,71 @@ |
884 | <property name="text"> |
885 | <string notr="true">(preset name goes here)</string> |
886 | </property> |
887 | + <property name="wordWrap"> |
888 | + <bool>true</bool> |
889 | + </property> |
890 | + </widget> |
891 | + </item> |
892 | + <item row="1" column="1"> |
893 | + <widget class="QLabel" name="label_description"> |
894 | + <property name="sizePolicy"> |
895 | + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> |
896 | + <horstretch>0</horstretch> |
897 | + <verstretch>0</verstretch> |
898 | + </sizepolicy> |
899 | + </property> |
900 | + <property name="text"> |
901 | + <string>Description:</string> |
902 | + </property> |
903 | + <property name="alignment"> |
904 | + <set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set> |
905 | + </property> |
906 | + </widget> |
907 | + </item> |
908 | + <item row="1" column="2"> |
909 | + <widget class="QLabel" name="labelLoadedPresetDescription"> |
910 | + <property name="sizePolicy"> |
911 | + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> |
912 | + <horstretch>0</horstretch> |
913 | + <verstretch>0</verstretch> |
914 | + </sizepolicy> |
915 | + </property> |
916 | + <property name="minimumSize"> |
917 | + <size> |
918 | + <width>400</width> |
919 | + <height>0</height> |
920 | + </size> |
921 | + </property> |
922 | + <property name="text"> |
923 | + <string notr="true">(preset description goes here) even when it is a damn long text which should wrap but does not</string> |
924 | + </property> |
925 | + <property name="alignment"> |
926 | + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> |
927 | + </property> |
928 | + <property name="wordWrap"> |
929 | + <bool>true</bool> |
930 | + </property> |
931 | </widget> |
932 | </item> |
933 | </layout> |
934 | </widget> |
935 | </item> |
936 | - <item row="5" column="0"> |
937 | - <widget class="QPushButton" name="pushButtonLearning"> |
938 | + <item row="1" column="0"> |
939 | + <widget class="QLabel" name="labelDeviceCategory"> |
940 | <property name="enabled"> |
941 | - <bool>false</bool> |
942 | + <bool>true</bool> |
943 | </property> |
944 | - <property name="toolTip"> |
945 | - <string>Click to start the Controller Learning wizard.</string> |
946 | + <property name="sizePolicy"> |
947 | + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> |
948 | + <horstretch>0</horstretch> |
949 | + <verstretch>0</verstretch> |
950 | + </sizepolicy> |
951 | </property> |
952 | <property name="text"> |
953 | - <string>Learning Wizard (MIDI Only)</string> |
954 | + <string>TextLabel</string> |
955 | </property> |
956 | </widget> |
957 | </item> |
958 | - <item row="5" column="1"> |
959 | - <spacer name="horizontalSpacer"> |
960 | - <property name="orientation"> |
961 | - <enum>Qt::Horizontal</enum> |
962 | - </property> |
963 | - <property name="sizeHint" stdset="0"> |
964 | - <size> |
965 | - <width>40</width> |
966 | - <height>20</height> |
967 | - </size> |
968 | - </property> |
969 | - </spacer> |
970 | - </item> |
971 | - <item row="7" column="0"> |
972 | - <spacer name="verticalSpacer"> |
973 | - <property name="orientation"> |
974 | - <enum>Qt::Vertical</enum> |
975 | - </property> |
976 | - <property name="sizeHint" stdset="0"> |
977 | - <size> |
978 | - <width>20</width> |
979 | - <height>40</height> |
980 | - </size> |
981 | - </property> |
982 | - </spacer> |
983 | - </item> |
984 | </layout> |
985 | </widget> |
986 | <resources/> |
987 | |
988 | === modified file 'mixxx/src/controllers/hid/hidcontroller.cpp' |
989 | --- mixxx/src/controllers/hid/hidcontroller.cpp 2012-05-20 01:12:02 +0000 |
990 | +++ mixxx/src/controllers/hid/hidcontroller.cpp 2012-05-29 05:49:18 +0000 |
991 | @@ -80,6 +80,8 @@ |
992 | wcslen(deviceInfo.product_string) |
993 | ); |
994 | |
995 | + guessDeviceCategory(); |
996 | + |
997 | // Set the Unique Identifier to the serial_number |
998 | m_sUID = QString::fromWCharArray(hid_serial,wcslen(hid_serial)); |
999 | |
1000 | @@ -127,6 +129,68 @@ |
1001 | return handler.save(m_preset, getName(), fileName); |
1002 | } |
1003 | |
1004 | +bool HidController::matchProductInfo(QHash <QString,QString > info) { |
1005 | + int value; |
1006 | + bool ok; |
1007 | + // Product and vendor match is always required |
1008 | + value = info["vendor_id"].toInt(&ok,16); |
1009 | + if (!ok || hid_vendor_id!=value) return false; |
1010 | + value = info["product_id"].toInt(&ok,16); |
1011 | + if (!ok || hid_product_id!=value) return false; |
1012 | + |
1013 | + // Optionally check against interface_number / usage_page && usage |
1014 | + if (hid_interface_number!=-1) { |
1015 | + value = info["interface_number"].toInt(&ok,16); |
1016 | + if (!ok || hid_interface_number!=value) return false; |
1017 | + } else { |
1018 | + value = info["usage_page"].toInt(&ok,16); |
1019 | + if (!ok || hid_usage_page!=value) return false; |
1020 | + |
1021 | + value = info["usage"].toInt(&ok,16); |
1022 | + if (!ok || hid_usage!=value) return false; |
1023 | + } |
1024 | + // Match found |
1025 | + return true; |
1026 | +} |
1027 | +void HidController::guessDeviceCategory() { |
1028 | + // This should be done somehow else, I know. But at least we get started with |
1029 | + // the idea of mapping this information |
1030 | + QString info; |
1031 | + if (hid_interface_number==-1) { |
1032 | + if (hid_usage_page==0x1) { |
1033 | + switch (hid_usage) { |
1034 | + case 0x2: info = "Generic HID Mouse"; break; |
1035 | + case 0x4: info = "Generic HID Joystick"; break; |
1036 | + case 0x5: info = "Generic HID Gamepad"; break; |
1037 | + case 0x6: info = "Generic HID Keyboard"; break; |
1038 | + case 0x8: info = "Gereric HID Multiaxis Controller"; break; |
1039 | + default: |
1040 | + info.sprintf( |
1041 | + "Unknown HID Desktop Device 0x%0x/0x%0x",hid_usage_page,hid_usage |
1042 | + ); |
1043 | + break; |
1044 | + } |
1045 | + } else if (hid_vendor_id==0x5ac) { |
1046 | + // Apple laptop special HID devices |
1047 | + if (hid_product_id==0x8242) { |
1048 | + info = "HID Infrared Control"; |
1049 | + } else { |
1050 | + info.sprintf( |
1051 | + "Unknown Apple HID Device 0x%0x/0x%0x",hid_usage_page,hid_usage |
1052 | + ); |
1053 | + } |
1054 | + } else { |
1055 | + // Fill in the usage page and usage fields for debugging info |
1056 | + info.sprintf("HID Unknown Device 0x%0x/0x%0x",hid_usage_page,hid_usage); |
1057 | + } |
1058 | + } else { |
1059 | + // Guess linux device types somehow as well. Or maybe just |
1060 | + // fill in the interface number? |
1061 | + info.sprintf("HID Interface Number 0x%0x",hid_interface_number); |
1062 | + } |
1063 | + setDeviceCategory(info); |
1064 | +} |
1065 | + |
1066 | int HidController::open() { |
1067 | if (isOpen()) { |
1068 | qDebug() << "HID device" << getName() << "already open"; |
1069 | |
1070 | === modified file 'mixxx/src/controllers/hid/hidcontroller.h' |
1071 | --- mixxx/src/controllers/hid/hidcontroller.h 2012-05-16 14:58:38 +0000 |
1072 | +++ mixxx/src/controllers/hid/hidcontroller.h 2012-05-29 05:49:18 +0000 |
1073 | @@ -62,6 +62,9 @@ |
1074 | return m_preset.isMappable(); |
1075 | } |
1076 | |
1077 | + virtual bool matchProductInfo(QHash <QString,QString >); |
1078 | + virtual void guessDeviceCategory(); |
1079 | + |
1080 | protected: |
1081 | Q_INVOKABLE void send(QList<int> data, unsigned int length, unsigned int reportID = 0); |
1082 | |
1083 | |
1084 | === modified file 'mixxx/src/controllers/midi/midicontroller.cpp' |
1085 | --- mixxx/src/controllers/midi/midicontroller.cpp 2012-05-26 23:32:16 +0000 |
1086 | +++ mixxx/src/controllers/midi/midicontroller.cpp 2012-05-29 05:49:18 +0000 |
1087 | @@ -56,6 +56,11 @@ |
1088 | // TODO(XXX): throw a hissy fit. |
1089 | } |
1090 | |
1091 | +bool MidiController::matchProductInfo(QHash <QString,QString >) { |
1092 | + // Product info mapping not implemented for MIDI devices yet |
1093 | + return false; |
1094 | +} |
1095 | + |
1096 | bool MidiController::savePreset(const QString fileName) const { |
1097 | MidiControllerPresetFileHandler handler; |
1098 | return handler.save(m_preset, getName(), fileName); |
1099 | |
1100 | === modified file 'mixxx/src/controllers/midi/midicontroller.h' |
1101 | --- mixxx/src/controllers/midi/midicontroller.h 2012-05-25 04:24:48 +0000 |
1102 | +++ mixxx/src/controllers/midi/midicontroller.h 2012-05-29 05:49:18 +0000 |
1103 | @@ -48,6 +48,8 @@ |
1104 | return m_preset.isMappable(); |
1105 | } |
1106 | |
1107 | + virtual bool matchProductInfo(QHash <QString,QString >); |
1108 | + |
1109 | protected: |
1110 | Q_INVOKABLE void sendShortMsg(unsigned char status, unsigned char byte1, unsigned char byte2); |
1111 | // Alias for send() |
1112 | |
1113 | === modified file 'mixxx/src/dlgpreferences.cpp' |
1114 | --- mixxx/src/dlgpreferences.cpp 2012-04-29 05:43:31 +0000 |
1115 | +++ mixxx/src/dlgpreferences.cpp 2012-05-29 05:49:18 +0000 |
1116 | @@ -425,6 +425,11 @@ |
1117 | { |
1118 | //For each controller, create a dialog and put a little link to it in the treepane on the left |
1119 | QList<Controller*> controllerList = m_pControllerManager->getControllerList(false, true); |
1120 | + qSort( |
1121 | + controllerList.begin(), |
1122 | + controllerList.end(), |
1123 | + controllerCompare |
1124 | + ); |
1125 | QListIterator<Controller*> ctrlr(controllerList); |
1126 | while (ctrlr.hasNext()) |
1127 | { |
1128 | @@ -441,6 +446,7 @@ |
1129 | this, SLOT(show())); |
1130 | m_controllerWindows.append(controllerDlg); |
1131 | addPageWidget(controllerDlg); |
1132 | + connect(this, SIGNAL(showDlg()), controllerDlg, SLOT(enumeratePresets())); |
1133 | connect(this, SIGNAL(showDlg()), controllerDlg, SLOT(slotUpdate())); |
1134 | connect(buttonBox, SIGNAL(accepted()), controllerDlg, SLOT(slotApply())); |
1135 | connect(controllerDlg, SIGNAL(deviceStateChanged(DlgPrefController*,bool)), this, SLOT(slotHighlightDevice(DlgPrefController*,bool))); |
1136 | @@ -450,6 +456,7 @@ |
1137 | config); |
1138 | m_controllerWindows.append(controllerDlg); |
1139 | addPageWidget(controllerDlg); |
1140 | + connect(this, SIGNAL(showDlg()), controllerDlg, SLOT(enumeratePresets())); |
1141 | connect(this, SIGNAL(showDlg()), controllerDlg, SLOT(slotUpdate())); |
1142 | connect(buttonBox, SIGNAL(accepted()), controllerDlg, SLOT(slotApply())); |
1143 | connect(controllerDlg, SIGNAL(deviceStateChanged(DlgPrefController*,bool)), |