1 /*
2  * liquidsfz - sfz sampler
3  *
4  * Copyright (C) 2020  Stefan Westerfeld
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your
9  * option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "pugixml.hh"
22 #include "liquidsfz.hh"
23 
24 using pugi::xml_node;
25 using pugi::xml_document;
26 using std::string;
27 
28 namespace LiquidSFZInternal
29 {
30 
31 string
gen_midnam(const LiquidSFZ::Synth & synth,const string & model)32 gen_midnam (const LiquidSFZ::Synth& synth, const string& model)
33 {
34   xml_document doc;
35 
36   doc.append_child (pugi::node_doctype).set_value ("MIDINameDocument PUBLIC"
37                                                    " \"-//MIDI Manufacturers Association//DTD MIDINameDocument 1.0//EN\""
38                                                    " \"http://www.midi.org/dtds/MIDINameDocument10.dtd\"");
39 
40   xml_node midi_name_document = doc.append_child ("MIDINameDocument");
41 
42   midi_name_document.append_child ("Author");
43   xml_node master_device_names = midi_name_document.append_child ("MasterDeviceNames");
44   master_device_names.append_child ("Manufacturer").append_child (pugi::node_pcdata).set_value ("LiquidSFZ");
45   master_device_names.append_child ("Model").append_child (pugi::node_pcdata).set_value (model.c_str());
46 
47   // ------------ <CustomDeviceMode>
48   xml_node custom_device_mode = master_device_names.append_child ("CustomDeviceMode");
49   custom_device_mode.append_attribute ("Name").set_value ("Default");
50 
51   xml_node channel_name_set_assignments = custom_device_mode.append_child ("ChannelNameSetAssignments");
52   for (int channel = 1; channel <= 16; channel++)
53     {
54       pugi::xml_node channel_name_set_assign = channel_name_set_assignments.append_child ("ChannelNameSetAssign");
55       channel_name_set_assign.append_attribute ("Channel").set_value (channel);
56       channel_name_set_assign.append_attribute ("NameSet").set_value ("Names");
57     }
58   // ------------ </CustomDeviceMode>
59 
60   // ------------ <ChannelNameSet>
61   xml_node channel_name_set = master_device_names.append_child ("ChannelNameSet");
62   channel_name_set.append_attribute ("Name").set_value("Names");
63 
64   xml_node available_for_channels = channel_name_set.append_child ("AvailableForChannels");
65   for (int channel = 1; channel <= 16; channel++)
66     {
67       xml_node available_channel = available_for_channels.append_child ("AvailableChannel");
68       available_channel.append_attribute ("Channel").set_value (channel);
69       available_channel.append_attribute ("Available").set_value ("true");
70     }
71   channel_name_set.append_child ("UsesControlNameList").append_attribute ("Name").set_value ("Controls");
72   channel_name_set.append_child ("UsesNoteNameList").append_attribute ("Name").set_value ("Notes");
73   // ------------ </ChannelNameSet>
74 
75   // ------------ <NoteNameList>
76   xml_node note_name_list = master_device_names.append_child ("NoteNameList");
77   note_name_list.append_attribute ("Name").set_value ("Notes");
78   for (const auto& key_info : synth.list_keys())
79     {
80       if (key_info.label() != "")
81         {
82           xml_node note = note_name_list.append_child ("Note");
83           note.append_attribute("Number").set_value (key_info.key());
84           note.append_attribute("Name").set_value (key_info.label().c_str());
85         }
86     }
87   // </NoteNameList>
88 
89   // ------------- <ControlNameList>
90   pugi::xml_node control_name_list = master_device_names.append_child ("ControlNameList");
91   control_name_list.append_attribute ("Name").set_value ("Controls");
92   for (const auto& cc_info : synth.list_ccs())
93     {
94       xml_node control = control_name_list.append_child ("Control");
95       control.append_attribute ("Type").set_value ("7bit");
96       control.append_attribute ("Number").set_value (cc_info.cc());
97       control.append_attribute ("Name").set_value (cc_info.label().c_str());
98     }
99   // ------------- </ControlNameList>
100 
101   struct xml_string_writer : pugi::xml_writer
102   {
103     string result;
104 
105     virtual void
106     write (const void* data, size_t size)
107     {
108       result.append (static_cast<const char*>(data), size);
109     }
110   } writer;
111 
112   doc.save (writer);
113   return writer.result;
114 }
115 
116 }
117