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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 411 - (show annotations) (download)
Sat Feb 26 02:01:14 2005 UTC (19 years, 1 month ago) by schoenebeck
File size: 9711 byte(s)
* design change: using now one sampler engine instance and one disk thread
  instance for all sampler channels that are connected to the same audio
  output device (and are using the same engine type of course)
* added EngineFactory / EngineChannelFactory to remove the annoying build
  dependencies e.g. of the lscpserver to the actual sampler engine
  implementations
* bumped version to 0.3.0 (current CVS state is still quite broken,
  previous, stable CVS version was tagged as "v0_2_0" and is also available
  as source tarball)

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 "drivers/midi/MidiInputDeviceFactory.h"
29 #include "drivers/audio/AudioOutputDeviceFactory.h"
30 #include "engines/gig/Profiler.h"
31 #include "network/lscpserver.h"
32 #include "common/stacktrace.h"
33 #include "common/Features.h"
34
35 using namespace LinuxSampler;
36
37 Sampler* pSampler = NULL;
38 LSCPServer* pLSCPServer = NULL;
39 pthread_t main_thread;
40 bool profile = false;
41 bool tune = true;
42
43 void parse_options(int argc, char **argv);
44 void signal_handler(int signal);
45 void kill_app();
46
47 int main(int argc, char **argv) {
48
49 // initialize the stack trace mechanism with our binary file
50 StackTraceInit(argv[0], -1);
51
52 main_thread = pthread_self();
53
54 // setting signal handler for catching SIGINT (thus e.g. <CTRL><C>)
55 signal(SIGINT, signal_handler);
56
57 // register signal handler for all unusual signals
58 // (we will print the stack trace and exit)
59 struct sigaction sact;
60 sigemptyset(&sact.sa_mask);
61 sact.sa_flags = 0;
62 sact.sa_handler = signal_handler;
63 sigaction(SIGSEGV, &sact, NULL);
64 sigaction(SIGBUS, &sact, NULL);
65 sigaction(SIGILL, &sact, NULL);
66 sigaction(SIGFPE, &sact, NULL);
67 sigaction(SIGUSR1, &sact, NULL);
68 sigaction(SIGUSR2, &sact, NULL);
69
70 // parse and assign command line options
71 parse_options(argc, argv);
72
73 dmsg(1,("LinuxSampler %s\n", VERSION));
74 dmsg(1,("Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck\n"));
75 dmsg(1,("Copyright (C) 2005 Christian Schoenebeck\n"));
76
77 if (tune)
78 {
79 // detect and print system / CPU specific features
80 String sFeatures;
81 Features::detect();
82 #if ARCH_X86
83 if (Features::supportsMMX()) sFeatures += " MMX";
84 if (Features::supportsSSE()) sFeatures += " SSE";
85 #endif // ARCH_X86
86 if (!sFeatures.size()) sFeatures = " None";
87 dmsg(1,("Detected features:%s\n",sFeatures.c_str()));
88 }
89
90 // create LinuxSampler instance
91 dmsg(1,("Creating Sampler..."));
92 pSampler = new Sampler;
93 dmsg(1,("OK\n"));
94
95 dmsg(1,("Registered MIDI input drivers: %s\n", MidiInputDeviceFactory::AvailableDriversAsString().c_str()));
96 dmsg(1,("Registered audio output drivers: %s\n", AudioOutputDeviceFactory::AvailableDriversAsString().c_str()));
97
98 // start LSCP network server
99 dmsg(1,("Starting LSCP network server (on TCP port %d)...", LSCP_PORT));
100 pLSCPServer = new LSCPServer(pSampler);
101 pLSCPServer->StartThread();
102 pLSCPServer->WaitUntilInitialized();
103 dmsg(1,("OK\n"));
104
105 if (profile)
106 {
107 dmsg(1,("Calibrating profiler..."));
108 gig::Profiler::Calibrate();
109 gig::Profiler::Reset();
110 dmsg(1,("OK\n"));
111 }
112
113 printf("LinuxSampler initialization completed.\n");
114
115 std::list<LSCPEvent::event_t> rtEvents;
116 rtEvents.push_back(LSCPEvent::event_voice_count);
117 rtEvents.push_back(LSCPEvent::event_stream_count);
118 rtEvents.push_back(LSCPEvent::event_buffer_fill);
119
120 while(true)
121 {
122 /*printf("Voices: %3.3d (Max: %3.3d) Streams: %3.3d (Max: %3.3d, Unused: %3.3d)\r",
123 pEngine->ActiveVoiceCount, pEngine->ActiveVoiceCountMax,
124 pEngine->pDiskThread->ActiveStreamCount, pEngine->pDiskThread->ActiveStreamCountMax, Stream::GetUnusedStreams());
125 fflush(stdout);*/
126 sleep(1);
127 if (profile)
128 {
129 unsigned int samplingFreq = 48000; //FIXME: hardcoded for now
130 unsigned int bv = gig::Profiler::GetBogoVoices(samplingFreq);
131 if (bv != 0)
132 {
133 printf(" BogoVoices: %i \r", bv);
134 fflush(stdout);
135 }
136 }
137
138 if (LSCPServer::EventSubscribers(rtEvents))
139 {
140 LSCPServer::LockRTNotify();
141 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
142 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
143 for (; iter != channels.end(); iter++) {
144 SamplerChannel* pSamplerChannel = iter->second;
145 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
146 if (!pEngineChannel) continue;
147 Engine* pEngine = pEngineChannel->GetEngine();
148 if (!pEngine) continue;
149 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, iter->first, pEngine->VoiceCount()));
150 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, iter->first, pEngine->DiskStreamCount()));
151 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, iter->first, pEngine->DiskStreamBufferFillPercentage()));
152 }
153 LSCPServer::UnlockRTNotify();
154 }
155
156 }
157
158 return EXIT_SUCCESS;
159 }
160
161 void signal_handler(int iSignal) {
162 switch (iSignal) {
163 case SIGINT: {
164 if (pthread_equal(pthread_self(), main_thread)) {
165 if (pLSCPServer) {
166 pLSCPServer->StopThread();
167 delete pLSCPServer;
168 }
169 if (pSampler) delete pSampler;
170 printf("LinuxSampler stopped due to SIGINT.\n");
171 exit(EXIT_SUCCESS);
172 }
173 return;
174 }
175 case SIGSEGV:
176 std::cerr << ">>> FATAL ERROR: Segmentation fault (SIGSEGV) occured! <<<\n" << std::flush;
177 break;
178 case SIGBUS:
179 std::cerr << ">>> FATAL ERROR: Access to undefined portion of a memory object (SIGBUS) occured! <<<\n" << std::flush;
180 break;
181 case SIGILL:
182 std::cerr << ">>> FATAL ERROR: Illegal instruction (SIGILL) occured! <<<\n" << std::flush;
183 break;
184 case SIGFPE:
185 std::cerr << ">>> FATAL ERROR: Erroneous arithmetic operation (SIGFPE) occured! <<<\n" << std::flush;
186 break;
187 case SIGUSR1:
188 std::cerr << ">>> User defined signal 1 (SIGUSR1) received <<<\n" << std::flush;
189 break;
190 case SIGUSR2:
191 std::cerr << ">>> User defined signal 2 (SIGUSR2) received <<<\n" << std::flush;
192 break;
193 default: { // this should never happen, as we register for the signals we want
194 std::cerr << ">>> FATAL ERROR: Unknown signal received! <<<\n" << std::flush;
195 break;
196 }
197 }
198 signal(iSignal, SIG_DFL); // Reinstall default handler to prevent race conditions
199 std::cerr << "Showing stack trace...\n" << std::flush;
200 StackTrace();
201 sleep(2);
202 std::cerr << "Killing LinuxSampler...\n" << std::flush;
203 kill_app(); // Use abort() if we want to generate a core dump.
204 }
205
206 void kill_app() {
207 kill(main_thread, SIGKILL);
208 }
209
210 void parse_options(int argc, char **argv) {
211 int res;
212 int option_index = 0;
213 static struct option long_options[] =
214 {
215 {"help",0,0,0},
216 {"version",0,0,0},
217 {"profile",0,0,0},
218 {"no-tune",0,0,0},
219 {0,0,0,0}
220 };
221
222 while (true) {
223 /*
224 Stephane Letz : letz@grame.fr
225 getopt_long_only does not exist on OSX : replaced by getopt_long for now.
226 */
227 res = getopt_long(argc, argv, "", long_options, &option_index);
228 if(res == -1) break;
229 if (res == 0) {
230 switch(option_index) {
231 case 0: // --help
232 printf("usage: linuxsampler [OPTIONS]\n\n");
233 printf("--help prints this message\n");
234 printf("--version prints version information\n");
235 printf("--profile profile synthesis algorithms\n");
236 printf("--no-tune disable assembly optimization\n");
237 exit(EXIT_SUCCESS);
238 break;
239 case 1: // --version
240 printf("LinuxSampler %s\n", VERSION);
241 exit(EXIT_SUCCESS);
242 break;
243 case 2: // --profile
244 profile = true;
245 break;
246 case 3: // --no-tune
247 tune = false;
248 break;
249 }
250 }
251 }
252 }

  ViewVC Help
Powered by ViewVC