1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: globals.cpp,v 1.15.2.11 2009/11/25 09:09:43 terminator356 Exp $
5 //
6 //  (C) Copyright 1999-2004 Werner Schweer (ws@seh.de)
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU General Public License
10 //  as published by the Free Software Foundation; version 2 of
11 //  the License, or (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 //=========================================================
23 
24 #include <stdio.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 
29 #include <QActionGroup>
30 #include <QDir>
31 #include <QFileInfo>
32 #include <QToolButton>
33 
34 #include "globals.h"
35 #include "config.h"
36 
37 namespace MusEGlobal {
38 
39 int sampleRate   = 44100;
40 unsigned segmentSize  = 1024U;    // segmentSize in frames (set by JACK)
41 unsigned fifoLength =  128;       // 131072/segmentSize
42                                   // 131072 - magic number that gives a sufficient buffer size
43 int segmentCount = 2;
44 
45 //   NOTE: For now, this is TEMPORARILY set to the project sample rate during song loading,
46 //          then at the END of song loading is immediately set to the real current rate.
47 //         See comments in Song::read() at the "samplerate" tag section.
48 int projectSampleRate = sampleRate;
49 const int numAudioSampleRates = 8;
50 const int selectableAudioSampleRates[] = {
51       22050, 32000, 44100, 48000, 64000, 88200, 96000, 192000
52       };
53 
54 MusECore::SndFileList sndFiles;
55 
56 MusECore::AudioConverterPluginList audioConverterPluginList;
57 // This global variable is a pointer so that we can replace it quickly with a new one in RT operations.
58 MusECore::AudioConverterSettingsGroup* defaultAudioConverterSettings = nullptr;
59 
60 // denormal bias value used to eliminate the manifestation of denormals by
61 // lifting the zero level slightly above zero
62 // denormal problems occur when values get extremely close to zero
63 const float denormalBias=1e-18;
64 
65 bool overrideAudioOutput = false;
66 bool overrideAudioInput = false;
67 
68 const QString selectableAudioBackendDevices[] = {
69     "Jack Audio (default)",
70     "Midi only",
71     "RtAudio Pulse Audio",
72     "RtAudio ALSA",
73     "RtAudio OSS - Open Sound System",
74     "RtAudio best guess"
75 };
76 
77 const int numRtAudioDevices = 6;
78 
79 MusEGui::Rasterizer *globalRasterizer = nullptr;
80 
81 QTimer* heartBeatTimer;
82 
83 bool blinkTimerPhase = false;
84 
85 bool hIsB = true;             // call note h "b"
86 
87 const signed char sharpTab[14][7] = {
88       { 0, 3, -1, 2, 5, 1, 4 },
89       { 0, 3, -1, 2, 5, 1, 4 },
90       { 0, 3, -1, 2, 5, 1, 4 },
91       { 0, 3, -1, 2, 5, 1, 4 },
92       { 2, 5,  1, 4, 7, 3, 6 },
93       { 2, 5,  1, 4, 7, 3, 6 },
94       { 2, 5,  1, 4, 7, 3, 6 },
95       { 4, 0,  3, -1, 2, 5, 1 },
96       { 7, 3,  6, 2, 5, 1, 4 },
97       { 5, 8,  4, 7, 3, 6, 2 },
98       { 3, 6,  2, 5, 1, 4, 7 },
99       { 1, 4,  0, 3, 6, 2, 5 },
100       { 6, 2,  5, 1, 4, 0, 3 },
101       { 0, 3, -1, 2, 5, 1, 4 },
102       };
103 const signed char flatTab[14][7]  = {
104       { 4, 1, 5, 2, 6, 3, 7 },
105       { 4, 1, 5, 2, 6, 3, 7 },
106       { 4, 1, 5, 2, 6, 3, 7 },
107       { 4, 1, 5, 2, 6, 3, 7 },
108       { 6, 3, 7, 4, 8, 5, 9 },
109       { 6, 3, 7, 4, 8, 5, 9 },
110       { 6, 3, 7, 4, 8, 5, 9 },
111 
112       { 1, 5, 2, 6, 3, 7, 4 },
113       { 4, 1, 5, 2, 6, 3, 7 },
114       { 2, 6, 3, 7, 4, 8, 5 },
115       { 7, 4, 1, 5, 2, 6, 3 },
116       { 5, 2, 6, 3, 7, 4, 8 },
117       { 3, 0, 4, 1, 5, 2, 6 },
118       { 4, 1, 5, 2, 6, 3, 7 },
119       };
120 
121 QString museGlobalLib;
122 QString museGlobalShare;
123 QString museUser;
124 QString museProject;
125 QString museProjectInitPath("./");
126 
127 QString configName;
128 QString configPath;
129 QString cachePath;
130 QString museInstruments;
131 QString museUserInstruments;
132 
133 QString lastWavePath(".");
134 QString lastMidiPath(".");
135 
136 bool debugMode = false;
137 bool unityWorkaround = false;
138 bool debugMsg = false;
139 bool heavyDebugMsg = false;
140 bool midiInputTrace = false;
141 bool midiOutputTrace = false;
142 bool realTimeScheduling = false;
143 int realTimePriority = 40;  // 80
144 int midiRTPrioOverride = -1;
145 bool loadPlugins = true;
146 bool loadMESS = true;
147 bool loadVST = true;
148 bool loadNativeVST = true;
149 bool loadDSSI = true;
150 bool loadLV2 = true;
151 bool usePythonBridge = false;
152 QString pythonBridgePyroNSHostname;
153 QString pythonBridgePyroNSPort;
154 QString pythonBridgePyroDaemonHostname;
155 QString pythonBridgePyroDaemonPort;
156 float pythonBridgePyroCommTimeout = 5.0;
157 bool useLASH = true;
158 bool useAlsaWithJack = false;
159 bool noAutoStartJack = false;
160 bool populateMidiPortsOnStart = true;
161 
162 const char* midi_file_pattern[] = {
163       QT_TRANSLATE_NOOP("file_patterns", "Midi/Kar (*.mid *.MID *.kar *.KAR *.mid.gz *.mid.bz2)"),
164       QT_TRANSLATE_NOOP("file_patterns", "Midi (*.mid *.MID *.mid.gz *.mid.bz2)"),
165       QT_TRANSLATE_NOOP("file_patterns", "Karaoke (*.kar *.KAR *.kar.gz *.kar.bz2)"),
166       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
167       0
168       };
169 
170 //FIXME: By T356 01/19/2010
171 // If saving as a compressed file (gz or bz2),
172 //  the file is a pipe, and pipes can't seek !
173 // This results in a corrupted midi file from MidiFile::writeTrack().
174 // So exporting compressed midi has simply been disabled here for now...
175 // For re-enabling, add .mid.gz and .mid.bz2 and same for .kar again
176 const char* midi_file_save_pattern[] = {
177       QT_TRANSLATE_NOOP("file_patterns", "Midi (*.mid)"),
178       QT_TRANSLATE_NOOP("file_patterns", "Karaoke (*.kar)"),
179       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
180       0
181       };
182 
183 const char* med_file_pattern[] = {
184       QT_TRANSLATE_NOOP("file_patterns", "all known files (*.med *.med.gz *.med.bz2 *.mid *.midi *.kar)"),
185       QT_TRANSLATE_NOOP("file_patterns", "med Files (*.med *.med.gz *.med.bz2)"),
186       QT_TRANSLATE_NOOP("file_patterns", "Uncompressed med Files (*.med)"),
187       QT_TRANSLATE_NOOP("file_patterns", "gzip compressed med Files (*.med.gz)"),
188       QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed med Files (*.med.bz2)"),
189       QT_TRANSLATE_NOOP("file_patterns", "mid Files (*.mid *.midi *.kar *.MID *.MIDI *.KAR)"),
190       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
191       0
192       };
193 const char* med_file_save_pattern[] = {
194       QT_TRANSLATE_NOOP("file_patterns", "Uncompressed med Files (*.med)"),
195       QT_TRANSLATE_NOOP("file_patterns", "gzip compressed med Files (*.med.gz)"),
196       QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed med Files (*.med.bz2)"),
197       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
198       0
199       };
200 const char* project_create_file_save_pattern[] = {
201       QT_TRANSLATE_NOOP("file_patterns", "Uncompressed med Files (*.med)"),
202       QT_TRANSLATE_NOOP("file_patterns", "gzip compressed med Files (*.med.gz)"),
203       QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed med Files (*.med.bz2)"),
204       0
205       };
206 
207 const char* image_file_pattern[] = {
208       QT_TRANSLATE_NOOP("file_patterns", "(*.jpg *.gif *.png)"),
209       QT_TRANSLATE_NOOP("file_patterns", "(*.jpg)"),
210       QT_TRANSLATE_NOOP("file_patterns", "(*.gif)"),
211       QT_TRANSLATE_NOOP("file_patterns", "(*.png)"),
212       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
213       0
214       };
215 
216 const char* part_file_pattern[] = {
217       QT_TRANSLATE_NOOP("file_patterns", "part Files (*.mpt *.mpt.gz *.mpt.bz2)"),
218       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
219       0
220       };
221 const char* part_file_save_pattern[] = {
222       QT_TRANSLATE_NOOP("file_patterns", "part Files (*.mpt)"),
223       QT_TRANSLATE_NOOP("file_patterns", "gzip compressed part Files (*.mpt.gz)"),
224       QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed part Files (*.mpt.bz2)"),
225       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
226       0
227       };
228 
229 const char* preset_file_pattern[] = {
230       QT_TRANSLATE_NOOP("file_patterns", "Presets (*.pre *.pre.gz *.pre.bz2)"),
231       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
232       0
233       };
234 
235 const char* preset_file_save_pattern[] = {
236       QT_TRANSLATE_NOOP("file_patterns", "Presets (*.pre)"),
237       QT_TRANSLATE_NOOP("file_patterns", "gzip compressed presets (*.pre.gz)"),
238       QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed presets (*.pre.bz2)"),
239       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
240       0
241       };
242 
243 const char* drum_map_file_pattern[] = {
244       QT_TRANSLATE_NOOP("file_patterns", "Presets (*.map *.map.gz *.map.bz2)"),
245       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
246       0
247 };
248 
249 const char* drum_map_file_save_pattern[] = {
250       QT_TRANSLATE_NOOP("file_patterns", "Presets (*.map)"),
251       QT_TRANSLATE_NOOP("file_patterns", "gzip compressed presets (*.map.gz)"),
252       QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed presets (*.map.bz2)"),
253       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
254       0
255 };
256 
257 const char* audio_file_pattern[] = {
258       QT_TRANSLATE_NOOP("file_patterns", "Wave/Binary (*.wav *.ogg *.flac *.bin)"),
259       QT_TRANSLATE_NOOP("file_patterns", "Wave (*.wav *.ogg *.flac)"),
260       QT_TRANSLATE_NOOP("file_patterns", "Binary (*.bin)"),
261       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
262       0
263 };
264 
265 const char* colors_config_file_pattern[] = {
266       QT_TRANSLATE_NOOP("file_patterns", "Color configuration files (*.cfc)"),
267       QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
268       0
269 };
270 
271 const char* stylesheet_file_pattern[] = {
272     QT_TRANSLATE_NOOP("file_patterns", "Qt style sheets (*.qss)"),
273     QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
274     0
275 };
276 
277 Qt::KeyboardModifiers globalKeyState;
278 
279 // Midi Filter Parameter
280 int midiInputPorts   = 0;    // receive from all devices
281 int midiInputChannel = 0;    // receive all channel
282 int midiRecordType   = 0;    // receive all events
283 int midiThruType = 0;        // transmit all events
284 int midiFilterCtrl1 = 0;
285 int midiFilterCtrl2 = 0;
286 int midiFilterCtrl3 = 0;
287 int midiFilterCtrl4 = 0;
288 
289 QActionGroup* undoRedo;
290 QAction* undoAction;
291 QAction* redoAction;
292 QActionGroup* transportAction;
293 QAction* playAction;
294 QAction* startAction;
295 QAction* stopAction;
296 QAction* rewindAction;
297 QAction* forwardAction;
298 QAction* loopAction;
299 QAction* punchinAction;
300 QAction* punchoutAction;
301 QAction* recordAction;
302 QAction* panicAction;
303 QAction* metronomeAction;
304 QAction* cpuLoadAction;
305 
306 MusEGui::MusE* muse = nullptr;
307 
308 MusECore::MetroAccentsPresetsMap metroAccentPresets;
309 MusECore::MetronomeSettings metroGlobalSettings;
310 MusECore::MetronomeSettings metroSongSettings;
311 // Whether to use the global or song metronome settings.
312 bool metroUseSongSettings = false;
313 
314 bool rcEnable = false;
315 unsigned char rcStopNote = 28;
316 unsigned char rcRecordNote = 31;
317 unsigned char rcGotoLeftMarkNote = 33;
318 unsigned char rcPlayNote = 29;
319 unsigned char rcSteprecNote = 36;
320 unsigned char rcForwardNote = 26;
321 unsigned char rcBackwardNote = 24;
322 
323 bool rcEnableCC = false;
324 unsigned char rcGotoLeftMarkCC = 111;
325 unsigned char rcBackwardCC = 112;
326 unsigned char rcForwardCC = 113;
327 unsigned char rcStopCC = 114;
328 unsigned char rcPlayCC = 115;
329 //unsigned char rcInsertPauseCC = 116;
330 unsigned char rcRecordCC = 117;
331 
332 // REMOVE Tim. automation. Remove this.
333 // Deprecated. MusEGlobal::automation is now fixed TRUE
334 //   for now until we decide what to do with it.
335 bool automation = true;
336 
337 // Midi learn params. These will be initialized to -1 by any midi learn function,
338 //  and then filled by the midi engine in response to the drivers.
339 int midiLearnPort = -1;
340 int midiLearnChan = -1;
341 int midiLearnCtrl = -1;
342 
343 const QString inputRoutingToolTipBase = QObject::tr("Input routing");
344 const QString noInputRoutingToolTipWarn = inputRoutingToolTipBase + QString("\n") + QObject::tr("Warning: No input routes! Click to connect...");
345 
346 const QString outputRoutingToolTipBase = QObject::tr("Output routing");
347 const QString noOutputRoutingToolTipWarn = outputRoutingToolTipBase + QString("\n") + QObject::tr("Warning: No output routes! Click to connect...");
348 
349 // REMOVE Tim. setuid. Removed.
350 //uid_t euid, ruid;  // effective user id, real user id
351 
352 bool midiSeqRunning = false;
353 
354 QString defaultStyle = "Fusion";
355 
356 //---------------------------------------------------------
357 //   convertFrame4ProjectSampleRate
358 //---------------------------------------------------------
359 
convertFrame4ProjectSampleRate(unsigned frame)360 unsigned convertFrame4ProjectSampleRate(unsigned frame)
361 {
362   return double(frame) * double(MusEGlobal::sampleRate) / double(MusEGlobal::projectSampleRate);
363 }
364 
365 //---------------------------------------------------------
366 //   doSetuid
367 //    Restore the effective UID to its original value.
368 //---------------------------------------------------------
369 
doSetuid()370 void doSetuid()
371       {
372 // BUG REMOVE Tim. setuid. Removed. Ancient stuff no longer required?
373 //     Tests OK under several scenarios: Jack started externally,
374 //      Jack started by MusE, Jack started as root, dummy driver etc.
375 //     Was causing crash with new DrumGizmo 0.9.11
376 // #ifndef RTCAP
377 //       int status;
378 // #ifdef _POSIX_SAVED_IDS
379 //       status = seteuid (euid);
380 // #else
381 //       status = setreuid (ruid, euid);
382 // #endif
383 //       if (status < 0) {
384 //             perror("doSetuid: Couldn't set uid");
385 //             }
386 // #endif
387       }
388 
389 //---------------------------------------------------------
390 //   undoSetuid
391 //    Set the effective UID to the real UID.
392 //---------------------------------------------------------
393 
undoSetuid()394 void undoSetuid()
395       {
396 // BUG REMOVE Tim. setuid. Removed. Ancient stuff no longer required?
397 //     Tests OK under several scenarios: Jack started externally,
398 //      Jack started by MusE, Jack started as root, dummy driver etc.
399 //     Was causing crash with new DrumGizmo 0.9.11
400 // #ifndef RTCAP
401 //       int status;
402 //
403 // #ifdef _POSIX_SAVED_IDS
404 //       status = seteuid (ruid);
405 // #else
406 //       status = setreuid (euid, ruid);
407 // #endif
408 //       if (status < 0) {
409 //             fprintf(stderr, "undoSetuid: Couldn't set uid (eff:%d,real:%d): %s\n",
410 //                euid, ruid, strerror(errno));
411 //             exit (status);
412 //             }
413 // #endif
414       }
415 
416 //---------------------------------------------------------
417 //   getUniqueTmpfileName
418 //---------------------------------------------------------
getUniqueTmpfileName(QString subDir,QString ext,QString & newFilename)419 bool getUniqueTmpfileName(QString subDir, QString ext, QString& newFilename)
420 {
421     // Check if tmp-directory exists under project path
422     QString tmpInDir = museProject + "/" + subDir;
423     QDir absDir(tmpInDir);
424     tmpInDir = absDir.cleanPath(absDir.absolutePath());
425 
426     QFileInfo tmpdirfi(tmpInDir);
427     if (!tmpdirfi.isDir()) {
428         // Try to create a tmpdir
429         QDir projdir(museProject);
430         if (!projdir.mkdir(subDir)) {
431             printf("Could not create tmp dir %s!\n", tmpInDir.toLatin1().data() );
432             return false;
433         }
434     }
435 
436     tmpdirfi.setFile(tmpInDir);
437 
438     if (!tmpdirfi.isWritable()) {
439         printf("Temp directory is not writable - aborting\n");
440         return false;
441     }
442 
443     QDir tmpdir = tmpdirfi.dir();
444 
445     // Find a new filename
446     for (int i=0; i<10000; i++) {
447         QString filename = "muse_tmp";
448         filename.append(QString::number(i));
449         if (!ext.startsWith("."))
450             filename.append(".");
451         filename.append(ext);
452 
453         if (!tmpdir.exists(tmpInDir +"/" + filename)) {
454             newFilename = tmpInDir + "/" + filename;
455             if (debugMsg)
456                 printf("returning temporary filename %s\n", newFilename.toLatin1().data());
457             return true;
458         }
459 
460     }
461 
462     printf("Could not find a suitable tmpfilename (more than 10000 tmpfiles in tmpdir - clean up!\n");
463     return false;
464 }
465 
466 } // namespace MusEGlobal
467