1202a47d94dc53de1a3180e3f5976379c7a6deba
[ardour.git] / libs / midi++2 / test / MidnamTest.cpp
1 #include "MidnamTest.hpp"
2
3 #include <glibmm/fileutils.h>
4 #include <glibmm/miscutils.h>
5
6 #include "pbd/xml++.h"
7 #include "pbd/file_utils.h"
8 #include "pbd/compose.h"
9 #include "midi++/midnam_patch.h"
10
11 using namespace std;
12 using namespace PBD;
13 using namespace MIDI::Name;
14
15 CPPUNIT_TEST_SUITE_REGISTRATION( MidnamTest );
16
17 PBD::Searchpath
18 test_search_path ()
19 {
20 #ifdef PLATFORM_WINDOWS
21         std::vector<std::string> path_tok;
22         path_tok.push_back (g_win32_get_package_installation_directory_of_module(NULL));
23         path_tok.push_back ("share");
24         path_tok.push_back ("ardour3");
25         path_tok.push_back ("patchfiles");
26         return Glib::build_filename (path_tok);
27 #else
28         return Glib::getenv("MIDIPP_TEST_PATH");
29 #endif
30 }
31
32 void
33 MidnamTest::protools_patchfile_test()
34 {
35     std::string test_file_path;
36
37     CPPUNIT_ASSERT(find_file (test_search_path (), "Roland_SC-88_Pro.midnam", test_file_path));
38     XMLTree xmldoc(test_file_path);
39     boost::shared_ptr<XMLSharedNodeList> result = xmldoc.find(
40             "//MIDINameDocument");
41     CPPUNIT_ASSERT(result->size() == 1);
42
43     result = xmldoc.find("//ChannelNameSet");
44     CPPUNIT_ASSERT(result->size() == 2);
45
46     MIDINameDocument doc(test_file_path);
47     CPPUNIT_ASSERT(doc.all_models().size() == 1);
48     CPPUNIT_ASSERT(doc.author().find("Mark of the Unicorn") == 0);
49
50     const string model = *doc.all_models().begin();
51     CPPUNIT_ASSERT_EQUAL(string("SC-88 Pro"), model);
52     boost::shared_ptr<MasterDeviceNames> masterDeviceNames =
53             doc.master_device_names_by_model().find(model)->second;
54     CPPUNIT_ASSERT_EQUAL(string("Roland"), masterDeviceNames->manufacturer());
55
56     string modename = masterDeviceNames->custom_device_mode_names().front();
57     CPPUNIT_ASSERT_EQUAL(string("Default"), modename);
58
59     boost::shared_ptr<CustomDeviceMode> mode =
60             masterDeviceNames->custom_device_mode_by_name(modename);
61
62     CPPUNIT_ASSERT_EQUAL(modename, mode->name());
63
64     string ns1 = string("Name Set 1");
65     string ns2 = string("Name Set 2");
66
67     for (uint8_t i = 0; i <= 15; i++) {
68         if (i != 9)
69             CPPUNIT_ASSERT_EQUAL(ns1,
70                     mode->channel_name_set_name_by_channel(i));
71         else
72             CPPUNIT_ASSERT_EQUAL(ns2,
73                     mode->channel_name_set_name_by_channel(i));
74     }
75
76     boost::shared_ptr<ChannelNameSet> nameSet1 =
77             masterDeviceNames->channel_name_set_by_channel(modename, 0);
78     boost::shared_ptr<ChannelNameSet> nameSet2 =
79             masterDeviceNames->channel_name_set_by_channel(modename, 9);
80
81     CPPUNIT_ASSERT_EQUAL(ns1, nameSet1->name());
82     CPPUNIT_ASSERT_EQUAL(ns2, nameSet2->name());
83
84     const ChannelNameSet::PatchBanks& banks1 = nameSet1->patch_banks();
85     const ChannelNameSet::PatchBanks& banks2 = nameSet2->patch_banks();
86     CPPUNIT_ASSERT(banks1.size() == 16);
87     CPPUNIT_ASSERT(banks2.size() == 1);
88
89     boost::shared_ptr<PatchBank> bank = banks1.front();
90     CPPUNIT_ASSERT_EQUAL(string("Piano"), bank->name());
91     const PatchNameList& plist1 = bank->patch_name_list();
92     CPPUNIT_ASSERT(plist1.size() == 110);
93
94     bank = banks2.front();
95     CPPUNIT_ASSERT_EQUAL(string("Drum sets"), bank->name());
96     const PatchNameList& plist2 = bank->patch_name_list();
97     CPPUNIT_ASSERT(plist2.size() == 49);
98 }
99
100 void
101 MidnamTest::yamaha_PSRS900_patchfile_test()
102 {
103     std::string test_file_path;
104
105     CPPUNIT_ASSERT(find_file (test_search_path (), "Yamaha_PSR-S900.midnam", test_file_path));
106     XMLTree xmldoc(test_file_path);
107     boost::shared_ptr<XMLSharedNodeList> result = xmldoc.find(
108             "//MIDINameDocument");
109     CPPUNIT_ASSERT(result->size() == 1);
110
111     result = xmldoc.find("//ChannelNameSet");
112     CPPUNIT_ASSERT(result->size() == 3);
113
114     MIDINameDocument doc(test_file_path);
115     CPPUNIT_ASSERT(doc.all_models().size() == 1);
116     CPPUNIT_ASSERT(doc.author().find("Hans Baier") == 0);
117
118     const string model = *doc.all_models().begin();
119     CPPUNIT_ASSERT_EQUAL(string("PSR-S900"), model);
120     boost::shared_ptr<MasterDeviceNames> masterDeviceNames =
121             doc.master_device_names_by_model().find(model)->second;
122     CPPUNIT_ASSERT_EQUAL(string("Yamaha"), masterDeviceNames->manufacturer());
123
124     const MasterDeviceNames::CustomDeviceModeNames& modes = masterDeviceNames->custom_device_mode_names();
125     CPPUNIT_ASSERT(masterDeviceNames->custom_device_mode_names().size() == 3);
126
127     string modename = modes.front();
128     CPPUNIT_ASSERT_EQUAL(string("Standard"), modename);
129
130     modename = (*(++modes.begin()));
131     CPPUNIT_ASSERT_EQUAL(string("GM+XG"), modename);
132
133     modename = modes.back();
134     CPPUNIT_ASSERT_EQUAL(string("GM2"), modename);
135
136     for (list<string>::const_iterator modename = modes.begin(); modename != modes.end(); ++modename) {
137         boost::shared_ptr<CustomDeviceMode> mode =
138                 masterDeviceNames->custom_device_mode_by_name(*modename);
139
140         CPPUNIT_ASSERT_EQUAL(*modename, mode->name());
141
142         string ns = mode->name();
143
144         if (ns != string("Standard"))
145         for (uint8_t i = 0; i <= 15; i++) {
146                 CPPUNIT_ASSERT_EQUAL(ns,
147                         mode->channel_name_set_name_by_channel(i));
148                 boost::shared_ptr<ChannelNameSet> nameSet =
149                         masterDeviceNames->channel_name_set_by_channel(ns, 1);
150
151                 CPPUNIT_ASSERT_EQUAL(ns, nameSet->name());
152
153                 const ChannelNameSet::PatchBanks& banks1 = nameSet->patch_banks();
154                 CPPUNIT_ASSERT(banks1.size() > 1);
155
156                 boost::shared_ptr<PatchBank> bank = banks1.front();
157                 const PatchNameList& list = bank->patch_name_list();
158
159                 for(PatchNameList::const_iterator p = list.begin(); p != list.end(); ++p) {
160
161                 if (ns == string("GM+XG")) {
162                     uint8_t msb = (((*p)->bank_number()) >> 7) & 0x7f;
163                     CPPUNIT_ASSERT( msb == 0 || msb == 64);
164                 }
165
166                 if (ns == string("GM2")) {
167                     CPPUNIT_ASSERT((*p)->bank_number() >= (uint16_t(120) << 7));
168                 }
169                 }
170         }
171     }
172 }
173
174 void 
175 MidnamTest::load_all_midnams_test ()
176 {
177     vector<std::string> result;
178
179     PBD::find_files_matching_pattern (result, test_search_path (), "*.midnam");
180
181     CPPUNIT_ASSERT(!result.empty());
182
183     cout << "Loading " << result.size() << " MIDI patches from " << test_search_path ().to_string () << endl;
184
185     for (vector<std::string>::iterator i = result.begin(); i != result.end(); ++i) {
186         cout << "Processing file " << *i << endl;
187         boost::shared_ptr<MIDINameDocument> document(new MIDINameDocument(*i));
188
189         XMLTree xmldoc(*i);
190         boost::shared_ptr<XMLSharedNodeList> result = xmldoc.find("//MIDINameDocument");
191         CPPUNIT_ASSERT(result->size() == 1);
192
193         result = xmldoc.find("//MasterDeviceNames");
194         CPPUNIT_ASSERT(result->size() == 1);
195
196         result = xmldoc.find("//PatchBank");
197         //int banks = result->size();
198
199
200         result = xmldoc.find("//CustomDeviceMode[1]");
201         string deviceModeName = result->front()->property("Name")->value();
202
203         MIDINameDocument::MasterDeviceNamesList::const_iterator device =
204                     document->master_device_names_by_model().begin();
205
206         string modename = device->second->custom_device_mode_names().front();
207         boost::shared_ptr<CustomDeviceMode> mode = device->second->custom_device_mode_by_name(modename);
208         CPPUNIT_ASSERT_EQUAL(deviceModeName, mode->name());
209
210         boost::shared_ptr<ChannelNameSet> nameSet = device->second->channel_name_set_by_channel(modename, 0);
211     }
212 }
213