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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (show annotations) (download)
Thu Dec 22 19:29:52 2005 UTC (18 years, 3 months ago) by wylder
File size: 11570 byte(s)
change kill statement to use pid rather than thread id

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 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 "engines/EngineFactory.h"
29 #include "drivers/midi/MidiInputDeviceFactory.h"
30 #include "drivers/audio/AudioOutputDeviceFactory.h"
31 #include "engines/gig/Profiler.h"
32 #include "network/lscpserver.h"
33 #include "common/stacktrace.h"
34 #include "common/Features.h"
35
36 using namespace LinuxSampler;
37
38 Sampler* pSampler = NULL;
39 LSCPServer* pLSCPServer = NULL;
40 pthread_t main_thread;
41 pid_t main_pid;
42 bool bPrintStatistics = false;
43 bool profile = false;
44 bool tune = true;
45 unsigned long int lscp_addr;
46 unsigned short int lscp_port;
47
48 void parse_options(int argc, char **argv);
49 void signal_handler(int signal);
50 void kill_app();
51
52 int main(int argc, char **argv) {
53
54 // initialize the stack trace mechanism with our binary file
55 StackTraceInit(argv[0], -1);
56
57 main_pid = getpid();
58 main_thread = pthread_self();
59
60
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 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 MIDI input drivers: %s\n", MidiInputDeviceFactory::AvailableDriversAsString().c_str()));
102 dmsg(1,("Registered audio output drivers: %s\n", AudioOutputDeviceFactory::AvailableDriversAsString().c_str()));
103
104 // start LSCP network server
105 struct in_addr addr;
106 addr.s_addr = lscp_addr;
107 dmsg(1,("Starting LSCP network server (%s:%d)...", inet_ntoa(addr), ntohs(lscp_port)));
108 pLSCPServer = new LSCPServer(pSampler, lscp_addr, lscp_port);
109 pLSCPServer->StartThread();
110 pLSCPServer->WaitUntilInitialized();
111 dmsg(1,("OK\n"));
112
113 if (profile)
114 {
115 dmsg(1,("Calibrating profiler..."));
116 gig::Profiler::Calibrate();
117 gig::Profiler::Reset();
118 gig::Profiler::enable();
119 dmsg(1,("OK\n"));
120 }
121
122 printf("LinuxSampler initialization completed. :-)\n\n");
123
124 std::list<LSCPEvent::event_t> rtEvents;
125 rtEvents.push_back(LSCPEvent::event_voice_count);
126 rtEvents.push_back(LSCPEvent::event_stream_count);
127 rtEvents.push_back(LSCPEvent::event_buffer_fill);
128 rtEvents.push_back(LSCPEvent::event_total_voice_count);
129
130 while (true) {
131 if (bPrintStatistics) {
132 std::set<Engine*> engines = EngineFactory::EngineInstances();
133 std::set<Engine*>::iterator itEngine = engines.begin();
134 for (int i = 0; itEngine != engines.end(); itEngine++, i++) {
135 Engine* pEngine = *itEngine;
136 printf("Engine %d) Voices: %3.3d (Max: %3.3d) Streams: %3.3d (Max: %3.3d)\n", i,
137 pEngine->VoiceCount(), pEngine->VoiceCountMax(),
138 pEngine->DiskStreamCount(), pEngine->DiskStreamCountMax()
139 );
140 fflush(stdout);
141 }
142 }
143
144 sleep(1);
145 if (profile)
146 {
147 unsigned int samplingFreq = 48000; //FIXME: hardcoded for now
148 unsigned int bv = gig::Profiler::GetBogoVoices(samplingFreq);
149 if (bv != 0)
150 {
151 printf(" BogoVoices: %i \r", bv);
152 fflush(stdout);
153 }
154 }
155
156 if (LSCPServer::EventSubscribers(rtEvents))
157 {
158 LSCPServer::LockRTNotify();
159 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
160 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
161 for (; iter != channels.end(); iter++) {
162 SamplerChannel* pSamplerChannel = iter->second;
163 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
164 if (!pEngineChannel) continue;
165 Engine* pEngine = pEngineChannel->GetEngine();
166 if (!pEngine) continue;
167 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, iter->first, pEngine->VoiceCount()));
168 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, iter->first, pEngine->DiskStreamCount()));
169 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, iter->first, pEngine->DiskStreamBufferFillPercentage()));
170 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, pSampler->GetVoiceCount()));
171 }
172 LSCPServer::UnlockRTNotify();
173 }
174
175 }
176
177 return EXIT_SUCCESS;
178 }
179
180 void signal_handler(int iSignal) {
181 switch (iSignal) {
182 case SIGINT: {
183 if (pthread_equal(pthread_self(), main_thread)) {
184 if (pLSCPServer) {
185 pLSCPServer->StopThread();
186 delete pLSCPServer;
187 }
188 if (pSampler) delete pSampler;
189 printf("LinuxSampler stopped due to SIGINT.\n");
190 exit(EXIT_SUCCESS);
191 }
192 return;
193 }
194 case SIGSEGV:
195 std::cerr << ">>> FATAL ERROR: Segmentation fault (SIGSEGV) occured! <<<\n" << std::flush;
196 break;
197 case SIGBUS:
198 std::cerr << ">>> FATAL ERROR: Access to undefined portion of a memory object (SIGBUS) occured! <<<\n" << std::flush;
199 break;
200 case SIGILL:
201 std::cerr << ">>> FATAL ERROR: Illegal instruction (SIGILL) occured! <<<\n" << std::flush;
202 break;
203 case SIGFPE:
204 std::cerr << ">>> FATAL ERROR: Erroneous arithmetic operation (SIGFPE) occured! <<<\n" << std::flush;
205 break;
206 case SIGUSR1:
207 std::cerr << ">>> User defined signal 1 (SIGUSR1) received <<<\n" << std::flush;
208 break;
209 case SIGUSR2:
210 std::cerr << ">>> User defined signal 2 (SIGUSR2) received <<<\n" << std::flush;
211 break;
212 default: { // this should never happen, as we register for the signals we want
213 std::cerr << ">>> FATAL ERROR: Unknown signal received! <<<\n" << std::flush;
214 break;
215 }
216 }
217 signal(iSignal, SIG_DFL); // Reinstall default handler to prevent race conditions
218 std::cerr << "Showing stack trace...\n" << std::flush;
219 StackTrace();
220 sleep(2);
221 std::cerr << "Killing LinuxSampler...\n" << std::flush;
222 kill_app(); // Use abort() if we want to generate a core dump.
223 }
224
225 void kill_app() {
226 kill(main_pid, SIGKILL);
227 }
228
229 void parse_options(int argc, char **argv) {
230 int res;
231 int option_index = 0;
232 static struct option long_options[] =
233 {
234 {"help",0,0,0},
235 {"version",0,0,0},
236 {"profile",0,0,0},
237 {"no-tune",0,0,0},
238 {"statistics",0,0,0},
239 {"lscp-addr",1,0,0},
240 {"lscp-port",1,0,0},
241 {0,0,0,0}
242 };
243
244 while (true) {
245 /*
246 Stephane Letz : letz@grame.fr
247 getopt_long_only does not exist on OSX : replaced by getopt_long for now.
248 */
249 res = getopt_long(argc, argv, "", long_options, &option_index);
250 if(res == -1) break;
251 if (res == 0) {
252 switch(option_index) {
253 case 0: // --help
254 printf("usage: linuxsampler [OPTIONS]\n\n");
255 printf("--help prints this message\n");
256 printf("--version prints version information\n");
257 printf("--profile profile synthesis algorithms\n");
258 printf("--no-tune disable assembly optimization\n");
259 printf("--statistics periodically prints statistics\n");
260 printf("--lscp-addr set LSCP address (default: any)\n");
261 printf("--lscp-port set LSCP port (default: 8888)\n");
262 exit(EXIT_SUCCESS);
263 break;
264 case 1: // --version
265 printf("LinuxSampler %s\n", VERSION);
266 exit(EXIT_SUCCESS);
267 break;
268 case 2: // --profile
269 profile = true;
270 break;
271 case 3: // --no-tune
272 tune = false;
273 break;
274 case 4: // --statistics
275 bPrintStatistics = true;
276 break;
277 case 5: // --lscp-addr
278 struct in_addr addr;
279 if (inet_aton(optarg, &addr) == 0)
280 printf("WARNING: Failed to parse lscp-addr argument, ignoring!\n");
281 else
282 lscp_addr = addr.s_addr;
283 break;
284 case 6: // --lscp-port
285 long unsigned int port = 0;
286 if ((sscanf(optarg, "%u", &port) != 1) || (port == 0) || (port > 65535))
287 printf("WARNING: Failed to parse lscp-port argument, ignoring!\n");
288 else
289 lscp_port = htons(port);
290 break;
291 }
292 }
293 }
294 }

  ViewVC Help
Powered by ViewVC