1 /*
2     PresetsStore.cpp - Presets and Clipboard store
3 
4     Original ZynAddSubFX author Nasca Octavian Paul
5     Copyright (C) 2002-2005 Nasca Octavian Paul
6     Copyright 2009-2010, Alan Calvert
7     Copyright 2017-2019 Will Godfrey
8 
9     This file is part of yoshimi, which is free software: you can redistribute
10     it and/or modify it under the terms of the GNU Library General Public
11     License as published by the Free Software Foundation; either version 2 of
12     the License, or (at your option) any later version.
13 
14     yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
15     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16     FOR A PARTICULAR PURPOSE.   See the GNU General Public License (version 2 or
17     later) for more details.
18 
19     You should have received a copy of the GNU General Public License along with
20     yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
21     Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 
23     This file is a derivative of a ZynAddSubFX original.
24 */
25 
26 #include <dirent.h>
27 //#include <iostream>
28 
29 #include "Misc/XMLwrapper.h"
30 #include "Params/PresetsStore.h"
31 #include "Misc/FileMgrFuncs.h"
32 #include "Misc/SynthEngine.h"
33 
34 using file::make_legit_filename;
35 
36 
37 extern SynthEngine *firstSynth;
38 
39 PresetsStore::_clipboard PresetsStore::clipboard;
40 
41 
PresetsStore(SynthEngine * _synth)42 PresetsStore::PresetsStore(SynthEngine *_synth) :
43     preset_extension(".xpz"),
44     synth(_synth)
45 {
46     clipboard.data = NULL;
47     clipboard.type.clear();
48 
49     for (int i = 0; i < MAX_PRESETS; ++i)
50     {
51         presets[i].file.clear();
52         presets[i].name.clear();
53     }
54 }
55 
56 
~PresetsStore()57 PresetsStore::~PresetsStore()
58 {
59     if (clipboard.data != NULL)
60     {
61         char *_data = __sync_fetch_and_and(&clipboard.data, 0);
62         free(_data);
63 
64     }
65     clearpresets();
66 }
67 
68 
69 // Clipboard management
copyclipboard(XMLwrapper * xml,const string & type)70 void PresetsStore::copyclipboard(XMLwrapper *xml, const string& type)
71 {
72     clipboard.type = type;
73     if (clipboard.data != NULL)
74     {
75         char *_data = __sync_fetch_and_and(&clipboard.data, 0);
76         free(_data);
77 
78     }
79     clipboard.data = xml->getXMLdata();
80 }
81 
82 
pasteclipboard(XMLwrapper * xml)83 bool PresetsStore::pasteclipboard(XMLwrapper *xml)
84 {
85     if (clipboard.data != NULL)
86     {
87         xml->putXMLdata(clipboard.data);
88         if (synth->getRuntime().effectChange != UNUSED)
89             synth->getRuntime().effectChange |= 0xff0000; // temporary fix
90         return true;
91     }
92     synth->getRuntime().effectChange = UNUSED; // temporary fix
93     return false;
94 }
95 
96 
checkclipboardtype(const string & type)97 bool PresetsStore::checkclipboardtype(const string& type)
98 {
99     // makes LFO's compatible
100     if (type.find("Plfo") != string::npos
101         && clipboard.type.find("Plfo") != string::npos)
102         return true;
103     return (!type.compare(clipboard.type));
104 }
105 
106 
clearpresets(void)107 void PresetsStore::clearpresets(void)
108 {
109     for (int i = 0; i < MAX_PRESETS; ++i)
110     {
111         presets[i].file.clear();
112         presets[i].name.clear();
113     }
114 }
115 
116 
rescanforpresets(const string & type,int root)117 void PresetsStore::rescanforpresets(const string& type, int root)
118 {
119     for (int i = 0; i < MAX_PRESETS; ++i)
120     {
121         presets[i].file.clear();
122         presets[i].name.clear();
123     }
124     int presetk = 0;
125     string ftype = "." + type + preset_extension;
126 
127     //std::cout << "type " << type << std::endl;
128     string altType = "";
129     if (type == "Padsyth")
130         altType = ".ADnoteParameters" + preset_extension;
131     else if (type == "Padsythn")
132         altType = ".ADnoteParametersn" + preset_extension;
133     else if (type == "Psubsyth")
134         altType = ".SUBnoteParameters" + preset_extension;
135     else if (type == "Ppadsyth")
136         altType = ".PADnoteParameters" + preset_extension;
137     string dirname = firstSynth->getRuntime().presetsDirlist[root];
138     if (dirname.empty())
139         return;
140     //std::cout << "Preset root " << dirname << std::endl;
141     DIR *dir = opendir(dirname.c_str());
142     if (dir == NULL)
143         return;
144 
145     struct dirent *fn;
146     while ((fn = readdir(dir)))
147     {
148         string filename = string(fn->d_name);
149         //std::cout << "file " << filename << std::endl;
150         if (filename.find(ftype) == string::npos)
151         {
152             if (altType.empty() || filename.find(altType) == string::npos)
153                 continue;
154         }
155         if (dirname.at(dirname.size() - 1) != '/')
156             dirname += "/";
157         presets[presetk].file = dirname + filename;
158 
159         size_t endpos = filename.find(ftype);
160         if (endpos == string::npos)
161             if (!altType.empty())
162                 endpos = filename.find(altType);
163         presets[presetk].name = filename.substr(0, endpos);
164 //        std::cout << "Preset name " << presets[presetk].name << std::endl;
165         presetk++;
166         if (presetk >= MAX_PRESETS)
167             return;
168     }
169     closedir(dir);
170 
171     // sort the presets
172     bool check = true;
173     while (check)
174     {
175         check = false;
176         for (int j = 0; j < MAX_PRESETS - 1; ++j)
177         {
178             for (int i = j + 1; i < MAX_PRESETS; ++i)
179             {
180                 if (presets[i].name.empty() || presets[j].name.empty())
181                     continue;
182                 if (strcasecmp(presets[i].name.c_str(), presets[j].name.c_str()) < 0)
183                 {
184                     presets[i].file.swap(presets[j].file);
185                     presets[i].name.swap(presets[j].name);
186                     check = true;
187                 }
188             }
189         }
190     }
191 }
192 
193 
copypreset(XMLwrapper * xml,const string & type,const string & name)194 void PresetsStore::copypreset(XMLwrapper *xml, const string& type, const string& name)
195 {
196     if (firstSynth->getRuntime().presetsDirlist[0].empty())
197         return;
198     synth->getRuntime().xmlType = TOPLEVEL::XML::Presets;
199     synth->getRuntime().Log(name);
200     string tmpfilename = name;
201     make_legit_filename(tmpfilename);
202     string dirname = firstSynth->getRuntime().presetsDirlist[synth->getRuntime().currentPreset];
203     if (dirname.find_last_of("/") != (dirname.size() - 1))
204         dirname += "/";
205     xml->saveXMLfile(dirname + tmpfilename + "." + type + preset_extension);
206 }
207 
208 
pastepreset(XMLwrapper * xml,int npreset)209 bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset)
210 {
211     if (npreset >= MAX_PRESETS || npreset < 1)
212         return false;
213     npreset--;
214     if (presets[npreset].file.empty())
215         return false;
216     if (synth->getRuntime().effectChange != UNUSED)
217         synth->getRuntime().effectChange |= 0xff0000; // temporary fix
218     return xml->loadXMLfile(presets[npreset].file);
219 }
220 
221 
deletepreset(int npreset)222 void PresetsStore::deletepreset(int npreset)
223 {
224     if (npreset >= MAX_PRESETS || npreset < 1)
225         return;
226     npreset--;
227     if (!presets[npreset].file.empty())
228         remove(presets[npreset].file.c_str());
229 }
230