Commit 77a2ba41 authored by Jonathan Wilkes's avatar Jonathan Wilkes

Merge branch 'fix-pd-tilde'

parents dc10921a 18a305d6
Pipeline #1351 passed with stage
in 352 minutes and 30 seconds
......@@ -786,7 +786,7 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
ap++;
break;
case A_FLOAT:
if (!argc) goto badarg;
if (!argc) goto badarg; /* falls through */
case A_DEFFLOAT:
if (!argc) *dp = 0;
else
......@@ -814,7 +814,7 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
ap++;
break;
case A_SYMBOL:
if (!argc) goto badarg;
if (!argc) goto badarg; /* falls through */
case A_DEFSYM:
if (!argc) *ap = (t_int)(&s_);
else
......
......@@ -405,8 +405,6 @@ void sched_set_using_audio(int flag)
post("sorry, can't turn off callbacks yet; restart Pd");
/* not right yet! */
sys_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)sys_schedblocksize) / sys_dacsr;
// XXXFIXME
//sys_vgui("pdtk_pd_dsp %s\n", flag ? "on" : "off");
}
......@@ -414,7 +412,8 @@ void sched_set_using_audio(int flag)
/* take the scheduler forward one DSP tick, also handling clock timeouts */
void sched_tick( void)
{
double next_sys_time = pd_this->pd_systime + sys_time_per_dsp_tick;
double next_sys_time = pd_this->pd_systime +
(sys_schedblocksize / sys_dacsr) * TIMEUNITPERSECOND;
int countdown = 5000;
while (pd_this->pd_clock_setlist &&
pd_this->pd_clock_setlist->c_settime < next_sys_time)
......@@ -459,6 +458,7 @@ int (*sys_idlehook)(void);
static void m_pollingscheduler( void)
{
int idlecount = 0;
/* delete this when I'm sure it's not needed for back compatibilty? */
sys_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)sys_schedblocksize) / sys_dacsr;
......@@ -635,8 +635,6 @@ int m_mainloop(void)
int m_batchmain(void)
{
sys_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)sys_schedblocksize) / sys_dacsr;
while (sys_quit != SYS_QUIT_QUIT)
sched_tick();
return (0);
......
......@@ -291,12 +291,39 @@ void sys_setalarm(int microsec)
#endif
#ifdef __linux
void sys_setsignalhandlers(void)
{
#if !defined(_WIN32) && !defined(__CYGWIN__)
signal(SIGHUP, sys_huphandler);
signal(SIGINT, sys_exithandler);
signal(SIGQUIT, sys_exithandler);
signal(SIGILL, sys_exithandler);
# ifdef SIGIOT
signal(SIGIOT, sys_exithandler);
# endif
signal(SIGFPE, SIG_IGN);
/* signal(SIGILL, sys_exithandler);
signal(SIGBUS, sys_exithandler);
signal(SIGSEGV, sys_exithandler); */
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, SIG_IGN);
#if 0 /* GG says: don't use that */
signal(SIGSTKFLT, sys_exithandler);
#endif
#endif /* NOT _WIN32 && NOT __CYGWIN__ */
}
#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#if defined(_POSIX_PRIORITY_SCHEDULING) || defined(_POSIX_MEMLOCK)
#include <sched.h>
#endif
#define MODE_NRT 0
#define MODE_RT 1
#define MODE_WATCHDOG 2
void sys_set_priority(int higher)
{
#ifdef _POSIX_PRIORITY_SCHEDULING
......@@ -1204,10 +1231,6 @@ int sys_startgui(const char *guidir)
if (!getcwd(cwd, FILENAME_MAX))
strcpy(cwd, ".");
#endif
#ifdef MSW
short version = MAKEWORD(2, 0);
WSADATA nobby;
#endif
#ifdef HAVE_UNISTD_H
int stdinpipe[2];
#endif
......@@ -1215,27 +1238,6 @@ int sys_startgui(const char *guidir)
sys_fdpoll = (t_fdpoll *)t_getbytes(0);
sys_nfdpoll = 0;
inbinbuf = binbuf_new();
#ifdef HAVE_UNISTD_H
signal(SIGHUP, sys_huphandler);
signal(SIGINT, sys_exithandler);
signal(SIGQUIT, sys_exithandler);
signal(SIGILL, sys_exithandler);
signal(SIGIOT, sys_exithandler);
signal(SIGFPE, SIG_IGN);
/* signal(SIGILL, sys_exithandler);
signal(SIGBUS, sys_exithandler);
signal(SIGSEGV, sys_exithandler); */
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, SIG_IGN);
#if 0 /* GG says: don't use that */
signal(SIGSTKFLT, sys_exithandler);
#endif
#endif
#ifdef MSW
if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup");
#endif
if (sys_nogui)
{
/* fake the GUI's message giving cwd and font sizes; then
......@@ -1374,7 +1376,6 @@ int sys_startgui(const char *guidir)
/* this glob is needed so the Wish executable can have the same
* filename as the Pd.app, i.e. 'Pd-0.42-3.app' should have a Wish
* executable called 'Pd-0.42-3.app/Contents/MacOS/Pd-0.42-3' */
// sprintf(embed_glob, "%s/../../MacOS/Pd*", guidir);
sprintf(embed_glob, "%s/../../MacOS/nwjs", guidir);
glob_buffer.gl_matchc = 1; /* we only need one match */
glob(embed_glob, GLOB_LIMIT, NULL, &glob_buffer);
......@@ -1408,7 +1409,7 @@ int sys_startgui(const char *guidir)
use the nw binary and GUI code from your local
copy of the Purr Data repo. (Make sure to run
tar_em_up.sh first to fetch the nw binary.) */
//strcpy(guidir2, "\"/home/grieg/purr-data/pd/nw\"");
//strcpy(guidir2, "\"/home/user/purr-data/pd/nw\"");
sprintf(cmdbuf,
"\"%s\" %s %s "
"%d localhost %s %s " X_SPECIFIER,
......@@ -1449,7 +1450,7 @@ int sys_startgui(const char *guidir)
use the nw binary and GUI code from your local
copy of the Purr Data repo. (Make sure to run
tar_em_up.sh first to fetch the nw binary.) */
//strcpy(guidir2, "\"/home/grieg/purr-data/pd/nw\"");
//strcpy(guidir2, "\"/home/user/purr-data/pd/nw\"");
sprintf(cmdbuf,
"%s/nw/nw %s %s "
"%d localhost %s %s " X_SPECIFIER,
......@@ -1472,11 +1473,15 @@ int sys_startgui(const char *guidir)
{
if (errno) perror("sys_startgui");
else fprintf(stderr, "sys_startgui failed\n");
sys_closesocket(xsock);
return (1);
}
else if (!childpid) /* we're the child */
{
setuid(getuid()); /* lose setuid priveliges */
sys_closesocket(xsock); /* we're the child */
#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
sys_set_priority(MODE_NRT);
#endif
#ifndef __APPLE__
/* the wish process in Unix will make a wish shell and
read/write standard in and out unless we close the
......@@ -1548,23 +1553,101 @@ int sys_startgui(const char *guidir)
#endif /* MSW */
}
if (!sys_nogui && !sys_guisetportnumber)
{
if (sys_verbose)
fprintf(stderr, "Waiting for connection request... \n");
if (listen(xsock, 5) < 0) sys_sockerror("listen");
sys_guisock = accept(xsock, (struct sockaddr *) &server,
(socklen_t *)&len);
#ifdef OOPS
sys_closesocket(xsock);
#endif
if (sys_guisock < 0) sys_sockerror("accept");
if (sys_verbose)
fprintf(stderr, "... connected\n");
}
if (!sys_nogui)
{
char buf[256], buf2[256];
sys_socketreceiver = socketreceiver_new(0, 0, 0, 0);
sys_addpollfn(sys_guisock, (t_fdpollfn)socketreceiver_read,
sys_socketreceiver);
/* here is where we start the pinging. */
#if defined(__linux__) || defined(IRIX)
/* now that we've spun off the child process we can promote
our process's priority, if we can and want to. If not specfied
(-1), we assume real-time was wanted. Afterward, just in case
someone made Pd setuid in order to get permission to do this,
unset setuid and lose root priveliges after doing this. Starting
in Linux 2.6 this is accomplished by putting lines like:
if (sys_hipriority)
gui_vmess("gui_watchdog", "");
#endif
sys_get_audio_apis(buf);
sys_get_midi_apis(buf2);
t_binbuf *aapis = binbuf_new(), *mapis = binbuf_new();
sys_get_audio_apis2(aapis);
sys_get_midi_apis2(mapis);
gui_start_vmess("gui_startup", "sss",
pd_version,
sys_font,
sys_fontweight);
int i;
gui_start_array(); // audio apis
for (i = 0; i < binbuf_getnatom(aapis); i+=2)
{
gui_s(atom_getsymbol(binbuf_getvec(aapis)+i)->s_name);
gui_i(atom_getint(binbuf_getvec(aapis)+i+1));
}
gui_end_array();
gui_start_array(); // midi apis
for (i = 0; i < binbuf_getnatom(mapis); i+=2)
{
gui_s(atom_getsymbol(binbuf_getvec(mapis)+i)->s_name);
gui_i(atom_getint(binbuf_getvec(mapis)+i+1));
}
gui_end_array();
gui_end_vmess();
gui_vmess("gui_set_cwd", "xs", 0, cwd);
binbuf_free(aapis);
binbuf_free(mapis);
}
return (0);
}
void sys_setrealtime(const char *libdir)
{
char cmdbuf[MAXPDSTRING];
#if defined(__linux__) || defined(__FreeBSD_kernel__)
/* promote this process's priority, if we can and want to.
If sys_hipriority not specfied (-1), we assume real-time was wanted.
Starting in Linux 2.6 one can permit real-time operation of Pd by
putting lines like:
@audio - rtprio 99
@audio - memlock unlimited
in the system limits file, perhaps /etc/limits.conf or
/etc/security/limits.conf */
/etc/security/limits.conf, and calling Pd from a user in group audio. */
if (sys_hipriority == -1)
sys_hipriority = 1; //(!getuid() || !geteuid());
sys_hipriority = 1;
sprintf(cmdbuf, "%s/pd-watchdog\n", guidir);
snprintf(cmdbuf, MAXPDSTRING, "%s/bin/pd-watchdog", libdir);
cmdbuf[MAXPDSTRING-1] = 0;
if (sys_hipriority)
{
struct stat statbuf;
if (stat(cmdbuf, &statbuf) < 0)
{
fprintf(stderr,
"disabling real-time priority due to missing pd-watchdog (%s)\n",
cmdbuf);
sys_hipriority = 0;
}
}
if (sys_hipriority)
{
int pipe9[2], watchpid;
/* To prevent lockup, we fork off a watchdog process with
higher real-time priority than ours. The GUI has to send
a stream of ping messages to the watchdog THROUGH the Pd
......@@ -1574,27 +1657,23 @@ int sys_startgui(const char *guidir)
to make it timeshare with the rest of the system. (Version
0.33P2 : if there's no GUI, the watchdog pinging is done
from the scheduler idle routine in this process instead.) */
int pipe9[2], watchpid;
if (pipe(pipe9) < 0)
{
setuid(getuid()); /* lose setuid priveliges */
sys_sockerror("pipe");
return (1);
return;
}
watchpid = fork();
if (watchpid < 0)
{
setuid(getuid()); /* lose setuid priveliges */
if (errno)
perror("sys_startgui");
else fprintf(stderr, "sys_startgui failed\n");
return (1);
perror("sys_setpriority");
else fprintf(stderr, "sys_setpriority failed\n");
return;
}
else if (!watchpid) /* we're the child */
{
sys_set_priority(1);
setuid(getuid()); /* lose setuid priveliges */
sys_set_priority(MODE_WATCHDOG);
if (pipe9[1] != 0)
{
dup2(pipe9[0], 0);
......@@ -1602,26 +1681,31 @@ int sys_startgui(const char *guidir)
}
close(pipe9[1]);
if (sys_verbose) fprintf(stderr, "%s", cmdbuf);
if (sys_verbose) fprintf(stderr, "%s\n", cmdbuf);
execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0);
perror("pd: exec");
_exit(1);
}
else /* we're the parent */
{
sys_set_priority(0);
setuid(getuid()); /* lose setuid priveliges */
sys_set_priority(MODE_RT);
close(pipe9[0]);
/* set close-on-exec so that watchdog will see an EOF when we
close our copy - otherwise it might hang waiting for some
stupid child process (as seems to happen if jackd auto-starts
for us.) */
if(fcntl(pipe9[1], F_SETFD, FD_CLOEXEC) < 0)
perror("close-on-exec");
sys_watchfd = pipe9[1];
/* We also have to start the ping loop in the GUI;
this is done later when the socket is open. */
}
}
setuid(getuid()); /* lose setuid priveliges */
else if (sys_verbose)
post("not setting real-time priority");
#endif /* __linux__ */
#ifdef MSW
#ifdef _WIN32
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
fprintf(stderr, "pd: couldn't set high priority class\n");
#endif
......@@ -1638,71 +1722,6 @@ int sys_startgui(const char *guidir)
post("warning: high priority scheduling failed\n");
}
#endif /* __APPLE__ */
if (!sys_nogui && !sys_guisetportnumber)
{
if (sys_verbose)
fprintf(stderr, "Waiting for connection request... \n");
if (listen(xsock, 5) < 0) sys_sockerror("listen");
sys_guisock = accept(xsock, (struct sockaddr *) &server,
(socklen_t *)&len);
#ifdef OOPS
sys_closesocket(xsock);
#endif
if (sys_guisock < 0) sys_sockerror("accept");
if (sys_verbose)
fprintf(stderr, "... connected\n");
}
if (!sys_nogui)
{
char buf[256], buf2[256];
sys_socketreceiver = socketreceiver_new(0, 0, 0, 0);
sys_addpollfn(sys_guisock, (t_fdpollfn)socketreceiver_read,
sys_socketreceiver);
/* here is where we start the pinging. */
#if defined(__linux__) || defined(IRIX)
if (sys_hipriority)
gui_vmess("gui_watchdog", "");
#endif
sys_get_audio_apis(buf);
sys_get_midi_apis(buf2);
// sys_vgui("pdtk_pd_startup {%s} %s %s {%s} %s\n", pd_version, buf, buf2,
// sys_font, sys_fontweight);
t_binbuf *aapis = binbuf_new(), *mapis = binbuf_new();
sys_get_audio_apis2(aapis);
sys_get_midi_apis2(mapis);
gui_start_vmess("gui_startup", "sss",
pd_version,
sys_font,
sys_fontweight);
int i;
gui_start_array(); // audio apis
for (i = 0; i < binbuf_getnatom(aapis); i+=2)
{
gui_s(atom_getsymbol(binbuf_getvec(aapis)+i)->s_name);
gui_i(atom_getint(binbuf_getvec(aapis)+i+1));
}
gui_end_array();
gui_start_array(); // midi apis
for (i = 0; i < binbuf_getnatom(mapis); i+=2)
{
gui_s(atom_getsymbol(binbuf_getvec(mapis)+i)->s_name);
gui_i(atom_getint(binbuf_getvec(mapis)+i+1));
}
gui_end_array();
gui_end_vmess();
gui_vmess("gui_set_cwd", "xs", 0, cwd);
binbuf_free(aapis);
binbuf_free(mapis);
}
return (0);
}
extern void sys_exit(void);
......
......@@ -32,7 +32,9 @@ static const char pd_compiledate[] = __DATE__;
void pd_init(void);
int sys_argparse(int argc, char **argv);
void sys_findprogdir(char *progname);
void sys_setsignalhandlers(void);
int sys_startgui(const char *guipath);
void sys_setrealtime(const char *guipath);
int sys_rcfile(void);
int m_mainloop(void);
int m_batchmain(void);
......@@ -243,6 +245,41 @@ void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv)
sys_messagelist = 0;
}
// font char metric triples: pointsize width(pixels) height(pixels)
static int defaultfontshit[] = {
8, 5, 11, 9, 6, 12,
10, 6, 13, 12, 7, 16,
14, 8, 17, 16, 10, 19,
18, 11, 22, 24, 14, 29,
30, 18, 37, 36, 22, 44
};
#define NDEFAULTFONT (sizeof(defaultfontshit)/sizeof(*defaultfontshit))
static t_clock *sys_fakefromguiclk;
static void sys_fakefromgui(void)
{
/* fake the GUI's message giving cwd and font sizes in case
we aren't starting the gui. */
t_atom zz[NDEFAULTFONT+2];
int i;
char buf[MAXPDSTRING];
#ifdef _WIN32
if (GetCurrentDirectory(MAXPDSTRING, buf) == 0)
strcpy(buf, ".");
#else
if (!getcwd(buf, MAXPDSTRING))
strcpy(buf, ".");
#endif
SETSYMBOL(zz, gensym(buf));
for (i = 0; i < (int)NDEFAULTFONT; i++)
SETFLOAT(zz+i+1, defaultfontshit[i]);
SETFLOAT(zz+NDEFAULTFONT+1,0);
glob_initfromgui(0, 0, 2+NDEFAULTFONT, zz);
clock_free(sys_fakefromguiclk);
}
static void sys_afterargparse(void);
static void pd_makeversion(void)
......@@ -298,6 +335,34 @@ int sys_main(int argc, char **argv)
#ifdef PD_DEBUG
fprintf(stderr, "Pd-L2Ork: COMPILED FOR DEBUGGING\n");
#endif
/* We need to call WSAStartup regardless of gui mode, since a user
* might want to make socket connections even in -nogui mode. So we
* go ahead and do that here. */
#ifdef _WIN32
short version = MAKEWORD(2, 0);
WSADATA nobby;
if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup");
/* use Win32 "binary" mode by default since we don't want the
* translation that Win32 does by default */
# ifdef _MSC_VER /* MS Visual Studio */
_set_fmode( _O_BINARY );
# else /* MinGW */
{
extern int _fmode;
_fmode = _O_BINARY;
}
# endif /* _MSC_VER */
#endif /* _WIN32 */
#ifndef _WIN32
/* long ago Pd used setuid to promote itself to real-time priority.
Just in case anyone's installation script still makes it setuid, we
complain to stderr and lose setuid here. */
if (getuid() != geteuid())
{
fprintf(stderr, "warning: canceling setuid privilege\n");
setuid(getuid());
}
#endif /* _WIN32 */
pd_init(); /* start the message system */
logpost(NULL, 2, "PD_FLOATSIZE = %lu bits", sizeof(t_float)*8);
sys_findprogdir(argv[0]); /* set sys_progname, guipath */
......@@ -320,7 +385,11 @@ int sys_main(int argc, char **argv)
pd_version, pd_compiletime, pd_compiledate);
if (sys_version) /* if we were just asked our version, exit here. */
return (0);
if (sys_startgui(sys_guidir->s_name)) /* start the gui */
sys_setsignalhandlers();
if (sys_nogui)
clock_set((sys_fakefromguiclk =
clock_new(0, (t_method)sys_fakefromgui)), 0);
else if (sys_startgui(sys_guidir->s_name)) /* start the gui */
return(1);
/* send the libdir to the GUI */
gui_vmess("gui_set_lib_dir", "s", sys_libdir->s_name);
......@@ -340,6 +409,8 @@ int sys_main(int argc, char **argv)
gui_end_array();
gui_end_vmess();
if (sys_hipriority)
sys_setrealtime(sys_libdir->s_name); /* set desired process priority */
if (sys_externalschedlib)
return (sys_run_scheduler(sys_externalschedlibname,
sys_extraflagsstring));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment