1 #include "controllers/controllerpresetinfo.h"
2 
3 #include "controllers/defs_controllers.h"
4 #include "util/xml.h"
5 
PresetInfo()6 PresetInfo::PresetInfo()
7         : m_valid(false) {
8 }
9 
PresetInfo(const QString & preset_path)10 PresetInfo::PresetInfo(const QString& preset_path)
11         : m_valid(false) {
12     // Parse <info> header section from a controller description XML file
13     // Contents parsed by xml path:
14     // info.name        Preset name, used for drop down menus in dialogs
15     // info.author      Preset author
16     // info.description Preset description
17     // info.forums      Link to mixxx forum discussion for the preset
18     // info.wiki        Link to mixxx wiki for the preset
19     // info.devices.product List of device matches, specific to device type
20     QFileInfo fileInfo(preset_path);
21     m_path = fileInfo.absoluteFilePath();
22     m_dirPath = fileInfo.dir().absolutePath();
23     m_name = "";
24     m_author = "";
25     m_description = "";
26     m_forumlink = "";
27     m_wikilink = "";
28 
29     QDomElement root = XmlParse::openXMLFile(m_path, "controller");
30     if (root.isNull()) {
31         qWarning() << "ERROR parsing" << m_path;
32         return;
33     }
34     QDomElement info = root.firstChildElement("info");
35     if (info.isNull()) {
36         qDebug() << "MISSING <info> ELEMENT: " << m_path;
37         return;
38     }
39 
40     m_valid = true;
41 
42     QDomElement dom_name = info.firstChildElement("name");
43     if (!dom_name.isNull()) {
44         m_name = dom_name.text();
45     } else {
46         m_name = fileInfo.baseName();
47     }
48 
49     QDomElement dom_author = info.firstChildElement("author");
50     if (!dom_author.isNull()) {
51         m_author = dom_author.text();
52     }
53 
54     QDomElement dom_description = info.firstChildElement("description");
55     if (!dom_description.isNull()) {
56         m_description = dom_description.text();
57     }
58 
59     QDomElement dom_forums = info.firstChildElement("forums");
60     if (!dom_forums.isNull()) {
61         m_forumlink = dom_forums.text();
62     }
63 
64     QDomElement dom_wiki = info.firstChildElement("wiki");
65     if (!dom_wiki.isNull()) {
66         m_wikilink = dom_wiki.text();
67     }
68 
69     QDomElement devices = info.firstChildElement("devices");
70     if (!devices.isNull()) {
71         QDomElement product = devices.firstChildElement("product");
72         while (!product.isNull()) {
73             QString protocol = product.attribute("protocol","");
74             if (protocol=="hid") {
75                 m_products.append(parseHIDProduct(product));
76             } else if (protocol=="bulk") {
77                 m_products.append(parseBulkProduct(product));
78             } else if (protocol=="midi") {
79                 qDebug("MIDI product info parsing not yet implemented");
80                 //m_products.append(parseMIDIProduct(product);
81             } else if (protocol=="osc") {
82                 qDebug("OSC product info parsing not yet implemented");
83                 //m_products.append(parseOSCProduct(product);
84             } else {
85                 qDebug("Product specification missing protocol attribute");
86             }
87             product = product.nextSiblingElement("product");
88         }
89     }
90 }
91 
parseBulkProduct(const QDomElement & element) const92 ProductInfo PresetInfo::parseBulkProduct(const QDomElement& element) const {
93     // <product protocol="bulk" vendor_id="0x06f8" product_id="0x0b105" in_epaddr="0x82" out_epaddr="0x03">
94     ProductInfo product;
95     product.protocol = element.attribute("protocol");
96     product.vendor_id = element.attribute("vendor_id");
97     product.product_id = element.attribute("product_id");
98     product.in_epaddr = element.attribute("in_epaddr");
99     product.out_epaddr = element.attribute("out_epaddr");
100     return product;
101 }
102 
parseHIDProduct(const QDomElement & element) const103 ProductInfo PresetInfo::parseHIDProduct(const QDomElement& element) const {
104     // HID device <product> element parsing. Example of valid element:
105     //   <product protocol="hid" vendor_id="0x1" product_id="0x2" usage_page="0x3" usage="0x4" interface_number="0x3" />
106     // All numbers must be hex prefixed with 0x
107     // Only vendor_id and product_id fields are required to map a device.
108     // usage_page and usage are matched on OS/X and windows
109     // interface_number is matched on linux, which does support usage_page/usage
110 
111     ProductInfo product;
112     product.protocol = element.attribute("protocol");
113     product.vendor_id = element.attribute("vendor_id");
114     product.product_id = element.attribute("product_id");
115     product.usage_page = element.attribute("usage_page");
116     product.usage = element.attribute("usage");
117     product.interface_number = element.attribute("interface_number");
118     return product;
119 }
120