--- linuxsampler/trunk/src/linuxsampler.cpp 2004/07/13 22:44:13 203 +++ linuxsampler/trunk/src/linuxsampler.cpp 2004/10/08 20:51:39 271 @@ -24,98 +24,63 @@ #include #include "Sampler.h" +#include "drivers/midi/MidiInputDeviceFactory.h" #include "drivers/audio/AudioOutputDeviceFactory.h" #include "network/lscpserver.h" - -#if 0 -#define AUDIO_CHANNELS 2 // stereo -#define AUDIO_FRAGMENTS 3 // 3 fragments, if it does not work set it to 2 -#define AUDIO_FRAGMENTSIZE 512 // each fragment has 512 frames -#define AUDIO_SAMPLERATE 44100 // Hz -#endif +#include "common/stacktrace.h" using namespace LinuxSampler; -/*enum patch_format_t { - patch_format_unknown, - patch_format_gig, - patch_format_dls -} patch_format = patch_format_unknown;*/ - -Sampler* pSampler = NULL; -LSCPServer* pLSCPServer = NULL; -pthread_t signalhandlerthread; -/*AudioThread* pEngine = NULL; -uint instrument_index = 0; -double volume = 0.25; -int num_fragments = AUDIO_FRAGMENTS; -int fragmentsize = AUDIO_FRAGMENTSIZE; -uint samplerate = AUDIO_SAMPLERATE; -String input_client; -String alsaout = "0,0"; // default card -String jack_playback[2] = { "", "" }; -bool use_jack = true; -bool run_server = false;*/ - +Sampler* pSampler = NULL; +LSCPServer* pLSCPServer = NULL; +pthread_t main_thread; void parse_options(int argc, char **argv); void signal_handler(int signal); +void kill_app(); int main(int argc, char **argv) { + // initialize the stack trace mechanism with our binary file + StackTraceInit(argv[0], -1); + + main_thread = pthread_self(); + // setting signal handler for catching SIGINT (thus e.g. ) - signalhandlerthread = pthread_self(); signal(SIGINT, signal_handler); + // register signal handler for all unusual signals + // (we will print the stack trace and exit) + struct sigaction sact; + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; + sact.sa_handler = signal_handler; + sigaction(SIGSEGV, &sact, NULL); + sigaction(SIGBUS, &sact, NULL); + sigaction(SIGILL, &sact, NULL); + sigaction(SIGFPE, &sact, NULL); + sigaction(SIGUSR1, &sact, NULL); + sigaction(SIGUSR2, &sact, NULL); + // parse and assign command line options //parse_options(argc, argv); - /*if (patch_format != patch_format_gig) { - printf("Sorry only Gigasampler loading migrated in LinuxSampler so far, use --gig to load a .gig file!\n"); - printf("Use 'linuxsampler --help' to see all available options.\n"); - return EXIT_FAILURE; - }*/ - + dmsg(1,("LinuxSampler %s\n", VERSION)); + dmsg(1,("Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck\n")); // create LinuxSampler instance dmsg(1,("Creating Sampler...")); pSampler = new Sampler; dmsg(1,("OK\n")); + dmsg(1,("Registered MIDI input drivers: %s\n", MidiInputDeviceFactory::AvailableDriversAsString().c_str())); dmsg(1,("Registered audio output drivers: %s\n", AudioOutputDeviceFactory::AvailableDriversAsString().c_str())); - // create an audio output device - /* bool no_jack = true; -#if HAVE_JACK - if (use_jack) { - dmsg(1,("Creating audio output device (Jack)...")); - try { - pSampler->CreateAudioOutputDevice(audio_output_type_jack); - no_jack = false; - } - catch (AudioOutputException aoe) { - aoe.PrintMessage(); - dmsg(1,("Trying to create Alsa output device instead.\n")); - } - } -#endif // HAVE_JACK - if (no_jack) { - dmsg(1,("Creating audio output device (Alsa)...")); - try { - pSampler->CreateAudioOutputDevice(audio_output_type_alsa); - } - catch (AudioOutputException aoe) { - aoe.PrintMessage(); - dmsg(1,("Trying to create Alsa output device instead.\n")); - return EXIT_FAILURE; - } - } - dmsg(1,("OK\n"));*/ - // start LSCP network server - dmsg(1,("Starting network server...")); + dmsg(1,("Starting LSCP network server (on TCP port %d)...", LSCP_PORT)); pLSCPServer = new LSCPServer(pSampler); pLSCPServer->StartThread(); + pLSCPServer->WaitUntilInitialized(); dmsg(1,("OK\n")); printf("LinuxSampler initialization completed.\n"); @@ -131,16 +96,53 @@ return EXIT_SUCCESS; } -void signal_handler(int signal) { - if (pthread_equal(pthread_self(), signalhandlerthread) && signal == SIGINT) { - if (pLSCPServer) { - pLSCPServer->StopThread(); - delete pLSCPServer; +void signal_handler(int iSignal) { + switch (iSignal) { + case SIGINT: { + if (pthread_equal(pthread_self(), main_thread)) { + if (pLSCPServer) { + pLSCPServer->StopThread(); + delete pLSCPServer; + } + if (pSampler) delete pSampler; + printf("LinuxSampler stopped due to SIGINT.\n"); + exit(EXIT_SUCCESS); + } + return; + } + case SIGSEGV: + std::cerr << ">>> FATAL ERROR: Segmentation fault (SIGSEGV) occured! <<<\n" << std::flush; + break; + case SIGBUS: + std::cerr << ">>> FATAL ERROR: Access to undefined portion of a memory object (SIGBUS) occured! <<<\n" << std::flush; + break; + case SIGILL: + std::cerr << ">>> FATAL ERROR: Illegal instruction (SIGILL) occured! <<<\n" << std::flush; + break; + case SIGFPE: + std::cerr << ">>> FATAL ERROR: Erroneous arithmetic operation (SIGFPE) occured! <<<\n" << std::flush; + break; + case SIGUSR1: + std::cerr << ">>> User defined signal 1 (SIGUSR1) received <<<\n" << std::flush; + break; + case SIGUSR2: + std::cerr << ">>> User defined signal 2 (SIGUSR2) received <<<\n" << std::flush; + break; + default: { // this should never happen, as we register for the signals we want + std::cerr << ">>> FATAL ERROR: Unknown signal received! <<<\n" << std::flush; + break; } - if (pSampler) delete pSampler; - printf("LinuxSampler stopped due to SIGINT\n"); - exit(EXIT_SUCCESS); } + signal(iSignal, SIG_DFL); // Reinstall default handler to prevent race conditions + std::cerr << "Showing stack trace...\n" << std::flush; + StackTrace(); + sleep(2); + std::cerr << "Killing LinuxSampler...\n" << std::flush; + kill_app(); // Use abort() if we want to generate a core dump. +} + +void kill_app() { + kill(main_thread, SIGKILL); } /*void parse_options(int argc, char **argv) {