void *safe_large_malloc(size_t count) { void *p; static int errflag = 0; if(errflag) safe_exit(10); if(count == 0) /* Some malloc routine return NULL if count is zero, such as * malloc routine from libmalloc.a of Solaris. * But TiMidity doesn't want to return NULL even if count is zero. */ count = 1; if((p = (void *)malloc(count)) != NULL) return p; errflag = 1; ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't malloc %d bytes.", count); #ifdef ABORT_AT_FATAL abort(); #endif /* ABORT_AT_FATAL */ safe_exit(10); /*NOTREACHED*/ }
void *safe_realloc(void *ptr, size_t count) { void *p; static int errflag = 0; if(errflag) safe_exit(10); if(count > MAX_SAFE_MALLOC_SIZE) { errflag = 1; ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Strange, I feel like allocating %d bytes. " "This must be a bug.", count); } else { if (ptr == NULL) return safe_malloc(count); if(count == 0) /* Some malloc routine return NULL if count is zero, such as * malloc routine from libmalloc.a of Solaris. * But TiMidity doesn't want to return NULL even if count is zero. */ count = 1; if((p = (void *)realloc(ptr, count)) != NULL) return p; errflag = 1; ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't malloc %d bytes.", count); } #ifdef ABORT_AT_FATAL abort(); #endif /* ABORT_AT_FATAL */ safe_exit(10); /*NOTREACHED*/ }
int exception_pop_handler(int code, ExceptionHandler handler) { unsigned int state = safe_entry(); if (code > (int)(sizeof(exception_stacks) / sizeof(*exception_stacks))) { e9printf("exception_add_handler: invalid code: %d\n", code); kerror(-1, "invalid code"); safe_exit(state); return -1; } for (LinkNode *node=exception_stacks[code].first; node; node=node->next) { if (node->data == handler) { klist_remove(exception_stacks+code, node); exc_free_node(node); safe_exit(state); return 0; //success } } e9printf("failed to find handler %x for %d\n", handler, code); safe_exit(state); return -1; //couldn't find handler }
static void encode(const std::string& input_file, const std::string& output_file) { try { std::ifstream ifile(input_file.c_str(), std::ios_base::in | std::ios_base::binary); ifile.peek(); // We need to touch the stream to set the eof bit if(!ifile.good()) { std::cerr << "Input file " << input_file << " is not good for reading. Exiting to prevent bzip2 from segfaulting\n"; safe_exit(1); } std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary); boost::iostreams::filtering_stream<boost::iostreams::output> stream; stream.push(filter()); stream.push(ofile); boost::iostreams::copy(ifile, stream); ifile.close(); safe_exit(remove(input_file.c_str())); } catch(filesystem::io_exception& e) { std::cerr << "IO error: " << e.what() << "\n"; } }
/* get access to the port */ void open_port(void) { if (ioperm(BASEPORT, 3, 1)) { perror("ioperm"); safe_exit(1); } }
/* lose access to the port */ void close_port(void) { if (ioperm(BASEPORT, 3, 0)) { perror("ioperm"); safe_exit(1); } }
void wait_for_space(void) { ALLEGRO_EVENT ev; ALLEGRO_KEYBOARD_STATE wait_key_State; fprintf(stdout, "\n press space to continue\n\r"); int unpressed = 0; while(TRUE) { al_wait_for_event(event_queue, &ev); al_get_keyboard_state(&wait_key_State); if(!al_key_down(&wait_key_State, ALLEGRO_KEY_SPACE)) unpressed = 1; if(al_key_down(&wait_key_State, ALLEGRO_KEY_ESCAPE)) safe_exit(0); if(unpressed && al_key_down(&wait_key_State, ALLEGRO_KEY_SPACE)) return; }; }
/* return 1 on success, 0 on failure */ int play_frame(void) { unsigned char *audio; int mc; size_t bytes; debug("play_frame"); /* The first call will not decode anything but return MPG123_NEW_FORMAT! */ mc = mpg123_decode_frame(mh, &framenum, &audio, &bytes); /* Play what is there to play (starting with second decode_frame call!) */ if(bytes) { if(param.frame_number > -1) --frames_left; if(fresh && framenum >= param.start_frame) { fresh = FALSE; } /* Normal flushing of data, includes buffer decoding. */ if(flush_output(ao, audio, bytes) < (int)bytes && !intflag) { error("Deep trouble! Cannot flush to my output anymore!"); safe_exit(133); } if(param.checkrange) { long clip = mpg123_clip(mh); if(clip > 0) fprintf(stderr,"%ld samples clipped\n", clip); } } /* Special actions and errors. */ if(mc != MPG123_OK) { if(mc == MPG123_ERR || mc == MPG123_DONE) { if(mc == MPG123_ERR) error1("...in decoding next frame: %s", mpg123_strerror(mh)); return 0; } if(mc == MPG123_NO_SPACE) { error("I have not enough output space? I didn't plan for this."); return 0; } if(mc == MPG123_NEW_FORMAT) { long rate; int channels, format; mpg123_getformat(mh, &rate, &channels, &format); if(param.verbose > 2) fprintf(stderr, "\nNote: New output format %liHz %ich, format %i\n", rate, channels, format); if(!param.quiet) { fprintf(stderr, "\n"); if(param.verbose) print_header(mh); else print_header_compact(mh); } reset_audio(rate, channels, format); } } return 1; }
std::string EditLine::gets() { int count; const char* c = el_gets(el, &count); if(c == 0) { safe_exit(0); } std::string s = c; return s.substr(0, s.size() - 1); }
/* * Change the playback sample rate. * Consider that changing it after starting playback is not covered by gapless code! */ static void reset_audio(long rate, int channels, int format) { #ifndef NOXFERMEM if (param.usebuffer) { /* wait until the buffer is empty, * then tell the buffer process to * change the sample rate. [OF] */ while (xfermem_get_usedspace(buffermem) > 0) if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) { intflag = TRUE; break; } buffermem->freeindex = -1; buffermem->readindex = 0; /* I know what I'm doing! ;-) */ buffermem->freeindex = 0; if (intflag) return; buffermem->rate = pitch_rate(rate); buffermem->channels = channels; buffermem->format = format; buffer_reset(); } else { #endif if(ao == NULL) { error("Audio handle should not be NULL here!"); safe_exit(98); } ao->rate = pitch_rate(rate); ao->channels = channels; ao->format = format; if(reset_output(ao) < 0) { error1("failed to reset audio device: %s", strerror(errno)); safe_exit(1); } #ifndef NOXFERMEM } #endif }
int main(int argc, char *argv[]) { open_port(); /* open lp1 port */ outb(0, BASEPORT); /* safe to turn on switch */ if (argc < 2) { printf("\nusage: tank [MODE] {FILE/ADDRESS}\n"); printf("\nmanual: tank man\n"); printf("macro: tank mac /dir/file\n"); printf("network: tank net 0.0.0.0 /dir/file\n\n"); safe_exit(1); } else if (!strcmp(argv[1], "man")) { man_mode(); } else if (!strcmp(argv[1], "mac")) { if (argc < 3) { printf("No file specified.\n"); safe_exit(1); } mac_mode(argv[2]); } else if (!strcmp(argv[1], "net")) { if (argc < 3) { printf("No address specified.\n"); safe_exit(1); } net_mode(argv[2]); } else { printf("ERROR: '%s' is unknown argument\n",argv[1]); printf("give no argument to see usage information\n"); safe_exit(1); } outb(0,BASEPORT); /* safe to turn switch off */ safe_exit(0); }
/* This'll allocate memory or die. */ char *safe_strdup(const char *s) { char *p; static int errflag = 0; if(errflag) safe_exit(10); if(s == NULL) p = strdup(""); else p = strdup(s); if(p != NULL) return p; errflag = 1; ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't alloc memory."); #ifdef ABORT_AT_FATAL abort(); #endif /* ABORT_AT_FATAL */ safe_exit(10); /*NOTREACHED*/ }
static void set_output(char *arg) { /* If single letter, it's the legacy output switch for AIX/HP/Sun. If longer, it's module[:device] . If zero length, it's rubbish. */ if(strlen(arg) <= 1) switch(arg[0]) { case 'h': set_output_h(arg); break; case 's': set_output_s(arg); break; case 'l': set_output_l(arg); break; default: error1("\"%s\" is no valid output", arg); safe_exit(1); } else set_output_module(arg); }
static void decode(const std::string & input_file, const std::string & output_file) { try { std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary); std::ifstream ifile(input_file.c_str(), std::ios_base::in | std::ios_base::binary); boost::iostreams::filtering_stream<boost::iostreams::input> stream; stream.push(filter()); stream.push(ifile); boost::iostreams::copy(stream, ofile); ifile.close(); safe_exit(remove(input_file.c_str())); } catch(filesystem::io_exception& e) { std::cerr << "IO error: " << e.what() << "\n"; } }
static void usage(int err) /* print syntax & exit */ { FILE* o = stdout; if(err) { o = stderr; fprintf(o, "You made some mistake in program usage... let me briefly remind you:\n\n"); } print_title(o); fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName); fprintf(o,"supported options [defaults in brackets]:\n"); fprintf(o," -v increase verbosity level -q quiet (don't print title)\n"); fprintf(o," -t testmode (no output) -s write to stdout\n"); fprintf(o," -w <filename> write Output as WAV file\n"); fprintf(o," -k n skip first n frames [0] -n n decode only n frames [all]\n"); fprintf(o," -c check range violations -y DISABLE resync on errors\n"); fprintf(o," -b n output buffer: n Kbytes [0] -f n change scalefactor [%li]\n", param.outscale); fprintf(o," -r n set/force samplerate [auto]\n"); fprintf(o," -os,-ol,-oh output to built-in speaker,line-out connector,headphones\n"); #ifdef NAS fprintf(o," -a d set NAS server\n"); #elif defined(SGI) fprintf(o," -a [1..4] set RAD device\n"); #else fprintf(o," -a d set audio device\n"); #endif fprintf(o," -2 downsample 1:2 (22 kHz) -4 downsample 1:4 (11 kHz)\n"); fprintf(o," -d n play every n'th frame only -h n play every frame n times\n"); fprintf(o," -0 decode channel 0 (left) only -1 decode channel 1 (right) only\n"); fprintf(o," -m mix both channels (mono) -p p use HTTP proxy p [$HTTP_PROXY]\n"); #ifdef HAVE_SCHED_SETSCHEDULER fprintf(o," -@ f read filenames/URLs from f -T get realtime priority\n"); #else fprintf(o," -@ f read filenames/URLs from f\n"); #endif fprintf(o," -z shuffle play (with wildcards) -Z random play\n"); fprintf(o," -u a HTTP authentication string -E f Equalizer, data from file\n"); #ifdef HAVE_TERMIOS fprintf(o," -C enable control keys --no-gapless not skip junk/padding in mp3s\n"); #else fprintf(o," --no-gapless not skip junk/padding in mp3s\n"); #endif fprintf(o," -? this help --version print name + version\n"); fprintf(o,"See the manpage %s(1) or call %s with --longhelp for more parameters and information.\n", prgName,prgName); safe_exit(err); }
int single_literal_encoding(){ try{ computeCodesAvailable(); if(singleLiteralEncoding(total) != 0){ safe_exit("Single-literal encoding failed."); return -1; } if (export_variables(single_literal) != 0){ safe_exit("Error exporting variables for external environment\ for single-literal encoding."); return -1; } synthesisSpaceSingleLiteral(); } catch(...) {
void error_call(void) { ALLEGRO_EVENT ev; ALLEGRO_KEYBOARD_STATE error_key_State; fprintf(stdout, "\n\r\n\rPress space to exit (with game window as focus)"); while(TRUE) { al_wait_for_event(event_queue, &ev); al_get_keyboard_state(&error_key_State); if(al_key_down(&error_key_State, ALLEGRO_KEY_ESCAPE) || al_key_down(&error_key_State, ALLEGRO_KEY_SPACE)) safe_exit(1); }; }
static void set_out_file(char *arg) { param.outmode=DECODE_FILE; #ifdef WIN32 #ifdef WANT_WIN32_UNICODE wchar_t *argw = NULL; OutputDescriptor = win32_utf8_wide(arg, &argw, NULL); if(argw != NULL) { OutputDescriptor=_wopen(argw,_O_CREAT|_O_WRONLY|_O_BINARY|_O_TRUNC,0666); free(argw); } #else OutputDescriptor=_open(arg,_O_CREAT|_O_WRONLY|_O_BINARY|_O_TRUNC,0666); #endif /*WANT_WIN32_UNICODE*/ #else /*WIN32*/ OutputDescriptor=open(arg,O_CREAT|O_WRONLY|O_TRUNC,0666); #endif /*WIN32*/ if(OutputDescriptor==-1) { error2("Can't open %s for writing (%s).\n",arg,strerror(errno)); safe_exit(1); } }
/* used primarily for taking contents of macro file */ void move_tank(char direc[], int time) { if (!strcmp(direc, "ff")) { forward(time); } else if (!strcmp(direc, "bb")) { backward(time); } else if (!strcmp(direc, "fr")) { foright(time); } else if (!strcmp(direc, "fl")) { foleft(time); } else if (!strcmp(direc, "br")) { baright(time); } else if (!strcmp(direc, "bl")) { baleft(time); } else if (!strcmp(direc, "ss")) { stop(time); } else { printf("ERROR: cannot move tank in that direction\n"); safe_exit(1); } } /* end move_tank function */
void sigINT_handler(int sig) { signal(sig, SIG_IGN); safe_exit(0); }
int main(int argc, char **argv) { pagekite_mgr m; unsigned int bail_on_errors = 0; unsigned int conn_eviction_idle_s = 0; char* proto; char* kitename; char* secret; char* lua_settings[MAX_PLUGIN_ARGS+1]; int lua_settingc = 0; int lua_no_defaults = 0; int gotargs = 0; int verbosity = 0; int use_ipv4 = 1; #ifdef HAVE_IPV6 int use_ipv6 = 1; #endif int use_current = 1; int use_ssl = 1; int use_fake_ping = 0; int use_watchdog = 0; int max_conns = 25; int spare_frontends = 0; char* fe_hostname = NULL; char* ddns_url = PAGEKITE_NET_DDNS; int ac; int pport; int lport; /* FIXME: Is this too lame? */ srand(time(0) ^ getpid()); while (-1 != (ac = getopt(argc, argv, "46c:B:CE:F:Io:Ln:qRSvWZ"))) { switch (ac) { case '4': use_ipv4 = 0; break; case '6': #ifdef HAVE_IPV6 use_ipv6 = 0; #endif break; case 'C': use_current = 0; break; case 'v': verbosity++; break; case 'q': verbosity--; break; case 'I': use_ssl = 0; break; case 'R': use_fake_ping = 1; break; case 'S': ddns_url = NULL; break; case 'W': use_watchdog = 1; break; case 'F': gotargs++; assert(fe_hostname == NULL); fe_hostname = strdup(optarg); break; case 'B': gotargs++; if (1 == sscanf(optarg, "%u", &bail_on_errors)) break; usage(EXIT_ERR_USAGE); case 'c': gotargs++; if (1 == sscanf(optarg, "%d", &max_conns)) break; usage(EXIT_ERR_USAGE); case 'E': gotargs++; if (1 == sscanf(optarg, "%u", &conn_eviction_idle_s)) break; usage(EXIT_ERR_USAGE); case 'o': if (lua_settingc >= MAX_PLUGIN_ARGS) usage(EXIT_ERR_USAGE); gotargs++; lua_settings[lua_settingc++] = strdup(optarg); break; case 'L': lua_no_defaults = 1; break; case 'n': gotargs++; if (1 == sscanf(optarg, "%d", &spare_frontends)) break; usage(EXIT_ERR_USAGE); default: usage(EXIT_ERR_USAGE); } gotargs++; } lua_settings[lua_settingc] = NULL; if ((argc-1-gotargs) < 5 || ((argc-1-gotargs) % 5) != 0) { usage(EXIT_ERR_USAGE); } #ifndef _MSC_VER signal(SIGUSR1, &raise_log_level); #endif int flags = 0; if (use_ssl) flags |= PK_WITH_SSL; if (use_ipv4) flags |= PK_WITH_IPV4; #ifdef HAVE_IPV6 if (use_ipv6) flags |= PK_WITH_IPV6; #endif if (NULL == (m = pagekite_init("pagekitec", 1 + (argc-1-gotargs)/5, /* Kites */ PAGEKITE_NET_FE_MAX, max_conns, ddns_url, flags, verbosity))) { pagekite_perror(m, argv[0]); safe_exit(EXIT_ERR_MANAGER_INIT); } /* Set all the parameters */ pagekite_want_spare_frontends(m, spare_frontends); pagekite_enable_watchdog(m, use_watchdog); pagekite_enable_fake_ping(m, use_fake_ping); pagekite_set_bail_on_errors(m, bail_on_errors); pagekite_set_conn_eviction_idle_s(m, conn_eviction_idle_s); pagekite_enable_lua_plugins(m, !lua_no_defaults, lua_settings); for (ac = gotargs; ac+5 < argc; ac += 5) { if ((1 != sscanf(argv[ac+1], "%d", &lport)) || (1 != sscanf(argv[ac+4], "%d", &pport))) { usage(EXIT_ERR_USAGE); } proto = argv[ac+2]; kitename = argv[ac+3]; secret = argv[ac+5]; if ((0 > pagekite_add_kite(m, proto, kitename, 0, secret, "localhost", lport)) || (use_current && (0 > (pagekite_add_frontend(m, kitename, pport))))) { pagekite_perror(m, argv[0]); safe_exit(EXIT_ERR_ADD_KITE); } } /* The API could do this stuff on INIT, but since we allow for manually specifying a front-end hostname, we do things by hand. */ if (fe_hostname) { if (0 > pagekite_add_frontend(m, fe_hostname, 443)) { pagekite_perror(m, argv[0]); safe_exit(EXIT_ERR_FRONTENDS); } } else if (ddns_url != NULL) { if (0 > pagekite_add_service_frontends(m, flags)) { pagekite_perror(m, argv[0]); safe_exit(EXIT_ERR_FRONTENDS); } } if (0 > pagekite_start(m)) { pagekite_perror(m, argv[0]); safe_exit(EXIT_ERR_START_THREAD); } pagekite_wait(m); pagekite_free(m); return 0; }
int main(int argc, char** argv) #endif { #ifdef HAVE_VISUAL_LEAK_DETECTOR VLDEnable(); #endif #ifdef _WIN32 (void)argc; (void)argv; //windows argv is ansi encoded by default std::vector<std::string> args = parse_commandline_arguments(unicode_cast<std::string>(std::wstring(GetCommandLineW()))); // HACK: we don't parse command line arguments using program_options until // the startup banner is printed. We need to get a console up and // running before then if requested, so just perform a trivial search // here and let program_options ignore the switch later. for(size_t k = 0; k < args.size(); ++k) { if(args[k] == "--wconsole" || args[k] == "--help" || args[k] == "--nogui" || args[k] == "--logdomains" || args[k] == "--path" || args[k] == "--render-image" || args[k] == "--screenshot" || args[k] == "--data-path" || args[k] == "--userdata-path" || args[k] == "--userconfig-path" || args[k] == "--version") { lg::enable_native_console_output(); break; } } lg::early_log_file_setup(); #else std::vector<std::string> args; for(int i = 0; i < argc; ++i) { args.push_back(std::string(argv[i])); } #endif assert(!args.empty()); #ifdef _OPENMP // Wesnoth is a special case for OMP // OMP wait strategy is to have threads busy-loop for 100ms // if there is nothing to do, they then go to sleep. // this avoids the scheduler putting the thread to sleep when work // is about to be available // // However Wesnoth has a lot of very small jobs that need to be done // at each redraw => 50fps every 2ms. // All the threads are thus busy-waiting all the time, hogging the CPU // To avoid that problem, we need to set the OMP_WAIT_POLICY env var // but that var is read by OMP at library loading time (before main) // thus the relaunching of ourselves after setting the variable. #if !defined(_WIN32) && !defined(__APPLE__) if (!getenv("OMP_WAIT_POLICY")) { setenv("OMP_WAIT_POLICY", "PASSIVE", 1); execv(argv[0], argv); } #elif _MSC_VER >= 1600 if (!getenv("OMP_WAIT_POLICY")) { _putenv_s("OMP_WAIT_POLICY", "PASSIVE"); args[0] = utils::quote(args[0]); restart_process(args); } #endif #endif //_OPENMP if(SDL_Init(SDL_INIT_TIMER) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); return(1); } #ifndef _WIN32 struct sigaction terminate_handler; terminate_handler.sa_handler = wesnoth_terminate_handler; terminate_handler.sa_flags = 0; sigemptyset(&terminate_handler.sa_mask); sigaction(SIGTERM, &terminate_handler, nullptr); sigaction(SIGINT, &terminate_handler, nullptr); #endif //declare this here so that it will always be at the front of the event queue. events::event_context global_context; try { std::cerr << "Battle for Wesnoth v" << game_config::revision << '\n'; const time_t t = time(nullptr); std::cerr << "Started on " << ctime(&t) << "\n"; const std::string& exe_dir = filesystem::get_exe_dir(); if(!exe_dir.empty()) { // Try to autodetect the location of the game data dir. Note that // the root of the source tree currently doubles as the data dir. std::string auto_dir; // scons leaves the resulting binaries at the root of the source // tree by default. if(filesystem::file_exists(exe_dir + "/data/_main.cfg")) { auto_dir = exe_dir; } // cmake encourages creating a subdir at the root of the source // tree for the build, and the resulting binaries are found in it. else if(filesystem::file_exists(exe_dir + "/../data/_main.cfg")) { auto_dir = filesystem::normalize_path(exe_dir + "/.."); } // In Windows debug builds, the EXE is placed away from the game data dir // (in projectfiles\VCx\Debug), but the working directory is set to the // game data dir. Thus, check if the working dir is the game data dir. else if(filesystem::file_exists(filesystem::get_cwd() + "/data/_main.cfg")) { auto_dir = filesystem::get_cwd(); } if(!auto_dir.empty()) { std::cerr << "Automatically found a possible data directory at " << auto_dir << '\n'; game_config::path = auto_dir; } } const int res = do_gameloop(args); safe_exit(res); } catch(boost::program_options::error& e) { std::cerr << "Error in command line: " << e.what() << '\n'; return 1; } catch(CVideo::error&) { std::cerr << "Could not initialize video. Exiting.\n"; return 1; } catch(font::manager::error&) { std::cerr << "Could not initialize fonts. Exiting.\n"; return 1; } catch(config::error& e) { std::cerr << e.message << "\n"; return 1; } catch(gui::button::error&) { std::cerr << "Could not create button: Image could not be found\n"; return 1; } catch(CVideo::quit&) { //just means the game should quit } catch(return_to_play_side_exception&) { std::cerr << "caught return_to_play_side_exception, please report this bug (quitting)\n"; } catch(quit_game_exception&) { std::cerr << "caught quit_game_exception (quitting)\n"; } catch(twml_exception& e) { std::cerr << "WML exception:\nUser message: " << e.user_message << "\nDev message: " << e.dev_message << '\n'; return 1; } catch(game_logic::formula_error& e) { std::cerr << e.what() << "\n\nGame will be aborted.\n"; return 1; } catch(const sdl::texception& e) { std::cerr << e.what(); return 1; } catch(game::error &) { // A message has already been displayed. return 1; } catch(std::bad_alloc&) { std::cerr << "Ran out of memory. Aborted.\n"; return ENOMEM; #if !defined(NO_CATCH_AT_GAME_END) } catch(std::exception & e) { // Try to catch unexpected exceptions. std::cerr << "Caught general exception:\n" << e.what() << std::endl; return 1; } catch(std::string & e) { std::cerr << "Caught a string thrown as an exception:\n" << e << std::endl; return 1; } catch(const char * e) { std::cerr << "Caught a string thrown as an exception:\n" << e << std::endl; return 1; } catch(...) { // Ensure that even when we terminate with `throw 42`, the exception // is caught and all destructors are actually called. (Apparently, // some compilers will simply terminate without calling destructors if // the exception isn't caught.) std::cerr << "Caught unspecified general exception. Terminating." << std::endl; return 1; #endif } return 0; } // end main
uint16_t transmitSerialData(void) { uint16_t i, res=0; int fd_flags=0; struct sigaction save_buffer[2]; fd_flags=fcntl(serialportFd, F_GETFL); fcntl(serialportFd, F_SETFL, O_RDWR | O_SYNC); // tcflush(serialportFd, TCIFLUSH); // tcflush(serialportFd, TCOFLUSH); // // if(tcsetattr(serialportFd, TCSANOW, &tp)<0) // { // perror("Couldn't set term attributes"); // return -1; // } sigaction(SIGALRM, NULL, save_buffer); setRTS(1); switch(mode) { case RADIOTFTP_MODE_UHF: usleep(RADIOTFTP_BIM2A_TX_PREDELAY); break; case RADIOTFTP_MODE_VHF: usleep(RADIOTFTP_UHX1_TX_PREDELAY); break; case RADIOTFTP_MODE_SERIAL: usleep(RADIOTFTP_SERIAL_TX_PREDELAY); break; default: perror("unknown baud rate"); safe_exit(-1); break; } { #if 0 res = write(serialportFd, transmit_buffer, transmit_length); #else printf("transmit_length=%d\n", transmit_length); srand(time(NULL)); for(i=0; i < transmit_length; i++) { double myFloatRandom=(((float) rand()) / (float) RAND_MAX); if(myFloatRandom < BYTE_ERROR_PROB) { printf("%f < %f [0x%02X]=", myFloatRandom, BYTE_ERROR_PROB, transmit_buffer[i]); transmit_buffer[i]^=0xFF; printf("[0x%02X]\n", transmit_buffer[i]); } res=write(serialportFd, transmit_buffer + i, 1); //fprintf(stdout, "%c", io[i]); // Potential preamble problem?? //usleep(10000); if(res < 0) { printf("serial write failed\n"); return -3; } } #endif if(res < 0) { return -2; } //wait for the buffer to be flushed tcdrain(serialportFd); switch(mode) { case RADIOTFTP_MODE_UHF: usleep(RADIOTFTP_BIM2A_TX_POSTDELAY); break; case RADIOTFTP_MODE_VHF: usleep(RADIOTFTP_UHX1_TX_POSTDELAY); break; case RADIOTFTP_MODE_SERIAL: usleep(RADIOTFTP_SERIAL_TX_POSTDELAY); break; default: perror("unknown baud rate"); safe_exit(-1); break; } } sigaction(SIGALRM, save_buffer, NULL); setRTS(0); fcntl(serialportFd, F_GETFL); fcntl(serialportFd, F_SETFL, fd_flags | O_RDWR | O_ASYNC); // print_time("data sent"); return 0; }
int main(int ac, char *av[]) { //TODO extract the serial port codes into another source file, this is too ugly! uint16_t i, j, len; int16_t res=0, result=0; uint8_t destination_ip[32]; uint8_t outbuf[512]; uint8_t linebuf[32]; uint8_t local_filename[32]="\0"; FILE* sptr; if(ac == 1) usage(); //for(i=0; i<ac; i++) // printf("%s\n",av[i]); if(!strcmp("uhf", av[1])) { mode=RADIOTFTP_MODE_UHF; preamble_length=RADIOTFTP_BIM2A_PREAMBLE_LENGTH; baud=RADIOTFTP_BIM2A_BAUD_RATE; printf("Running with UHF band 19200 baud version\n"); openLogFile(RADIOTFTP_BIM2A_EVENTLOG); } else if(!strcmp("vhf", av[1])) { mode=RADIOTFTP_MODE_VHF; preamble_length=RADIOTFTP_UHX1_PREAMBLE_LENGTH; baud=RADIOTFTP_UHX1_BAUD_RATE; printf("Running with VHF band 2400 baud version\n"); openLogFile(RADIOTFTP_UHX1_EVENTLOG); } else if(!strcmp("serial", av[1])) { mode=RADIOTFTP_MODE_SERIAL; preamble_length=RADIOTFTP_SERIAL_PREAMBLE_LENGTH; baud=RADIOTFTP_SERIAL_BAUD_RATE; printf("Couldn't understand the uhf/vhf mode: using %d mode\n", mode); printf("Running with NO BAND %d baud version\n", baud); printf("Opening file %s for logging\n",RADIOTFTP_SERIAL_EVENTLOG); openLogFile(RADIOTFTP_SERIAL_EVENTLOG); } else { printf("Mode not entered, exiting...\n"); return 0; } //setting defaults udp_get_broadcast_ip(destination_ip); strcpy(dial_tty, "/dev/ttyUSB0"); //scanning command line parameters for(i=2; (i < ac) && (av[i][0] == '-'); i++) { if(strcmp(av[i], "-b") == 0) { background=1; } else if(strncmp(av[i], "-f", 2) == 0) { strncpy(local_filename, av[i] + 2, 32); printf("different filename = '%s'\n", local_filename); } else if(strncmp(av[i], "-dst", 4) == 0) { memset(destination_ip, 0, 32); memcpy(destination_ip, av[i] + 4, strlen(av[i]) - 4); /*! convert text ip to numerical */ text_to_ip(destination_ip, strlen(av[i]) - 4 + 1); printf("Destination: "); print_addr_dec(destination_ip); } else { printf("unknown parameter: %s\n", av[i]); usage(); } } res=0; result=0; strncpy(dial_tty, devtag_get(av[i]), sizeof(dial_tty)); while(!get_lock(dial_tty)) { if(decrementLockRetries() == 0) exit(-1); sleep(1); } if((serialportFd=open(devtag_get(av[i]), O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) { perror("bad terminal device, try another"); exit(-1); } signal(SIGIO, SIG_IGN); signal(SIGINT, sigINT_handler); // Make the file descriptor asynchronous (the manual page says only // O_APPEND and O_NONBLOCK, will work with F_SETFL...) fcntl(serialportFd, F_GETFL); fcntl(serialportFd, F_SETFL, O_RDWR | O_SYNC); if(tcgetattr(serialportFd, &tp) < 0) { perror("Couldn't get term attributes"); exit(-1); } old=tp; /* SANE is a composite flag that sets the following parameters from termio(M): CREAD BRKINT IGNPAR ISTRIP ICRNL IXON ISIG ICANON ECHO ECHOK OPOST ONLCR SANE also clears the following modes: CLOCAL IGNBRK PARMRK INPCK INLCR IUCLC IXOFF XCASE ECHOE ECHONL NOFLSH OLCUC OCRNL ONOCR ONLRET OFILL OFDEL NLDLY CRDLY TABDLY BSDLY VTDLY FFDLY */ /* 8 bits + baud rate + local control */ tp.c_cflag=baud | CS8 | CLOCAL | CREAD; tp.c_cflag&=~PARENB; tp.c_cflag&=~CSTOPB; tp.c_cflag&=~CSIZE; tp.c_cflag|=CS8; tp.c_cflag|=CRTSCTS; tp.c_oflag=0; /* Raw Input */ tp.c_lflag=0; /* No conoical */ tp.c_cc[VTIME]=0; tp.c_cc[VMIN]=1; /* ignore CR, ignore parity */ //ISTRIP is a dangerous flag, it strips the 8th bit of bytes //tp.c_iflag= ~( ISTRIP ) | IGNPAR | IGNBRK; tp.c_iflag=~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IUCLC | IXOFF) | BRKINT | IGNPAR | ICRNL | IXON | ISIG | ICANON; /* set output and input baud rates */ cfsetospeed(&tp, baud); cfsetispeed(&tp, baud); tcflush(serialportFd, TCIFLUSH); tcflush(serialportFd, TCOFLUSH); if(tcsetattr(serialportFd, TCSANOW, &tp) < 0) { perror("Couldn't set term attributes"); goto error; } restore=1; //TODO go over the background codes if(background) { int i; if(getppid() == 1) return 0; /* Already a daemon */ i=fork(); if(i < 0) exit(1); /* error */ if(i > 0) _exit(0); /* parent exits */ /* child */ setsid(); /* obtain a new process group */ for(i=getdtablesize(); i >= 0; --i) { if(i == serialportFd) continue; if(i == 1) continue; close(i); /* close all descriptors */ } i=open("/dev/null", O_RDWR); dup(i); dup(i); /* handle standard I/O */ umask(027); /* set newly created file permissions */ chdir("/"); /* change running directory */ } srand((unsigned) time(NULL)); j=0; i++; for(; i < ac; i++) { len=strlen(av[i]); memcpy(command_buffer + j, av[i], len); j+=len; if(i != ac - 1) { command_buffer[j++]=' '; } } //process the escape characters for(i=0; i < j; i++) { if(command_buffer[i] == '\\') { if(i + 1 < j) { if(command_buffer[i + 1] == 'n') { command_buffer[i]='\r'; command_buffer[i + 1]='\n'; } } } } timers_initialize(&sigRTALRM_handler); /*! read settings from radiotftp.conf file */ sptr=fopen("radiotftp.conf", "r"); if(sptr != NULL) { readnline(sptr, linebuf, 32); linebuf[6]=atoi(linebuf + 6); linebuf[8]=0; printf("AX.25 Callsign: "); print_callsign(linebuf); #if AX25_ENABLED==1 ax25_initialize_network(linebuf); printf("USING AX25 LINK LAYER!!!\n"); #else AX25_ENABLED==0 printf("NOT USING ANY LINK LAYER!!!\n"); #endif readnline(sptr, linebuf, 32); text_to_ip(linebuf, strlen(linebuf)); printf("IPv4 Address: "); print_addr_dec(linebuf); udp_initialize_ip_network(linebuf, &queueSerialData); } else { #if AX25_ENABLED==1 ax25_initialize_network(my_ax25_callsign); printf("AX.25 CALLSIGN = "); print_callsign(ax25_get_local_callsign(NULL)); #endif udp_initialize_ip_network(my_ip_address, &queueSerialData); printf("IPv4 Address = "); print_addr_dec(udp_get_localhost_ip(NULL)); } switch(mode) { case RADIOTFTP_MODE_UHF: tftp_initialize(udp_get_data_queuer_fptr(), RADIOTFTP_BIM2A_ACK_TIMEOUT_MIN, RADIOTFTP_BIM2A_ACK_TIMEOUT_MAX, RADIOTFTP_BIM2A_READ_TIMEOUT); break; case RADIOTFTP_MODE_VHF: tftp_initialize(udp_get_data_queuer_fptr(), RADIOTFTP_UHX1_ACK_TIMEOUT_MIN, RADIOTFTP_UHX1_ACK_TIMEOUT_MAX, RADIOTFTP_UHX1_READ_TIMEOUT); break; case RADIOTFTP_MODE_SERIAL: tftp_initialize(udp_get_data_queuer_fptr(), RADIOTFTP_SERIAL_ACK_TIMEOUT_MIN, RADIOTFTP_SERIAL_ACK_TIMEOUT_MAX, RADIOTFTP_SERIAL_READ_TIMEOUT); break; default: perror("unknown baud rate"); safe_exit(-1); break; } if(!strncasecmp(RADIOTFTP_COMMAND_PUT, command_buffer, strlen(RADIOTFTP_COMMAND_PUT))) { printf(RADIOTFTP_COMMAND_PUT"\n"); registerEvent(RADIOTFTP_COMMAND_PUT, command_buffer + strlen(RADIOTFTP_COMMAND_PUT) + 1); if((res=tftp_sendRequest(TFTP_OPCODE_WRQ, destination_ip, local_filename, command_buffer + strlen(RADIOTFTP_COMMAND_PUT) + 1, j - strlen(RADIOTFTP_COMMAND_PUT) - 1, 0))) { printf("%d\n", res); perror("tftp request fail"); goto error; } } else if(!strncasecmp(RADIOTFTP_COMMAND_BEACON, command_buffer, strlen(RADIOTFTP_COMMAND_BEACON))) { printf(RADIOTFTP_COMMAND_BEACON"\n"); registerEvent(RADIOTFTP_COMMAND_BEACON, command_buffer + strlen(RADIOTFTP_COMMAND_BEACON) + 1); if((res=tftp_sendSingleBlockData(destination_ip, command_buffer + strlen(RADIOTFTP_COMMAND_BEACON) + 1, j - strlen(RADIOTFTP_COMMAND_BEACON) - 1, local_filename))) { printf("%d\n", res); perror("tftp request fail"); goto error; } } else if(!strncasecmp(RADIOTFTP_COMMAND_APPEND_LINE, command_buffer, strlen(RADIOTFTP_COMMAND_APPEND_LINE))) { printf(RADIOTFTP_COMMAND_APPEND_LINE"\n"); registerEvent(RADIOTFTP_COMMAND_APPEND_LINE, command_buffer + strlen(RADIOTFTP_COMMAND_APPEND_LINE) + 1); i=createTempFile(TEMPFILE_PREFIX, TEMPFILE_POSTFIX); if(tempFile == NULL) { perror("couldn't create temp file to store the line feed"); goto error; } fwrite(command_buffer + strlen(RADIOTFTP_COMMAND_APPEND_LINE) + 1, 1, j - strlen(RADIOTFTP_COMMAND_APPEND_LINE) - 1, tempFile); fflush(tempFile); fclose(tempFile); printf("tempfileName=%s\nlocal_filename=%s\n", tempFileName, local_filename); if((res=tftp_sendRequest(TFTP_OPCODE_WRQ, destination_ip, tempFileName, local_filename, strlen(local_filename), 1))) { printf("%d\n", res); perror("tftp request fail"); goto error; } } else if(!strncasecmp(RADIOTFTP_COMMAND_APPEND_FILE, command_buffer, strlen(RADIOTFTP_COMMAND_APPEND_FILE))) { printf(RADIOTFTP_COMMAND_APPEND_FILE"\n"); registerEvent(RADIOTFTP_COMMAND_APPEND_FILE, command_buffer + strlen(RADIOTFTP_COMMAND_APPEND_FILE) + 1); if((res=tftp_sendRequest(TFTP_OPCODE_WRQ, destination_ip, local_filename, command_buffer + strlen(RADIOTFTP_COMMAND_APPEND_FILE) + 1, j - strlen(RADIOTFTP_COMMAND_APPEND_FILE) - 1, 1))) { printf("%d\n", res); perror("tftp request fail"); goto error; } } else if(!strncasecmp(RADIOTFTP_COMMAND_GET, command_buffer, strlen(RADIOTFTP_COMMAND_GET))) { printf(RADIOTFTP_COMMAND_GET"\n"); registerEvent(RADIOTFTP_COMMAND_GET, command_buffer + strlen(RADIOTFTP_COMMAND_GET) + 1); if((res=tftp_sendRequest(TFTP_OPCODE_RRQ, destination_ip, local_filename, command_buffer + strlen(RADIOTFTP_COMMAND_GET) + 1, j - strlen(RADIOTFTP_COMMAND_GET) - 1, 0))) { printf("%d\n", res); perror("tftp request fail"); goto error; } } else { printf("hello radio world!\n"); registerEvent("helloWorld", ""); if((res=queueSerialData(udp_get_localhost_ip(NULL), HELLO_WORLD_PORT, udp_get_broadcast_ip(NULL), HELLO_WORLD_PORT, "hello world\n\0x00", strlen("hello world\n\0x00")))) { printf("%d\n", res); perror("tftp request fail"); goto error; } } int sync_counter=0; int sync_passed=0; int save_index=0; //entering the main while loop printf("started listening...\n"); while(1) { if(timer_flag) { idle_timer_handler(); tftp_timer_handler(); timer_flag=0; } if(idle_flag) { //print_time("System Idle"); idle_flag=0; } if(queue_flag) { // printf("queue flag\n"); if(!sync_passed && sync_counter < 1) { //wait_some switch(mode) { case RADIOTFTP_MODE_UHF: usleep(RADIOTFTP_BIM2A_TX_MESSAGE_INTERVAL); break; case RADIOTFTP_MODE_VHF: usleep(RADIOTFTP_UHX1_TX_MESSAGE_INTERVAL); break; case RADIOTFTP_MODE_SERIAL: usleep(RADIOTFTP_SERIAL_TX_MESSAGE_INTERVAL); break; default: perror("unknown baud rate"); safe_exit(-1); break; } transmitSerialData(); queue_flag=0; } } if((res=read(serialportFd, io, IO_BUFSIZE)) > 0) { io_index=0; //printf("# of bytes read = %d\n", res); for(i=0; i < res; i++) { //putchar(io[i]); //printf("%\n",io[i]); if(sync_counter < SYNC_LENGTH && io[i] == syncword[sync_counter]) { sync_counter++; /* sync continued */ //printf("sync counting %d\n",sync_counter); } else { //printf("sync reset %d\n",sync_counter); sync_counter=0; /* not a preamble, reset counter */ } if(sync_counter >= SYNC_LENGTH && sync_passed == 0) { /* preamble passed */ sync_passed=1; } if(sync_passed) { //printf("getting data '%c'\n", io[i]); if(io[i] == END_OF_FILE && !isManchester_encoded(io[i])) { // printf("non-manchester character received\n"); outbuf[0]=0; result=manchester_decode(buf + 1, manchester_buffer, save_index); #if AX25_ENABLED==1 result=ax25_open_ui_packet(NULL, NULL, ax25_buffer, manchester_buffer, result); #else result=1; #endif if(result) { // printf("opened link-layer packet\n"); #if AX25_ENABLED==1 result=udp_open_packet(udp_src, &udp_src_prt, udp_dst, &udp_dst_prt, udp_buffer, ax25_buffer); #else result = udp_open_packet(udp_src, &udp_src_prt, udp_dst, &udp_dst_prt, udp_buffer, manchester_buffer); #endif if(result) { // printf("opened transport-layer packet\n"); udp_packet_demultiplexer(udp_src, udp_src_prt, udp_dst, udp_dst_prt, udp_buffer, result); } else { strcat(outbuf, "!udp discarded!"); if(write(1, outbuf, strlen(outbuf)) <= 0) { fputs("couldn't write to tty\n", stderr); } if(write(1, "\n", 1) <= 0) { fputs("couldn't write to tty\n", stderr); } } } else { strcat(outbuf, "!ax25 discarded!"); if(write(1, outbuf, strlen(outbuf)) <= 0) { fputs("couldn't write to tty\n", stderr); } if(write(1, "\n", 1) <= 0) { fputs("couldn't write to tty\n", stderr); } } sync_passed=0; sync_counter=0; save_index=0; } else { // printf("saved data '%c'\n", io[i]); // printf("save_index=%d/%d\n",save_index, sizeof(buf)); if(save_index >= sizeof(buf)) { sync_passed=0; sync_counter=0; save_index=0; } buf[save_index++]=io[i]; buf[save_index + 1]=0; // printf("-\n%s\n-\n", buf); } } } io_flag=0; } } safe_exit(0); error: safe_exit(-1); return -2; }
/** * Setups the game environment and enters * the titlescreen or game loops. */ static int do_gameloop(const std::vector<std::string>& args) { srand(time(nullptr)); commandline_options cmdline_opts = commandline_options(args); game_config::wesnoth_program_dir = filesystem::directory_name(args[0]); int finished = process_command_args(cmdline_opts); if(finished != -1) { #ifdef _WIN32 if(lg::using_own_console()) { std::cerr << "Press enter to continue..." << std::endl; std::cin.get(); } #endif return finished; } const std::unique_ptr<game_launcher> game(new game_launcher(cmdline_opts, args[0].c_str())); const int start_ticks = SDL_GetTicks(); init_locale(); bool res; // Do initialize fonts before reading the game config, to have game // config error messages displayed. fonts will be re-initialized later // when the language is read from the game config. res = font::load_font_config(); if(res == false) { std::cerr << "could not initialize fonts\n"; // The most common symptom of a bogus data dir path -- warn the user. warn_early_init_failure(); return 1; } res = game->init_language(); if(res == false) { std::cerr << "could not initialize the language\n"; return 1; } res = game->init_video(); if(res == false) { std::cerr << "could not initialize display\n"; return 1; } res = image::update_from_preferences(); if(res == false) { std::cerr << "could not initialize image preferences\n"; return 1; } if(preferences::joystick_support_enabled()) { res = game->init_joystick(); if(res == false) { std::cerr << "could not initialize joystick\n"; } } check_fpu(); const cursor::manager cursor_manager; cursor::set(cursor::WAIT); #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32) SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); #endif gui2::init(); const gui2::event::manager gui_event_manager; game_config_manager config_manager(cmdline_opts, game->jump_to_editor()); gui2::dialogs::loading_screen::display([&res, &config_manager]() { gui2::dialogs::loading_screen::progress(loading_stage::load_config); res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD); if(res == false) { std::cerr << "could not initialize game config\n"; return; } gui2::dialogs::loading_screen::progress(loading_stage::init_fonts); res = font::load_font_config(); if(res == false) { std::cerr << "could not re-initialize fonts for the current language\n"; return; } gui2::dialogs::loading_screen::progress(loading_stage::refresh_addons); refresh_addon_version_info_cache(); }); if(res == false) { return 1; } LOG_CONFIG << "time elapsed: " << (SDL_GetTicks() - start_ticks) << " ms\n"; plugins_manager plugins_man(new application_lua_kernel); plugins_context::Reg const callbacks[] { {"play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::MP_CONNECT)}, }; plugins_context::aReg const accessors[] { {"command_line", std::bind(&commandline_options::to_config, &cmdline_opts)}, }; plugins_context plugins("titlescreen", callbacks, accessors); plugins.set_callback("exit", [](const config& cfg) { safe_exit(cfg["code"].to_int(0)); }, false); for(;;) { // reset the TC, since a game can modify it, and it may be used // by images in add-ons or campaigns dialogs image::set_team_colors(); statistics::fresh_stats(); if(!game->is_loading()) { const config& cfg = config_manager.game_config().child("titlescreen_music"); if(cfg) { sound::play_music_repeatedly(game_config::title_music); for(const config& i : cfg.child_range("music")) { sound::play_music_config(i); } sound::commit_music_changes(); } else { sound::empty_playlist(); sound::stop_music(); } } handle_lua_script_args(&*game, cmdline_opts); plugins.play_slice(); plugins.play_slice(); if(cmdline_opts.unit_test) { if(cmdline_opts.timeout) { std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl; std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n" << std::endl; std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository." << std::endl; std::cerr << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n" << std::endl; } int worker_result = game->unit_test(); std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ") << ((worker_result == 3) ? "(INVALID REPLAY)" : "") << ((worker_result == 4) ? "(ERRORED REPLAY)" : "") << ": " << *cmdline_opts.unit_test << std::endl; return worker_result; } if(game->play_test() == false) { return 0; } if(game->play_screenshot_mode() == false) { return 0; } if(game->play_render_image_mode() == false) { return 0; } // Start directly a campaign if(game->goto_campaign() == false) { if(game->jump_to_campaign_id().empty()) continue; // Go to main menu else return 1; // we got an error starting the campaign from command line } // Start directly a multiplayer // Eventually with a specified server if(game->goto_multiplayer() == false) { continue; // Go to main menu } // Start directly a commandline multiplayer game if(game->play_multiplayer_commandline() == false) { return 0; } if(game->goto_editor() == false) { return 0; } preferences::load_hotkeys(); const font::floating_label_context label_manager; cursor::set(cursor::NORMAL); game_launcher::RELOAD_GAME_DATA should_reload = game_launcher::RELOAD_DATA; // If loading a game, skip the titlescreen entirely if(game->is_loading()) { if(!game->load_game()) { game->clear_loaded_game(); } game->launch_game(should_reload); continue; } gui2::dialogs::title_screen dlg(*game); /* * Quick explanation of the titlscreen loop: * * The dialog's redraw_background_ flag is initialized as true in the constructor, so the dialog will always * display at least once when this loop is executed. Each time it's opened, the aforementioned flag is set to * false, and any selection that results in leaving the dialog simply sets the window's retval and proceeds to * the appropriate action. * * Certain actions (such as window resizing) set the flag to true, which allows the dialog to reopen with any * layout changes such as those dictated by window resolution. */ while(dlg.get_retval() == gui2::dialogs::title_screen::REDRAW_BACKGROUND) { dlg.show(); } switch(dlg.get_retval()) { case gui2::dialogs::title_screen::QUIT_GAME: LOG_GENERAL << "quitting game...\n"; return 0; case gui2::dialogs::title_screen::MP_CONNECT: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_CONNECT)) { continue; } break; case gui2::dialogs::title_screen::MP_HOST: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_HOST)) { continue; } break; case gui2::dialogs::title_screen::MP_LOCAL: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_LOCAL)) { continue; } break; case gui2::dialogs::title_screen::RELOAD_GAME_DATA: gui2::dialogs::loading_screen::display([&config_manager]() { config_manager.reload_changed_game_config(); image::flush_cache(); }); break; case gui2::dialogs::title_screen::MAP_EDITOR: game->start_editor(); break; case gui2::dialogs::title_screen::SHOW_ABOUT: gui2::dialogs::end_credits::display(); break; case gui2::dialogs::title_screen::LAUNCH_GAME: game->launch_game(should_reload); break; case gui2::dialogs::title_screen::REDRAW_BACKGROUND: break; } } }
static void long_usage(int err) { char *enclist; FILE* o = stdout; if(err) { o = stderr; fprintf(o, "You made some mistake in program usage... let me remind you:\n\n"); } print_title(o); fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName); fprintf(o,"\ninput options\n\n"); fprintf(o," -k <n> --skip <n> skip n frames at beginning\n"); fprintf(o," --skip-id3v2 skip ID3v2 tags without parsing\n"); fprintf(o," -n --frames <n> play only <n> frames of every stream\n"); fprintf(o," --fuzzy Enable fuzzy seeks (guessing byte offsets or using approximate seek points from Xing TOC)\n"); fprintf(o," -y --no-resync DISABLES resync on error (--resync is deprecated)\n"); fprintf(o," -p <f> --proxy <f> set WWW proxy\n"); fprintf(o," -u --auth set auth values for HTTP access\n"); fprintf(o," --ignore-mime ignore HTTP MIME types (content-type)\n"); fprintf(o," --no-seekbuffer disable seek buffer\n"); fprintf(o," -@ <f> --list <f> play songs in playlist <f> (plain list, m3u, pls (shoutcast))\n"); fprintf(o," -l <n> --listentry <n> play nth title in playlist; show whole playlist for n < 0\n"); fprintf(o," --continue playlist continuation mode (see man page)\n"); fprintf(o," --loop <n> loop track(s) <n> times, < 0 means infinite loop (not with --random!)\n"); fprintf(o," --keep-open (--remote mode only) keep loaded file open after reaching end\n"); fprintf(o," --timeout <n> Timeout in seconds before declaring a stream dead (if <= 0, wait forever)\n"); fprintf(o," -z --shuffle shuffle song-list before playing\n"); fprintf(o," -Z --random full random play\n"); fprintf(o," --no-icy-meta Do not accept ICY meta data\n"); fprintf(o," -i --index index / scan through the track before playback\n"); fprintf(o," --index-size <n> change size of frame index\n"); fprintf(o," --preframes <n> number of frames to decode in advance after seeking (to keep layer 3 bit reservoir happy)\n"); fprintf(o," --resync-limit <n> Set number of bytes to search for valid MPEG data; <0 means search whole stream.\n"); fprintf(o," --streamdump <f> Dump a copy of input data (as read by libmpg123) to given file.\n"); fprintf(o," --icy-interval <n> Enforce ICY interval in bytes (for playing a stream dump.\n"); fprintf(o," --ignore-streamlength Ignore header info about length of MPEG streams."); fprintf(o,"\noutput/processing options\n\n"); fprintf(o," -o <o> --output <o> select audio output module\n"); fprintf(o," --list-modules list the available modules\n"); fprintf(o," -a <d> --audiodevice <d> select audio device\n"); fprintf(o," -s --stdout write raw audio to stdout (host native format)\n"); fprintf(o," -S --STDOUT play AND output stream (not implemented yet)\n"); fprintf(o," -w <f> --wav <f> write samples as WAV file in <f> (- is stdout)\n"); fprintf(o," --au <f> write samples as Sun AU file in <f> (- is stdout)\n"); fprintf(o," --cdr <f> write samples as raw CD audio file in <f> (- is stdout)\n"); fprintf(o," --reopen force close/open on audiodevice\n"); #ifdef OPT_MULTI fprintf(o," --cpu <string> set cpu optimization\n"); fprintf(o," --test-cpu list optimizations possible with cpu and exit\n"); fprintf(o," --list-cpu list builtin optimizations and exit\n"); #endif #ifdef OPT_3DNOW fprintf(o," --test-3dnow display result of 3DNow! autodetect and exit (obsoleted by --cpu)\n"); fprintf(o," --force-3dnow force use of 3DNow! optimized routine (obsoleted by --test-cpu)\n"); fprintf(o," --no-3dnow force use of floating-pointer routine (obsoleted by --cpu)\n"); #endif fprintf(o," -g --gain [DEPRECATED] set audio hardware output gain\n"); fprintf(o," -f <n> --scale <n> scale output samples (soft gain - based on 32768), default=%li)\n", param.outscale); fprintf(o," --rva-mix,\n"); fprintf(o," --rva-radio use RVA2/ReplayGain values for mix/radio mode\n"); fprintf(o," --rva-album,\n"); fprintf(o," --rva-audiophile use RVA2/ReplayGain values for album/audiophile mode\n"); fprintf(o," -0 --left --single0 play only left channel\n"); fprintf(o," -1 --right --single1 play only right channel\n"); fprintf(o," -m --mono --mix mix stereo to mono\n"); fprintf(o," --stereo duplicate mono channel\n"); fprintf(o," -r --rate force a specific audio output rate\n"); fprintf(o," -2 --2to1 2:1 downsampling\n"); fprintf(o," -4 --4to1 4:1 downsampling\n"); fprintf(o," --pitch <value> set hardware pitch (speedup/down, 0 is neutral; 0.05 is 5%%)\n"); fprintf(o," --8bit force 8 bit output\n"); fprintf(o," --float force floating point output (internal precision)\n"); audio_enclist(&enclist); fprintf(o," -e <c> --encoding <c> force a specific encoding (%s)\n", enclist != NULL ? enclist : "OOM!"); fprintf(o," -d n --doublespeed n play only every nth frame\n"); fprintf(o," -h n --halfspeed n play every frame n times\n"); fprintf(o," --equalizer exp.: scales freq. bands acrd. to 'equalizer.dat'\n"); fprintf(o," --gapless remove padding/junk on mp3s (best with Lame tag)\n"); fprintf(o," This is on by default when libmpg123 supports it.\n"); fprintf(o," --no-gapless disable gapless mode, not remove padding/junk\n"); fprintf(o," -D n --delay n insert a delay of n seconds before each track\n"); fprintf(o," -o h --headphones (aix/hp/sun) output on headphones\n"); fprintf(o," -o s --speaker (aix/hp/sun) output on speaker\n"); fprintf(o," -o l --lineout (aix/hp/sun) output to lineout\n"); #ifndef NOXFERMEM fprintf(o," -b <n> --buffer <n> set play buffer (\"output cache\")\n"); fprintf(o," --preload <value> fraction of buffer to fill before playback\n"); fprintf(o," --smooth keep buffer over track boundaries\n"); #endif fprintf(o,"\nmisc options\n\n"); fprintf(o," -t --test only decode, no output (benchmark)\n"); fprintf(o," -c --check count and display clipped samples\n"); fprintf(o," -v[*] --verbose increase verboselevel\n"); fprintf(o," -q --quiet quiet mode\n"); #ifdef HAVE_TERMIOS fprintf(o," -C --control enable terminal control keys\n"); fprintf(o," --ctrlusr1 <c> control key (characer) to map to SIGUSR1\n"); fprintf(o," (default is for stop/start)\n"); fprintf(o," --ctrlusr2 <c> control key (characer) to map to SIGUSR2\n"); fprintf(o," (default is for next track)\n"); #endif #ifndef GENERIC fprintf(o," --title set terminal title to filename\n"); #endif fprintf(o," --long-tag spacy id3 display with every item on a separate line\n"); fprintf(o," --lyrics show lyrics (from ID3v2 USLT frame)\n"); fprintf(o," --utf8 Regardless of environment, print metadata in UTF-8.\n"); fprintf(o," -R --remote generic remote interface\n"); fprintf(o," --remote-err force use of stderr for generic remote interface\n"); #ifdef FIFO fprintf(o," --fifo <path> open a FIFO at <path> for commands instead of stdin\n"); #endif #ifdef HAVE_SETPRIORITY fprintf(o," --aggressive tries to get higher priority (nice)\n"); #endif #if defined (HAVE_SCHED_SETSCHEDULER) || defined (HAVE_WINDOWS_H) fprintf(o," -T --realtime tries to get realtime priority\n"); #endif #ifdef HAVE_WINDOWS_H fprintf(o," --priority <n> use specified process priority\n"); fprintf(o," accepts -2 to 3 as integer arguments\n"); fprintf(o," -2 as idle, 0 as normal and 3 as realtime.\n"); #endif fprintf(o," -? --help give compact help\n"); fprintf(o," --longhelp give this long help listing\n"); fprintf(o," --version give name / version string\n"); fprintf(o,"\nSee the manpage %s(1) for more information.\n", prgName); safe_exit(err); }
static void give_version(char* arg) { fprintf(stdout, PACKAGE_NAME" "PACKAGE_VERSION"\n"); safe_exit(0); }
void init_sound(int camstate_rand_seed) { settings.sound_on = 1; // al_init_acodec_addon(); - shouldn't need this if (!al_install_audio() || !al_init_acodec_addon()) { fprintf(stdout, "\nAllegro audio installation failed. Starting without sound."); settings.sound_on = 0; return; } if (!al_reserve_samples(24)) { fprintf(stdout, "\nCould not set up Allegro audio voice/mixer. Starting without sound."); settings.sound_on = 0; return; } if (settings.option [OPTION_VOL_MUSIC] == 0 && settings.option [OPTION_VOL_EFFECT] == 0) { settings.sound_on = 0; return; } load_in_sample(SAMPLE_BLIP1, "data/sound/blip.wav"); load_in_sample(SAMPLE_BLIP2, "data/sound/blip2.wav"); load_in_sample(SAMPLE_BLIP3, "data/sound/blip3.wav"); load_in_sample(SAMPLE_BLIP4, "data/sound/blip4.wav"); load_in_sample(SAMPLE_KILL, "data/sound/kill.wav"); load_in_sample(SAMPLE_CHIRP, "data/sound/chirp.wav"); load_in_sample(SAMPLE_OVER, "data/sound/over.wav"); load_in_sample(SAMPLE_ALLOC, "data/sound/alloc.wav"); load_in_sample(SAMPLE_NEW, "data/sound/new.wav"); load_in_sample(SAMPLE_BANG, "data/sound/bang.wav"); load_in_sample(SAMPLE_BANG2, "data/sound/bang2.wav"); load_in_sample(SAMPLE_INT_UP, "data/sound/int_up.wav"); load_in_sample(SAMPLE_INT_BREAK, "data/sound/int_break.wav"); load_in_sample(SAMPLE_RESTORE, "data/sound/restore.wav"); load_in_sample(SAMPLE_STREAM1, "data/sound/stream1.wav"); load_in_sample(SAMPLE_STREAM2, "data/sound/stream2.wav"); load_in_sample(SAMPLE_ZAP, "data/sound/zap.wav"); load_in_sample(SAMPLE_SPIKE, "data/sound/spike.wav"); load_in_sample(SAMPLE_SLICE, "data/sound/slice.wav"); load_in_sample(SAMPLE_ULTRA, "data/sound/ultra.wav"); load_in_sample(SAMPLE_BUBBLE, "data/sound/bubble.wav"); load_in_sample(SAMPLE_DRUM1, "data/sound/music/drum1.wav"); load_in_sample(SAMPLE_DRUM2, "data/sound/music/drum2.wav"); load_in_sample(SAMPLE_DRUM3, "data/sound/music/drum3.wav"); load_in_sample(SAMPLE_CLICK, "data/sound/music/click.wav"); load_in_sample(SAMPLE_THUMP, "data/sound/music/thump.wav"); // load_in_msample(MSAMPLE_NOTE, "data/sound/amb/note.wav"); // load_in_msample(MSAMPLE_NOTE2, "data/sound/amb/note_harm.wav"); // load_in_msample(MSAMPLE_NOTE3, "data/sound/amb/note_sine.wav"); // load_in_msample(MSAMPLE_NOTE4, "data/sound/amb/note_sq.wav"); // load_in_amb_sample(AMB_WARBLE, "sound/amb/warble.wav"); // load_in_amb_sample(AMB_NOTE, "sound/amb/note.wav"); //al_stop_samples(); build_tone_array(); sound_config.music_volume = settings.option [OPTION_VOL_MUSIC] * 0.01; sound_config.effect_volume = settings.option [OPTION_VOL_EFFECT] * 0.01; sound_timer = al_create_timer(0.22); // 0.20 if (!sound_timer) { fprintf(stdout, "\nError: failed to create sound timer."); safe_exit(-1); } al_start_timer(sound_timer); al_init_user_event_source(&sound_event_source); sound_queue = al_create_event_queue(); al_register_event_source(sound_queue, &sound_event_source); al_register_event_source(sound_queue, al_get_timer_event_source(sound_timer)); sound_event.user.type = ALLEGRO_GET_EVENT_TYPE(1, 0, 4, 0); sthread_init_sample_pointers(); if (settings.option [OPTION_VOL_MUSIC] != 0) init_camstate(-1, 1, 0, camstate_rand_seed); // this is usually only called from within the sound thread // but can be called here because the sound thread hasn't been started yet. // -1 means start new music else init_camstate(-2, 0, 0, 0); // -2 means turn the music off sound_thread = al_create_thread(thread_check_sound_queue, NULL); al_start_thread(sound_thread); started_sound_thread = 1; }
void boot_dynamic_text(void) { DIR *dir; struct dirent *dirp; dynamic_text_file *newdyn = NULL; dynamic_text_file_save savedyn; unsigned int i; if (!(dir = opendir(DYN_TEXT_CONTROL_DIR))) { errlog("Cannot open dynamic text control dir."); safe_exit(1); } while ((dirp = readdir(dir))) { size_t br; if ((strlen(dirp->d_name) < 4) || strcmp(dirp->d_name + strlen(dirp->d_name) - 4, ".dyn") != 0) { continue; } char *path = tmp_sprintf("%s/%s", DYN_TEXT_CONTROL_DIR, dirp->d_name); FILE *fl = fopen(path, "r"); if (fl == NULL) { errlog("error opening dynamic control file '%s'.", path); perror("fopen:"); continue; } CREATE(newdyn, dynamic_text_file, 1); if (newdyn == NULL) { errlog("error allocating dynamic control block, aborting."); closedir(dir); fclose(fl); return; } br = fread(&savedyn, sizeof(dynamic_text_file_save), 1, fl); if (br == 0) { errlog("error reading information from '%s'.", path); free(newdyn); fclose(fl); continue; } fclose(fl); strcpy_s(newdyn->filename, sizeof(newdyn->filename), savedyn.filename); for (i = 0; i < DYN_TEXT_HIST_SIZE; i++) { newdyn->last_edit[i].idnum = savedyn.last_edit[i].idnum; newdyn->last_edit[i].tEdit = savedyn.last_edit[i].tEdit; } for (i = 0; i < DYN_TEXT_PERM_SIZE; i++) newdyn->perms[i] = savedyn.perms[i]; newdyn->level = savedyn.level; newdyn->lock = 0; newdyn->next = NULL; newdyn->buffer = NULL; newdyn->tmp_buffer = NULL; if (load_dyntext_buffer(newdyn) == 0) { slog("dyntext BOOTED %s.", dirp->d_name); } else { errlog("dyntext FAILED TO BOOT %s.", dirp->d_name); } newdyn->next = dyntext_list; dyntext_list = newdyn; } closedir(dir); }
int main(int sys_argc, char ** sys_argv) { int result; char end_of_files = FALSE; long parr; char *fname; int libpar = 0; mpg123_pars *mp; #if !defined(WIN32) && !defined(GENERIC) struct timeval start_time; #endif aux_out = stdout; /* Need to initialize here because stdout is not a constant?! */ #if defined (WANT_WIN32_UNICODE) if(win32_cmdline_utf8(&argc, &argv) != 0) { error("Cannot convert command line to UTF8!"); safe_exit(76); } #else argv = sys_argv; argc = sys_argc; #endif #if defined (WANT_WIN32_SOCKETS) win32_net_init(); #endif /* Extract binary and path, take stuff before/after last / or \ . */ if((prgName = strrchr(argv[0], '/')) || (prgName = strrchr(argv[0], '\\'))) { /* There is some explicit path. */ prgName[0] = 0; /* End byte for path. */ prgName++; binpath = argv[0]; } else { prgName = argv[0]; /* No path separators there. */ binpath = NULL; /* No path at all. */ } /* Need to initialize mpg123 lib here for default parameter values. */ result = mpg123_init(); if(result != MPG123_OK) { error1("Cannot initialize mpg123 library: %s", mpg123_plain_strerror(result)); safe_exit(77); } cleanup_mpg123 = TRUE; mp = mpg123_new_pars(&result); /* This may get leaked on premature exit(), which is mainly a cosmetic issue... */ if(mp == NULL) { error1("Crap! Cannot get mpg123 parameters: %s", mpg123_plain_strerror(result)); safe_exit(78); } /* get default values */ mpg123_getpar(mp, MPG123_DOWN_SAMPLE, &parr, NULL); param.down_sample = (int) parr; mpg123_getpar(mp, MPG123_RVA, ¶m.rva, NULL); mpg123_getpar(mp, MPG123_DOWNSPEED, ¶m.halfspeed, NULL); mpg123_getpar(mp, MPG123_UPSPEED, ¶m.doublespeed, NULL); mpg123_getpar(mp, MPG123_OUTSCALE, ¶m.outscale, NULL); mpg123_getpar(mp, MPG123_FLAGS, &parr, NULL); mpg123_getpar(mp, MPG123_INDEX_SIZE, ¶m.index_size, NULL); param.flags = (int) parr; param.flags |= MPG123_SEEKBUFFER; /* Default on, for HTTP streams. */ mpg123_getpar(mp, MPG123_RESYNC_LIMIT, ¶m.resync_limit, NULL); mpg123_getpar(mp, MPG123_PREFRAMES, ¶m.preframes, NULL); #ifdef OS2 _wildcard(&argc,&argv); #endif while ((result = getlopt(argc, argv, opts))) switch (result) { case GLO_UNKNOWN: fprintf (stderr, "%s: Unknown option \"%s\".\n", prgName, loptarg); usage(1); case GLO_NOARG: fprintf (stderr, "%s: Missing argument for option \"%s\".\n", prgName, loptarg); usage(1); } /* Do this _after_ parameter parsing. */ check_locale(); /* Check/set locale; store if it uses UTF-8. */ if(param.list_cpu) { const char **all_dec = mpg123_decoders(); printf("Builtin decoders:"); while(*all_dec != NULL){ printf(" %s", *all_dec); ++all_dec; } printf("\n"); mpg123_delete_pars(mp); return 0; } if(param.test_cpu) { const char **all_dec = mpg123_supported_decoders(); printf("Supported decoders:"); while(*all_dec != NULL){ printf(" %s", *all_dec); ++all_dec; } printf("\n"); mpg123_delete_pars(mp); return 0; } if(param.gain != -1) { warning("The parameter -g is deprecated and may be removed in the future."); } if (loptind >= argc && !param.listname && !param.remote) usage(1); /* Init audio as early as possible. If there is the buffer process to be spawned, it shouldn't carry the mpg123_handle with it. */ bufferblock = mpg123_safe_buffer(); /* Can call that before mpg123_init(), it's stateless. */ if(init_output(&ao) < 0) { error("Failed to initialize output, goodbye."); mpg123_delete_pars(mp); return 99; /* It's safe here... nothing nasty happened yet. */ } have_output = TRUE; /* ========================================================================================================= */ /* Enterning the leaking zone... we start messing with stuff here that should be taken care of when leaving. */ /* Don't just exit() or return out... */ /* ========================================================================================================= */ httpdata_init(&htd); #if !defined(WIN32) && !defined(GENERIC) if (param.remote) { param.verbose = 0; param.quiet = 1; param.flags |= MPG123_QUIET; } #endif /* Set the frame parameters from command line options */ if(param.quiet) param.flags |= MPG123_QUIET; #ifdef OPT_3DNOW if(dnow != 0) param.cpu = (dnow == SET_3DNOW) ? "3dnow" : "i586"; #endif if(param.cpu != NULL && (!strcmp(param.cpu, "auto") || !strcmp(param.cpu, ""))) param.cpu = NULL; if(!( MPG123_OK == (result = mpg123_par(mp, MPG123_VERBOSE, param.verbose, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_FLAGS, param.flags, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_DOWN_SAMPLE, param.down_sample, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_RVA, param.rva, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_FORCE_RATE, param.force_rate, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_DOWNSPEED, param.halfspeed, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_UPSPEED, param.doublespeed, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_ICY_INTERVAL, 0, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_RESYNC_LIMIT, param.resync_limit, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_TIMEOUT, param.timeout, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_OUTSCALE, param.outscale, 0)) && ++libpar && MPG123_OK == (result = mpg123_par(mp, MPG123_PREFRAMES, param.preframes, 0)) )) { error2("Cannot set library parameter %i: %s", libpar, mpg123_plain_strerror(result)); safe_exit(45); } if (!(param.listentry < 0) && !param.quiet) print_title(stderr); /* do not pollute stdout! */ { long default_index; mpg123_getpar(mp, MPG123_INDEX_SIZE, &default_index, NULL); if( param.index_size != default_index && (result = mpg123_par(mp, MPG123_INDEX_SIZE, param.index_size, 0.)) != MPG123_OK ) error1("Setting of frame index size failed: %s", mpg123_plain_strerror(result)); } if(param.force_rate && param.down_sample) { error("Down sampling and fixed rate options not allowed together!"); safe_exit(1); } /* Now actually get an mpg123_handle. */ mh = mpg123_parnew(mp, param.cpu, &result); if(mh == NULL) { error1("Crap! Cannot get a mpg123 handle: %s", mpg123_plain_strerror(result)); safe_exit(77); } mpg123_delete_pars(mp); /* Don't need the parameters anymore ,they're in the handle now. */ /* Prepare stream dumping, possibly replacing mpg123 reader. */ if(dump_open(mh) != 0) safe_exit(78); /* Now either check caps myself or query buffer for that. */ audio_capabilities(ao, mh); load_equalizer(mh); #ifdef HAVE_SETPRIORITY if(param.aggressive) { /* tst */ int mypid = getpid(); setpriority(PRIO_PROCESS,mypid,-20); } #endif #if defined (HAVE_SCHED_SETSCHEDULER) && !defined (__CYGWIN__) && !defined (HAVE_WINDOWS_H) /* Cygwin --realtime seems to fail when accessing network, using win32 set priority instead */ /* MinGW may have pthread installed, we prefer win32API */ if (param.realtime) { /* Get real-time priority */ struct sched_param sp; fprintf(stderr,"Getting real-time priority\n"); memset(&sp, 0, sizeof(struct sched_param)); sp.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(0, SCHED_RR, &sp) == -1) fprintf(stderr,"Can't get real-time priority\n"); } #endif #ifdef HAVE_WINDOWS_H /* argument "3" is equivalent to realtime priority class */ win32_set_priority( param.realtime ? 3 : param.w32_priority); #endif if(!param.remote) prepare_playlist(argc, argv); #if !defined(WIN32) && !defined(GENERIC) /* Remote mode is special... but normal console and terminal-controlled operation needs to catch the SIGINT. For one it serves for track skip when not in terminal control mode. The more important use being a graceful exit, including telling the buffer process what's going on. */ if(!param.remote) catchsignal (SIGINT, catch_interrupt); #endif if(param.remote) { int ret; ret = control_generic(mh); safe_exit(ret); } #ifdef HAVE_TERMIOS debug1("param.term_ctrl: %i", param.term_ctrl); if(param.term_ctrl) term_init(); #endif if(APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number; while ((fname = get_next_file())) { char *dirname, *filename; int newdir; /* skip_tracks includes the previous one. */ if(skip_tracks) --skip_tracks; if(skip_tracks) { debug("Skipping this track."); continue; } if(param.delay > 0) { /* One should enable terminal control during that sleeping phase! */ if(param.verbose > 2) fprintf(stderr, "Note: pausing %i seconds before next track.\n", param.delay); output_pause(ao); #ifdef WIN32 Sleep(param.delay*1000); #else sleep(param.delay); #endif output_unpause(ao); } if(!APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number; debug1("Going to play %s", strcmp(fname, "-") ? fname : "standard input"); if(intflag || !open_track(fname)) { #ifdef HAVE_TERMIOS /* We need the opportunity to cancel in case of --loop -1 . */ if(param.term_ctrl) term_control(mh, ao); #endif /* No wait for a second interrupt before we started playing. */ if(intflag) break; continue; } if(!param.quiet) fprintf(stderr, "\n"); if(param.index) { if(param.verbose) fprintf(stderr, "indexing...\r"); mpg123_scan(mh); } /* Only trigger a seek if we do not want to start with the first frame. Rationale: Because of libmpg123 sample accuracy, this could cause an unnecessary backwards seek, that even may fail on non-seekable streams. For start frame of 0, we are already at the correct position! */ framenum = 0; if(param.start_frame > 0) framenum = mpg123_seek_frame(mh, param.start_frame, SEEK_SET); if(APPFLAG(MPG123APP_CONTINUE)) param.start_frame = 0; if(framenum < 0) { error1("Initial seek failed: %s", mpg123_strerror(mh)); if(mpg123_errcode(mh) == MPG123_BAD_OUTFORMAT) { fprintf(stderr, "%s", "So, you have trouble getting an output format... this is the matrix of currently possible formats:\n"); print_capabilities(ao, mh); fprintf(stderr, "%s", "Somehow the input data and your choices don't allow one of these.\n"); } mpg123_close(mh); continue; } /* Prinout and xterm title need this, possibly independently. */ newdir = split_dir_file(fname ? fname : "standard input", &dirname, &filename); if (!param.quiet) { if(newdir) fprintf(stderr, "Directory: %s\n", dirname); #ifdef HAVE_TERMIOS /* Reminder about terminal usage. */ if(param.term_ctrl) term_hint(); #endif fprintf(stderr, "Playing MPEG stream %lu of %lu: %s ...\n", (unsigned long)pl.pos, (unsigned long)pl.fill, filename); if(htd.icy_name.fill) fprintf(stderr, "ICY-NAME: %s\n", htd.icy_name.p); if(htd.icy_url.fill) fprintf(stderr, "ICY-URL: %s\n", htd.icy_url.p); } #if !defined(GENERIC) { const char *term_type; term_type = getenv("TERM"); if(term_type && param.xterm_title) { if(!strncmp(term_type,"xterm",5) || !strncmp(term_type,"rxvt",4)) fprintf(stderr, "\033]0;%s\007", filename); else if(!strncmp(term_type,"screen",6)) fprintf(stderr, "\033k%s\033\\", filename); else if(!strncmp(term_type,"iris-ansi",9)) fprintf(stderr, "\033P1.y %s\033\\\033P3.y%s\033\\", filename, filename); fflush(stderr); /* Paranoia: will the buffer buffer the escapes? */ } } #endif /* Rethink that SIGINT logic... */ #if !defined(WIN32) && !defined(GENERIC) #ifdef HAVE_TERMIOS if(!param.term_ctrl) #endif gettimeofday (&start_time, NULL); #endif while(!intflag) { int meta; if(param.frame_number > -1) { debug1("frames left: %li", (long) frames_left); if(!frames_left) { if(APPFLAG(MPG123APP_CONTINUE)) end_of_files = TRUE; break; } } if(!play_frame()) break; if(!param.quiet) { meta = mpg123_meta_check(mh); if(meta & (MPG123_NEW_ID3|MPG123_NEW_ICY)) { if(meta & MPG123_NEW_ID3) print_id3_tag(mh, param.long_id3, stderr); if(meta & MPG123_NEW_ICY) print_icy(mh, stderr); mpg123_meta_free(mh); /* Do not waste memory after delivering. */ } } if(!fresh && param.verbose) { #ifndef NOXFERMEM if (param.verbose > 1 || !(framenum & 0x7)) print_stat(mh,0,xfermem_get_usedspace(buffermem)); #else if(param.verbose > 1 || !(framenum & 0x7)) print_stat(mh,0,0); #endif } #ifdef HAVE_TERMIOS if(!param.term_ctrl) continue; else term_control(mh, ao); #endif } if(!param.smooth && param.usebuffer) buffer_drain(); if(param.verbose) print_stat(mh,0,xfermem_get_usedspace(buffermem)); if(!param.quiet) { double secs; long frank; fprintf(stderr, "\n"); if(mpg123_getstate(mh, MPG123_FRANKENSTEIN, &frank, NULL) == MPG123_OK && frank) fprintf(stderr, "This was a Frankenstein track.\n"); mpg123_position(mh, 0, 0, NULL, NULL, &secs, NULL); fprintf(stderr,"[%d:%02d] Decoding of %s finished.\n", (int)(secs / 60), ((int)secs) % 60, filename); } else if(param.verbose) fprintf(stderr, "\n"); mpg123_close(mh); if (intflag) { if(!skip_or_die(&start_time)) break; intflag = FALSE; #ifndef NOXFERMEM if(!param.smooth && param.usebuffer) buffer_resync(); #endif } if(end_of_files) break; } /* end of loop over input files */ /* Ensure we played everything. */ if(param.smooth && param.usebuffer) { buffer_drain(); buffer_resync(); } if(APPFLAG(MPG123APP_CONTINUE)) { continue_msg("CONTINUE"); } /* Free up memory used by playlist */ if(!param.remote) free_playlist(); safe_exit(0); /* That closes output and restores terminal, too. */ return 0; }