1 |
/* |
2 |
* JSampler - a java front-end for LinuxSampler |
3 |
* |
4 |
* Copyright (C) 2009 Grigor Iliev <grigor@grigoriliev.com> |
5 |
* |
6 |
* This file is part of JSampler. |
7 |
* |
8 |
* JSampler is free software; you can redistribute it and/or modify |
9 |
* it under the terms of the GNU General Public License version 2 |
10 |
* as published by the Free Software Foundation. |
11 |
* |
12 |
* JSampler is distributed in the hope that it will be useful, |
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
* GNU General Public License for more details. |
16 |
* |
17 |
* You should have received a copy of the GNU General Public License |
18 |
* along with JSampler; if not, write to the Free Software |
19 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
20 |
* MA 02111-1307 USA |
21 |
*/ |
22 |
|
23 |
package org.jsampler; |
24 |
|
25 |
import java.io.ByteArrayOutputStream; |
26 |
|
27 |
import java.io.File; |
28 |
import java.text.DateFormat; |
29 |
import java.util.logging.Level; |
30 |
|
31 |
import org.jsampler.view.JSChannel; |
32 |
import org.jsampler.view.JSChannelsPane; |
33 |
|
34 |
import org.linuxsampler.lscp.AudioOutputChannel; |
35 |
import org.linuxsampler.lscp.AudioOutputDevice; |
36 |
import org.linuxsampler.lscp.Client; |
37 |
import org.linuxsampler.lscp.FxSend; |
38 |
import org.linuxsampler.lscp.MidiInputDevice; |
39 |
import org.linuxsampler.lscp.MidiPort; |
40 |
import org.linuxsampler.lscp.Parameter; |
41 |
import org.linuxsampler.lscp.SamplerChannel; |
42 |
|
43 |
import static org.jsampler.CC.preferences; |
44 |
import static org.jsampler.JSI18n.i18n; |
45 |
|
46 |
/** |
47 |
* |
48 |
* @author Grigor Iliev |
49 |
*/ |
50 |
public class JSUtils { |
51 |
|
52 |
/** Forbids the instantiation of this class */ |
53 |
private |
54 |
JSUtils() { } |
55 |
|
56 |
/** |
57 |
* Checks whether the JSampler home directory is specified and exist. |
58 |
* If the JSampler home directory is not specifed, or is specified |
59 |
* but doesn't exist, a procedure of specifying a JSampler home |
60 |
* directory is initiated. |
61 |
* @see org.jsampler.view.JSMainFrame#installJSamplerHome |
62 |
*/ |
63 |
public static void |
64 |
checkJSamplerHome() { |
65 |
if(CC.getJSamplerHome() != null) { |
66 |
File f = new File(CC.getJSamplerHome()); |
67 |
if(f.exists() && f.isDirectory()) { |
68 |
return; |
69 |
} |
70 |
} |
71 |
|
72 |
CC.getMainFrame().installJSamplerHome(); |
73 |
} |
74 |
|
75 |
/** |
76 |
* Changes the JSampler's home directory and moves all files from |
77 |
* the old JSampler's home directory to the new one. If all files are |
78 |
* moved succesfully, the old directory is deleted. |
79 |
* @param path The location of the new JSampler's home directory. If |
80 |
* the last directory in the path doesn't exist, it is created. |
81 |
*/ |
82 |
public static void |
83 |
changeJSamplerHome(String path) { |
84 |
File fNew = new File(path); |
85 |
if(fNew.exists() && fNew.isFile()) { |
86 |
HF.showErrorMessage(i18n.getError("CC.JSamplerHomeIsNotDir!")); |
87 |
return; |
88 |
} |
89 |
|
90 |
if(!fNew.exists()) { |
91 |
if(!fNew.mkdir()) { |
92 |
String s = fNew.getAbsolutePath(); |
93 |
HF.showErrorMessage(i18n.getError("CC.mkdirFailed", s)); |
94 |
return; |
95 |
} |
96 |
} |
97 |
|
98 |
if(CC.getJSamplerHome() == null || path.equals(CC.getJSamplerHome())) { |
99 |
CC.setJSamplerHome(fNew.getAbsolutePath()); |
100 |
return; |
101 |
} |
102 |
|
103 |
File fOld = new File(CC.getJSamplerHome()); |
104 |
if(!fOld.exists() || !fOld.isDirectory()) { |
105 |
CC.setJSamplerHome(fNew.getAbsolutePath()); |
106 |
return; |
107 |
} |
108 |
|
109 |
File[] files = fOld.listFiles(); |
110 |
boolean b = true; |
111 |
if(files != null) { |
112 |
String s = fNew.getAbsolutePath() + File.separator; |
113 |
for(File f : files) if(!f.renameTo(new File(s + f.getName()))) b = false; |
114 |
} |
115 |
|
116 |
if(b) fOld.delete(); |
117 |
CC.setJSamplerHome(fNew.getAbsolutePath()); |
118 |
} |
119 |
|
120 |
public static String |
121 |
exportInstrMapsToLscpScript() { |
122 |
StringBuffer sb = new StringBuffer("# Exported by: "); |
123 |
sb.append("JSampler - a java front-end for LinuxSampler\r\n# Version: "); |
124 |
sb.append(JSampler.VERSION).append("\r\n"); |
125 |
sb.append("# Date: ").append(new java.util.Date().toString()).append("\r\n\r\n"); |
126 |
|
127 |
Client lscpClient = new Client(true); |
128 |
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
129 |
lscpClient.setPrintOnlyModeOutputStream(out); |
130 |
|
131 |
exportInstrMapsToLscpScript(lscpClient); |
132 |
sb.append(out.toString()); |
133 |
out.reset(); |
134 |
|
135 |
return sb.toString(); |
136 |
} |
137 |
|
138 |
private static void |
139 |
exportInstrMapsToLscpScript(Client lscpClient) { |
140 |
try { |
141 |
lscpClient.removeAllMidiInstrumentMaps(); |
142 |
MidiInstrumentMap[] maps = CC.getSamplerModel().getMidiInstrumentMaps(); |
143 |
for(int i = 0; i < maps.length; i++) { |
144 |
lscpClient.addMidiInstrumentMap(maps[i].getName()); |
145 |
exportInstrumentsToLscpScript(i, maps[i], lscpClient); |
146 |
} |
147 |
} catch(Exception e) { |
148 |
CC.getLogger().log(Level.FINE, HF.getErrorMessage(e), e); |
149 |
HF.showErrorMessage(e); |
150 |
} |
151 |
} |
152 |
|
153 |
private static void |
154 |
exportInstrumentsToLscpScript(int mapId, MidiInstrumentMap map, Client lscpClient) |
155 |
throws Exception { |
156 |
|
157 |
boolean b = preferences().getBoolProperty(JSPrefs.LOAD_MIDI_INSTRUMENTS_IN_BACKGROUND); |
158 |
|
159 |
for(MidiInstrument i : map.getAllMidiInstruments()) { |
160 |
lscpClient.mapMidiInstrument(mapId, i.getInfo().getEntry(), i.getInfo(), b); |
161 |
} |
162 |
} |
163 |
|
164 |
public static String |
165 |
exportInstrMapsToText() { |
166 |
String nl = System.getProperty("line.separator"); |
167 |
StringBuffer sb = new StringBuffer(); |
168 |
|
169 |
|
170 |
MidiInstrumentMap[] maps = CC.getSamplerModel().getMidiInstrumentMaps(); |
171 |
for(int i = 0; i < maps.length; i++) { |
172 |
sb.append("MIDI Instrument Map: "); |
173 |
sb.append(maps[i].getName()).append(nl); |
174 |
exportInstrumentsToText(maps[i], sb); |
175 |
} |
176 |
|
177 |
String date = DateFormat.getDateInstance().format(new java.util.Date()); |
178 |
sb.append("Date: ").append(date).append(nl); |
179 |
sb.append("Exported by: JSampler - a java front-end for LinuxSampler, Version "); |
180 |
sb.append(JSampler.VERSION).append(nl); |
181 |
|
182 |
return sb.toString(); |
183 |
} |
184 |
|
185 |
private static void |
186 |
exportInstrumentsToText(MidiInstrumentMap map, StringBuffer sb) { |
187 |
int bank = -1; |
188 |
String nl = System.getProperty("line.separator"); |
189 |
int bnkOffset = preferences().getIntProperty(JSPrefs.FIRST_MIDI_BANK_NUMBER); |
190 |
int prgOffset = preferences().getIntProperty(JSPrefs.FIRST_MIDI_PROGRAM_NUMBER); |
191 |
|
192 |
for(MidiInstrument i : map.getAllMidiInstruments()) { |
193 |
int newBank = i.getInfo().getMidiBank(); |
194 |
if(newBank != bank) { |
195 |
bank = newBank; |
196 |
sb.append(nl).append("\tMIDI Bank "); |
197 |
sb.append(bank + bnkOffset).append(nl); |
198 |
} |
199 |
sb.append("\t[").append(bank + bnkOffset).append("] "); |
200 |
sb.append(i.getInfo().getMidiProgram() + prgOffset); |
201 |
sb.append(" - ").append(i.getName()).append(nl); |
202 |
} |
203 |
|
204 |
sb.append(nl); |
205 |
} |
206 |
|
207 |
public static String |
208 |
exportInstrMapsToHtml() { |
209 |
String nl = System.getProperty("line.separator"); |
210 |
StringBuffer sb = new StringBuffer("<html>").append(nl); |
211 |
|
212 |
sb.append("<head><title>MIDI Instrument Maps</title></head>"); |
213 |
|
214 |
sb.append("<body>").append(nl); |
215 |
sb.append("<h1>MIDI Instrument Maps</h1>").append(nl); |
216 |
|
217 |
String date = DateFormat.getDateInstance().format(new java.util.Date()); |
218 |
sb.append("Date: ").append(date).append("<br>").append(nl); |
219 |
sb.append("Exported by <a href=http://linuxsampler.org/jsampler/manual/html/jsampler.html>"); |
220 |
sb.append("JSampler</a> version "); |
221 |
sb.append(JSampler.VERSION).append("<br>").append(nl); |
222 |
|
223 |
MidiInstrumentMap[] maps = CC.getSamplerModel().getMidiInstrumentMaps(); |
224 |
|
225 |
sb.append("<ol>").append(nl); |
226 |
for(int i = 0; i < maps.length; i++) { |
227 |
String name = toHtmlEscapedText(maps[i].getName()); |
228 |
sb.append("<li><a href=#map-").append(i + 1).append(">"); |
229 |
sb.append(name).append("</a></li>").append(nl); |
230 |
} |
231 |
sb.append("</ol>").append(nl); |
232 |
|
233 |
for(int i = 0; i < maps.length; i++) { |
234 |
String s = toHtmlEscapedText(maps[i].getName()); |
235 |
sb.append("<h2><a name=map-").append(i + 1).append(">"); |
236 |
sb.append(s).append("</a></h2>").append(nl); |
237 |
exportInstrumentsToHtml(i, maps[i], sb); |
238 |
} |
239 |
|
240 |
sb.append(nl).append("</body>").append(nl).append("</html>"); |
241 |
return sb.toString(); |
242 |
} |
243 |
|
244 |
private static void |
245 |
exportInstrumentsToHtml(int mapId, MidiInstrumentMap map, StringBuffer sb) { |
246 |
int bank = -1; |
247 |
String nl = System.getProperty("line.separator"); |
248 |
int bnkOffset = preferences().getIntProperty(JSPrefs.FIRST_MIDI_BANK_NUMBER); |
249 |
int prgOffset = preferences().getIntProperty(JSPrefs.FIRST_MIDI_PROGRAM_NUMBER); |
250 |
|
251 |
sb.append("<ol>").append(nl); |
252 |
for(MidiInstrument i : map.getAllMidiInstruments()) { |
253 |
int newBank = i.getInfo().getMidiBank(); |
254 |
if(newBank != bank) { |
255 |
bank = newBank; |
256 |
String s = "map-" + (mapId + 1) + "-bank-" + (bank + bnkOffset); |
257 |
sb.append(nl).append("<li><a href=#").append(s); |
258 |
sb.append(">MIDI Bank "); |
259 |
sb.append(bank + bnkOffset).append("</a></li>").append(nl); |
260 |
} |
261 |
} |
262 |
sb.append("</ol>").append(nl); |
263 |
|
264 |
bank = -1; |
265 |
String bankName = ""; |
266 |
|
267 |
sb.append("<table border=0>").append(nl); |
268 |
for(MidiInstrument i : map.getAllMidiInstruments()) { |
269 |
int newBank = i.getInfo().getMidiBank(); |
270 |
if(newBank != bank) { |
271 |
bank = newBank; |
272 |
sb.append("</table>").append(nl); |
273 |
|
274 |
bankName = "map-" + (mapId + 1) + "-bank-" + (bank + bnkOffset); |
275 |
sb.append(nl).append("<h4><a name=").append(bankName); |
276 |
sb.append(">MIDI Bank "); |
277 |
sb.append(bank + bnkOffset).append("</a></h4>").append(nl); |
278 |
|
279 |
sb.append("<table border=0>").append(nl); |
280 |
} |
281 |
|
282 |
sb.append("<tr><td align='right'>"); |
283 |
sb.append(i.getInfo().getMidiProgram() + prgOffset).append(" - </td>"); |
284 |
String file = i.getInfo().getFilePath(); |
285 |
String tooltip = "File: " + file + ", Index: " + i.getInfo().getInstrumentIndex(); |
286 |
sb.append("<td><a title='").append(tooltip).append("'>"); |
287 |
String s = toHtmlEscapedText(i.getName()); |
288 |
sb.append(s).append("</a></td>"); |
289 |
|
290 |
sb.append("<td> <a href=#").append(bankName).append(">"); |
291 |
sb.append("[").append(bank + bnkOffset).append("]</a></td>").append(nl); |
292 |
sb.append("</tr>"); |
293 |
} |
294 |
sb.append("</table>").append(nl); |
295 |
|
296 |
sb.append(nl); |
297 |
} |
298 |
|
299 |
private static String |
300 |
toHtmlEscapedText(String s) { |
301 |
s = s.replaceAll("&", "&"); |
302 |
s = s.replaceAll("<", "<"); |
303 |
s = s.replaceAll(">", ">"); |
304 |
|
305 |
return s; |
306 |
} |
307 |
|
308 |
public static String |
309 |
exportSessionToLscpScript() { |
310 |
CC.getSamplerModel().setModified(false); |
311 |
|
312 |
StringBuffer sb = new StringBuffer("# Exported by: "); |
313 |
sb.append("JSampler - a java front-end for LinuxSampler\r\n# Version: "); |
314 |
sb.append(JSampler.VERSION).append("\r\n"); |
315 |
sb.append("# Date: ").append(new java.util.Date().toString()).append("\r\n\r\n"); |
316 |
|
317 |
Client lscpClient = new Client(true); |
318 |
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
319 |
lscpClient.setPrintOnlyModeOutputStream(out); |
320 |
|
321 |
try { |
322 |
lscpClient.resetSampler(); |
323 |
sb.append(out.toString()); |
324 |
out.reset(); |
325 |
sb.append("\r\n"); |
326 |
lscpClient.setVolume(CC.getSamplerModel().getVolume()); |
327 |
sb.append(out.toString()); |
328 |
out.reset(); |
329 |
sb.append("\r\n"); |
330 |
} catch(Exception e) { CC.getLogger().log(Level.FINE, HF.getErrorMessage(e), e); } |
331 |
|
332 |
MidiDeviceModel[] mDevs = CC.getSamplerModel().getMidiDevices(); |
333 |
for(int i = 0; i < mDevs.length; i++) { |
334 |
exportMidiDeviceToLscpScript(mDevs[i].getDeviceInfo(), i, lscpClient); |
335 |
sb.append(out.toString()); |
336 |
out.reset(); |
337 |
sb.append("\r\n"); |
338 |
} |
339 |
|
340 |
AudioDeviceModel[] aDevs = CC.getSamplerModel().getAudioDevices(); |
341 |
for(int i = 0; i < aDevs.length; i++) { |
342 |
exportAudioDeviceToLscpScript(aDevs[i].getDeviceInfo(), i, lscpClient); |
343 |
sb.append(out.toString()); |
344 |
out.reset(); |
345 |
sb.append("\r\n"); |
346 |
} |
347 |
|
348 |
boolean b = preferences().getBoolProperty(JSPrefs.EXPORT_MIDI_MAPS_TO_SESSION_SCRIPT); |
349 |
if(b) { |
350 |
exportInstrMapsToLscpScript(lscpClient); |
351 |
sb.append(out.toString()); |
352 |
out.reset(); |
353 |
sb.append("\r\n"); |
354 |
} |
355 |
|
356 |
int chnId = 0; |
357 |
for(JSChannelsPane cp : CC.getMainFrame().getChannelsPaneList()) { |
358 |
for(JSChannel chn : cp.getChannels()) { |
359 |
SamplerChannelModel scm; |
360 |
scm = CC.getSamplerModel().getChannelById(chn.getChannelId()); |
361 |
exportChannelToLscpScript(scm.getChannelInfo(), chnId, lscpClient); |
362 |
sb.append(out.toString()); |
363 |
out.reset(); |
364 |
|
365 |
sb.append("\r\n"); |
366 |
|
367 |
exportFxSendsToLscpScript(scm, chnId, lscpClient); |
368 |
sb.append(out.toString()); |
369 |
out.reset(); |
370 |
|
371 |
sb.append("\r\n"); |
372 |
|
373 |
chnId++; |
374 |
} |
375 |
} |
376 |
|
377 |
sb.append(CC.getViewConfig().exportSessionViewConfig()); |
378 |
|
379 |
return sb.toString(); |
380 |
} |
381 |
|
382 |
private static void |
383 |
exportMidiDeviceToLscpScript(MidiInputDevice mid, int devId, Client lscpCLient) { |
384 |
try { |
385 |
String s = mid.getDriverName(); |
386 |
lscpCLient.createMidiInputDevice(s, mid.getAdditionalParameters()); |
387 |
|
388 |
MidiPort[] mPorts = mid.getMidiPorts(); |
389 |
int l = mPorts.length; |
390 |
if(l != 1) lscpCLient.setMidiInputPortCount(devId, l); |
391 |
|
392 |
for(int i = 0; i < l; i++) { |
393 |
Parameter[] prms = mPorts[i].getAllParameters(); |
394 |
for(Parameter p : prms) { |
395 |
if(!p.isFixed() && p.getStringValue().length() > 0) |
396 |
lscpCLient.setMidiInputPortParameter(devId, i, p); |
397 |
} |
398 |
} |
399 |
} catch(Exception e) { |
400 |
CC.getLogger().log(Level.FINE, HF.getErrorMessage(e), e); |
401 |
} |
402 |
} |
403 |
|
404 |
private static void |
405 |
exportAudioDeviceToLscpScript(AudioOutputDevice aod, int devId, Client lscpCLient) { |
406 |
try { |
407 |
String s = aod.getDriverName(); |
408 |
lscpCLient.createAudioOutputDevice(s, aod.getAllParameters()); |
409 |
|
410 |
AudioOutputChannel[] chns = aod.getAudioChannels(); |
411 |
|
412 |
for(int i = 0; i < chns.length; i++) { |
413 |
Parameter[] prms = chns[i].getAllParameters(); |
414 |
for(Parameter p : prms) { |
415 |
if(p.isFixed() || p.getStringValue().length() == 0); |
416 |
else lscpCLient.setAudioOutputChannelParameter(devId, i, p); |
417 |
} |
418 |
} |
419 |
} catch(Exception e) { |
420 |
CC.getLogger().log(Level.FINE, HF.getErrorMessage(e), e); |
421 |
} |
422 |
} |
423 |
|
424 |
private static void |
425 |
exportChannelToLscpScript(SamplerChannel chn, int chnId, Client lscpCLient) { |
426 |
try { |
427 |
lscpCLient.addSamplerChannel(); |
428 |
|
429 |
SamplerModel sm = CC.getSamplerModel(); |
430 |
int id = chn.getMidiInputDevice(); |
431 |
if(id != -1) { |
432 |
for(int i = 0; i < sm.getMidiDeviceCount(); i++) { |
433 |
if(sm.getMidiDevice(i).getDeviceId() == id) { |
434 |
lscpCLient.setChannelMidiInputDevice(chnId, i); |
435 |
break; |
436 |
} |
437 |
} |
438 |
lscpCLient.setChannelMidiInputPort(chnId, chn.getMidiInputPort()); |
439 |
lscpCLient.setChannelMidiInputChannel(chnId, chn.getMidiInputChannel()); |
440 |
} |
441 |
|
442 |
if(chn.getEngine() != null) { |
443 |
lscpCLient.loadSamplerEngine(chn.getEngine().getName(), chnId); |
444 |
lscpCLient.setChannelVolume(chnId, chn.getVolume()); |
445 |
int mapId = chn.getMidiInstrumentMapId(); |
446 |
lscpCLient.setChannelMidiInstrumentMap(chnId, mapId); |
447 |
} |
448 |
|
449 |
id = chn.getAudioOutputDevice(); |
450 |
if(id != -1) { |
451 |
for(int i = 0; i < sm.getAudioDeviceCount(); i++) { |
452 |
if(sm.getAudioDevice(i).getDeviceId() == id) { |
453 |
lscpCLient.setChannelAudioOutputDevice(chnId, i); |
454 |
break; |
455 |
} |
456 |
} |
457 |
|
458 |
Integer[] routing = chn.getAudioOutputRouting(); |
459 |
|
460 |
for(int j = 0; j < routing.length; j++) { |
461 |
int k = routing[j]; |
462 |
if(k == j) continue; |
463 |
|
464 |
lscpCLient.setChannelAudioOutputChannel(chnId, j, k); |
465 |
} |
466 |
} |
467 |
|
468 |
String s = chn.getInstrumentFile(); |
469 |
int i = chn.getInstrumentIndex(); |
470 |
if(s != null) lscpCLient.loadInstrument(s, i, chnId, true); |
471 |
|
472 |
if(chn.isMuted() && !chn.isMutedBySolo()) lscpCLient.setChannelMute(chnId, true); |
473 |
if(chn.isSoloChannel()) lscpCLient.setChannelSolo(chnId, true); |
474 |
} catch(Exception e) { |
475 |
CC.getLogger().log(Level.FINE, HF.getErrorMessage(e), e); |
476 |
} |
477 |
} |
478 |
|
479 |
private static void |
480 |
exportFxSendsToLscpScript(SamplerChannelModel scm, int chnId, Client lscpClient) { |
481 |
try { |
482 |
FxSend[] fxSends = scm.getFxSends(); |
483 |
|
484 |
for(int i = 0; i < fxSends.length; i++) { |
485 |
FxSend f = fxSends[i]; |
486 |
lscpClient.createFxSend(chnId, f.getMidiController(), f.getName()); |
487 |
lscpClient.setFxSendLevel(chnId, i, f.getLevel()); |
488 |
|
489 |
Integer[] r = f.getAudioOutputRouting(); |
490 |
for(int j = 0; j < r.length; j++) { |
491 |
lscpClient.setFxSendAudioOutputChannel(chnId, i, j, r[j]); |
492 |
} |
493 |
} |
494 |
} catch(Exception e) { |
495 |
CC.getLogger().log(Level.FINE, HF.getErrorMessage(e), e); |
496 |
} |
497 |
} |
498 |
} |