/[svn]/linuxsampler/trunk/src/linuxsampler.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/linuxsampler.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1424 - (show annotations) (download)
Sun Oct 14 22:00:17 2007 UTC (16 years, 6 months ago) by schoenebeck
File size: 14856 byte(s)
* code cleanup:
- global.h now only covers global definitions that are needed for the C++
  API header files, all implementation internal global definitions are now
  in global_private.h
- atomic.h is not exposed to the C++ API anymore (replaced the references
  in SynchronizedConfig.h for this with local definitions)
- no need to include config.h anymore for using LS's API header files
- DB instruments classes are not exposed to the C++ API
- POSIX callback functions of Thread.h are hidden
- the (optional) gig Engine benchmark compiles again
- updated Doxyfile.in
- fixed warnings in API doc generation
* preparations for release 0.5.0

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003-2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005-2007 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 #include <getopt.h>
25 #include <signal.h>
26
27 #include "Sampler.h"
28 #include "common/global_private.h"
29 #include "engines/EngineFactory.h"
30 #include "plugins/InstrumentEditorFactory.h"
31 #include "drivers/midi/MidiInputDeviceFactory.h"
32 #include "drivers/audio/AudioOutputDeviceFactory.h"
33 #include "engines/gig/Profiler.h"
34 #include "network/lscpserver.h"
35 #include "common/stacktrace.h"
36 #include "common/Features.h"
37
38 using namespace LinuxSampler;
39
40 Sampler* pSampler = NULL;
41 LSCPServer* pLSCPServer = NULL;
42 pthread_t main_thread;
43 pid_t main_pid;
44 bool bPrintStatistics = false;
45 bool profile = false;
46 bool tune = true;
47 unsigned long int lscp_addr;
48 unsigned short int lscp_port;
49
50 void parse_options(int argc, char **argv);
51 void signal_handler(int signal);
52 void kill_app();
53
54 int main(int argc, char **argv) {
55
56 // initialize the stack trace mechanism with our binary file
57 StackTraceInit(argv[0], -1);
58
59 main_pid = getpid();
60 main_thread = pthread_self();
61
62 // setting signal handler for catching SIGINT (thus e.g. <CTRL><C>)
63 signal(SIGINT, signal_handler);
64
65 // register signal handler for all unusual signals
66 // (we will print the stack trace and exit)
67 struct sigaction sact;
68 sigemptyset(&sact.sa_mask);
69 sact.sa_flags = 0;
70 sact.sa_handler = signal_handler;
71 sigaction(SIGSEGV, &sact, NULL);
72 sigaction(SIGBUS, &sact, NULL);
73 sigaction(SIGILL, &sact, NULL);
74 sigaction(SIGFPE, &sact, NULL);
75 sigaction(SIGUSR1, &sact, NULL);
76 sigaction(SIGUSR2, &sact, NULL);
77
78 lscp_addr = htonl(LSCP_ADDR);
79 lscp_port = htons(LSCP_PORT);
80
81 // parse and assign command line options
82 parse_options(argc, argv);
83
84 dmsg(1,("LinuxSampler %s\n", VERSION));
85 dmsg(1,("Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck\n"));
86 dmsg(1,("Copyright (C) 2005-2007 Christian Schoenebeck\n"));
87
88 if (tune) {
89 // detect and print system / CPU specific features
90 Features::detect();
91 dmsg(1,("Detected features: %s\n", Features::featuresAsString().c_str()));
92 // prevent slow denormal FPU modes
93 Features::enableDenormalsAreZeroMode();
94 }
95
96 // create LinuxSampler instance
97 dmsg(1,("Creating Sampler..."));
98 pSampler = new Sampler;
99 dmsg(1,("OK\n"));
100
101 dmsg(1,("Registered sampler engines: %s\n", EngineFactory::AvailableEngineTypesAsString().c_str()));
102 dmsg(1,("Registered MIDI input drivers: %s\n", MidiInputDeviceFactory::AvailableDriversAsString().c_str()));
103 dmsg(1,("Registered audio output drivers: %s\n", AudioOutputDeviceFactory::AvailableDriversAsString().c_str()));
104 dmsg(1,("Registered instrument editors: %s\n", InstrumentEditorFactory::AvailableEditorsAsString().c_str()));
105
106 // start LSCP network server
107 struct in_addr addr;
108 addr.s_addr = lscp_addr;
109 dmsg(1,("Starting LSCP network server (%s:%d)...", inet_ntoa(addr), ntohs(lscp_port)));
110 pLSCPServer = new LSCPServer(pSampler, lscp_addr, lscp_port);
111 pLSCPServer->StartThread();
112 pLSCPServer->WaitUntilInitialized();
113 dmsg(1,("OK\n"));
114
115 if (profile)
116 {
117 dmsg(1,("Calibrating profiler..."));
118 LinuxSampler::gig::Profiler::Calibrate();
119 LinuxSampler::gig::Profiler::Reset();
120 LinuxSampler::gig::Profiler::enable();
121 dmsg(1,("OK\n"));
122 }
123
124 printf("LinuxSampler initialization completed. :-)\n\n");
125
126 std::list<LSCPEvent::event_t> rtEvents;
127 rtEvents.push_back(LSCPEvent::event_voice_count);
128 rtEvents.push_back(LSCPEvent::event_stream_count);
129 rtEvents.push_back(LSCPEvent::event_buffer_fill);
130 rtEvents.push_back(LSCPEvent::event_total_voice_count);
131
132 while (true) {
133 if (bPrintStatistics) {
134 const std::set<Engine*>& engines = EngineFactory::EngineInstances();
135 std::set<Engine*>::iterator itEngine = engines.begin();
136 for (int i = 0; itEngine != engines.end(); itEngine++, i++) {
137 Engine* pEngine = *itEngine;
138 printf("Engine %d) Voices: %3.3d (Max: %3.3d) Streams: %3.3d (Max: %3.3d)\n", i,
139 pEngine->VoiceCount(), pEngine->VoiceCountMax(),
140 pEngine->DiskStreamCount(), pEngine->DiskStreamCountMax()
141 );
142 fflush(stdout);
143 }
144 }
145
146 sleep(1);
147 if (profile)
148 {
149 unsigned int samplingFreq = 48000; //FIXME: hardcoded for now
150 unsigned int bv = LinuxSampler::gig::Profiler::GetBogoVoices(samplingFreq);
151 if (bv != 0)
152 {
153 printf(" BogoVoices: %i \r", bv);
154 fflush(stdout);
155 }
156 }
157
158 if (LSCPServer::EventSubscribers(rtEvents))
159 {
160 LSCPServer::LockRTNotify();
161 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
162 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
163 for (; iter != channels.end(); iter++) {
164 SamplerChannel* pSamplerChannel = iter->second;
165 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
166 if (!pEngineChannel) continue;
167 Engine* pEngine = pEngineChannel->GetEngine();
168 if (!pEngine) continue;
169 pSampler->fireVoiceCountChanged(iter->first, pEngineChannel->GetVoiceCount());
170 pSampler->fireStreamCountChanged(iter->first, pEngineChannel->GetDiskStreamCount());
171 pSampler->fireBufferFillChanged(iter->first, pEngine->DiskStreamBufferFillPercentage());
172 pSampler->fireTotalVoiceCountChanged(pSampler->GetVoiceCount());
173 }
174 LSCPServer::UnlockRTNotify();
175 }
176
177 }
178
179 return EXIT_SUCCESS;
180 }
181
182 void signal_handler(int iSignal) {
183 switch (iSignal) {
184 case SIGINT: {
185 if (pthread_equal(pthread_self(), main_thread)) {
186 if (pLSCPServer) pLSCPServer->StopThread();
187 // the delete order here is important: the Sampler
188 // destructor sends notifications to the lscpserver
189 if (pSampler) delete pSampler;
190 if (pLSCPServer) delete pLSCPServer;
191 #if HAVE_SQLITE3
192 InstrumentsDb::Destroy();
193 #endif
194 printf("LinuxSampler stopped due to SIGINT.\n");
195 exit(EXIT_SUCCESS);
196 }
197 return;
198 }
199 case SIGSEGV:
200 std::cerr << ">>> FATAL ERROR: Segmentation fault (SIGSEGV) occured! <<<\n" << std::flush;
201 break;
202 case SIGBUS:
203 std::cerr << ">>> FATAL ERROR: Access to undefined portion of a memory object (SIGBUS) occured! <<<\n" << std::flush;
204 break;
205 case SIGILL:
206 std::cerr << ">>> FATAL ERROR: Illegal instruction (SIGILL) occured! <<<\n" << std::flush;
207 break;
208 case SIGFPE:
209 std::cerr << ">>> FATAL ERROR: Erroneous arithmetic operation (SIGFPE) occured! <<<\n" << std::flush;
210 break;
211 case SIGUSR1:
212 std::cerr << ">>> User defined signal 1 (SIGUSR1) received <<<\n" << std::flush;
213 break;
214 case SIGUSR2:
215 std::cerr << ">>> User defined signal 2 (SIGUSR2) received <<<\n" << std::flush;
216 break;
217 default: { // this should never happen, as we register for the signals we want
218 std::cerr << ">>> FATAL ERROR: Unknown signal received! <<<\n" << std::flush;
219 break;
220 }
221 }
222 signal(iSignal, SIG_DFL); // Reinstall default handler to prevent race conditions
223 std::cerr << "Showing stack trace...\n" << std::flush;
224 StackTrace();
225 sleep(2);
226 std::cerr << "Killing LinuxSampler...\n" << std::flush;
227 kill_app(); // Use abort() if we want to generate a core dump.
228 }
229
230 void kill_app() {
231 kill(main_pid, SIGKILL);
232 }
233
234 void parse_options(int argc, char **argv) {
235 int res;
236 int option_index = 0;
237 static struct option long_options[] =
238 {
239 {"help",0,0,0},
240 {"version",0,0,0},
241 {"profile",0,0,0},
242 {"no-tune",0,0,0},
243 {"statistics",0,0,0},
244 {"instruments-db-location",1,0,0},
245 {"create-instruments-db",1,0,0},
246 {"lscp-addr",1,0,0},
247 {"lscp-port",1,0,0},
248 {0,0,0,0}
249 };
250
251 while (true) {
252 /*
253 Stephane Letz : letz@grame.fr
254 getopt_long_only does not exist on OSX : replaced by getopt_long for now.
255 */
256 res = getopt_long(argc, argv, "", long_options, &option_index);
257 if(res == -1) break;
258 if (res == 0) {
259 switch(option_index) {
260 case 0: // --help
261 printf("usage: linuxsampler [OPTIONS]\n\n");
262 printf("--help prints this message\n");
263 printf("--version prints version information\n");
264 printf("--profile profile synthesis algorithms\n");
265 printf("--no-tune disable assembly optimization\n");
266 printf("--statistics periodically prints statistics\n");
267 printf("--lscp-addr set LSCP address (default: any)\n");
268 printf("--lscp-port set LSCP port (default: 8888)\n");
269 printf("--create-instruments-db creates an instruments DB\n");
270 printf("--instruments-db-location specifies the instruments DB file\n");
271 exit(EXIT_SUCCESS);
272 break;
273 case 1: // --version
274 printf("LinuxSampler %s\n", VERSION);
275 exit(EXIT_SUCCESS);
276 break;
277 case 2: // --profile
278 profile = true;
279 break;
280 case 3: // --no-tune
281 tune = false;
282 break;
283 case 4: // --statistics
284 bPrintStatistics = true;
285 break;
286 case 5: // --instruments-db-location
287 #if HAVE_SQLITE3
288 try {
289 if (optarg) {
290 struct stat statBuf;
291 int res = stat(optarg, &statBuf);
292
293 if (res) {
294 std::stringstream ss;
295 ss << "Failed to stat `" << optarg << "`: " << strerror(errno);
296 throw Exception(ss.str());
297 }
298
299 if (!S_ISREG(statBuf.st_mode)) {
300 std::stringstream ss;
301 ss << "`" << optarg << "` is not a regular file";
302 throw Exception(ss.str());
303 }
304
305 InstrumentsDb::GetInstrumentsDb()->SetDbFile(String(optarg));
306 }
307 } catch(Exception e) {
308 std::cerr << "Could not open instruments DB file: "
309 << e.Message() << std::endl;
310 exit(EXIT_FAILURE);
311 }
312 break;
313 #else
314 std::cerr << "LinuxSampler was not build with ";
315 std::cerr << "instruments database support!\n";
316 exit(EXIT_FAILURE);
317 break;
318 #endif
319 case 6: // --create-instruments-db
320 #if HAVE_SQLITE3
321 try {
322 if (optarg) {
323 std::cout << "Creating instruments database..." << std::endl;
324 InstrumentsDb::CreateInstrumentsDb(String(optarg));
325 InstrumentsDb::Destroy();
326 std::cout << "Done" << std::endl;
327 }
328 } catch(Exception e) {
329 std::cerr << e.Message() << std::endl;
330 exit(EXIT_FAILURE);
331 return;
332 }
333
334 exit(EXIT_SUCCESS);
335 return;
336 #else
337 std::cerr << "Failed to create the database. LinuxSampler was ";
338 std::cerr << "not build with instruments database support!\n";
339 exit(EXIT_FAILURE);
340 return;
341 #endif
342 case 7: // --lscp-addr
343 struct in_addr addr;
344 if (inet_aton(optarg, &addr) == 0)
345 printf("WARNING: Failed to parse lscp-addr argument, ignoring!\n");
346 else
347 lscp_addr = addr.s_addr;
348 break;
349 case 8: // --lscp-port
350 long unsigned int port = 0;
351 if ((sscanf(optarg, "%u", &port) != 1) || (port == 0) || (port > 65535))
352 printf("WARNING: Failed to parse lscp-port argument, ignoring!\n");
353 else
354 lscp_port = htons(port);
355 break;
356 }
357 }
358 }
359 }

  ViewVC Help
Powered by ViewVC