1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2020 Christian Schoenebeck                       *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (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., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  ***************************************************************************/
23 
24 // Allow to avoid inclusion of config.h
25 // (we used it for the _old_ xcode project file to avoid inclusion of
26 // config.h here and rather used our manually maintained version.h)
27 #ifndef OVERRIDE_CONFIG_H
28 # include <config.h>
29 #endif
30 
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string>
35 #if !defined(WIN32)
36 # include <execinfo.h> // for backtrace() and backtrace_symbols()
37 #endif
38 #if defined (__APPLE__)
39 # include <mach-o/dyld.h>
40 #endif
41 
42 // Make sure all mandatory configuration macros are defined.
43 // We don't care about optional configuration macros though.
44 #ifndef CONFIG_GLOBAL_ATTENUATION_DEFAULT
45 # error "Configuration macro CONFIG_GLOBAL_ATTENUATION_DEFAULT not defined!"
46 #endif // CONFIG_GLOBAL_ATTENUATION_DEFAULT
47 #ifndef CONFIG_MAX_PITCH
48 # error "Configuration macro CONFIG_MAX_PITCH not defined!"
49 #endif // CONFIG_MAX_PITCH
50 #ifndef CONFIG_MAX_EVENTS_PER_FRAGMENT
51 # error "Configuration macro CONFIG_MAX_EVENTS_PER_FRAGMENT not defined!"
52 #endif // CONFIG_MAX_EVENTS_PER_FRAGMENT
53 #ifndef CONFIG_EG_BOTTOM
54 # error "Configuration macro CONFIG_EG_BOTTOM not defined!"
55 #endif // CONFIG_EG_BOTTOM
56 #ifndef CONFIG_EG_MIN_RELEASE_TIME
57 # error "Configuration macro CONFIG_EG_MIN_RELEASE_TIME not defined!"
58 #endif // CONFIG_EG_MIN_RELEASE_TIME
59 #ifndef CONFIG_REFILL_STREAMS_PER_RUN
60 # error "Configuration macro CONFIG_REFILL_STREAMS_PER_RUN not defined!"
61 #endif // CONFIG_REFILL_STREAMS_PER_RUN
62 #ifndef CONFIG_STREAM_MIN_REFILL_SIZE
63 # error "Configuration macro CONFIG_STREAM_MIN_REFILL_SIZE not defined!"
64 #endif // CONFIG_STREAM_MIN_REFILL_SIZE
65 #ifndef CONFIG_STREAM_MAX_REFILL_SIZE
66 # error "Configuration macro CONFIG_STREAM_MAX_REFILL_SIZE not defined!"
67 #endif // CONFIG_STREAM_MAX_REFILL_SIZE
68 #ifndef CONFIG_STREAM_BUFFER_SIZE
69 # error "Configuration macro CONFIG_STREAM_BUFFER_SIZE not defined!"
70 #endif // CONFIG_STREAM_BUFFER_SIZE
71 #ifndef CONFIG_DEFAULT_MAX_STREAMS
72 # error "Configuration macro CONFIG_DEFAULT_MAX_STREAMS not defined!"
73 #endif // CONFIG_DEFAULT_MAX_STREAMS
74 #ifndef CONFIG_DEFAULT_MAX_VOICES
75 # error "Configuration macro CONFIG_DEFAULT_MAX_VOICES not defined!"
76 #endif // CONFIG_DEFAULT_MAX_VOICES
77 #ifndef CONFIG_DEFAULT_SUBFRAGMENT_SIZE
78 # error "Configuration macro CONFIG_DEFAULT_SUBFRAGMENT_SIZE not defined!"
79 #endif // CONFIG_DEFAULT_SUBFRAGMENT_SIZE
80 #ifndef CONFIG_VOICE_STEAL_ALGO
81 # error "Configuration macro CONFIG_VOICE_STEAL_ALGO not defined!"
82 #endif // CONFIG_VOICE_STEAL_ALGO
83 #ifndef CONFIG_SYSEX_BUFFER_SIZE
84 # error "Configuration macro CONFIG_SYSEX_BUFFER_SIZE not defined!"
85 #endif // CONFIG_SYSEX_BUFFER_SIZE
86 #ifndef CONFIG_FILTER_CUTOFF_MIN
87 # error "Configuration macro CONFIG_FILTER_CUTOFF_MIN not defined!"
88 #endif // CONFIG_FILTER_CUTOFF_MIN
89 #ifndef CONFIG_FILTER_CUTOFF_MAX
90 # error "Configuration macro CONFIG_FILTER_CUTOFF_MAX not defined!"
91 #endif // CONFIG_FILTER_CUTOFF_MAX
92 #ifndef CONFIG_PORTAMENTO_TIME_MIN
93 # error "Configuration macro CONFIG_PORTAMENTO_TIME_MIN not defined!"
94 #endif // CONFIG_PORTAMENTO_TIME_MIN
95 #ifndef CONFIG_PORTAMENTO_TIME_MAX
96 # error "Configuration macro CONFIG_PORTAMENTO_TIME_MAX not defined!"
97 #endif // CONFIG_PORTAMENTO_TIME_MAX
98 #ifndef CONFIG_PORTAMENTO_TIME_DEFAULT
99 # error "Configuration macro CONFIG_PORTAMENTO_TIME_DEFAULT not defined!"
100 #endif // CONFIG_PORTAMENTO_TIME_DEFAULT
101 
102 // this is the sampler global volume coefficient that should be obeyed by all
103 // sampler engine implementations
104 double GLOBAL_VOLUME = CONFIG_GLOBAL_ATTENUATION_DEFAULT;
105 
106 // this is the sampler global setting for maximum voices
107 int GLOBAL_MAX_VOICES = CONFIG_DEFAULT_MAX_VOICES;
108 
109 // this is the sampler global setting for maximum disk streams
110 int GLOBAL_MAX_STREAMS = CONFIG_DEFAULT_MAX_STREAMS;
111 
112 //TODO: (hopefully) just a temporary nasty hack for launching gigedit on the main thread on Mac (see comments in gigedit.cpp for details)
113 #if defined(__APPLE__)
114 bool g_mainThreadCallbackSupported = false;
115 void (*g_mainThreadCallback)(void* info) = 0;
116 void* g_mainThreadCallbackInfo = 0;
117 bool g_fireMainThreadCallback = false;
118 #endif
119 
hexToNumber(char hex_digit)120 int hexToNumber(char hex_digit) {
121     switch (hex_digit) {
122         case '0': return 0;
123         case '1': return 1;
124         case '2': return 2;
125         case '3': return 3;
126         case '4': return 4;
127         case '5': return 5;
128         case '6': return 6;
129         case '7': return 7;
130         case '8': return 8;
131         case '9': return 9;
132 
133         case 'a': return 10;
134         case 'b': return 11;
135         case 'c': return 12;
136         case 'd': return 13;
137         case 'e': return 14;
138         case 'f': return 15;
139 
140         case 'A': return 10;
141         case 'B': return 11;
142         case 'C': return 12;
143         case 'D': return 13;
144         case 'E': return 14;
145         case 'F': return 15;
146 
147         default:  return 0; //TODO: we might want to throw an exception here
148     }
149 }
150 
hexsToNumber(char hex_digit0,char hex_digit1)151 int hexsToNumber(char hex_digit0, char hex_digit1) {
152     return hexToNumber(hex_digit1)*16 + hexToNumber(hex_digit0);
153 }
154 
155 #if defined (__APPLE__)
156 
dyldImagesAsString()157 static std::string dyldImagesAsString() {
158     std::string s;
159     const uint32_t n = _dyld_image_count();
160     for (uint32_t i = 0; i < n; ++i) {
161         const std::string name = _dyld_get_image_name(i);
162 
163         // ignore system frameworks
164         // (as we don't have their source files anyway, do we?)
165         if (name.find("/System/Library/") == 0)
166             continue;
167         if (name.find("/usr/lib/") != std::string::npos)
168             continue;
169 
170         const intptr_t slide = _dyld_get_image_vmaddr_slide(i);
171         const struct mach_header* loadaddr = _dyld_get_image_header(i);
172         char* cs = NULL;
173         asprintf(&cs, "%d. '%s' loadaddr %p, slide %p\n", i+1, name.c_str(), loadaddr, (void*)slide);
174         s += cs;
175         free(cs);
176     }
177     return s;
178 }
179 
180 #endif
181 
182 /** @brief Return a backtrace of call.
183  *
184  * Calling this function will return the calling stack as text representation
185  * for debugging purposes.
186  */
backtraceAsString()187 std::string backtraceAsString() {
188     std::string s;
189     #ifdef WIN32
190     //TODO: Windows implementation using CaptureStackBackTrace() (plus maybe SymFromAddr())
191     s = "not implemented";
192     #else
193     # ifdef __APPLE__
194     s += dyldImagesAsString();
195     s += "   \n\n";
196     # endif
197     const size_t bufSz = 1024;
198     void* array[bufSz];
199     const size_t sz = backtrace(array, bufSz);
200     char** strings = backtrace_symbols(array, sz);
201     for (int i = 0; i < sz; ++i) {
202         s += strings[i];
203         s += "\n";
204     }
205     free(strings);
206     #endif
207     return s;
208 }
209