From 386c50d41ced23773f664984edeb159157d7967d Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 27 Jun 2010 10:08:58 +0000 Subject: [PATCH] SDL/non-Windows: external midi playing with fork/exec and signals; double initprintf internal buffers since they got too long for the --help text; warn on replacing empty tile with a hightile; fix a keypad issue in Mapster32 git-svn-id: https://svn.eduke32.com/eduke32@1663 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/src/hightile.c | 12 ++ polymer/eduke32/build/src/sdlayer.c | 6 +- polymer/eduke32/build/src/winlayer.c | 6 +- polymer/eduke32/source/astub.c | 4 +- polymer/eduke32/source/game.c | 4 +- polymer/eduke32/source/sdlmusic.c | 220 ++++++++++++++++++++++++--- 6 files changed, 224 insertions(+), 28 deletions(-) diff --git a/polymer/eduke32/build/src/hightile.c b/polymer/eduke32/build/src/hightile.c index 861be5a49..a3acff2f5 100644 --- a/polymer/eduke32/build/src/hightile.c +++ b/polymer/eduke32/build/src/hightile.c @@ -163,6 +163,18 @@ int32_t hicsetsubsttex(int32_t picnum, int32_t palnum, char *filen, float alphac hicreplc[picnum] = hrn; } + if (tilesizx[picnum]<=0 || tilesizy[picnum]<=0) + { + static int32_t first=1; + OSD_Printf("warning: defined hightile replacement for empty tile %d.", picnum); + if (first) + { + OSD_Printf(" Maybe some tiles???.art are not loaded?"); + first = 0; + } + OSD_Printf("\n"); + } + //printf("Replacement [%d,%d]: %s\n", picnum, palnum, hicreplc[i]->filename); return 0; diff --git a/polymer/eduke32/build/src/sdlayer.c b/polymer/eduke32/build/src/sdlayer.c index 9545fd861..a786290e4 100644 --- a/polymer/eduke32/build/src/sdlayer.c +++ b/polymer/eduke32/build/src/sdlayer.c @@ -355,11 +355,11 @@ void uninitsystem(void) void initprintf(const char *f, ...) { va_list va; - char buf[1024]; - static char dabuf[1024]; + char buf[2048]; + static char dabuf[2048]; va_start(va, f); - Bvsnprintf(buf, 1024, f, va); + Bvsnprintf(buf, sizeof(buf), f, va); va_end(va); OSD_Printf(buf); diff --git a/polymer/eduke32/build/src/winlayer.c b/polymer/eduke32/build/src/winlayer.c index bb4f58a50..ebc437469 100644 --- a/polymer/eduke32/build/src/winlayer.c +++ b/polymer/eduke32/build/src/winlayer.c @@ -667,11 +667,11 @@ void uninitsystem(void) void initprintf(const char *f, ...) { va_list va; - char buf[1024]; - static char dabuf[1024]; + char buf[2048]; + static char dabuf[2048]; va_start(va, f); - Bvsnprintf(buf, 1024, f, va); + Bvsnprintf(buf, sizeof(buf), f, va); va_end(va); OSD_Printf(buf); diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index fcc3e2b11..cde77d551 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -6587,9 +6587,9 @@ static void Keys2d(void) for (k=0; k<2; k++) // panning/repeat { if (k==0) - j = (keystatus[KEYSC_gLEFT]<<2)|keystatus[KEYSC_gRIGHT]; // 4 & 6 (keypad 2D) + j = (keystatus[KEYSC_gLEFT]<<1)|keystatus[KEYSC_gRIGHT]; // 4 & 6 (keypad 2D) else - j = (keystatus[KEYSC_gUP]<<2)|keystatus[KEYSC_gDOWN]; // 2 & 8 (keypad 2D) + j = (keystatus[KEYSC_gUP]<<1)|keystatus[KEYSC_gDOWN]; // 2 & 8 (keypad 2D) if (j) { diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index d251f8629..b566a2833 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -9551,7 +9551,7 @@ static void G_ShowParameterHelp(void) "\nSee eduke32 -debughelp for debug parameters" ; #if defined RENDERTYPEWIN - Bsprintf(tempbuf,HEAD2 " %s",s_buildDate); + Bsnprintf(tempbuf, sizeof(tempbuf), HEAD2 " %s", s_buildDate); wm_msgbox(tempbuf,s); #else initprintf("%s\n",s); @@ -9575,7 +9575,7 @@ static void G_ShowDebugHelp(void) "-z#/-condebug\tEnable line-by-line CON compile debugging at level #\n" ; #if defined RENDERTYPEWIN - Bsprintf(tempbuf,HEAD2 " %s",s_buildDate); + Bsnprintf(tempbuf, sizeof(tempbuf), HEAD2 " %s", s_buildDate); wm_msgbox(tempbuf,s); #else initprintf("%s\n",s); diff --git a/polymer/eduke32/source/sdlmusic.c b/polymer/eduke32/source/sdlmusic.c index 4747e848c..ab9e2a001 100644 --- a/polymer/eduke32/source/sdlmusic.c +++ b/polymer/eduke32/source/sdlmusic.c @@ -36,11 +36,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sdl_inc.h" #include "music.h" +#if !defined _WIN32 // fork/exec based external midi player +#include +#include +#include +#include +static char **external_midi_argv; +static pid_t external_midi_pid=-1; +static int8_t external_midi_restart=0; +#endif +static char *external_midi_tempfn = "/tmp/eduke32-music.mid"; +static int32_t external_midi = 0; + int32_t MUSIC_ErrorCode = MUSIC_Ok; static char warningMessage[80]; static char errorMessage[80]; -static int32_t external_midi = 0; static int32_t music_initialized = 0; static int32_t music_context = 0; @@ -106,6 +117,12 @@ int32_t MUSIC_Init(int32_t SoundCard, int32_t Address) char *command = getenv("EDUKE32_MUSIC_CMD"); const SDL_version *linked = Mix_Linked_Version(); + if (music_initialized) + { + setErrorMessage("Music system is already initialized."); + return(MUSIC_Error); + } // if + UNREFERENCED_PARAMETER(Address); if (SDL_VERSIONNUM(linked->major,linked->minor,linked->patch) < MIX_REQUIREDVERSION) { @@ -119,13 +136,89 @@ int32_t MUSIC_Init(int32_t SoundCard, int32_t Address) if (external_midi) { initprintf("Setting music command to `%s'.\n", command); + +#if defined _WIN32 if (Mix_SetMusicCMD(command)==-1) + { perror("Mix_SetMusicCMD"); + goto fallback; + } +#else + int32_t ws=1, numargs=0, pagesize=sysconf(_SC_PAGE_SIZE); + char *c, *cmd; + size_t sz; + + if (pagesize==-1) + goto fallback; + + for (c=command; *c; c++) + { + if (isspace(*c)) + ws = 1; + else if (ws) + { + ws = 0; + numargs++; + } + } + + if (numargs==0) + goto fallback; + + sz = (numargs+2)*sizeof(char *) + (c-command+1); + sz = ((sz+pagesize)/pagesize)*pagesize; + + external_midi_argv = memalign(pagesize, sz); + if (!external_midi_argv) + goto fallback; + + cmd = (char *)external_midi_argv + (numargs+2)*sizeof(char *); + Bmemcpy(cmd, command, c-command+1); + + ws = 1; + numargs = 0; + for (c=cmd; *c; c++) + { + if (isspace(*c)) + { + ws = 1; + *c = 0; + } + else if (ws) + { + ws = 0; + external_midi_argv[numargs++] = c; + } + } + external_midi_argv[numargs] = external_midi_tempfn; + external_midi_argv[numargs+1] = NULL; + + if (mprotect(external_midi_argv, sz, PROT_READ)==-1) // make argv and command string read-only + { + perror("MUSIC_Init: mprotect"); + goto fallback; + } +/* + { + int i; + initprintf("----Music argv:\n"); + for (i=0; i=0; i--) @@ -147,14 +240,7 @@ int32_t MUSIC_Init(int32_t SoundCard, int32_t Address) Bfclose(fp); } - if (music_initialized) - { - setErrorMessage("Music system is already initialized."); - return(MUSIC_Error); - } // if - SoundCard = 1; - music_initialized = 1; return(MUSIC_Ok); } // MUSIC_Init @@ -163,8 +249,10 @@ int32_t MUSIC_Init(int32_t SoundCard, int32_t Address) int32_t MUSIC_Shutdown(void) { // TODO - make sure this is being called from the menu -- SA +#if defined _WIN32 if (external_midi) Mix_SetMusicCMD(NULL); +#endif MUSIC_StopSong(); music_context = 0; @@ -232,9 +320,43 @@ void MUSIC_Pause(void) Mix_PauseMusic(); } // MUSIC_Pause - int32_t MUSIC_StopSong(void) { +#if !defined _WIN32 + if (external_midi) + { + if (external_midi_pid > 0) + { + int32_t ret; + + external_midi_restart = 0; // make SIGCHLD handler a no-op + + kill(external_midi_pid, SIGTERM); + nanosleep(&(const struct timespec){ .tv_sec=0, .tv_nsec=5000000 }, NULL); // sleep 5ms at most + ret = waitpid(external_midi_pid, NULL, WNOHANG|WUNTRACED); +// printf("(%d)", ret); + + if (ret != external_midi_pid) + { + if (ret==-1) + perror("waitpid"); + else + { + // we tried to be nice, but no... + kill(external_midi_pid, SIGKILL); + initprintf("%s: wait for SIGTERM timed out.\n", __func__); + if (waitpid(external_midi_pid, NULL, WUNTRACED)==-1) + perror("waitpid (2)"); + } + } + + external_midi_pid = -1; + } + + return(MUSIC_Ok); + } +#endif + //if (!fx_initialized) if (!Mix_QuerySpec(NULL, NULL, NULL)) { @@ -253,27 +375,89 @@ int32_t MUSIC_StopSong(void) return(MUSIC_Ok); } // MUSIC_StopSong +#if !defined _WIN32 +static void playmusic() +{ + pid_t pid = vfork(); + + if (pid==-1) // error + { + initprintf("%s: vfork: %s\n", __func__, strerror(errno)); + } + else if (pid==0) // child + { + // exec with PATH lookup + if (execvp(external_midi_argv[0], external_midi_argv) < 0) + { + perror("execv"); + _exit(1); + } + } + else // parent + { + external_midi_pid = pid; + } +} + +static void sigchld_handler(int signo) +{ + if (signo==SIGCHLD && external_midi_restart) + { + int status; + + if (waitpid(external_midi_pid, &status, WUNTRACED)==-1) + perror("waitpid (3)"); + + if (WIFEXITED(status) && WEXITSTATUS(status)==0) + { + // loop ... + playmusic(); + } + } +} +#endif + // Duke3D-specific. --ryan. // void MUSIC_PlayMusic(char *_filename) int32_t MUSIC_PlaySong(char *song, int32_t loopflag) { - static char *tempfn = "/tmp/eduke32-music.mid"; - FILE *fp; - MUSIC_StopSong(); if (external_midi) { - fp = Bfopen(tempfn, "wb"); + FILE *fp; + +#if !defined _WIN32 + static int32_t sigchld_handler_set = 0; + + if (!sigchld_handler_set) + { + struct sigaction sa = { .sa_handler=sigchld_handler, .sa_flags=0 }; + sigemptyset(&sa.sa_mask); + + if (sigaction(SIGCHLD, &sa, NULL)==-1) + initprintf("%s: sigaction: %s\n", __func__, strerror(errno)); + + sigchld_handler_set = 1; + } +#endif + + fp = Bfopen(external_midi_tempfn, "wb"); if (fp) { fwrite(song, 1, g_musicSize, fp); Bfclose(fp); - music_musicchunk = Mix_LoadMUS(tempfn); + +#if !defined _WIN32 + external_midi_restart = loopflag; + playmusic(); +#else + music_musicchunk = Mix_LoadMUS(external_midi_tempfn); if (!music_musicchunk) initprintf("Mix_LoadMUS: %s\n", Mix_GetError()); +#endif } - else initprintf("MUSIC_PlaySong: fopen: %s\n", strerror(errno)); + else initprintf("%s: fopen: %s\n", __func__, strerror(errno)); } else music_musicchunk = Mix_LoadMUS_RW(SDL_RWFromMem((char *) song, g_musicSize));