aboutsummaryrefslogtreecommitdiff
path: root/pd/src
diff options
context:
space:
mode:
Diffstat (limited to 'pd/src')
-rw-r--r--pd/src/Makefile.am145
-rw-r--r--pd/src/configure.in31
-rw-r--r--pd/src/d_array.c56
-rw-r--r--pd/src/d_ctl.c2
-rw-r--r--pd/src/d_delay.c32
-rw-r--r--pd/src/d_fft_fftw.c138
-rw-r--r--pd/src/d_fftroutine.c41
-rw-r--r--pd/src/d_math.c23
-rw-r--r--pd/src/d_osc.c57
-rw-r--r--pd/src/d_soundfile.c6
-rw-r--r--pd/src/d_ugen.c2
-rw-r--r--pd/src/g_all_guis.c13
-rw-r--r--pd/src/g_array.c53
-rw-r--r--pd/src/g_bang.c8
-rw-r--r--pd/src/g_canvas.c89
-rw-r--r--pd/src/g_canvas.h5
-rw-r--r--pd/src/g_editor.c201
-rw-r--r--pd/src/g_graph.c32
-rw-r--r--pd/src/g_hdial.c8
-rw-r--r--pd/src/g_hslider.c13
-rw-r--r--pd/src/g_mycanvas.c2
-rw-r--r--pd/src/g_numbox.c8
-rw-r--r--pd/src/g_readwrite.c9
-rw-r--r--pd/src/g_rtext.c187
-rw-r--r--pd/src/g_template.c28
-rw-r--r--pd/src/g_text.c42
-rw-r--r--pd/src/g_toggle.c8
-rw-r--r--pd/src/g_vdial.c8
-rw-r--r--pd/src/g_vslider.c8
-rw-r--r--pd/src/g_vumeter.c14
-rw-r--r--pd/src/m_atom.c2
-rw-r--r--pd/src/m_binbuf.c164
-rw-r--r--pd/src/m_class.c10
-rw-r--r--pd/src/m_glob.c5
-rw-r--r--pd/src/m_obj.c28
-rw-r--r--pd/src/m_pd.h25
-rw-r--r--pd/src/m_sched.c18
-rw-r--r--pd/src/makefile.in3
-rw-r--r--pd/src/makefile.mingw297
-rw-r--r--pd/src/makefile.nt23
-rw-r--r--pd/src/notes.txt7
-rwxr-xr-xpd/src/pd.icobin0 -> 25214 bytes
-rw-r--r--pd/src/pd.rc25
-rw-r--r--pd/src/s_audio.c196
-rw-r--r--pd/src/s_audio_alsa.c39
-rw-r--r--pd/src/s_audio_alsa.h2
-rw-r--r--pd/src/s_audio_alsamm.c8
-rw-r--r--pd/src/s_audio_audiounit.c43
-rw-r--r--pd/src/s_audio_dummy.c37
-rw-r--r--pd/src/s_audio_esd.c135
-rw-r--r--pd/src/s_audio_jack.c517
-rw-r--r--pd/src/s_audio_mmio.c4
-rw-r--r--pd/src/s_audio_oss.c21
-rw-r--r--pd/src/s_audio_pa.c450
-rw-r--r--pd/src/s_audio_pablio.c350
-rw-r--r--pd/src/s_audio_pablio.h111
-rw-r--r--pd/src/s_audio_paring.c13
-rw-r--r--pd/src/s_audio_paring.h5
-rw-r--r--pd/src/s_file.c37
-rw-r--r--pd/src/s_inter.c124
-rw-r--r--pd/src/s_loader.c31
-rw-r--r--pd/src/s_main.c77
-rw-r--r--pd/src/s_midi.c16
-rw-r--r--pd/src/s_midi_alsa.c12
-rw-r--r--pd/src/s_midi_dummy.c34
-rw-r--r--pd/src/s_midi_pm.c1
-rw-r--r--pd/src/s_path.c144
-rw-r--r--pd/src/s_print.c187
-rw-r--r--pd/src/s_stuff.h124
-rw-r--r--pd/src/s_utf8.c280
-rw-r--r--pd/src/s_utf8.h88
-rw-r--r--pd/src/u_pdreceive.c2
-rw-r--r--pd/src/x_arithmetic.c13
-rw-r--r--pd/src/x_connective.c23
-rw-r--r--pd/src/x_gui.c13
-rw-r--r--pd/src/x_interface.c26
-rw-r--r--pd/src/x_misc.c47
-rw-r--r--pd/src/x_net.c8
-rw-r--r--pd/src/x_time.c7
79 files changed, 3422 insertions, 1679 deletions
diff --git a/pd/src/Makefile.am b/pd/src/Makefile.am
new file mode 100644
index 00000000..b85f726d
--- /dev/null
+++ b/pd/src/Makefile.am
@@ -0,0 +1,145 @@
+AUTOMAKE_OPTIONS = foreign
+
+pd_CFLAGS = -DPD -DINSTALL_PREFIX=\"$(prefix)\"
+pd_LDFLAGS =
+
+pdsend_CFLAGS =
+pdreceive_CFLAGS =
+pd_watchdog_CFLAGS =
+LIBS =
+INCLUDES = @INCLUDES@
+
+SUFFIXES = .@EXTENSION@ .@SHARED_LIB@
+
+bin_PROGRAMS = pd pdsend pdreceive
+pdsend_SOURCES = u_pdsend.c
+pdreceive_SOURCES = u_pdreceive.c
+pd_watchdog_SOURCES = s_watchdog.c
+pd_LDADD =
+pd_SOURCES = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c \
+ g_io.c g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
+ g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
+ g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
+ m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
+ m_conf.c m_glob.c m_sched.c \
+ s_main.c s_inter.c s_file.c s_print.c \
+ s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ s_utf8.c \
+ d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
+ d_math.c d_fft.c d_array.c d_global.c \
+ d_delay.c d_resample.c \
+ x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
+ x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c x_list.c d_soundfile.c
+
+pd_includedir = ${includedir}/pd
+pd_include_HEADERS = m_pd.h m_imp.h g_canvas.h s_stuff.h g_all_guis.h
+# compatibility: m_pd.h also goes into ${includedir}/
+include_HEADERS = m_pd.h
+noinst_HEADERS = g_all_guis.h s_audio_alsa.h s_audio_paring.h s_utf8.h
+
+# we want these in the dist tarball
+EXTRA_DIST = CHANGELOG.txt notes.txt makefile.mingw
+
+# configurations per library
+if ALSA
+pd_CFLAGS += -DUSEAPI_ALSA
+pd_SOURCES += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c
+endif
+
+if COREAUDIO
+LIBS += -framework CoreAudio -framework CoreMIDI \
+ -framework AudioUnit -framework AudioToolbox
+endif
+
+if FFTW
+pd_SOURCES += d_fft_fftw.c d_fftroutine.c
+else
+pd_SOURCES += d_fft_mayer.c d_fftroutine.c
+endif
+
+# TODO support Jack xrun
+if JACK
+pd_CFLAGS += -DUSEAPI_JACK -DJACK_XRUN
+pd_SOURCES += s_audio_jack.c
+if MACOSX
+LIBS += -weak_framework Jackmp
+else
+LIBS += -ljack
+endif
+endif
+
+# Cygwin has a function OSS /dev/dsp, but not MIDI, and Pd is only set up to
+# handle a single MIDI API
+if OSS
+if !WINDOWS
+pd_CFLAGS += -DUSEAPI_OSS
+pd_SOURCES += s_audio_oss.c s_midi_oss.c
+endif
+endif
+
+if PORTAUDIO
+pd_CFLAGS += -DUSEAPI_PORTAUDIO -I../portaudio/include
+pd_LDADD += ../portaudio/libportaudio.la
+pd_SOURCES += s_audio_pa.c s_audio_paring.c
+endif
+
+# ASIO needs to go after PORTAUDIO in order for it to link properly
+if ASIO
+pd_LDADD += ../asio/libasio.la
+endif
+
+if PORTMIDI
+INCLUDES += -I../portmidi/pm_common -I../portmidi/porttime
+pd_LDADD += ../portmidi/libportmidi.la
+pd_SOURCES += s_midi_pm.c
+endif
+
+
+# FIXXXME
+# GNU/HURD, IPHONEOS, ... have no MIDI (not even OSS)
+# i think it would be better to add s_midi_dummy.c only if no other midi API can be found
+# (without OS-specific checks)
+# even better would be, to allow Pd to have simply have no MIDI (nor AUDIO)
+if IPHONEOS
+pd_SOURCES += s_midi_dummy.c
+endif
+
+if HURD
+pd_SOURCES += s_midi_dummy.c
+endif
+
+if LINUX
+libpdbindir = $(pkglibdir)/bin
+libpdbin_DATA =
+libpdbin_PROGRAMS = pd-watchdog pd
+# this flag has to have a single leading "-" for libtool, even though ld uses
+# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld...
+pd_LDFLAGS += -export-dynamic
+# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it
+pd_LDFLAGS += $(LIBM)
+endif
+
+if MACOSX
+LIBS += -framework Carbon
+pd_CFLAGS += -DMACOSX #kludge, should use auto macro __APPLE__
+bin_SCRIPTS =
+bin_PROGRAMS += pd-watchdog
+endif
+
+if WINDOWS
+LIBS += -lwsock32 -lwinmm -lole32
+pd_CFLAGS += -DUSEAPI_MMIO -DPD_INTERNAL
+pd_SOURCES += s_audio_mmio.c s_midi_mmio.c
+bin_SCRIPTS =
+endif
+
+# Cygwin is not _WIN32 and MSW vaguely means the same thing, so MINGW only
+if MINGW
+pd_CFLAGS += -DWISHAPP='"wish85.exe"' -DMSW #kludge, MSW should be _WIN32
+pdsend_CFLAGS += -DMSW #kludge, should use _WIN32
+pdreceive_CFLAGS += -DMSW #kludge, should use _WIN32
+bin_PROGRAMS += pd-watchdog
+endif
+
+etags: TAGS
+ etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl
diff --git a/pd/src/configure.in b/pd/src/configure.in
index e4f4edd7..e5d2e00b 100644
--- a/pd/src/configure.in
+++ b/pd/src/configure.in
@@ -95,8 +95,8 @@ AC_CHECK_LIB(pthread, pthread_create,PDLIB="$PDLIB -lpthread",
dnl Check for fftw package
if test x$fftw = "xyes";
then
-AC_CHECK_LIB(fftw, fftw_one,PDLIB="$PDLIB -lfftw",
- echo "fftw package not found - using built-in FFT"; fftw=no)
+AC_CHECK_LIB(fftw3f, fftwf_version,PDLIB="$PDLIB -lfftw3f",
+ echo "fftw3 package not found - using built-in FFT"; fftw=no)
fi
dnl look for tcl 8.x... do I really have to go through all this!?
@@ -173,7 +173,7 @@ else
GUISRC=
fi
-if test `uname -s` = Linux;
+if test `uname -s` = Linux -o `uname -s` = "GNU/kFreeBSD" -o `uname -s` = "GNU";
then
dnl Ckecking for ALSA
echo .................... alsa= $alsa
@@ -195,10 +195,19 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
LDFLAGS="$LDFLAGS -static"
fi
EXT=pd_linux
- CPPFLAGS="-DHAVE_LIBDL -DPA_USE_OSS -DUNIX -DHAVE_UNISTD_H\
- -DUSEAPI_OSS \
+ CPPFLAGS="-DHAVE_LIBDL -DUNIX -DHAVE_UNISTD_H\
+ -DPDGUIDIR=\\\"tcl/\\\" \
-fno-strict-aliasing"
- SYSSRC="s_midi_oss.c s_audio_oss.c"
+dnl No OSS on hurd
+ if test `uname -s` = "GNU";
+ then
+ SYSSRC="s_midi_dummy.c"
+ else
+ SYSSRC="s_midi_oss.c s_audio_oss.c"
+ CPPFLAGS=$CPPFLAGS" -DPA_USE_OSS -DUSEAPI_OSS"
+ fi
+
+
if test x$alsa = "xyes";
then
SYSSRC=$SYSSRC" s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c"
@@ -215,7 +224,6 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
-I../portmidi/pm_common \
-I../portmidi/pm_linux"
SYSSRC="s_audio_pa.c \
- s_audio_pablio.c \
s_audio_paring.c \
../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \
@@ -295,7 +303,6 @@ then
EXTERNTARGET=d_ppc
fi
SYSSRC="s_midi_pm.c s_audio_pa.c \
- s_audio_pablio.c \
s_audio_paring.c \
../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \
@@ -347,11 +354,11 @@ then
OSNUMBER=2
if test x$jack = "xyes";
then
- LDFLAGS=$LDFLAGS" -weak_framework Jack"
+ LDFLAGS=$LDFLAGS" -weak_framework Jackmp"
fi
if test x$jack = "xrun";
then
- LDFLAGS=$LDFLAGS" -weak_framework Jack"
+ LDFLAGS=$LDFLAGS" -weak_framework Jackmp"
fi
fi
@@ -367,7 +374,7 @@ then
-mwindows -mms-bitfields "$MORECFLAGS
PDLIB=$PDLIB" -lwsock32 -lwinmm -lole32 -lstdc++"
- SYSSRC="s_audio_pa.c s_audio_pablio.c s_audio_paring.c \
+ SYSSRC="s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c s_midi_mmio.c \
../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \
@@ -408,7 +415,7 @@ fi
if test x$fftw = "xyes";
then
SYSSRC=$SYSSRC" d_fft_fftw.c d_fftroutine.c"
- LDFLAGS=$LDFLAGS" -lfftw"
+ LDFLAGS=$LDFLAGS" -lfftw3"
else
SYSSRC=$SYSSRC" d_fft_mayer.c d_fftroutine.c"
fi
diff --git a/pd/src/d_array.c b/pd/src/d_array.c
index 11a55b5d..c0aab61e 100644
--- a/pd/src/d_array.c
+++ b/pd/src/d_array.c
@@ -498,50 +498,52 @@ static void tabread4_tilde_setup(void)
/* this is all copied from d_osc.c... what include file could this go in? */
#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
- /* machine-dependent definitions. These ifdefs really
- should have been by CPU type and not by operating system! */
#ifdef IRIX
- /* big-endian. Most significant byte is at low address in memory */
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#define int32 long /* a data type that has 32 bits */
-#endif /* IRIX */
-
-#ifdef MSW
- /* little-endian; most significant byte is at highest address */
-#define HIOFFSET 1
-#define LOWOFFSET 0
-#define int32 long
+#include <sys/endian.h>
#endif
-#if defined(__FreeBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__)
#include <machine/endian.h>
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(ANDROID)
#include <endian.h>
#endif
-#if defined(__unix__) || defined(__APPLE__)
+#ifdef __MINGW32__
+#include <sys/param.h>
+#endif
+
+#ifdef _MSC_VER
+/* _MSVC lacks BYTE_ORDER and LITTLE_ENDIAN */
+#define LITTLE_ENDIAN 0x0001
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN)
#error No byte order defined
-#endif
+#endif
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define HIOFFSET 1
-#define LOWOFFSET 0
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define HIOFFSET 1
+# define LOWOFFSET 0
#else
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#endif /* __BYTE_ORDER */
-#include <sys/types.h>
-#define int32 int32_t
-#endif /* __unix__ or __APPLE__*/
+# define HIOFFSET 0 /* word offset to find MSB */
+# define LOWOFFSET 1 /* word offset to find LSB */
+#endif
+
+#ifdef _MSC_VER
+ typedef __int32 int32_t; /* use MSVC's internal type */
+#elif defined(IRIX)
+ typedef long int32_t; /* a data type that has 32 bits */
+#else
+# include <stdint.h> /* this is where int32_t is defined in C99 */
+#endif
union tabfudge
{
double tf_d;
- int32 tf_i[2];
+ int32_t tf_i[2];
};
static t_class *tabosc4_tilde_class;
diff --git a/pd/src/d_ctl.c b/pd/src/d_ctl.c
index 92467abe..8d6bb000 100644
--- a/pd/src/d_ctl.c
+++ b/pd/src/d_ctl.c
@@ -657,7 +657,7 @@ static void env_tilde_dsp(t_sigenv *x, t_signal **sp)
(x->x_npoints + sp[0]->s_n) * sizeof(t_sample));
if (!xx)
{
- post("env~: out of memory");
+ error("env~: out of memory");
return;
}
x->x_buf = (t_sample *)xx;
diff --git a/pd/src/d_delay.c b/pd/src/d_delay.c
index 98cc1149..a6e5f7cf 100644
--- a/pd/src/d_delay.c
+++ b/pd/src/d_delay.c
@@ -24,6 +24,7 @@ typedef struct _sigdelwrite
{
t_object x_obj;
t_symbol *x_sym;
+ t_float x_deltime; /* delay in msec (added by Mathieu Bouchard) */
t_delwritectl x_cspace;
int x_sortno; /* DSP sort number at which this was last put on chain */
int x_rsortno; /* DSP sort # for first delread or write in chain */
@@ -34,6 +35,21 @@ typedef struct _sigdelwrite
#define XTRASAMPS 4
#define SAMPBLK 4
+static void sigdelwrite_updatesr (t_sigdelwrite *x, t_float sr) /* added by Mathieu Bouchard */
+{
+ int nsamps = x->x_deltime * sr * (t_float)(0.001f);
+ if (nsamps < 1) nsamps = 1;
+ nsamps += ((- nsamps) & (SAMPBLK - 1));
+ nsamps += DEFDELVS;
+ if (x->x_cspace.c_n != nsamps) {
+ x->x_cspace.c_vec = (t_sample *)resizebytes(x->x_cspace.c_vec,
+ (x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample),
+ ( nsamps + XTRASAMPS) * sizeof(t_sample));
+ x->x_cspace.c_n = nsamps;
+ x->x_cspace.c_phase = XTRASAMPS;
+ }
+}
+
/* routine to check that all delwrites/delreads/vds have same vecsize */
static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
{
@@ -54,19 +70,13 @@ static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
static void *sigdelwrite_new(t_symbol *s, t_floatarg msec)
{
- int nsamps;
t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class);
if (!*s->s_name) s = gensym("delwrite~");
pd_bind(&x->x_obj.ob_pd, s);
x->x_sym = s;
- nsamps = msec * sys_getsr() * (t_float)(0.001f);
- if (nsamps < 1) nsamps = 1;
- nsamps += ((- nsamps) & (SAMPBLK - 1));
- nsamps += DEFDELVS;
- x->x_cspace.c_n = nsamps;
- x->x_cspace.c_vec =
- (t_sample *)getbytes((nsamps + XTRASAMPS) * sizeof(t_sample));
- x->x_cspace.c_phase = XTRASAMPS;
+ x->x_deltime = msec;
+ x->x_cspace.c_n = 0;
+ x->x_cspace.c_vec = getbytes(XTRASAMPS * sizeof(t_sample));
x->x_sortno = 0;
x->x_vecsize = 0;
x->x_f = 0;
@@ -98,8 +108,6 @@ static t_int *sigdelwrite_perform(t_int *w)
phase -= nsamps;
}
}
- bp = vp + c->c_phase;
-
c->c_phase = phase;
return (w+4);
}
@@ -109,6 +117,7 @@ static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp)
dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n);
x->x_sortno = ugen_getsortno();
sigdelwrite_checkvecsize(x, sp[0]->s_n);
+ sigdelwrite_updatesr(x, sp[0]->s_sr);
}
static void sigdelwrite_free(t_sigdelwrite *x)
@@ -200,6 +209,7 @@ static void sigdelread_dsp(t_sigdelread *x, t_signal **sp)
x->x_n = sp[0]->s_n;
if (delwriter)
{
+ sigdelwrite_updatesr(delwriter, sp[0]->s_sr);
sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
0 : delwriter->x_vecsize);
diff --git a/pd/src/d_fft_fftw.c b/pd/src/d_fft_fftw.c
index 0ead62be..04e4729d 100644
--- a/pd/src/d_fft_fftw.c
+++ b/pd/src/d_fft_fftw.c
@@ -4,31 +4,32 @@
/* --------- Pd interface to FFTW library; imitate Mayer API ---------- */
-#include "m_pd.h"
-#ifdef MSW
-#include <malloc.h>
-#else
-#include <alloca.h>
-#endif
-
-#error oops -- I'm talking to the old fftw. Apparently it's still changing.
+/* changes and additions for FFTW3 by Thomas Grill */
-#include <fftw.h>
+#include "m_pd.h"
+#include <fftw3.h>
int ilog2(int n);
-#define MINFFT 5
+#define MINFFT 0
#define MAXFFT 30
/* from the FFTW website:
- fftw_complex in[N], out[N];
+ #include <fftw3.h>
+ ...
+ {
+ fftw_complex *in, *out;
fftw_plan p;
...
- p = fftw_create_plan(N, FFTW_FORWARD, FFTW_ESTIMATE);
+ in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
+ out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
+ p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
...
- fftw_one(p, in, out);
+ fftw_execute(p);
...
fftw_destroy_plan(p);
+ fftw_free(in); fftw_free(out);
+ }
FFTW_FORWARD or FFTW_BACKWARD, and indicates the direction of the transform you
are interested in. Alternatively, you can use the sign of the exponent in the
@@ -37,57 +38,126 @@ respectively. The flags argument is either FFTW_MEASURE
*/
-static fftw_plan fftw_pvec[2 * (MAXFFT+1 - MINFFT)];
+/* complex stuff */
+
+typedef struct {
+ fftwf_plan plan;
+ fftwf_complex *in,*out;
+} cfftw_info;
+
+static cfftw_info cfftw_fwd[MAXFFT+1 - MINFFT],cfftw_bwd[MAXFFT+1 - MINFFT];
+
+static cfftw_info *cfftw_getplan(int n,int fwd)
+{
+ cfftw_info *info;
+ int logn = ilog2(n);
+ if (logn < MINFFT || logn > MAXFFT)
+ return (0);
+ info = (fwd?cfftw_fwd:cfftw_bwd)+(logn-MINFFT);
+ if (!info->plan)
+ {
+ info->in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
+ info->out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
+ info->plan = fftwf_plan_dft_1d(n, info->in, info->out, fwd?FFTW_FORWARD:FFTW_BACKWARD, FFTW_MEASURE);
+ }
+ return info;
+}
+
-static fftw_plan fftw_getplan(int n, int dir)
+/* real stuff */
+
+typedef struct {
+ fftwf_plan plan;
+ float *in,*out;
+} rfftw_info;
+
+static rfftw_info rfftw_fwd[MAXFFT+1 - MINFFT],rfftw_bwd[MAXFFT+1 - MINFFT];
+
+static rfftw_info *rfftw_getplan(int n,int fwd)
{
- logn = ilog2(n);
+ rfftw_info *info;
+ int logn = ilog2(n);
if (logn < MINFFT || logn > MAXFFT)
return (0);
- int indx = 2*(logn-MINFFT) + inverse);
- if (!fftw_pvec[indx]
- fftw_pvec[indx] = fftw_create_plan(N, dir, FFTW_MEASURE);
- return (fftw_pvec[indx]);
+ info = (fwd?rfftw_fwd:rfftw_bwd)+(logn-MINFFT);
+ if (!info->plan)
+ {
+ info->in = (float*) fftwf_malloc(sizeof(float) * n);
+ info->out = (float*) fftwf_malloc(sizeof(float) * n);
+ info->plan = fftwf_plan_r2r_1d(n, info->in, info->out, fwd?FFTW_R2HC:FFTW_HC2R, FFTW_MEASURE);
+ }
+ return info;
}
+
+
EXTERN void mayer_fht(float *fz, int n)
{
post("FHT: not yet implemented");
}
-static void mayer_dofft(int n, float *fz1, float *fz2, int dir)
+static void mayer_do_cfft(int n, float *fz1, float *fz2, int fwd)
{
- float *inbuf, *outbuf, *fp1, *fp2, *fp3;
int i;
- fftw_plan p = fftw_getplan(n, dir);
- inbuf = alloca(n * (4 * sizeof(float)));
- outbuf = inbuf + 2*n;
+ float *fz;
+ cfftw_info *p = cfftw_getplan(n, fwd);
if (!p)
return;
- for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = inbuf; i < n; i++)
- fp3[0] = *fp1++, fp3[1] = *fp2++, fp3 += 2;
- fftw_one(p, inbuf, outbuf);
- for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = outbuf; i < n; i++)
- *fp1++ = fp3[0], *fp2++ = fp3[1], fp3 += 2;
+
+ for (i = 0, fz = (float *)p->in; i < n; i++)
+ fz[i*2] = fz1[i], fz[i*2+1] = fz2[i];
+
+ fftwf_execute(p->plan);
+
+ for (i = 0, fz = (float *)p->out; i < n; i++)
+ fz1[i] = fz[i*2], fz2[i] = fz[i*2+1];
}
EXTERN void mayer_fft(int n, float *fz1, float *fz2)
{
- mayer_dofft(n, fz1, fz2, FFTW_FORWARD);
+ mayer_do_cfft(n, fz1, fz2, 1);
}
EXTERN void mayer_ifft(int n, float *fz1, float *fz2)
{
- mayer_dofft(n, fz1, fz2, FFTW_BACKWARD);
+ mayer_do_cfft(n, fz1, fz2, 0);
}
+/*
+ in the following the sign flips are done to
+ be compatible with the mayer_fft implementation,
+ but it's probably the mayer_fft that should be corrected...
+*/
+
EXTERN void mayer_realfft(int n, float *fz)
{
- post("rfft: not yet implemented");
+ int i;
+ rfftw_info *p = rfftw_getplan(n, 1);
+ if (!p)
+ return;
+
+ for (i = 0; i < n; i++)
+ p->in[i] = fz[i];
+ fftwf_execute(p->plan);
+ for (i = 0; i < n/2+1; i++)
+ fz[i] = p->out[i];
+ for (; i < n; i++)
+ fz[i] = -p->out[i];
}
EXTERN void mayer_realifft(int n, float *fz)
{
- post("rifft: not yet implemented");
+ int i;
+ rfftw_info *p = rfftw_getplan(n, 0);
+ if (!p)
+ return;
+
+ for (i = 0; i < n/2+1; i++)
+ p->in[i] = fz[i];
+ for (; i < n; i++)
+ p->in[i] = -fz[i];
+ fftwf_execute(p->plan);
+ for (i = 0; i < n; i++)
+ fz[i] = p->out[i];
}
diff --git a/pd/src/d_fftroutine.c b/pd/src/d_fftroutine.c
index 0222a0c0..5882abb2 100644
--- a/pd/src/d_fftroutine.c
+++ b/pd/src/d_fftroutine.c
@@ -98,11 +98,10 @@
#define FALSE 0
#endif
-#define SAMPLE PD_FLOATTYPE /* data type used in calculation */
+#define SAMPLE t_float /* data type used in calculation */
#define SHORT_SIZE sizeof(short)
#define INT_SIZE sizeof(int)
-#define FLOAT_SIZE sizeof(float)
#define SAMPLE_SIZE sizeof(SAMPLE)
#define PNTR_SIZE sizeof(char *)
@@ -171,7 +170,7 @@ void net_dealloc(FFT_NET *fft_net);
int power_of_two(int n);
void create_hanning(SAMPLE *window, int n, SAMPLE scale);
void create_rectangular(SAMPLE *window, int n, SAMPLE scale);
-void short_to_float(short *short_buf, float *float_buf, int n);
+void short_to_float(short *short_buf, SAMPLE *float_buf, int n);
void load_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
int buf_scale, int trnsfrm_dir);
void compute_fft(FFT_NET *fft_net);
@@ -629,20 +628,20 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
switch (buf_form) {
case REAL: { /* pure REAL */
do {
- *buf++ = (float)fft_net->regr[i];
+ *buf++ = (SAMPLE)fft_net->regr[i];
} while (++i < n);
} break;
case IMAG: { /* pure IMAGinary */
do {
- *buf++ = (float)fft_net->regi[i];
+ *buf++ = (SAMPLE)fft_net->regi[i];
} while (++i < n);
} break;
case RECT: { /* both REAL and IMAGinary */
do {
- *buf++ = (float)fft_net->regr[i];
- *buf++ = (float)fft_net->regi[i];
+ *buf++ = (SAMPLE)fft_net->regr[i];
+ *buf++ = (SAMPLE)fft_net->regi[i];
} while (++i < n);
} break;
@@ -650,7 +649,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)sqrt(real*real+imag*imag);
+ *buf++ = (SAMPLE)sqrt(real*real+imag*imag);
} while (++i < n);
} break;
@@ -659,7 +658,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
real = fft_net->regr[i];
imag = fft_net->regi[i];
if (real > .00001)
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0){ *buf++ = PI / 2.;
if(debug) fprintf(stderr,"real=0 and imag > 0\n");}
@@ -675,9 +674,9 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)sqrt(real*real+imag*imag);
+ *buf++ = (SAMPLE)sqrt(real*real+imag*imag);
if (real) /* a hack to avoid div by zero */
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0) *buf++ = PI / 2.;
else if (imag < 0) *buf++ = -PI / 2.;
@@ -698,20 +697,20 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
switch (buf_form) {
case REAL: { /* real only */
do {
- *buf++ = (float)20.*log10(fft_net->regr[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regr[i]);
} while (++i < n);
} break;
case IMAG: { /* imag only */
do {
- *buf++ = (float)20.*log10(fft_net->regi[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regi[i]);
} while (++i < n);
} break;
case RECT: { /* real and imag */
do {
- *buf++ = (float)20.*log10(fft_net->regr[i]);
- *buf++ = (float)20.*log10(fft_net->regi[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regr[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regi[i]);
} while (++i < n);
} break;
@@ -719,7 +718,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)20.*log10(sqrt(real*real+imag*imag));
+ *buf++ = (SAMPLE)20.*log10(sqrt(real*real+imag*imag));
} while (++i < n);
} break;
@@ -728,7 +727,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
real = fft_net->regr[i];
imag = fft_net->regi[i];
if (real)
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0) *buf++ = PI / 2.;
else if (imag < 0) *buf++ = -PI / 2.;
@@ -741,9 +740,9 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)20.*log10(sqrt(real*real+imag*imag));
+ *buf++ = (SAMPLE)20.*log10(sqrt(real*real+imag*imag));
if (real)
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0) *buf++ = PI / 2.;
else if (imag < 0) *buf++ = -PI / 2.;
@@ -975,14 +974,14 @@ void create_rectangular(SAMPLE *window, int n, SAMPLE scale)
}
-void short_to_float(short *short_buf, float *float_buf, int n)
+void short_to_float(short *short_buf, SAMPLE *float_buf, int n)
/* effects; Converts short_buf to floats and stores them in float_buf.
*/
{
while (n--) {
- *float_buf++ = (float)*short_buf++;
+ *float_buf++ = (SAMPLE)*short_buf++;
}
}
diff --git a/pd/src/d_math.c b/pd/src/d_math.c
index 31c6c655..f76bffef 100644
--- a/pd/src/d_math.c
+++ b/pd/src/d_math.c
@@ -67,13 +67,12 @@ static void clip_setup(void)
#define DUMTAB1SIZE 256
#define DUMTAB2SIZE 1024
-#ifdef MSW
-#define int32 long
-#endif
-
-#if defined(__unix__) || defined(__APPLE__)
-#include <sys/types.h>
-#define int32 int32_t
+#ifdef _MSC_VER
+ typedef __int32 int32_t; /* use MSVC's internal type */
+#elif defined(IRIX)
+ typedef long int32_t; /* a data type that has 32 bits */
+#else
+# include <stdint.h> /* this is where int32_t is defined in C99 */
#endif
static float rsqrt_exptab[DUMTAB1SIZE], rsqrt_mantissatab[DUMTAB2SIZE];
@@ -84,8 +83,8 @@ static void init_rsqrt(void)
for (i = 0; i < DUMTAB1SIZE; i++)
{
float f;
- int32 l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23;
- *(int32 *)(&f) = l;
+ int32_t l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23;
+ *(int32_t *)(&f) = l;
rsqrt_exptab[i] = 1./sqrt(f);
}
for (i = 0; i < DUMTAB2SIZE; i++)
@@ -97,16 +96,18 @@ static void init_rsqrt(void)
/* these are used in externs like "bonk" */
-t_float q8_rsqrt(t_float f)
+t_float q8_rsqrt(t_float f0)
{
+ float f = (float)f0;
long l = *(long *)(&f);
if (f < 0) return (0);
else return (rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(l >> 13) & 0x3ff]);
}
-t_float q8_sqrt(t_float f)
+t_float q8_sqrt(t_float f0)
{
+ float f = (float)f0;
long l = *(long *)(&f);
if (f < 0) return (0);
else return (f * rsqrt_exptab[(l >> 23) & 0xff] *
diff --git a/pd/src/d_osc.c b/pd/src/d_osc.c
index 8336dd34..25e490db 100644
--- a/pd/src/d_osc.c
+++ b/pd/src/d_osc.c
@@ -10,50 +10,53 @@
#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
- /* machine-dependent definitions. These ifdefs really
- should have been by CPU type and not by operating system! */
+
#ifdef IRIX
- /* big-endian. Most significant byte is at low address in memory */
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#define int32 long /* a data type that has 32 bits */
-#endif /* IRIX */
-
-#ifdef MSW
- /* little-endian; most significant byte is at highest address */
-#define HIOFFSET 1
-#define LOWOFFSET 0
-#define int32 long
+#include <sys/endian.h>
#endif
-#if defined(__FreeBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__)
#include <machine/endian.h>
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(ANDROID)
#include <endian.h>
#endif
-#if defined(__unix__) || defined(__APPLE__)
+#ifdef __MINGW32__
+#include <sys/param.h>
+#endif
+
+#ifdef _MSC_VER
+/* _MSVC lacks BYTE_ORDER and LITTLE_ENDIAN */
+#define LITTLE_ENDIAN 0x0001
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN)
#error No byte order defined
-#endif
+#endif
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define HIOFFSET 1
-#define LOWOFFSET 0
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define HIOFFSET 1
+# define LOWOFFSET 0
#else
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#endif /* __BYTE_ORDER */
-#include <sys/types.h>
-#define int32 int32_t
-#endif /* __unix__ or __APPLE__*/
+# define HIOFFSET 0 /* word offset to find MSB */
+# define LOWOFFSET 1 /* word offset to find LSB */
+#endif
+
+#ifdef _MSC_VER
+ typedef __int32 int32_t; /* use MSVC's internal type */
+#elif defined(IRIX)
+ typedef long int32_t; /* a data type that has 32 bits */
+#else
+# include <stdint.h> /* this is where int32_t is defined in C99 */
+#endif
union tabfudge
{
double tf_d;
- int32 tf_i[2];
+ int32_t tf_i[2];
};
/* -------------------------- phasor~ ------------------------------ */
diff --git a/pd/src/d_soundfile.c b/pd/src/d_soundfile.c
index 8768fa55..8c350305 100644
--- a/pd/src/d_soundfile.c
+++ b/pd/src/d_soundfile.c
@@ -831,7 +831,7 @@ static void soundfile_finishwrite(void *obj, char *filename, int fd,
if (itemswritten < nframes)
{
if (nframes < 0x7fffffff)
- pd_error(obj, "soundfiler_write: %d out of %d bytes written",
+ pd_error(obj, "soundfiler_write: %ld out of %ld bytes written",
itemswritten, nframes);
/* try to fix size fields in header */
if (filetype == FORMAT_WAVE)
@@ -1261,7 +1261,7 @@ static void soundfiler_read(t_soundfiler *x, t_symbol *s,
framesinfile = (eofis - poswas) / (channels * bytespersamp);
if (framesinfile > maxsize)
{
- pd_error(x, "soundfiler_read: truncated to %d elements", maxsize);
+ pd_error(x, "soundfiler_read: truncated to %ld elements", maxsize);
framesinfile = maxsize;
}
if (framesinfile > bytelimit / (channels * bytespersamp))
@@ -1271,7 +1271,7 @@ static void soundfiler_read(t_soundfiler *x, t_symbol *s,
{
int vecsize;
- garray_resize(garrays[i], finalsize);
+ garray_resize_long(garrays[i], finalsize);
/* for sanity's sake let's clear the save-in-patch flag here */
garray_setsaveit(garrays[i], 0);
garray_getfloatwords(garrays[i], &vecsize,
diff --git a/pd/src/d_ugen.c b/pd/src/d_ugen.c
index fe49b7de..3fa7db54 100644
--- a/pd/src/d_ugen.c
+++ b/pd/src/d_ugen.c
@@ -219,7 +219,7 @@ static void block_float(t_block *x, t_floatarg f)
static void block_bang(t_block *x)
{
- if (x->x_switched && !x->x_switchon)
+ if (x->x_switched && !x->x_switchon && dsp_chain)
{
t_int *ip;
x->x_return = 1;
diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c
index f9314995..88f8d256 100644
--- a/pd/src/g_all_guis.c
+++ b/pd/src/g_all_guis.c
@@ -425,8 +425,8 @@ void iemgui_label_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av
if(glist_isvisible(iemgui->x_glist))
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
glist_getcanvas(iemgui->x_glist), x,
- iemgui->x_obj.te_xpix+iemgui->x_ldx,
- iemgui->x_obj.te_ypix+iemgui->x_ldy);
+ text_xpix((t_object *)x,iemgui->x_glist)+iemgui->x_ldx,
+ text_ypix((t_object *)x,iemgui->x_glist)+iemgui->x_ldy);
}
void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
@@ -456,7 +456,7 @@ void iemgui_size(void *x, t_iemgui *iemgui)
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(iemgui->x_glist), (t_text*)x);
+ canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}
@@ -467,7 +467,7 @@ void iemgui_delta(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(iemgui->x_glist), (t_text*)x);
+ canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}
@@ -478,7 +478,7 @@ void iemgui_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(iemgui->x_glist), (t_text*)x);
+ canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}
@@ -503,7 +503,7 @@ void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy)
x->x_gui.x_obj.te_xpix += dx;
x->x_gui.x_obj.te_ypix += dy;
(*x->x_gui.x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(glist), (t_text *)z);
+ canvas_fixlinesfor(glist, (t_text *)z);
}
void iemgui_select(t_gobj *z, t_glist *glist, int selected)
@@ -630,6 +630,7 @@ int iemgui_dialog(t_iemgui *iemgui, t_symbol **srl, int argc, t_atom *argv)
fs = 4;
iemgui->x_fontsize = fs;
iemgui_verify_snd_ne_rcv(iemgui);
+ canvas_dirty(iemgui->x_glist, 1);
return(oldsndrcvable);
}
diff --git a/pd/src/g_array.c b/pd/src/g_array.c
index a73c5ba5..2c8f86d9 100644
--- a/pd/src/g_array.c
+++ b/pd/src/g_array.c
@@ -385,6 +385,7 @@ void glist_arraydialog(t_glist *parent, t_symbol *name, t_floatarg size,
gl = glist_addglist(parent, &s_, 0, 1,
(size > 1 ? size-1 : size), -1, 0, 0, 0, 0);
a = graph_array(gl, sharptodollar(name), &s_float, size, flags);
+ canvas_dirty(parent, 1);
}
/* this is called from the properties dialog window for an existing array */
@@ -403,7 +404,7 @@ void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
}
else
{
- int size;
+ long size;
int styleonset, styletype;
t_symbol *stylearraytype;
t_symbol *argname = sharptodollar(name);
@@ -445,7 +446,7 @@ void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
if (size < 1)
size = 1;
if (size != a->a_n)
- garray_resize(x, size);
+ garray_resize_long(x, size);
else if (style != stylewas)
garray_fittograph(x, size, style);
template_setfloat(scalartemplate, gensym("style"),
@@ -453,6 +454,7 @@ void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
garray_setsaveit(x, (saveit != 0));
garray_redraw(x);
+ canvas_dirty(x->x_glist, 1);
}
}
@@ -1136,12 +1138,12 @@ int garray_getfloatwords(t_garray *x, int *size, t_word **vec)
t_array *a = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!a)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return (0);
}
else if (elemsize != sizeof(t_word))
{
- error("%s: has more than one field", x->x_realname);
+ error("%s: has more than one field", x->x_realname->s_name);
return (0);
}
*size = garray_npoints(x);
@@ -1178,7 +1180,7 @@ static void garray_const(t_garray *x, t_floatarg g)
int yonset, i, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
else for (i = 0; i < array->a_n; i++)
*((t_float *)((char *)array->a_vec
+ elemsize * i) + yonset) = g;
@@ -1186,7 +1188,7 @@ static void garray_const(t_garray *x, t_floatarg g)
}
/* sum of Fourier components; called from routines below */
-static void garray_dofo(t_garray *x, int npoints, t_float dcval,
+static void garray_dofo(t_garray *x, long npoints, t_float dcval,
int nsin, t_float *vsin, int sineflag)
{
double phase, phaseincr, fj;
@@ -1194,7 +1196,7 @@ static void garray_dofo(t_garray *x, int npoints, t_float dcval,
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
if (npoints == 0)
@@ -1202,7 +1204,7 @@ static void garray_dofo(t_garray *x, int npoints, t_float dcval,
if (npoints != (1 << ilog2(npoints)))
post("%s: rounnding to %d points", array->a_templatesym->s_name,
(npoints = (1<<ilog2(npoints))));
- garray_resize(x, npoints + 3);
+ garray_resize_long(x, npoints + 3);
phaseincr = 2. * 3.14159 / npoints;
for (i = 0, phase = -phaseincr; i < array->a_n; i++, phase += phaseincr)
{
@@ -1221,8 +1223,9 @@ static void garray_dofo(t_garray *x, int npoints, t_float dcval,
static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
- t_float *svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
- int npoints, i;
+ t_float *svec;
+ long npoints;
+ int i;
if (argc < 2)
{
error("sinesum: %s: need number of points and partial strengths",
@@ -1244,8 +1247,9 @@ static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
- t_float *svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
- int npoints, i;
+ t_float *svec;
+ long npoints;
+ int i;
if (argc < 2)
{
error("sinesum: %s: need number of points and partial strengths",
@@ -1267,13 +1271,13 @@ static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
static void garray_normalize(t_garray *x, t_float f)
{
- int type, npoints, i;
+ int type, i;
double maxv, renormer;
int yonset, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
@@ -1308,7 +1312,7 @@ static void garray_list(t_garray *x, t_symbol *s, int argc, t_atom *argv)
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
if (argc < 2) return;
@@ -1389,7 +1393,7 @@ static void garray_read(t_garray *x, t_symbol *filename)
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
nelem = array->a_n;
@@ -1402,8 +1406,8 @@ static void garray_read(t_garray *x, t_symbol *filename)
}
for (i = 0; i < nelem; i++)
{
- float f;
- if (!fscanf(fd, "%f", &f))
+ double f;
+ if (!fscanf(fd, "%lf", &f))
{
post("%s: read %d elements into table of size %d",
filename->s_name, i, nelem);
@@ -1426,7 +1430,7 @@ static void garray_write(t_garray *x, t_symbol *filename)
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
@@ -1458,11 +1462,12 @@ int garray_ambigendian(void)
return (c==0);
}
-void garray_resize(t_garray *x, t_floatarg f)
+void garray_resize_long(t_garray *x, long n)
{
t_array *array = garray_getarray(x);
t_glist *gl = x->x_glist;
- int n = (f < 1 ? 1 : f);
+ if (n < 1)
+ n = 1;
garray_fittograph(x, n, template_getfloat(
template_findbyname(x->x_scalar->sc_template),
gensym("style"), x->x_scalar->sc_vec, 1));
@@ -1471,6 +1476,12 @@ void garray_resize(t_garray *x, t_floatarg f)
canvas_update_dsp();
}
+ /* float version to use as Pd method */
+void garray_resize(t_garray *x, t_floatarg f)
+{
+ garray_resize_long(x, f);
+}
+
static void garray_print(t_garray *x)
{
t_array *array = garray_getarray(x);
diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c
index 8606b0ac..551b7aeb 100644
--- a/pd/src/g_bang.c
+++ b/pd/src/g_bang.c
@@ -55,19 +55,19 @@ void bng_draw_new(t_bng *x, t_glist *glist)
xpos + x->x_gui.x_w-1, ypos + x->x_gui.x_h-1,
x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xpos,
ypos + x->x_gui.x_h-1, xpos + IOWIDTH,
ypos + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xpos, ypos,
xpos + IOWIDTH, ypos+1, x, 0);
}
@@ -329,7 +329,7 @@ static void bng_dialog(t_bng *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void bng_click(t_bng *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index fd2df161..e5116c0c 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -46,7 +46,7 @@ t_canvas *canvas_list; /* list of all root canvases */
static void canvas_start_dsp(void);
static void canvas_stop_dsp(void);
static void canvas_drawlines(t_canvas *x);
-static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2);
+static void canvas_dosetbounds(t_canvas *x, int x1, int y1, int x2, int y2);
void canvas_reflecttitle(t_canvas *x);
static void canvas_addtolist(t_canvas *x);
static void canvas_takeofflist(t_canvas *x);
@@ -59,46 +59,11 @@ static t_symbol *canvas_newdirectory = &s_;
static int canvas_newargc;
static t_atom *canvas_newargv;
-static void glist_doupdatewindowlist(t_glist *gl, char *sbuf)
-{
- t_gobj *g;
- if (glist_amreloadingabstractions) /* not if we're in a reload */
- return;
- if (!gl->gl_owner)
- {
- /* this is a canvas; if we have a window, put on "windows" list */
- t_canvas *canvas = (t_canvas *)gl;
- if (canvas->gl_havewindow)
- {
- if (strlen(sbuf) + strlen(gl->gl_name->s_name) + 100 <= 1024)
- {
- char tbuf[1024];
- sprintf(tbuf, "{{%s} .x%lx} ", gl->gl_name->s_name,
- (t_int)canvas);
- strcat(sbuf, tbuf);
- }
- }
- }
- for (g = gl->gl_list; g; g = g->g_next)
- {
- if (pd_class(&g->g_pd) == canvas_class)
- glist_doupdatewindowlist((t_glist *)g, sbuf);
- }
- return;
-}
-
/* maintain the list of visible toplevels for the GUI's "windows" menu */
void canvas_updatewindowlist( void)
{
- t_canvas *x;
- char sbuf[1024];
- strcpy(sbuf, "set menu_windowlist {");
- /* find all root canvases */
- for (x = canvas_list; x; x = x->gl_next)
- glist_doupdatewindowlist(x, sbuf);
- /* next line updates the window menu state before -postcommand tries it */
- strcat(sbuf, "}\npdtk_fixwindowmenu\n");
- sys_gui(sbuf);
+ if (! glist_amreloadingabstractions) /* not if we're in a reload */
+ sys_gui("::pd_menus::update_window_menu\n");
}
/* add a glist the list of "root" canvases (toplevels without parents.) */
@@ -159,7 +124,7 @@ t_canvasenvironment *canvas_getenv(t_canvas *x)
if (!x) bug("canvas_getenv");
while (!x->gl_env)
if (!(x = x->gl_owner))
- bug("t_canvasenvironment", x);
+ bug("t_canvasenvironment");
return (x->gl_env);
}
@@ -234,7 +199,7 @@ void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir)
x->gl_name = s;
if (strcmp(x->gl_name->s_name, "Pd"))
pd_bind(&x->gl_pd, canvas_makebindsym(x->gl_name));
- if (glist_isvisible(x))
+ if (x->gl_havewindow)
canvas_reflecttitle(x);
if (dir && dir != &s_)
{
@@ -399,7 +364,7 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv)
x->gl_y1 = 0;
x->gl_x2 = 1;
x->gl_y2 = 1;
- canvas_setbounds(x, xloc, yloc, xloc + width, yloc + height);
+ canvas_dosetbounds(x, xloc, yloc, xloc + width, yloc + height);
x->gl_owner = owner;
x->gl_name = (*s->s_name ? s :
(canvas_newfilename ? canvas_newfilename : gensym("Pd")));
@@ -539,7 +504,14 @@ int glist_isgraph(t_glist *x)
/* This is sent from the GUI to inform a toplevel that its window has been
moved or resized. */
-static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2)
+static void canvas_setbounds(t_canvas *x, t_float left, t_float top,
+ t_float right, t_float bottom)
+{
+ canvas_dosetbounds(x, (int)left, (int)top, (int)right, (int)bottom);
+}
+
+/* this is the internal version using ints */
+static void canvas_dosetbounds(t_canvas *x, int x1, int y1, int x2, int y2)
{
int heightwas = y2 - y1;
int heightchange = y2 - y1 - (x->gl_screeny2 - x->gl_screeny1);
@@ -597,9 +569,8 @@ void canvas_reflecttitle(t_canvas *x)
strcat(namebuf, ")");
}
else namebuf[0] = 0;
- sys_vgui("wm title .x%lx {%s%c%s - %s}\n",
- x, x->gl_name->s_name, (x->gl_dirty? '*' : ' '), namebuf,
- canvas_getdir(x)->s_name);
+ sys_vgui("pdtk_canvas_reflecttitle .x%lx {%s} {%s} {%s} %d\n",
+ x, canvas_getdir(x)->s_name, x->gl_name->s_name, namebuf, x->gl_dirty);
}
/* mark a glist dirty or clean */
@@ -611,7 +582,7 @@ void canvas_dirty(t_canvas *x, t_floatarg n)
if ((unsigned)n != x2->gl_dirty)
{
x2->gl_dirty = n;
- if (glist_isvisible(x2))
+ if (x2->gl_havewindow)
canvas_reflecttitle(x2);
}
}
@@ -762,7 +733,7 @@ static void canvas_drawlines(t_canvas *x)
{
linetraverser_start(&t, x);
while (oc = linetraverser_next(&t))
- sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags l%lx\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n",
glist_getcanvas(x),
t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2,
(outlet_getsymbol(t.tr_outlet) == &s_signal ? 2:1),
@@ -904,22 +875,8 @@ void canvas_loadbang(t_canvas *x)
canvas_loadbangsubpatches(x);
}
- /* When you ask a canvas its size the result is more than what
- you gave it to open it; how much bigger apparently depends on the OS. */
-
-#ifdef __unix__
-#define HORIZBORDER 2
-#define VERTBORDER 2
-#else
-#ifdef MACOSX
-#define HORIZBORDER 6
-#define VERTBORDER 6
-#else
-#define HORIZBORDER 4
-#define VERTBORDER 4
-#endif
-#endif
-
+/* no longer used by 'pd-gui', but kept here for backwards compatibility. The
+ * new method calls canvas_setbounds() directly. */
static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom,
t_symbol *topgeom)
{
@@ -931,8 +888,8 @@ static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom,
/* for some reason this is initially called with cw=ch=1 so
we just suppress that here. */
if (cw > 5 && ch > 5)
- canvas_setbounds(x, txpix, typix,
- txpix + cw - HORIZBORDER, typix + ch - VERTBORDER);
+ canvas_dosetbounds(x, txpix, typix,
+ txpix + cw, typix + ch);
}
void canvas_popabstraction(t_canvas *x)
@@ -1543,6 +1500,8 @@ void g_canvas_setup(void)
A_DEFFLOAT, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_loadbang,
gensym("loadbang"), A_NULL);
+ class_addmethod(canvas_class, (t_method)canvas_setbounds,
+ gensym("setbounds"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_relocate,
gensym("relocate"), A_SYMBOL, A_SYMBOL, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_vis,
diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h
index e36fb48b..5dd55b45 100644
--- a/pd/src/g_canvas.h
+++ b/pd/src/g_canvas.h
@@ -108,6 +108,9 @@ typedef struct _editor
unsigned int e_lastmoved: 1; /* one if mouse has moved since click */
unsigned int e_textdirty: 1; /* one if e_textedfor has changed */
unsigned int e_selectedline: 1; /* one if a line is selected */
+ t_clock *e_clock; /* clock to filter GUI move messages */
+ int e_xnew; /* xpos for next move event */
+ int e_ynew; /* ypos, similarly */
} t_editor;
#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
@@ -478,7 +481,7 @@ EXTERN void canvas_resortinlets(t_canvas *x);
EXTERN void canvas_resortoutlets(t_canvas *x);
EXTERN void canvas_free(t_canvas *x);
EXTERN void canvas_updatewindowlist( void);
-EXTERN void canvas_editmode(t_canvas *x, t_floatarg yesplease);
+EXTERN void canvas_editmode(t_canvas *x, t_floatarg state);
EXTERN int canvas_isabstraction(t_canvas *x);
EXTERN int canvas_istable(t_canvas *x);
EXTERN int canvas_showtext(t_canvas *x);
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 0890d465..89dd874c 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -8,7 +8,11 @@
#include "m_imp.h"
#include "s_stuff.h"
#include "g_canvas.h"
+#include "s_utf8.h" /*-- moo --*/
#include <string.h>
+#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
+#define snprintf sprintf_s
+#endif
void glist_readfrombinbuf(t_glist *x, t_binbuf *b, char *filename,
int selectem);
@@ -66,7 +70,8 @@ int gobj_shouldvis(t_gobj *x, struct _glist *glist)
{
t_object *ob;
if (!glist->gl_havewindow && glist->gl_isgraph && glist->gl_goprect &&
- glist->gl_owner && (pd_class(&glist->gl_pd) != garray_class))
+ glist->gl_owner && (pd_class(&x->g_pd) != scalar_class)
+ && (pd_class(&x->g_pd) != garray_class))
{
/* if we're graphing-on-parent and the object falls outside the
graph rectangle, don't draw it. */
@@ -236,7 +241,7 @@ void glist_deselect(t_glist *x, t_gobj *y)
rtext_gettext(z, &buf, &bufsize);
text_setto((t_text *)y, x, buf, bufsize);
- canvas_fixlinesfor(glist_getcanvas(x), (t_text *)y);
+ canvas_fixlinesfor(x, (t_text *)y);
x->gl_editor->e_textedfor = 0;
}
if (fixdsp)
@@ -713,7 +718,7 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
{
t_gobj *g;
int i, nobj = glist_getindex(gl, 0); /* number of objects */
- int hadwindow = gl->gl_havewindow;
+ int hadwindow = (gl->gl_editor != 0);
for (g = gl->gl_list, i = 0; g && i < nobj; i++)
{
if (g != except && pd_class(&g->g_pd) == canvas_class &&
@@ -726,8 +731,10 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
replacement will be at the end of the list, so we don't
do g = g->g_next in this case. */
int j = glist_getindex(gl, g);
- if (!gl->gl_havewindow)
- canvas_vis(glist_getcanvas(gl), 1);
+ if (!gl->gl_editor)
+ canvas_vis(gl, 1);
+ if (!gl->gl_editor)
+ bug("editor");
glist_noselect(gl);
glist_select(gl, g);
canvas_setundo(gl, canvas_undo_cut,
@@ -744,7 +751,7 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
g = g->g_next;
}
}
- if (!hadwindow && gl->gl_havewindow)
+ if (!hadwindow && gl->gl_editor)
canvas_vis(glist_getcanvas(gl), 0);
}
@@ -768,17 +775,13 @@ void canvas_reload(t_symbol *name, t_symbol *dir, t_gobj *except)
/* ------------------------ event handling ------------------------ */
static char *cursorlist[] = {
-#ifdef MSW
- "right_ptr", /* CURSOR_RUNMODE_NOTHING */
-#else
- "left_ptr", /* CURSOR_RUNMODE_NOTHING */
-#endif
- "arrow", /* CURSOR_RUNMODE_CLICKME */
- "sb_v_double_arrow", /* CURSOR_RUNMODE_THICKEN */
- "plus", /* CURSOR_RUNMODE_ADDPOINT */
- "hand2", /* CURSOR_EDITMODE_NOTHING */
- "circle", /* CURSOR_EDITMODE_CONNECT */
- "X_cursor" /* CURSOR_EDITMODE_DISCONNECT */
+ "$cursor_runmode_nothing",
+ "$cursor_runmode_clickme",
+ "$cursor_runmode_thicken",
+ "$cursor_runmode_addpoint",
+ "$cursor_editmode_nothing",
+ "$cursor_editmode_connect",
+ "$cursor_editmode_disconnect"
};
void canvas_setcursor(t_canvas *x, unsigned int cursornum)
@@ -866,6 +869,7 @@ static t_editor *editor_new(t_glist *owner)
x->e_glist = owner;
sprintf(buf, ".x%lx", (t_int)owner);
x->e_guiconnect = guiconnect_new(&owner->gl_pd, gensym(buf));
+ x->e_clock = 0;
return (x);
}
@@ -875,6 +879,8 @@ static void editor_free(t_editor *x, t_glist *y)
guiconnect_notarget(x->e_guiconnect, 1000);
binbuf_free(x->e_connectbuf);
binbuf_free(x->e_deleted);
+ if (x->e_clock)
+ clock_free(x->e_clock);
freebytes((void *)x, sizeof(*x));
}
@@ -897,6 +903,7 @@ void canvas_destroy_editor(t_glist *x)
{
t_gobj *y;
t_object *ob;
+ glist_noselect(x);
if (x->gl_editor)
{
for (y = x->gl_list; y; y = y->g_next)
@@ -917,33 +924,38 @@ void canvas_vis(t_canvas *x, t_floatarg f)
{
char buf[30];
int flag = (f != 0);
- if (x != glist_getcanvas(x))
- bug("canvas_vis");
if (flag)
{
- /* post("havewindow %d, isgraph %d, isvisible %d editor %d",
- x->gl_havewindow, x->gl_isgraph, glist_isvisible(x),
- (x->gl_editor != 0)); */
- /* test if we're already visible and toplevel */
- if (x->gl_editor)
+ /* If a subpatch/abstraction has GOP/gl_isgraph set, then it will have
+ * a gl_editor already, if its not, it will not have a gl_editor.
+ * canvas_create_editor(x) checks if a gl_editor is already created,
+ * so its ok to run it on a canvas that already has a gl_editor. */
+ if (x->gl_editor && x->gl_havewindow)
{ /* just put us in front */
-#ifdef MSW
- canvas_vis(x, 0);
- canvas_vis(x, 1);
-#else
- sys_vgui("raise .x%lx\n", x);
- sys_vgui("focus .x%lx.c\n", x);
- sys_vgui("wm deiconify .x%lx\n", x);
-#endif
+ sys_vgui("pdtk_canvas_raise .x%lx\n", x);
}
else
{
+ char cbuf[MAXPDSTRING];
+ int cbuflen;
+ t_canvas *c = x;
canvas_create_editor(x);
sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x,
(int)(x->gl_screenx2 - x->gl_screenx1),
(int)(x->gl_screeny2 - x->gl_screeny1),
(int)(x->gl_screenx1), (int)(x->gl_screeny1),
x->gl_edit);
+ snprintf(cbuf, MAXPDSTRING - 2, "pdtk_canvas_setparents .x%lx",
+ (unsigned long)c);
+ while (c->gl_owner) {
+ c = c->gl_owner;
+ cbuflen = strlen(cbuf);
+ snprintf(cbuf + cbuflen,
+ MAXPDSTRING - cbuflen - 2,/* leave 2 for "\n\0" */
+ " .x%lx", (unsigned long)c);
+ }
+ strcat(cbuf, "\n");
+ sys_gui(cbuf);
canvas_reflecttitle(x);
x->gl_havewindow = 1;
canvas_updatewindowlist();
@@ -964,7 +976,6 @@ void canvas_vis(t_canvas *x, t_floatarg f)
canvas_destroy_editor(x);
return;
}
- sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
glist_noselect(x);
if (glist_isvisible(x))
canvas_map(x, 0);
@@ -972,7 +983,6 @@ void canvas_vis(t_canvas *x, t_floatarg f)
sys_vgui("destroy .x%lx\n", x);
for (i = 1, x2 = x; x2; x2 = x2->gl_next, i++)
;
- sys_vgui(".mbar.find delete %d\n", i);
/* if we're a graph on our parent, and if the parent exists
and is visible, show ourselves on parent. */
if (glist_isgraph(x) && x->gl_owner)
@@ -1019,16 +1029,7 @@ void canvas_setgraph(t_glist *x, int flag, int nogoprect)
gobj_vis(&x->gl_gobj, x->gl_owner, 0);
x->gl_isgraph = 1;
x->gl_hidetext = !(!(flag&2));
- if (!nogoprect && !x->gl_goprect)
- {
- t_gobj *g;
- for (g = x->gl_list; g; g = g->g_next)
- if (pd_checkobject(&g->g_pd))
- {
- x->gl_goprect = 1;
- break;
- }
- }
+ x->gl_goprect = !nogoprect;
if (glist_isvisible(x) && x->gl_goprect)
glist_redraw(x);
if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner))
@@ -1139,6 +1140,7 @@ static void canvas_donecanvasdialog(t_glist *x,
}
/* LATER avoid doing 2 redraws here (possibly one inside setgraph) */
canvas_setgraph(x, graphme, 0);
+ canvas_dirty(x, 1);
if (x->gl_havewindow)
canvas_redraw(x);
else if (glist_isvisible(x->gl_owner))
@@ -1513,10 +1515,11 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
((x22-x21-IOWIDTH) * closest2)/(ninlet2-1) : 0)
+ IOMIDDLE;
ly2 = y21;
- sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags l%lx\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n",
glist_getcanvas(x),
lx1, ly1, lx2, ly2,
(obj_issignaloutlet(ob1, closest1) ? 2 : 1), oc);
+ canvas_dirty(x, 1);
canvas_setundo(x, canvas_undo_connect,
canvas_undo_set_connect(x,
canvas_getindex(x, &ob1->ob_g), closest1,
@@ -1608,8 +1611,6 @@ void canvas_mouseup(t_canvas *x,
gobj_activate(x->gl_editor->e_selection->sel_what, x, 1);
}
}
- if (x->gl_editor->e_onmotion != MA_NONE)
- sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
x->gl_editor->e_onmotion = MA_NONE;
}
@@ -1634,6 +1635,7 @@ static void canvas_displaceselection(t_canvas *x, int dx, int dy)
}
if (resortin) canvas_resortinlets(x);
if (resortout) canvas_resortoutlets(x);
+ sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
if (x->gl_editor->e_selection)
canvas_dirty(x, 1);
}
@@ -1661,9 +1663,20 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
gotkeysym = av[1].a_w.w_symbol;
else if (av[1].a_type == A_FLOAT)
{
- char buf[3];
- sprintf(buf, "%c", (int)(av[1].a_w.w_float));
- gotkeysym = gensym(buf);
+ char buf[UTF8_MAXBYTES1];
+ switch((int)(av[1].a_w.w_float))
+ {
+ case 8: gotkeysym = gensym("BackSpace"); break;
+ case 9: gotkeysym = gensym("Tab"); break;
+ case 10: gotkeysym = gensym("Return"); break;
+ case 27: gotkeysym = gensym("Escape"); break;
+ case 32: gotkeysym = gensym("Space"); break;
+ case 127:gotkeysym = gensym("Delete"); break;
+ default:
+ /*-- moo: assume keynum is a Unicode codepoint; encode as UTF-8 --*/
+ u8_wc_toutf8_nul(buf, (UCS4)(av[1].a_w.w_float));
+ gotkeysym = gensym(buf);
+ }
}
else gotkeysym = gensym("?");
fflag = (av[0].a_type == A_FLOAT ? av[0].a_w.w_float : 0);
@@ -1770,6 +1783,15 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
CURSOR_RUNMODE_NOTHING :CURSOR_EDITMODE_NOTHING);
}
+static void delay_move(t_canvas *x)
+{
+ canvas_displaceselection(x,
+ x->gl_editor->e_xnew - x->gl_editor->e_xwas,
+ x->gl_editor->e_ynew - x->gl_editor->e_ywas);
+ x->gl_editor->e_xwas = x->gl_editor->e_xnew;
+ x->gl_editor->e_ywas = x->gl_editor->e_ynew;
+}
+
void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg fmod)
{
@@ -1783,10 +1805,12 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
glist_setlastxy(x, xpos, ypos);
if (x->gl_editor->e_onmotion == MA_MOVE)
{
- canvas_displaceselection(x,
- xpos - x->gl_editor->e_xwas, ypos - x->gl_editor->e_ywas);
- x->gl_editor->e_xwas = xpos;
- x->gl_editor->e_ywas = ypos;
+ if (!x->gl_editor->e_clock)
+ x->gl_editor->e_clock = clock_new(x, (t_method)delay_move);
+ clock_unset(x->gl_editor->e_clock);
+ clock_delay(x->gl_editor->e_clock, 5);
+ x->gl_editor->e_xnew = xpos;
+ x->gl_editor->e_ynew = ypos;
}
else if (x->gl_editor->e_onmotion == MA_REGION)
canvas_doregion(x, xpos, ypos, 0);
@@ -1858,13 +1882,12 @@ void glob_verifyquit(void *dummy, t_floatarg f)
if (g2 = glist_finddirty(g))
{
canvas_vis(g2, 1);
- sys_vgui(
-"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx menuclose 3;\n} no\n",
- canvas_getrootfor(g2), canvas_getrootfor(g2)->gl_name->s_name, g2);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;\n}\n",
+ canvas_getrootfor(g2), g2);
return;
}
if (f == 0 && sys_perf)
- sys_vgui("pdtk_check . {really quit?} {pd quit;\n} yes\n");
+ sys_vgui("pdtk_check .pdwindow {really quit?} {pd quit} yes\n");
else glob_quit(0);
}
@@ -1887,16 +1910,14 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce)
if (g)
{
vmess(&g->gl_pd, gensym("menu-open"), "");
- sys_vgui(
-"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx menuclose 2;\n} no\n",
- canvas_getrootfor(g), canvas_getrootfor(g)->gl_name->s_name, g);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n",
+ canvas_getrootfor(g), g);
return;
}
else if (sys_perf)
{
- sys_vgui(
-"pdtk_check .x%lx {Close '%s'?} {.x%lx menuclose 1;\n} yes\n",
- canvas_getrootfor(x), canvas_getrootfor(x)->gl_name->s_name, x);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 1;\n}\n",
+ canvas_getrootfor(g), g);
}
else pd_free(&x->gl_pd);
}
@@ -1911,9 +1932,8 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce)
if (g)
{
vmess(&g->gl_pd, gensym("menu-open"), "");
- sys_vgui(
-"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx menuclose 2;\n} no\n",
- canvas_getrootfor(x), canvas_getrootfor(x)->gl_name->s_name, g);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n",
+ canvas_getrootfor(x), g);
return;
}
else pd_free(&x->gl_pd);
@@ -1997,7 +2017,7 @@ static void canvas_find(t_canvas *x, t_symbol *s, t_floatarg wholeword)
if (!canvas_dofind(x, &myindex1))
{
binbuf_print(canvas_findbuf);
- post("... couldn't find");
+ sys_vgui("pdtk_couldnotfind .x%lx\n", x);
}
}
@@ -2009,7 +2029,7 @@ static void canvas_find_again(t_canvas *x)
if (!canvas_dofind(canvas_whichfind, &myindex1))
{
binbuf_print(canvas_findbuf);
- post("... couldn't find");
+ sys_vgui("pdtk_couldnotfind .x%lx\n", x);
}
}
@@ -2051,7 +2071,7 @@ void canvas_finderror(void *error_object)
if (glist_dofinderror(x, error_object))
return;
}
- post("... sorry, I couldn't find the source of that error.");
+ error("... sorry, I couldn't find the source of that error.");
}
void canvas_stowconnections(t_canvas *x)
@@ -2155,22 +2175,8 @@ static void canvas_copy(t_canvas *x)
char *buf;
int bufsize;
rtext_getseltext(x->gl_editor->e_textedfor, &buf, &bufsize);
-
-#if defined(MSW) || defined(__APPLE__)
- /* for Mac or Windows, copy the text to the clipboard here */
- sys_vgui("clipboard clear\n", bufsize, buf);
+ sys_gui("clipboard clear\n");
sys_vgui("clipboard append {%.*s}\n", bufsize, buf);
-#else
- /* in X windows the selection already went to the
- clipboard when it was made; here we "copy" it to our own buffer
- as well, because, annoyingly, the clipboard will usually be
- destroyed by the time the user asks to "paste". */
- if (canvas_textcopybuf)
- t_freebytes(canvas_textcopybuf, canvas_textcopybufsize);
- canvas_textcopybuf = (char *)getbytes(bufsize);
- memcpy(canvas_textcopybuf, buf, bufsize);
- canvas_textcopybufsize = bufsize;
-#endif
}
}
@@ -2182,6 +2188,7 @@ static void canvas_clearline(t_canvas *x)
x->gl_editor->e_selectline_outno,
x->gl_editor->e_selectline_index2,
x->gl_editor->e_selectline_inno);
+ canvas_dirty(x, 1);
canvas_setundo(x, canvas_undo_disconnect,
canvas_undo_set_disconnect(x,
x->gl_editor->e_selectline_index1,
@@ -2321,19 +2328,8 @@ static void canvas_paste(t_canvas *x)
return;
if (x->gl_editor->e_textedfor)
{
- /* simulate keystrokes as if the copy buffer were typed in. */
-#if defined(MSW) || defined(__APPLE__)
- /* for Mac or Windows, ask the GUI to send the clipboard down */
+ /* simulate keystrokes as if the copy buffer were typed in. */
sys_gui("pdtk_pastetext\n");
-#else
- /* in X windows we kept the text in our own copy buffer */
- int i;
- for (i = 0; i < canvas_textcopybufsize; i++)
- {
- pd_vmess(&x->gl_gobj.g_pd, gensym("key"), "iii",
- 1, canvas_textcopybuf[i]&0xff, 0);
- }
-#endif
}
else
{
@@ -2446,7 +2442,7 @@ void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
if (!(oc = obj_connect(objsrc, outno, objsink, inno))) goto bad;
if (glist_isvisible(x))
{
- sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags l%lx\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n",
glist_getcanvas(x), 0, 0, 0, 0,
(obj_issignaloutlet(objsrc, outno) ? 2 : 1),oc);
canvas_fixlinesfor(x, objsrc);
@@ -2586,12 +2582,9 @@ void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av)
canvas_key(canvas_editing, s, ac, av);
}
-void canvas_editmode(t_canvas *x, t_floatarg fyesplease)
+void canvas_editmode(t_canvas *x, t_floatarg state)
{
- int yesplease = fyesplease;
- if (yesplease && x->gl_edit)
- return;
- x->gl_edit = !x->gl_edit;
+ x->gl_edit = (unsigned int) state;
if (x->gl_edit && glist_isvisible(x) && glist_istoplevel(x))
canvas_setcursor(x, CURSOR_EDITMODE_NOTHING);
else
@@ -2600,7 +2593,7 @@ void canvas_editmode(t_canvas *x, t_floatarg fyesplease)
if (glist_isvisible(x) && glist_istoplevel(x))
canvas_setcursor(x, CURSOR_RUNMODE_NOTHING);
}
- sys_vgui("pdtk_canvas_editval .x%lx %d\n",
+ sys_vgui("pdtk_canvas_editmode .x%lx %d\n",
glist_getcanvas(x), x->gl_edit);
}
diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c
index b4112ddd..57db6556 100644
--- a/pd/src/g_graph.c
+++ b/pd/src/g_graph.c
@@ -176,8 +176,7 @@ void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
t_canvas *glist_getcanvas(t_glist *x)
{
- while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph &&
- gobj_shouldvis(&x->gl_gobj, x->gl_owner))
+ while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph)
x = x->gl_owner;
return((t_canvas *)x);
}
@@ -658,7 +657,6 @@ void glist_redraw(t_glist *x)
canvas_drawredrect(x, 0);
if (x->gl_goprect)
{
- post("draw it");
canvas_drawredrect(x, 1);
}
}
@@ -708,7 +706,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
if (vis)
{
sys_vgui(".x%lx.c create polygon\
- %d %d %d %d %d %d %d %d %d %d -tags %s -fill #c0c0c0\n",
+ %d %d %d %d %d %d %d %d %d %d -tags [list %s graph] -fill #c0c0c0\n",
glist_getcanvas(x->gl_owner),
x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
}
@@ -729,7 +727,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
t_garray *ga;
/* draw a rectangle around the graph */
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d -tags %s\n",
+ %d %d %d %d %d %d %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
@@ -741,7 +739,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
{
i -= sys_fontheight(glist_getfont(x));
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor nw\
- -font {{%s} -%d %s} -tags %s\n",
+ -font {{%s} -%d %s} -tags [list %s label graph]\n",
(long)glist_getcanvas(x), x1, i, arrayname->s_name, sys_font,
sys_hostfontsize(glist_getfont(x)), sys_fontweight, tag);
}
@@ -759,11 +757,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
f += x->gl_xtick.k_inc)
{
int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)upix,
(int)glist_xtopixels(x, f), (int)upix - tickpix, tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)lpix,
(int)glist_xtopixels(x, f), (int)lpix + tickpix, tag);
@@ -773,11 +771,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
i++, f -= x->gl_xtick.k_inc)
{
int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)upix,
(int)glist_xtopixels(x, f), (int)upix - tickpix, tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)lpix,
(int)glist_xtopixels(x, f), (int)lpix + tickpix, tag);
@@ -796,11 +794,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
i++, f += x->gl_ytick.k_inc)
{
int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x1, (int)glist_ytopixels(x, f),
x1 + tickpix, (int)glist_ytopixels(x, f), tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x2, (int)glist_ytopixels(x, f),
x2 - tickpix, (int)glist_ytopixels(x, f), tag);
@@ -810,11 +808,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
i++, f -= x->gl_ytick.k_inc)
{
int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x1, (int)glist_ytopixels(x, f),
x1 + tickpix, (int)glist_ytopixels(x, f), tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x2, (int)glist_ytopixels(x, f),
x2 - tickpix, (int)glist_ytopixels(x, f), tag);
@@ -823,7 +821,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
/* draw x labels */
for (i = 0; i < x->gl_nxlabels; i++)
sys_vgui(".x%lx.c create text\
- %d %d -text {%s} -font {{%s} -%d %s} -tags %s\n",
+ %d %d -text {%s} -font {{%s} -%d %s} -tags [list %s label graph]\n",
glist_getcanvas(x),
(int)glist_xtopixels(x, atof(x->gl_xlabel[i]->s_name)),
(int)glist_ytopixels(x, x->gl_xlabely),
@@ -833,7 +831,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
/* draw y labels */
for (i = 0; i < x->gl_nylabels; i++)
sys_vgui(".x%lx.c create text\
- %d %d -text {%s} -font {{%s} -%d %s} -tags %s\n",
+ %d %d -text {%s} -font {{%s} -%d %s} -tags [list %s label graph]\n",
glist_getcanvas(x),
(int)glist_xtopixels(x, x->gl_ylabelx),
(int)glist_ytopixels(x, atof(x->gl_ylabel[i]->s_name)),
@@ -936,7 +934,7 @@ static void graph_displace(t_gobj *z, t_glist *glist, int dx, int dy)
x->gl_obj.te_xpix += dx;
x->gl_obj.te_ypix += dy;
glist_redraw(x);
- canvas_fixlinesfor(glist_getcanvas(glist), &x->gl_obj);
+ canvas_fixlinesfor(glist, &x->gl_obj);
}
}
diff --git a/pd/src/g_hdial.c b/pd/src/g_hdial.c
index 19d21e84..2027dab9 100644
--- a/pd/src/g_hdial.c
+++ b/pd/src/g_hdial.c
@@ -73,16 +73,16 @@ void hradio_draw_new(t_hradio *x, t_glist *glist)
x->x_drawn = x->x_on;
}
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx11b+x->x_gui.x_ldx, yy11+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx11b, yy12-1, xx11b + IOWIDTH, yy12, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx11b, yy11, xx11b + IOWIDTH, yy11+1, x, 0);
}
@@ -311,7 +311,7 @@ static void hradio_dialog(t_hradio *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}
diff --git a/pd/src/g_hslider.c b/pd/src/g_hslider.c
index 143a8988..bf843f1a 100644
--- a/pd/src/g_hslider.c
+++ b/pd/src/g_hslider.c
@@ -33,12 +33,11 @@ static t_class *hslider_class;
static void hslider_draw_update(t_gobj *client, t_glist *glist)
{
t_hslider *x = (t_hslider *)client;
- t_canvas *canvas=glist_getcanvas(glist);
- int ypos=text_ypix(&x->x_gui.x_obj, glist);
-
if (glist_isvisible(glist))
{
int r = text_xpix(&x->x_gui.x_obj, glist) + (x->x_val + 50)/100;
+ int ypos=text_ypix(&x->x_gui.x_obj, glist);
+ t_canvas *canvas=glist_getcanvas(glist);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, r, ypos+1,
r, ypos + x->x_gui.x_h);
@@ -76,18 +75,18 @@ static void hslider_draw_new(t_hslider *x, t_glist *glist)
canvas, r, ypos+1, r,
ypos + x->x_gui.x_h, x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xpos-3, ypos + x->x_gui.x_h-1,
xpos+4, ypos + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xpos-3, ypos,
xpos+4, ypos+1, x, 0);
}
@@ -370,7 +369,7 @@ static void hslider_dialog(t_hslider *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void hslider_motion(t_hslider *x, t_floatarg dx, t_floatarg dy)
diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c
index f673f8ed..741e6871 100644
--- a/pd/src/g_mycanvas.c
+++ b/pd/src/g_mycanvas.c
@@ -44,7 +44,7 @@ void my_canvas_draw_new(t_my_canvas *x, t_glist *glist)
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c
index 75f6bbbf..60a6e51b 100644
--- a/pd/src/g_numbox.c
+++ b/pd/src/g_numbox.c
@@ -195,7 +195,7 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
xpos, ypos + x->x_gui.x_h,
x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
@@ -207,13 +207,13 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
x->x_buf, x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_fcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h-1,
xpos+IOWIDTH, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos,
xpos+IOWIDTH, ypos+1,
@@ -512,7 +512,7 @@ static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc,
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy)
diff --git a/pd/src/g_readwrite.c b/pd/src/g_readwrite.c
index 97b56c02..9f809759 100644
--- a/pd/src/g_readwrite.c
+++ b/pd/src/g_readwrite.c
@@ -704,7 +704,11 @@ static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir)
{
/* if not an abstraction, reset title bar and directory */
if (!x->gl_owner)
+{
canvas_rename(x, filename, dir);
+ /* update window list in case Save As changed the window name */
+ canvas_updatewindowlist();
+}
post("saved to: %s/%s", dir->s_name, filename->s_name);
canvas_dirty(x, 0);
canvas_reload(filename, dir, &x->gl_gobj);
@@ -715,7 +719,7 @@ static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir)
static void canvas_menusaveas(t_canvas *x)
{
t_canvas *x2 = canvas_getrootfor(x);
- sys_vgui("pdtk_canvas_saveas .x%lx \"%s\" \"%s\"\n", x2,
+ sys_vgui("pdtk_canvas_saveas .x%lx {%s} {%s}\n", x2,
x2->gl_name->s_name, canvas_getdir(x2)->s_name);
}
@@ -724,7 +728,8 @@ static void canvas_menusave(t_canvas *x)
t_canvas *x2 = canvas_getrootfor(x);
char *name = x2->gl_name->s_name;
if (*name && strncmp(name, "Untitled", 8)
- && (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat")))
+ && (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat")
+ || strcmp(name + strlen(name)-4, ".mxt")))
canvas_savetofile(x2, x2->gl_name, canvas_getdir(x2));
else canvas_menusaveas(x2);
}
diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c
index 976901e9..e63a172d 100644
--- a/pd/src/g_rtext.c
+++ b/pd/src/g_rtext.c
@@ -13,6 +13,7 @@
#include "m_pd.h"
#include "s_stuff.h"
#include "g_canvas.h"
+#include "s_utf8.h"
#define LMARGIN 2
@@ -32,10 +33,10 @@
struct _rtext
{
- char *x_buf;
- int x_bufsize;
- int x_selstart;
- int x_selend;
+ char *x_buf; /*-- raw byte string, assumed UTF-8 encoded (moo) --*/
+ int x_bufsize; /*-- byte length --*/
+ int x_selstart; /*-- byte offset --*/
+ int x_selend; /*-- byte offset --*/
int x_active;
int x_dragfrom;
int x_height;
@@ -104,8 +105,30 @@ void rtext_getseltext(t_rtext *x, char **buf, int *bufsize)
*bufsize = x->x_selend - x->x_selstart;
}
+/* convert t_text te_type symbol for use as a Tk tag */
+static t_symbol *rtext_gettype(t_rtext *x)
+{
+ switch (x->x_text->te_type)
+ {
+ case T_TEXT: return gensym("text");
+ case T_OBJECT: return gensym("obj");
+ case T_MESSAGE: return gensym("msg");
+ case T_ATOM: return gensym("atom");
+ }
+ return (&s_);
+}
+
/* LATER deal with tcl-significant characters */
+/* firstone(), lastone()
+ * + returns byte offset of (first|last) occurrence of 'c' in 's[0..n-1]', or
+ * -1 if none was found
+ * + 's' is a raw byte string
+ * + 'c' is a byte value
+ * + 'n' is the length (in bytes) of the prefix of 's' to be searched.
+ * + we could make these functions work on logical characters in utf8 strings,
+ * but we don't really need to...
+ */
static int firstone(char *s, int c, int n)
{
char *s2 = s + n;
@@ -142,6 +165,16 @@ static int lastone(char *s, int c, int n)
of the entire text in pixels.
*/
+ /*-- moo:
+ * + some variables from the original version have been renamed
+ * + variables with a "_b" suffix are raw byte strings, lengths, or offsets
+ * + variables with a "_c" suffix are logical character lengths or offsets
+ * (assuming valid UTF-8 encoded byte string in x->x_buf)
+ * + a fair amount of O(n) computations required to convert between raw byte
+ * offsets (needed by the C side) and logical character offsets (needed by
+ * the GUI)
+ */
+
/* LATER get this and sys_vgui to work together properly,
breaking up messages as needed. As of now, there's
a limit of 1950 characters, imposed by sys_vgui(). */
@@ -158,14 +191,16 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
{
t_float dispx, dispy;
char smallbuf[200], *tempbuf;
- int outchars = 0, nlines = 0, ncolumns = 0,
+ int outchars_b = 0, nlines = 0, ncolumns = 0,
pixwide, pixhigh, font, fontwidth, fontheight, findx, findy;
int reportedindex = 0;
t_canvas *canvas = glist_getcanvas(x->x_glist);
- int widthspec = x->x_text->te_width;
- int widthlimit = (widthspec ? widthspec : BOXWIDTH);
- int inindex = 0;
- int selstart = 0, selend = 0;
+ int widthspec_c = x->x_text->te_width;
+ int widthlimit_c = (widthspec_c ? widthspec_c : BOXWIDTH);
+ int inindex_b = 0;
+ int inindex_c = 0;
+ int selstart_b = 0, selend_b = 0;
+ int x_bufsize_c = u8_charnum(x->x_buf, x->x_bufsize);
/* if we're a GOP (the new, "goprect" style) borrow the font size
from the inside to preserve the spacing */
if (pd_class(&x->x_text->te_pd) == canvas_class &&
@@ -180,97 +215,109 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
if (x->x_bufsize >= 100)
tempbuf = (char *)t_getbytes(2 * x->x_bufsize + 1);
else tempbuf = smallbuf;
- while (x->x_bufsize - inindex > 0)
+ while (x_bufsize_c - inindex_c > 0)
{
- int inchars = x->x_bufsize - inindex;
- int maxindex = (inchars > widthlimit ? widthlimit : inchars);
+ int inchars_b = x->x_bufsize - inindex_b;
+ int inchars_c = x_bufsize_c - inindex_c;
+ int maxindex_c = (inchars_c > widthlimit_c ? widthlimit_c : inchars_c);
+ int maxindex_b = u8_offset(x->x_buf + inindex_b, maxindex_c);
int eatchar = 1;
- int foundit = firstone(x->x_buf + inindex, '\n', maxindex);
- if (foundit < 0)
+ int foundit_b = firstone(x->x_buf + inindex_b, '\n', maxindex_b);
+ int foundit_c;
+ if (foundit_b < 0)
{
- if (inchars > widthlimit)
+ if (inchars_c > widthlimit_c)
{
- foundit = lastone(x->x_buf + inindex, ' ', maxindex);
- if (foundit < 0)
+ foundit_b = lastone(x->x_buf + inindex_b, ' ', maxindex_b);
+ if (foundit_b < 0)
{
- foundit = maxindex;
+ foundit_b = maxindex_b;
+ foundit_c = maxindex_c;
eatchar = 0;
}
+ else
+ foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b);
}
else
{
- foundit = inchars;
+ foundit_b = inchars_b;
+ foundit_c = inchars_c;
eatchar = 0;
}
}
+ else
+ foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b);
+
if (nlines == findy)
{
int actualx = (findx < 0 ? 0 :
- (findx > foundit ? foundit : findx));
- *indexp = inindex + actualx;
+ (findx > foundit_c ? foundit_c : findx));
+ *indexp = inindex_b + u8_offset(x->x_buf + inindex_b, actualx);
reportedindex = 1;
}
- strncpy(tempbuf+outchars, x->x_buf + inindex, foundit);
- if (x->x_selstart >= inindex &&
- x->x_selstart <= inindex + foundit + eatchar)
- selstart = x->x_selstart + outchars - inindex;
- if (x->x_selend >= inindex &&
- x->x_selend <= inindex + foundit + eatchar)
- selend = x->x_selend + outchars - inindex;
- outchars += foundit;
- inindex += (foundit + eatchar);
- if (inindex < x->x_bufsize)
- tempbuf[outchars++] = '\n';
- if (foundit > ncolumns)
- ncolumns = foundit;
+ strncpy(tempbuf+outchars_b, x->x_buf + inindex_b, foundit_b);
+ if (x->x_selstart >= inindex_b &&
+ x->x_selstart <= inindex_b + foundit_b + eatchar)
+ selstart_b = x->x_selstart + outchars_b - inindex_b;
+ if (x->x_selend >= inindex_b &&
+ x->x_selend <= inindex_b + foundit_b + eatchar)
+ selend_b = x->x_selend + outchars_b - inindex_b;
+ outchars_b += foundit_b;
+ inindex_b += (foundit_b + eatchar);
+ inindex_c += (foundit_c + eatchar);
+ if (inindex_b < x->x_bufsize)
+ tempbuf[outchars_b++] = '\n';
+ if (foundit_c > ncolumns)
+ ncolumns = foundit_c;
nlines++;
}
if (!reportedindex)
- *indexp = outchars;
+ *indexp = outchars_b;
dispx = text_xpix(x->x_text, x->x_glist);
dispy = text_ypix(x->x_text, x->x_glist);
if (nlines < 1) nlines = 1;
- if (!widthspec)
+ if (!widthspec_c)
{
while (ncolumns < 3)
{
- tempbuf[outchars++] = ' ';
+ tempbuf[outchars_b++] = ' ';
ncolumns++;
}
}
- else ncolumns = widthspec;
+ else ncolumns = widthspec_c;
pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
if (action == SEND_FIRST)
- sys_vgui("pdtk_text_new .x%lx.c %s %f %f {%.*s} %d %s\n",
- canvas, x->x_tag,
+ sys_vgui("pdtk_text_new .x%lx.c {%s %s text} %f %f {%.*s} %d %s\n",
+ canvas, x->x_tag, rtext_gettype(x)->s_name,
dispx + LMARGIN, dispy + TMARGIN,
- outchars, tempbuf, sys_hostfontsize(font),
+ outchars_b, tempbuf, sys_hostfontsize(font),
(glist_isselected(x->x_glist,
&x->x_glist->gl_gobj)? "blue" : "black"));
else if (action == SEND_UPDATE)
{
sys_vgui("pdtk_text_set .x%lx.c %s {%.*s}\n",
- canvas, x->x_tag, outchars, tempbuf);
+ canvas, x->x_tag, outchars_b, tempbuf);
if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight)
text_drawborder(x->x_text, x->x_glist, x->x_tag,
pixwide, pixhigh, 0);
if (x->x_active)
{
- if (selend > selstart)
+ if (selend_b > selstart_b)
{
sys_vgui(".x%lx.c select from %s %d\n", canvas,
- x->x_tag, selstart);
+ x->x_tag, u8_charnum(x->x_buf, selstart_b));
sys_vgui(".x%lx.c select to %s %d\n", canvas,
- x->x_tag, selend + (sys_oldtclversion ? 0 : -1));
+ x->x_tag, u8_charnum(x->x_buf, selend_b)
+ + (sys_oldtclversion ? 0 : -1));
sys_vgui(".x%lx.c focus \"\"\n", canvas);
}
else
{
sys_vgui(".x%lx.c select clear\n", canvas);
sys_vgui(".x%lx.c icursor %s %d\n", canvas, x->x_tag,
- selstart);
+ u8_charnum(x->x_buf, selstart_b));
sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag);
}
}
@@ -398,7 +445,7 @@ void rtext_activate(t_rtext *x, int state)
t_canvas *canvas = glist_getcanvas(glist);
if (state)
{
- sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag);
+ sys_vgui("pdtk_text_editing .x%lx %s 1\n", canvas, x->x_tag);
glist->gl_editor->e_textedfor = x;
glist->gl_editor->e_textdirty = 0;
x->x_dragfrom = x->x_selstart = 0;
@@ -407,8 +454,7 @@ void rtext_activate(t_rtext *x, int state)
}
else
{
- sys_vgui("selection clear .x%lx.c\n", canvas);
- sys_vgui(".x%lx.c focus \"\"\n", canvas);
+ sys_vgui("pdtk_text_editing .x%lx {} 0\n", canvas);
if (glist->gl_editor->e_textedfor == x)
glist->gl_editor->e_textedfor = 0;
x->x_active = 0;
@@ -433,12 +479,12 @@ void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
....
} */
if (x->x_selstart && (x->x_selstart == x->x_selend))
- x->x_selstart--;
+ u8_dec(x->x_buf, &x->x_selstart);
}
else if (n == 127) /* delete */
{
if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend))
- x->x_selend++;
+ u8_inc(x->x_buf, &x->x_selend);
}
ndel = x->x_selend - x->x_selstart;
@@ -451,7 +497,13 @@ void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
/* at Guenter's suggestion, use 'n>31' to test wither a character might
be printable in whatever 8-bit character set we find ourselves. */
- if (n == '\n' || (n > 31 && n != 127))
+/*-- moo:
+ ... but test with "<" rather than "!=" in order to accomodate unicode
+ codepoints for n (which we get since Tk is sending the "%A" substitution
+ for bind <Key>), effectively reducing the coverage of this clause to 7
+ bits. Case n>127 is covered by the next clause.
+*/
+ if (n == '\n' || (n > 31 && n < 127))
{
newsize = x->x_bufsize+1;
x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
@@ -461,20 +513,39 @@ be printable in whatever 8-bit character set we find ourselves. */
x->x_bufsize = newsize;
x->x_selstart = x->x_selstart + 1;
}
+ /*--moo: check for unicode codepoints beyond 7-bit ASCII --*/
+ else if (n > 127)
+ {
+ int ch_nbytes = u8_wc_nbytes(n);
+ newsize = x->x_bufsize + ch_nbytes;
+ x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
+ for (i = x->x_bufsize; i > x->x_selstart; i--)
+ x->x_buf[i] = x->x_buf[i-1];
+ x->x_bufsize = newsize;
+ /*-- moo: assume canvas_key() has encoded keysym as UTF-8 */
+ strncpy(x->x_buf+x->x_selstart, keysym->s_name, ch_nbytes);
+ x->x_selstart = x->x_selstart + ch_nbytes;
+ }
x->x_selend = x->x_selstart;
x->x_glist->gl_editor->e_textdirty = 1;
}
else if (!strcmp(keysym->s_name, "Right"))
{
if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize)
- x->x_selend = x->x_selstart = x->x_selstart + 1;
+ {
+ u8_inc(x->x_buf, &x->x_selstart);
+ x->x_selend = x->x_selstart;
+ }
else
x->x_selstart = x->x_selend;
}
else if (!strcmp(keysym->s_name, "Left"))
{
if (x->x_selend == x->x_selstart && x->x_selstart > 0)
- x->x_selend = x->x_selstart = x->x_selstart - 1;
+ {
+ u8_dec(x->x_buf, &x->x_selstart);
+ x->x_selend = x->x_selstart;
+ }
else
x->x_selend = x->x_selstart;
}
@@ -482,18 +553,18 @@ be printable in whatever 8-bit character set we find ourselves. */
else if (!strcmp(keysym->s_name, "Up"))
{
if (x->x_selstart)
- x->x_selstart--;
+ u8_dec(x->x_buf, &x->x_selstart);
while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
- x->x_selstart--;
+ u8_dec(x->x_buf, &x->x_selstart);
x->x_selend = x->x_selstart;
}
else if (!strcmp(keysym->s_name, "Down"))
{
while (x->x_selend < x->x_bufsize &&
x->x_buf[x->x_selend] != '\n')
- x->x_selend++;
+ u8_inc(x->x_buf, &x->x_selend);
if (x->x_selend < x->x_bufsize)
- x->x_selend++;
+ u8_inc(x->x_buf, &x->x_selend);
x->x_selstart = x->x_selend;
}
rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
diff --git a/pd/src/g_template.c b/pd/src/g_template.c
index f216b104..a2b583d0 100644
--- a/pd/src/g_template.c
+++ b/pd/src/g_template.c
@@ -762,14 +762,20 @@ static void fielddesc_setfloat_var(t_fielddesc *fd, t_symbol *s)
else
{
int cpy = s1 - s->s_name, got;
+ double v1, v2, screen1, screen2, quantum;
if (cpy > MAXPDSTRING-5)
cpy = MAXPDSTRING-5;
strncpy(strbuf, s->s_name, cpy);
strbuf[cpy] = 0;
fd->fd_un.fd_varsym = gensym(strbuf);
- got = sscanf(s1, "(%f:%f)(%f:%f)(%f)",
- &fd->fd_v1, &fd->fd_v2, &fd->fd_screen1, &fd->fd_screen2,
- &fd->fd_quantum);
+ got = sscanf(s1, "(%lf:%lf)(%lf:%lf)(%lf)",
+ &v1, &v2, &screen1, &screen2,
+ &quantum);
+ fd->fd_v1=v1;
+ fd->fd_v2=v2;
+ fd->fd_screen1=screen1;
+ fd->fd_screen2=screen2;
+ fd->fd_quantum=quantum;
if (got < 2)
goto fail;
if (got == 3 || (got < 4 && strchr(s2, '(')))
@@ -1715,8 +1721,8 @@ static void plot_vis(t_gobj *z, t_glist *glist,
minyval = yval;
if (i == nelem-1 || inextx != ixpix)
{
- sys_vgui(
-".x%lx.c create rectangle %d %d %d %d -fill black -width 0 -tags plot%lx\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d \
+-fill black -width 0 -tags [list plot%lx array]\n",
glist_getcanvas(glist),
ixpix, (int)glist_ytopixels(glist,
basey + fielddesc_cvttocoord(yfielddesc, minyval)),
@@ -1815,7 +1821,7 @@ static void plot_vis(t_gobj *z, t_glist *glist,
outline, outline);
if (style == PLOTSTYLE_BEZ) sys_vgui("-smooth 1\\\n");
- sys_vgui("-tags plot%lx\n", data);
+ sys_vgui("-tags [list plot%lx array]\n", data);
}
else if (linewidth > 0)
{
@@ -1858,7 +1864,7 @@ static void plot_vis(t_gobj *z, t_glist *glist,
sys_vgui("-fill %s\\\n", outline);
if (style == PLOTSTYLE_BEZ) sys_vgui("-smooth 1\\\n");
- sys_vgui("-tags plot%lx\n", data);
+ sys_vgui("-tags [list plot%lx array]\n", data);
}
}
/* We're done with the outline; now draw all the points.
@@ -2138,7 +2144,7 @@ static void drawnumber_vis(t_gobj *z, t_glist *glist,
glist_getcanvas(glist), xloc, yloc, colorstring, buf);
sys_vgui(" -font {{%s} -%d %s}", sys_font,
sys_hostfontsize(glist_getfont(glist)), sys_fontweight);
- sys_vgui(" -tags drawnumber%lx\n", data);
+ sys_vgui(" -tags [list drawnumber%lx label]\n", data);
}
else sys_vgui(".x%lx.c delete drawnumber%lx\n", glist_getcanvas(glist), data);
}
@@ -2225,7 +2231,7 @@ static void drawnumber_key(void *z, t_floatarg fkey)
else
{
/* key entry for a numeric field. This is just a stopgap. */
- float newf;
+ double newf;
if (drawnumber_motion_firstkey)
sbuf[0] = 0;
else sprintf(sbuf, "%g", template_getfloat(drawnumber_motion_template,
@@ -2241,10 +2247,10 @@ static void drawnumber_key(void *z, t_floatarg fkey)
sbuf[strlen(sbuf)+1] = 0;
sbuf[strlen(sbuf)] = key;
}
- if (sscanf(sbuf, "%g", &newf) < 1)
+ if (sscanf(sbuf, "%lg", &newf) < 1)
newf = 0;
template_setfloat(drawnumber_motion_template,
- f->fd_un.fd_varsym, drawnumber_motion_wp, newf, 1);
+ f->fd_un.fd_varsym, drawnumber_motion_wp, (t_float)newf, 1);
if (drawnumber_motion_scalar)
template_notifyforscalar(drawnumber_motion_template,
drawnumber_motion_glist, drawnumber_motion_scalar,
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index cff52274..a6e50491 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -16,6 +16,8 @@
#include <string.h>
#include <math.h>
+#include "s_utf8.h"
+
t_class *text_class;
static t_class *message_class;
static t_class *gatom_class;
@@ -97,13 +99,13 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
if (!newest)
{
binbuf_print(b);
- post("... couldn't create");
+ error("... couldn't create");
x = 0;
}
else if (!(x = pd_checkobject(newest)))
{
binbuf_print(b);
- post("... didn't return a patchable object");
+ error("... didn't return a patchable object");
}
}
else x = 0;
@@ -675,7 +677,6 @@ static void gatom_key(void *z, t_floatarg f)
gatom_retext(x, 1);
return;
}
- else if (c == ' ') return;
else if (c == '\b')
{
if (len > 0)
@@ -700,8 +701,22 @@ static void gatom_key(void *z, t_floatarg f)
(c >= '0' && c <= '9' || c == '.' || c == '-'
|| c == 'e' || c == 'E'))
{
- x->a_buf[len] = c;
- x->a_buf[len+1] = 0;
+ /* the wchar could expand to up to 4 bytes, which
+ * which might overrun our a_buf;
+ * therefore we first expand into a temporary buffer,
+ * and only if the resulting utf8 string fits into a_buf
+ * we apply it
+ */
+ char utf8[UTF8_MAXBYTES];
+ int utf8len = u8_wc_toutf8(utf8, c);
+ if((len+utf8len) < (ATOMBUFSIZE-1))
+ {
+ int j=0;
+ for(j=0; j<utf8len; j++)
+ x->a_buf[len+j] = utf8[j];
+
+ x->a_buf[len+utf8len] = 0;
+ }
goto redraw;
}
}
@@ -793,6 +808,7 @@ static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
x->a_symto = symto;
x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
gobj_vis(&x->a_text.te_g, x->a_glist, 1);
+ canvas_dirty(x->a_glist, 1);
/* glist_retext(x->a_glist, &x->a_text); */
}
@@ -847,7 +863,7 @@ static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
{
int x1, y1;
gatom_getwherelabel(x, glist, &x1, &y1);
- sys_vgui("pdtk_text_new .x%lx.c %lx.l %f %f {%s} %d %s\n",
+ sys_vgui("pdtk_text_new .x%lx.c {%lx.l label text} %f %f {%s} %d %s\n",
glist_getcanvas(glist), x,
(double)x1, (double)y1,
canvas_realizedollar(x->a_glist, x->a_label)->s_name,
@@ -1026,7 +1042,7 @@ static void text_displace(t_gobj *z, t_glist *glist,
rtext_displace(y, dx, dy);
text_drawborder(x, glist, rtext_gettag(y),
rtext_width(y), rtext_height(y), 0);
- canvas_fixlinesfor(glist_getcanvas(glist), x);
+ canvas_fixlinesfor(glist, x);
}
}
@@ -1210,7 +1226,8 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
{
int onset = x1 + (width - IOWIDTH) * i / nplus;
if (firsttime)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %so%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d \
+-tags [list %so%d outlet]\n",
glist_getcanvas(glist),
onset, y2 - 1,
onset + IOWIDTH, y2,
@@ -1227,7 +1244,8 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
{
int onset = x1 + (width - IOWIDTH) * i / nplus;
if (firsttime)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %si%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d \
+-tags [list %si%d inlet]\n",
glist_getcanvas(glist),
onset, y1,
onset + IOWIDTH, y1 + EXTRAPIX,
@@ -1253,7 +1271,7 @@ void text_drawborder(t_text *x, t_glist *glist,
char *pattern = ((pd_class(&x->te_pd) == text_class) ? "-" : "\"\"");
if (firsttime)
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d -dash %s -tags %sR\n",
+ %d %d %d %d %d %d %d %d %d %d -dash %s -tags [list %sR obj]\n",
glist_getcanvas(glist),
x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, pattern, tag);
else
@@ -1270,7 +1288,7 @@ void text_drawborder(t_text *x, t_glist *glist,
{
if (firsttime)
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
+ %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags [list %sR msg]\n",
glist_getcanvas(glist),
x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
x1, y2, x1, y1,
@@ -1286,7 +1304,7 @@ void text_drawborder(t_text *x, t_glist *glist,
{
if (firsttime)
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
+ %d %d %d %d %d %d %d %d %d %d %d %d -tags [list %sR atom]\n",
glist_getcanvas(glist),
x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1,
tag);
diff --git a/pd/src/g_toggle.c b/pd/src/g_toggle.c
index 344e1522..7e112a47 100644
--- a/pd/src/g_toggle.c
+++ b/pd/src/g_toggle.c
@@ -61,17 +61,17 @@ void toggle_draw_new(t_toggle *x, t_glist *glist)
canvas, xx+w+1, yy + x->x_gui.x_h-w-1, xx + x->x_gui.x_w-w, yy+w, w,
(x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx+x->x_gui.x_ldx,
yy+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx, yy + x->x_gui.x_h-1, xx + IOWIDTH, yy + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx, yy, xx + IOWIDTH, yy+1, x, 0);
}
@@ -271,7 +271,7 @@ static void toggle_dialog(t_toggle *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void toggle_click(t_toggle *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
diff --git a/pd/src/g_vdial.c b/pd/src/g_vdial.c
index f5364750..71347794 100644
--- a/pd/src/g_vdial.c
+++ b/pd/src/g_vdial.c
@@ -75,16 +75,16 @@ void vradio_draw_new(t_vradio *x, t_glist *glist)
x->x_drawn = x->x_on;
}
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx11+x->x_gui.x_ldx, yy11b+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx11, yy11-1, xx11 + IOWIDTH, yy11, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx11, yy11b, xx11 + IOWIDTH, yy11b+1, x, 0);
}
@@ -312,7 +312,7 @@ static void vradio_dialog(t_vradio *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}
diff --git a/pd/src/g_vslider.c b/pd/src/g_vslider.c
index 6b547f84..ddeb5421 100644
--- a/pd/src/g_vslider.c
+++ b/pd/src/g_vslider.c
@@ -59,19 +59,19 @@ static void vslider_draw_new(t_vslider *x, t_glist *glist)
canvas, xpos+1, r,
xpos + x->x_gui.x_w, r, x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h+2,
xpos+7, ypos + x->x_gui.x_h+3,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos-2,
xpos+7, ypos-1,
@@ -336,7 +336,7 @@ static void vslider_dialog(t_vslider *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void vslider_motion(t_vslider *x, t_floatarg dx, t_floatarg dy)
diff --git a/pd/src/g_vumeter.c b/pd/src/g_vumeter.c
index 75047e8d..fb275b78 100644
--- a/pd/src/g_vumeter.c
+++ b/pd/src/g_vumeter.c
@@ -138,19 +138,19 @@ static void vu_draw_new(t_vu *x, t_glist *glist)
canvas, mid, ypos+10,
mid, ypos+10, x->x_led_size, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
{
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos-1, ypos + x->x_gui.x_h+1,
xpos + IOWIDTH-1, ypos + x->x_gui.x_h+2,
x, 0);
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]x\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos + x->x_gui.x_h+1,
xpos+x->x_gui.x_w+1, ypos + x->x_gui.x_h+2,
@@ -158,12 +158,12 @@ static void vu_draw_new(t_vu *x, t_glist *glist)
}
if(!x->x_gui.x_fsf.x_rcv_able)
{
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos-1, ypos-2,
xpos + IOWIDTH-1, ypos-1,
x, 0);
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos-2,
xpos+x->x_gui.x_w+1, ypos-1,
@@ -542,7 +542,7 @@ static void vu_dialog(t_vu *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av)
@@ -554,7 +554,7 @@ static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}
diff --git a/pd/src/m_atom.c b/pd/src/m_atom.c
index f8859c6f..16df0e35 100644
--- a/pd/src/m_atom.c
+++ b/pd/src/m_atom.c
@@ -79,7 +79,7 @@ void atom_string(t_atom *a, char *buf, unsigned int bufsize)
sprintf(tbuf, "%g", a->a_w.w_float);
if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf);
else if (a->a_w.w_float < 0) strcpy(buf, "-");
- else strcat(buf, "+");
+ else strcpy(buf, "+");
break;
case A_SYMBOL:
{
diff --git a/pd/src/m_binbuf.c b/pd/src/m_binbuf.c
index 360512d0..d109ae56 100644
--- a/pd/src/m_binbuf.c
+++ b/pd/src/m_binbuf.c
@@ -862,7 +862,8 @@ int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
if (*dir)
strcat(fbuf, dir), strcat(fbuf, "/");
strcat(fbuf, filename);
- if (!strcmp(filename + strlen(filename) - 4, ".pat"))
+ if (!strcmp(filename + strlen(filename) - 4, ".pat") ||
+ !strcmp(filename + strlen(filename) - 4, ".mxt"))
{
x = binbuf_convert(x, 0);
deleteit = 1;
@@ -943,14 +944,15 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
t_binbuf *newb = binbuf_new();
t_atom *vec = oldb->b_vec;
t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK],
- nobj = 0, i;
+ nobj = 0, i, gotfontsize = 0;
t_atom outmess[MAXSTACK], *nextmess;
+ t_float fontsize = 10;
if (!maxtopd)
binbuf_addv(newb, "ss;", gensym("max"), gensym("v2"));
for (nextindex = 0; nextindex < n; )
{
int endmess, natom;
- char *first, *second;
+ char *first, *second, *third;
for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI;
endmess++)
;
@@ -993,7 +995,7 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
{
if (stackdepth >= MAXSTACK)
{
- post("too many embedded patches");
+ error("stack depth exceeded: too many embedded patches");
return (newb);
}
stack[stackdepth] = nobj;
@@ -1137,11 +1139,49 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
}
else if (!strcmp(second, "user"))
{
- binbuf_addv(newb, "ssffs;",
- gensym("#X"), gensym("obj"),
- atom_getfloatarg(3, natom, nextmess),
- atom_getfloatarg(4, natom, nextmess),
- atom_getsymbolarg(2, natom, nextmess));
+ third = (nextmess+2)->a_w.w_symbol->s_name;
+ if (!strcmp(third, "hslider"))
+ {
+ t_float range = atom_getfloatarg(7, natom, nextmess);
+ t_float multiplier = atom_getfloatarg(8, natom, nextmess);
+ t_float offset = atom_getfloatarg(9, natom, nextmess);
+ binbuf_addv(newb, "ssffsffffffsssfffffffff;",
+ gensym("#X"), gensym("obj"),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(4, natom, nextmess),
+ gensym("hsl"),
+ atom_getfloatarg(6, natom, nextmess),
+ atom_getfloatarg(5, natom, nextmess),
+ offset,
+ range + offset,
+ 0., 0.,
+ gensym("empty"), gensym("empty"), gensym("empty"),
+ 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
+ }
+ else if (!strcmp(third, "uslider"))
+ {
+ t_float range = atom_getfloatarg(7, natom, nextmess);
+ t_float multiplier = atom_getfloatarg(8, natom, nextmess);
+ t_float offset = atom_getfloatarg(9, natom, nextmess);
+ binbuf_addv(newb, "ssffsffffffsssfffffffff;",
+ gensym("#X"), gensym("obj"),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(4, natom, nextmess),
+ gensym("vsl"),
+ atom_getfloatarg(5, natom, nextmess),
+ atom_getfloatarg(6, natom, nextmess),
+ offset,
+ range + offset,
+ 0., 0.,
+ gensym("empty"), gensym("empty"), gensym("empty"),
+ 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
+ }
+ else
+ binbuf_addv(newb, "ssffs;",
+ gensym("#X"), gensym("obj"),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(4, natom, nextmess),
+ atom_getsymbolarg(2, natom, nextmess));
nobj++;
}
else if (!strcmp(second, "connect")||
@@ -1162,20 +1202,26 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
{
if (!strcmp(second, "canvas"))
{
+ t_float x, y;
if (stackdepth >= MAXSTACK)
{
- post("too many embedded patches");
+ error("stack depth exceeded: too many embedded patches");
return (newb);
}
stack[stackdepth] = nobj;
stackdepth++;
nobj = 0;
+ if(!gotfontsize) { /* only the first canvas sets the font size */
+ fontsize = atom_getfloatarg(6, natom, nextmess);
+ gotfontsize = 1;
+ }
+ x = atom_getfloatarg(2, natom, nextmess);
+ y = atom_getfloatarg(3, natom, nextmess);
binbuf_addv(newb, "ssffff;",
gensym("#N"), gensym("vpatcher"),
- atom_getfloatarg(2, natom, nextmess),
- atom_getfloatarg(3, natom, nextmess),
- atom_getfloatarg(4, natom, nextmess),
- atom_getfloatarg(5, natom, nextmess));
+ x, y,
+ atom_getfloatarg(4, natom, nextmess) + x,
+ atom_getfloatarg(5, natom, nextmess) + y);
}
}
if (!strcmp(first, "#X"))
@@ -1184,12 +1230,17 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
&& (ISSYMBOL (&nextmess[4], "pd")))
{
binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
- binbuf_addv(newb, "ssffffss;",
- gensym("#P"), gensym("newobj"),
- atom_getfloatarg(2, natom, nextmess),
- atom_getfloatarg(3, natom, nextmess), 50., 1.,
- gensym("patcher"),
- atom_getsymbolarg(5, natom, nextmess));
+ SETSYMBOL(outmess, gensym("#P"));
+ SETSYMBOL(outmess + 1, gensym("newobj"));
+ outmess[2] = nextmess[2];
+ outmess[3] = nextmess[3];
+ SETFLOAT(outmess + 4, 50.*(natom-5));
+ SETFLOAT(outmess + 5, fontsize);
+ SETSYMBOL(outmess + 6, gensym("p"));
+ for (i = 5; i < natom; i++)
+ outmess[i+2] = nextmess[i];
+ SETSEMI(outmess + natom + 2);
+ binbuf_add(newb, natom + 3, outmess);
if (stackdepth) stackdepth--;
nobj = stack[stackdepth];
nobj++;
@@ -1203,25 +1254,25 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
gensym("inlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15.);
+ 10. + fontsize);
else if (classname == gensym("inlet~"))
binbuf_addv(newb, "ssffff;", gensym("#P"),
gensym("inlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15., 1.);
+ 10. + fontsize, 1.);
else if (classname == gensym("outlet"))
binbuf_addv(newb, "ssfff;", gensym("#P"),
gensym("outlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15.);
+ 10. + fontsize);
else if (classname == gensym("outlet~"))
binbuf_addv(newb, "ssffff;", gensym("#P"),
gensym("outlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15., 1.);
+ 10. + fontsize, 1.);
else if (classname == gensym("bng"))
binbuf_addv(newb, "ssffff;", gensym("#P"),
gensym("button"),
@@ -1246,16 +1297,65 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
(atom_getfloatarg(6, natom, nextmess) == 1? 1 :
atom_getfloatarg(6, natom, nextmess) - 1),
atom_getfloatarg(7, natom, nextmess));
+ else if (classname == gensym("hsl"))
+ {
+ t_float slmin = atom_getfloatarg(7, natom, nextmess);
+ t_float slmax = atom_getfloatarg(8, natom, nextmess);
+ binbuf_addv(newb, "sssffffffff;", gensym("#P"),
+ gensym("user"),
+ gensym("hslider"),
+ atom_getfloatarg(2, natom, nextmess),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(6, natom, nextmess),
+ atom_getfloatarg(5, natom, nextmess),
+ slmax - slmin + 1, /* range */
+ 1., /* multiplier */
+ slmin, /* offset */
+ 0.);
+ }
+ else if ( (classname == gensym("trigger")) ||
+ (classname == gensym("t")) )
+ {
+ t_symbol *arg;
+ SETSYMBOL(outmess, gensym("#P"));
+ SETSYMBOL(outmess + 1, gensym("newex"));
+ outmess[2] = nextmess[2];
+ outmess[3] = nextmess[3];
+ SETFLOAT(outmess + 4, 50.*(natom-4));
+ SETFLOAT(outmess + 5, fontsize);
+ outmess[6] = nextmess[4];
+ for (i = 5; i < natom; i++) {
+ arg = atom_getsymbolarg(i, natom, nextmess);
+ if (arg == gensym("a"))
+ SETSYMBOL(outmess + i + 2, gensym("l"));
+ else if (arg == gensym("anything"))
+ SETSYMBOL(outmess + i + 2, gensym("l"));
+ else if (arg == gensym("bang"))
+ SETSYMBOL(outmess + i + 2, gensym("b"));
+ else if (arg == gensym("float"))
+ SETSYMBOL(outmess + i + 2, gensym("f"));
+ else if (arg == gensym("list"))
+ SETSYMBOL(outmess + i + 2, gensym("l"));
+ else if (arg == gensym("symbol"))
+ SETSYMBOL(outmess + i + 2, gensym("s"));
+ else
+ outmess[i+2] = nextmess[i];
+ }
+ SETSEMI(outmess + natom + 2);
+ binbuf_add(newb, natom + 3, outmess);
+ }
else
{
SETSYMBOL(outmess, gensym("#P"));
SETSYMBOL(outmess + 1, gensym("newex"));
outmess[2] = nextmess[2];
outmess[3] = nextmess[3];
- SETFLOAT(outmess + 4, 50);
- SETFLOAT(outmess + 5, 1);
+ SETFLOAT(outmess + 4, 50.*(natom-4));
+ SETFLOAT(outmess + 5, fontsize);
for (i = 4; i < natom; i++)
outmess[i+2] = nextmess[i];
+ if (classname == gensym("osc~"))
+ SETSYMBOL(outmess + 6, gensym("cycle~"));
SETSEMI(outmess + natom + 2);
binbuf_add(newb, natom + 3, outmess);
}
@@ -1270,8 +1370,8 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
(strcmp(second, "msg") ? "comment" : "message")));
outmess[2] = nextmess[2];
outmess[3] = nextmess[3];
- SETFLOAT(outmess + 4, 50);
- SETFLOAT(outmess + 5, 1);
+ SETFLOAT(outmess + 4, 50.*(natom-4));
+ SETFLOAT(outmess + 5, fontsize);
for (i = 4; i < natom; i++)
outmess[i+2] = nextmess[i];
SETSEMI(outmess + natom + 2);
@@ -1280,10 +1380,13 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
}
else if (!strcmp(second, "floatatom"))
{
+ t_float width = atom_getfloatarg(4, natom, nextmess)*fontsize;
+ if(width<8) width = 150; /* if pd width=0, set it big */
binbuf_addv(newb, "ssfff;",
gensym("#P"), gensym("flonum"),
atom_getfloatarg(2, natom, nextmess),
- atom_getfloatarg(3, natom, nextmess), 35);
+ atom_getfloatarg(3, natom, nextmess),
+ width);
nobj++;
}
else if (!strcmp(second, "connect"))
@@ -1350,7 +1453,8 @@ void pd_doloadbang(void);
void binbuf_evalfile(t_symbol *name, t_symbol *dir)
{
t_binbuf *b = binbuf_new();
- int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat");
+ int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat") ||
+ !strcmp(name->s_name + strlen(name->s_name) - 4, ".mxt");
/* set filename so that new canvases can pick them up */
int dspstate = canvas_suspend_dsp();
glob_setfilename(0, name, dir);
diff --git a/pd/src/m_class.c b/pd/src/m_class.c
index 93d9c71b..0c67d34f 100644
--- a/pd/src/m_class.c
+++ b/pd/src/m_class.c
@@ -522,6 +522,7 @@ static t_symbol *addfileextent(t_symbol *s)
return (gensym(namebuf));
}
+#define MAXOBJDEPTH 1000
static int tryingalready;
void canvas_popabstraction(t_canvas *x);
@@ -537,14 +538,17 @@ void new_anything(void *dummy, t_symbol *s, int argc, t_atom *argv)
t_pd *current;
int fd;
char dirbuf[MAXPDSTRING], *nameptr;
- if (tryingalready) return;
+ if (tryingalready>MAXOBJDEPTH){
+ error("maximum object loading depth %d reached", MAXOBJDEPTH);
+ return;
+ }
newest = 0;
class_loadsym = s;
if (sys_load_lib(canvas_getcurrent(), s->s_name))
{
- tryingalready = 1;
+ tryingalready++;
typedmess(dummy, s, argc, argv);
- tryingalready = 0;
+ tryingalready--;
return;
}
class_loadsym = 0;
diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c
index ca3b5d1a..4431883c 100644
--- a/pd/src/m_glob.c
+++ b/pd/src/m_glob.c
@@ -20,6 +20,7 @@ void glob_meters(void *dummy, t_floatarg f);
void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av);
void glob_audiostatus(void *dummy);
void glob_finderror(t_pd *dummy);
+void glob_findinstance(t_pd *dummy, t_symbol*s);
void glob_audio_properties(t_pd *dummy, t_floatarg flongform);
void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_audio_setapi(t_pd *dummy, t_floatarg f);
@@ -103,6 +104,8 @@ void glob_init(void)
gensym("audiostatus"), 0);
class_addmethod(glob_pdobject, (t_method)glob_finderror,
gensym("finderror"), 0);
+ class_addmethod(glob_pdobject, (t_method)glob_findinstance,
+ gensym("findinstance"), A_SYMBOL, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_properties,
gensym("audio-properties"), A_DEFFLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_dialog,
@@ -130,7 +133,7 @@ void glob_init(void)
gensym("version"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_perf,
gensym("perf"), A_FLOAT, 0);
-#ifdef UNIX
+#if defined(__linux__) || defined(IRIX) || defined(__FreeBSD_kernel__)
class_addmethod(glob_pdobject, (t_method)glob_watchdog,
gensym("watchdog"), 0);
#endif
diff --git a/pd/src/m_obj.c b/pd/src/m_obj.c
index df8a2c12..bc6056b4 100644
--- a/pd/src/m_obj.c
+++ b/pd/src/m_obj.c
@@ -75,12 +75,16 @@ static void inlet_wrong(t_inlet *x, t_symbol *s)
x->i_symfrom->s_name, s->s_name);
}
+static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv);
+
/* LATER figure out how to make these efficient: */
static void inlet_bang(t_inlet *x)
{
if (x->i_symfrom == &s_bang)
pd_vmess(x->i_dest, x->i_symto, "");
else if (!x->i_symfrom) pd_bang(x->i_dest);
+ else if (x->i_symfrom == &s_list)
+ inlet_list(x, &s_bang, 0, 0);
else inlet_wrong(x, &s_bang);
}
@@ -89,6 +93,12 @@ static void inlet_pointer(t_inlet *x, t_gpointer *gp)
if (x->i_symfrom == &s_pointer)
pd_vmess(x->i_dest, x->i_symto, "p", gp);
else if (!x->i_symfrom) pd_pointer(x->i_dest, gp);
+ else if (x->i_symfrom == &s_list)
+ {
+ t_atom a;
+ SETPOINTER(&a, gp);
+ inlet_list(x, &s_pointer, 1, &a);
+ }
else inlet_wrong(x, &s_pointer);
}
@@ -100,6 +110,12 @@ static void inlet_float(t_inlet *x, t_float f)
x->i_un.iu_floatsignalvalue = f;
else if (!x->i_symfrom)
pd_float(x->i_dest, f);
+ else if (x->i_symfrom == &s_list)
+ {
+ t_atom a;
+ SETFLOAT(&a, f);
+ inlet_list(x, &s_float, 1, &a);
+ }
else inlet_wrong(x, &s_float);
}
@@ -108,6 +124,12 @@ static void inlet_symbol(t_inlet *x, t_symbol *s)
if (x->i_symfrom == &s_symbol)
pd_vmess(x->i_dest, x->i_symto, "s", s);
else if (!x->i_symfrom) pd_symbol(x->i_dest, s);
+ else if (x->i_symfrom == &s_list)
+ {
+ t_atom a;
+ SETSYMBOL(&a, s);
+ inlet_list(x, &s_symbol, 1, &a);
+ }
else inlet_wrong(x, &s_symbol);
}
@@ -118,6 +140,12 @@ static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
|| x->i_symfrom == &s_symbol || x->i_symfrom == &s_pointer)
typedmess(x->i_dest, x->i_symto, argc, argv);
else if (!x->i_symfrom) pd_list(x->i_dest, s, argc, argv);
+ else if (!argc)
+ inlet_bang(x);
+ else if (argc==1 && argv->a_type == A_FLOAT)
+ inlet_float(x, atom_getfloat(argv));
+ else if (argc==1 && argv->a_type == A_SYMBOL)
+ inlet_symbol(x, atom_getsymbol(argv));
else inlet_wrong(x, &s_list);
}
diff --git a/pd/src/m_pd.h b/pd/src/m_pd.h
index 31d7847f..d04eae3a 100644
--- a/pd/src/m_pd.h
+++ b/pd/src/m_pd.h
@@ -9,8 +9,8 @@ extern "C" {
#endif
#define PD_MAJOR_VERSION 0
-#define PD_MINOR_VERSION 42
-#define PD_BUGFIX_VERSION 5
+#define PD_MINOR_VERSION 43
+#define PD_BUGFIX_VERSION 0
#define PD_TEST_VERSION ""
/* old name for "MSW" flag -- we have to take it for the sake of many old
@@ -46,6 +46,12 @@ extern "C" {
#define EXTERN_STRUCT extern struct
#endif
+/* Define some attributes, specific to the compiler */
+#if defined(__GNUC__)
+#define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b)))
+#else
+#define ATTRIBUTE_FORMAT_PRINTF(a, b)
+#endif
#if !defined(_SIZE_T) && !defined(_SIZE_T_)
#include <stddef.h> /* just for size_t -- how lame! */
@@ -450,10 +456,12 @@ EXTERN void poststring(const char *s);
EXTERN void postfloat(t_floatarg f);
EXTERN void postatom(int argc, t_atom *argv);
EXTERN void endpost(void);
-EXTERN void error(const char *fmt, ...);
-EXTERN void verbose(int level, const char *fmt, ...);
-EXTERN void bug(const char *fmt, ...);
-EXTERN void pd_error(void *object, const char *fmt, ...);
+EXTERN void error(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
+EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
+EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
+EXTERN void pd_error(void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
+EXTERN void logpost(const void *object, const int level, const char *fmt, ...)
+ ATTRIBUTE_FORMAT_PRINTF(3, 4);
EXTERN void sys_logerror(const char *object, const char *s);
EXTERN void sys_unixerror(const char *object);
EXTERN void sys_ouch(void);
@@ -466,6 +474,7 @@ EXTERN void sys_bashfilename(const char *from, char *to);
EXTERN void sys_unbashfilename(const char *from, char *to);
EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
char *dirresult, char **nameresult, unsigned int size, int bin);
+EXTERN int sys_close(int fd);
EXTERN int sched_geteventno(void);
EXTERN double sys_getrealtime(void);
EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */
@@ -580,11 +589,11 @@ EXTERN_STRUCT _garray;
EXTERN t_class *garray_class;
EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec);
EXTERN int garray_getfloatwords(t_garray *x, int *size, t_word **vec);
-EXTERN t_float garray_get(t_garray *x, t_symbol *s, t_int indx);
EXTERN void garray_redraw(t_garray *x);
EXTERN int garray_npoints(t_garray *x);
EXTERN char *garray_vec(t_garray *x);
-EXTERN void garray_resize(t_garray *x, t_floatarg f);
+EXTERN void garray_resize(t_garray *x, t_floatarg f); /* avoid; use this: */
+EXTERN void garray_resize_long(t_garray *x, long n); /* better version */
EXTERN void garray_usedindsp(t_garray *x);
EXTERN void garray_setsaveit(t_garray *x, int saveit);
EXTERN t_class *scalar_class;
diff --git a/pd/src/m_sched.c b/pd/src/m_sched.c
index ae9f3664..634db357 100644
--- a/pd/src/m_sched.c
+++ b/pd/src/m_sched.c
@@ -272,7 +272,7 @@ static void sched_pollformeters( void)
/* if there's no GUI but we're running in "realtime", here is
where we arrange to ping the watchdog every 2 seconds. */
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
if (sys_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0))
{
glob_watchdog(0);
@@ -439,7 +439,7 @@ static void m_pollingscheduler( void)
timeforward = sys_send_dacs();
#ifdef THREAD_LOCKING
/* T.Grill - done */
- sys_unlock();
+ sys_lock();
#endif
/* if dacs remain "idle" for 1 sec, they're hung up. */
if (timeforward != 0)
@@ -461,7 +461,7 @@ static void m_pollingscheduler( void)
idletime = sys_getrealtime();
else if (sys_getrealtime() - idletime > 1.)
{
- post("audio I/O stuck... closing audio\n");
+ error("audio I/O stuck... closing audio\n");
sys_close_audio();
sched_set_using_audio(SCHED_AUDIO_NONE);
goto waitfortick;
@@ -522,6 +522,7 @@ static void m_pollingscheduler( void)
void sched_audio_callbackfn(void)
{
+ sys_lock();
sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
sys_addhist(1);
sched_tick(sys_time + sys_time_per_dsp_tick);
@@ -532,6 +533,7 @@ void sched_audio_callbackfn(void)
sys_addhist(5);
sched_pollformeters();
sys_addhist(0);
+ sys_unlock();
}
static void m_callbackscheduler(void)
@@ -539,11 +541,19 @@ static void m_callbackscheduler(void)
sys_initmidiqueue();
while (!sys_quit)
{
+ double timewas = sys_time;
#ifdef MSW
- Sleep(1000);
+ Sleep(1000);
#else
sleep(1);
#endif
+ if (sys_time == timewas)
+ {
+ sys_lock();
+ sys_pollgui();
+ sched_tick(sys_time + sys_time_per_dsp_tick);
+ sys_unlock();
+ }
if (sys_idlehook)
sys_idlehook();
}
diff --git a/pd/src/makefile.in b/pd/src/makefile.in
index e68c6781..23933085 100644
--- a/pd/src/makefile.in
+++ b/pd/src/makefile.in
@@ -55,6 +55,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_array.c d_global.c \
d_delay.c d_resample.c \
@@ -189,7 +190,7 @@ install: all
@echo "Pd install succeeded."
local-clean:
- -rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/$(GUINAME) $(BIN_DIR)/pdsend \
+ -rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c \
$(BIN_DIR)/*.tcl
-rm -f `find ../portaudio -name "*.o"`
diff --git a/pd/src/makefile.mingw b/pd/src/makefile.mingw
new file mode 100644
index 00000000..30e2bd9f
--- /dev/null
+++ b/pd/src/makefile.mingw
@@ -0,0 +1,297 @@
+# how Miller builds Pd on Windows:
+# http://lists.puredata.info/pipermail/pd-dev/2004-10/002981.html
+
+CC = gcc
+CXX = g++
+
+cvs_root_dir = ../..
+pd_src = $(cvs_root_dir)/pd
+DLL_DIR = $(pd_src)/src
+
+BIN_DIR = ../bin
+
+VPATH = $(pd_src)/src
+
+prefix = /usr/local/pd
+exec_prefix = $(prefix)
+includedir = $(prefix)/include
+libdir = $(exec_prefix)/lib
+mandir = $(prefix)/man
+bindir = $(exec_prefix)/bin
+
+GFLAGS = -DINSTALL_PREFIX=\"$(prefix)\"
+
+# varibles to match packages/Makefile.buildlayout so that they can be easily
+# overridden when building Pd-extended builds. <hans@at.or.at>
+libpddir = $(prefix)
+pddocdir = $(libpddir)/doc
+libpdbindir = $(libpddir)/bin
+
+PDEXEC = pd.exe
+PDDLL = pd.dll
+DLLWRAP= dllwrap
+
+MORECFLAGS = -O3 -funroll-loops -fomit-frame-pointer
+
+PADIR = $(pd_src)/portaudio
+ASIODIR = $(pd_src)/asio/ASIOSDK2
+# there is some old code in ASIO/common/combase.h that needs to be ignored, we
+# do this by setting the WINVER macro
+ASIOINC = -I$(ASIODIR)/common -I$(ASIODIR)/host -I$(ASIODIR)/host/pc -DWINVER=0xffff
+INCPA = -I$(PADIR) -I$(PADIR)/include -I$(PADIR)/src/common $(ASIOINC)
+INCLUDE = -I$(pd_src)/src
+GINCLUDE = -I/usr/local/include $(INCLUDE)
+
+LDFLAGS =
+LIBS = -lm -lwsock32 -lwinmm -lole32 -lpthreadGC2
+
+OPT_CFLAGS =
+
+WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused \
+ -Wno-unused-parameter -Wno-parentheses -Wno-switch
+ARCH_CFLAGS = -DPD -DPD_INTERNAL -DMSW -D_WIN32 -DPA_NO_DS -DUSEAPI_MMIO \
+ -DUSEAPI_PORTAUDIO -DPA19 -DPA_LITTLE_ENDIAN -mms-bitfields \
+ -DWISHAPP='"wish85.exe"'
+
+CFLAGS += $(ARCH_CFLAGS) $(WARN_CFLAGS) $(OPT_CFLAGS) $(MORECFLAGS)
+
+STRIP = strip --strip-unneeded -R .note -R .comment
+
+# the sources
+
+PASRC = s_audio_pa.c s_audio_paring.c \
+ s_audio_mmio.c s_midi_mmio.c \
+ $(PADIR)/src/common/pa_stream.c \
+ $(PADIR)/src/common/pa_trace.c \
+ $(PADIR)/src/common/pa_skeleton.c \
+ $(PADIR)/src/common/pa_process.c \
+ $(PADIR)/src/common/pa_front.c \
+ $(PADIR)/src/common/pa_dither.c \
+ $(PADIR)/src/common/pa_cpuload.c \
+ $(PADIR)/src/common/pa_converters.c \
+ $(PADIR)/src/common/pa_allocation.c \
+ $(PADIR)/src/common/pa_ringbuffer.c \
+ $(PADIR)/src/os/win/pa_win_hostapis.c \
+ $(PADIR)/src/os/win/pa_win_util.c \
+ $(PADIR)/src/os/win/pa_win_waveformat.c \
+ $(PADIR)/src/hostapi/wmme/pa_win_wmme.c
+
+ASIOSRC = $(PADIR)/src/hostapi/asio/iasiothiscallresolver.cpp \
+ $(PADIR)/src/hostapi/asio/pa_asio.cpp \
+ $(ASIODIR)/common/asio.cpp \
+ $(ASIODIR)/host/asiodrivers.cpp \
+ $(ASIODIR)/host/pc/asiolist.cpp
+
+#VSRC = s_audio_vst.c
+
+PMDIR = ../portmidi
+PMINCLUDE = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime -DNEWBUFFER
+PMSRC = $(PMDIR)/pm_common/portmidi.c \
+ $(PMDIR)/pm_common/pmutil.c \
+ $(PMDIR)/porttime/porttime.c \
+ $(PMDIR)/porttime/ptwinmm.c \
+ $(PMDIR)/pm_win/pmwin.c \
+ $(PMDIR)/pm_win/pmwinmm.c
+
+PMOBJ = $(PMSRC:.c=.o)
+
+HEADERS = g_all_guis.h m_imp.h g_canvas.h m_pd.h s_stuff.h \
+ $(wildcard ../portaudio/common/*.h) s_audio_paring.h
+
+SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
+ g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
+ g_all_guis.c g_bang.c g_hdial.c g_mycanvas.c g_numbox.c g_toggle.c \
+ g_hslider.c g_vumeter.c m_pd.c m_class.c m_obj.c m_atom.c m_memory.c \
+ m_binbuf.c m_conf.c m_glob.c m_sched.c s_main.c s_inter.c s_file.c \
+ s_print.c s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
+ d_math.c d_fft.c d_fft_mayer.c d_fftroutine.c d_array.c d_global.c \
+ d_delay.c d_resample.c x_arithmetic.c x_connective.c x_interface.c \
+ x_midi.c x_misc.c x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c \
+ x_list.c d_soundfile.c g_vslider.c g_vdial.c
+
+SRSRC = u_pdsend.c u_pdreceive.c
+
+OBJ = $(SRC:.c=.o)
+SROBJ = $(SRSRC:.c=.o)
+PAOBJ = $(PASRC:.c=.o)
+ASIOOBJ = $(ASIOSRC:.cpp=.o)
+#VOBJ = $(VSRC:.c=.o)
+OBJC = $(OBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)
+
+
+# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
+PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
+ sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
+PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
+ sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
+PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
+ sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
+PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
+ sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
+PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
+ifneq ($(PD_TEST_VERSION),)
+ PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
+endif
+
+
+#
+# ------------------ targets ------------------------------------
+#
+
+.PHONY: all install clean externs testbin
+
+all: $(PDDLL) $(PDEXEC) externs pdsend.exe pdreceive.exe pd.com
+
+$(OBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c
+
+$(GOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(GINCLUDE) -c -o $*.o $*.c
+
+$(SROBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c
+
+$(PAOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCPA) -c -o $*.o $*.c
+
+$(ASIOOBJ) : %.o : %.cpp
+ $(CXX) $(CFLAGS) $(INCPA) -c -o $*.o $*.cpp
+
+$(PMOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(PMINCLUDE) -c -o $*.o $*.c
+
+$(VOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c
+
+pdsend.exe: u_pdsend.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o pdsend.exe u_pdsend.o $(LIBS)
+ $(STRIP) pdsend.exe
+
+pdreceive.exe: u_pdreceive.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o pdreceive.exe u_pdreceive.o $(LIBS)
+ $(STRIP) pdreceive.exe
+
+$(PDEXEC): s_entry.o pd.res
+ $(CC) $(LDFLAGS) -mwindows -o $(PDEXEC) s_entry.o pd.res $(LIBS) -L. -lpd
+ $(STRIP) -s $(PDEXEC)
+
+pd.com: s_entry.o
+ $(CC) $(LDFLAGS) -o pd.com s_entry.o $(LIBS) -L. -lpd
+ $(STRIP) -s pd.com
+
+$(PDDLL): $(OBJC)
+ $(CXX) -shared $(LDFLAGS) -o $(PDDLL) $(OBJC) $(LIBS) \
+ -Wl,--export-all-symbols -Wl,--out-implib=pd.a;
+ $(STRIP) $(PDDLL)
+
+pd.res: pd.rc
+ windres pd.rc -O coff -o pd.res
+
+#vstschedlib.dll: $(VOBJ)
+# $(DLLWRAP) --export-all-symbols --output-def vst.def \
+# --output-lib=vst.a --dllname=vstschedlib.dll s_audio_vst.o pd.a $(LIBS)
+
+externs:
+ make -C ../extra all
+
+# kludge to put stuff into the pd/bin dir for testing
+testbin: $(PDEXEC) $(PDDLL) pd.com
+ echo "Copying files to $(BIN_DIR)"
+ install -d $(BIN_DIR)
+ install -p *.tcl $(BIN_DIR)
+ install -p $(PDDLL) $(BIN_DIR)
+ install -p pd.ico $(BIN_DIR)
+ install -p pd.com $(BIN_DIR)
+ install -p $(PDEXEC) $(BIN_DIR)
+
+ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
+install: all
+# locales
+ make libpddir=$(libpddir) -C ../po install
+# install extra stuff
+ make libpddir=$(libpddir) -C ../extra install
+# the real install
+ install -d $(DESTDIR)$(bindir)
+ install -p *.tcl $(DESTDIR)$(bindir)/
+ install -p $(PDEXEC) $(DESTDIR)$(bindir)/$(PDEXEC)
+ install -p pd.com $(DESTDIR)$(bindir)/pd.com
+ install -p pd.dll $(DESTDIR)$(bindir)/pd.dll
+ install -p pd.ico $(DESTDIR)$(bindir)/pd.ico
+ install -p pdsend.exe $(DESTDIR)$(bindir)/pdsend.exe
+ install -p pdreceive.exe $(DESTDIR)$(bindir)/pdreceive.exe
+ for dir in $(shell ls -1 ../doc | grep -v CVS); do \
+ echo "installing $$dir"; \
+ install -d $(DESTDIR)$(pddocdir)/$$dir ; \
+ install -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
+ done
+ for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
+ echo "installing 7.stuff/$$dir"; \
+ install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
+ install -p ../doc/7.stuff/$$dir/*.* $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
+ done
+ mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
+ cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
+ > $(ABOUT_FILE)
+ rm $(ABOUT_FILE).tmp
+ install -d $(DESTDIR)$(libpddir)/extra
+ install -p $(pd_src)/extra/*/*.dll $(DESTDIR)$(libpddir)/extra
+ install -p $(pd_src)/extra/*.pd $(DESTDIR)$(libpddir)/extra
+ install -d $(DESTDIR)$(pddocdir)/5.reference
+ install -p ../extra/*/*.pd $(DESTDIR)$(pddocdir)/5.reference
+ install -p ../extra/*-help.pd $(DESTDIR)$(pddocdir)/5.reference
+ install -d $(DESTDIR)$(prefix)/startup
+ install -p $(pd_src)/startup/*.* $(DESTDIR)$(prefix)/startup
+ install -d $(DESTDIR)$(prefix)/startup/disabled
+ install -p $(pd_src)/startup/disabled/*.* $(DESTDIR)$(prefix)/startup/disabled
+ install -d $(DESTDIR)$(includedir)
+ install -p m_pd.h $(DESTDIR)$(includedir)/m_pd.h
+ install -p s_stuff.h $(DESTDIR)$(includedir)/s_stuff.h
+ @echo "Pd install succeeded."
+
+
+clean:
+ -rm -f -- $(BIN_DIR)/*.*
+ -rm -f -- *.o *.a *.def
+ -rm -f -- pd*.exe pd*.dll pd.com
+ -rm -f -- $(OBJ) $(GOBJ) $(SROBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)
+ -rm -f -- $(pd_src)/extra/*/*.dll $(pd_src)/extra/*/*.o
+ -rm -f makefile.dependencies
+
+distclean: clean
+ rm -rf -- config.cache config.log config.status makefile tags \
+ autom4te-*.cache
+
+tags: $(SRC) $(GSRC); ctags *.[ch]
+
+depend: makefile.dependencies
+
+makefile.dependencies: $(SRC) $(PASRC) $(HEADERS)
+ $(CC) $(INCLUDE) $(INCPA) $(CFLAGS) -M $(SRC) $(PASRC) $(HEADERS) \
+ > makefile.dependencies
+
+uninstall:
+ -rm $(prefix)/bin/pd*.exe
+ -rm $(prefix)/bin/pd*.com
+ -rm $(prefix)/bin/pd*.dll
+ -rm $(prefix)/bin/*.tcl
+
+
+test_locations:
+ @echo "PD_VERSION: $(PD_VERSION)"
+ @echo "PACKAGE_VERSION: $(PACKAGE_VERSION)"
+ @echo "CWD $(CWD)"
+ @echo "DESTDIR $(DESTDIR)"
+ @echo "PREFIX $(prefix)"
+ @echo "BINDIR $(bindir)"
+ @echo "LIBDIR $(libdir)"
+ @echo "OBJECTSDIR $(objectsdir)"
+ @echo "PDDOCDIR $(pddocdir)"
+ @echo "LIBPDDIR $(libpddir)"
+ @echo "LIBPDBINDIR $(libpdbindir)"
+ @echo "HELPDIR $(helpdir)"
+ @echo "MANUALSDIR $(manualsdir)"
+ @echo "EXAMPLESDIR $(examplesdir)"
+
+
+include makefile.dependencies
diff --git a/pd/src/makefile.nt b/pd/src/makefile.nt
index 7b4e834e..b57c3d08 100644
--- a/pd/src/makefile.nt
+++ b/pd/src/makefile.nt
@@ -6,14 +6,14 @@ all: pd ..\bin\pdsend.exe ..\bin\pdreceive.exe
VCSDK = "C:\Program Files\Microsoft SDKs\Windows\v6.0A"
VC9 = "C:\Program Files\Microsoft Visual Studio 9.0\VC"
#VC="\Program Files\DevStudio\Vc"
-INCLUDE = -I.\ -I..\Tcl\include -I\DXSDK\include -I$(VC9)\Include \
+INCLUDE = -I.\ -I..\Tcl\include -I$(VC9)\Include \
-I$(VCSDK)\Include
LDIR = $(VCSDK)\lib
LD2 = $(VC9)\lib
-LIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:oldnames /NODEFAULTLIB:libc \
- /NODEFAULTLIB:uuid $(LDIR)\kernel32.lib \
+LIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:libcpmt /NODEFAULTLIB:oldnames \
+ /NODEFAULTLIB:libc /NODEFAULTLIB:uuid $(LDIR)\kernel32.lib \
$(LDIR)\wsock32.lib $(LDIR)\winmm.lib $(LDIR)\advapi32.lib \
$(LDIR)\setupapi.lib ..\bin\pthreadVC.lib \
$(LD2)\libcmt.lib $(LD2)\oldnames.lib
@@ -23,7 +23,7 @@ CFLAGS = /nologo /W3 /DMSW /DNT /DPD /DPD_INTERNAL /DWIN32 /DWINDOWS /Ox \
-D_CRT_SECURE_NO_WARNINGS
LFLAGS = /nologo
-SYSSRC = s_audio_pa.c s_audio_pablio.c s_audio_paring.c \
+SYSSRC = s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c s_midi_pm.c
SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
@@ -33,7 +33,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
- s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_fft_mayer.c d_fftroutine.c d_array.c d_global.c \
d_delay.c d_resample.c \
@@ -53,8 +53,10 @@ SRCPA = $(PASRC)/common/pa_stream.c \
$(PASRC)/common/pa_cpuload.c \
$(PASRC)/common/pa_converters.c \
$(PASRC)/common/pa_allocation.c \
+ $(PASRC)/common/pa_ringbuffer.c \
$(PASRC)/os/win/pa_win_hostapis.c \
$(PASRC)/os/win/pa_win_util.c \
+ $(PASRC)/os/win/pa_win_waveformat.c \
$(PASRC)/hostapi/wmme/pa_win_wmme.c
SRCASIO = $(PADIR)/pa_asio/pa_asio.cpp
@@ -67,8 +69,11 @@ $(LDIR)\odbc32.lib $(LDIR)\odbccp32.lib ..\lib\asio\asiolib.lib
PAOBJ = pa_stream.obj pa_trace.obj pa_skeleton.obj pa_process.obj \
pa_front.obj pa_dither.obj pa_cpuload.obj pa_converters.obj \
- pa_allocation.obj pa_win_hostapis.obj pa_win_util.obj pa_asio.obj \
- pa_win_wmme.obj
+ pa_allocation.obj pa_ringbuffer.obj \
+ pa_win_hostapis.obj pa_win_util.obj pa_win_waveformat.obj \
+ pa_win_wmme.obj \
+ pa_asio.obj
+
# pa_win_wdmks.obj
PMDIR = ..\portmidi
@@ -141,11 +146,15 @@ pa_converters.obj: $(PASRC)\common\pa_converters.c
cl /c $(ALLCF) $(PASRC)\common\pa_converters.c
pa_allocation.obj: $(PASRC)\common\pa_allocation.c
cl /c $(ALLCF) $(PASRC)\common\pa_allocation.c
+pa_ringbuffer.obj: $(PASRC)\common\pa_ringbuffer.c
+ cl /c $(ALLCF) $(PASRC)\common\pa_ringbuffer.c
pa_win_hostapis.obj: $(PASRC)\os\win\pa_win_hostapis.c
cl /c $(ALLCF) $(PASRC)\os\win\pa_win_hostapis.c
pa_win_util.obj: $(PASRC)\os\win\pa_win_util.c
cl /c $(ALLCF) $(PASRC)\os\win\pa_win_util.c
+pa_win_waveformat.obj: $(PASRC)\os\win\pa_win_waveformat.c
+ cl /c $(ALLCF) $(PASRC)\os\win\pa_win_waveformat.c
pa_win_wmme.obj: $(PASRC)\hostapi\wmme\pa_win_wmme.c
cl /c $(ALLCF) $(PASRC)\hostapi\wmme\pa_win_wmme.c
pa_win_wdmks.obj: $(PADIR)\pa_win_wdmks\pa_win_wdmks.c
diff --git a/pd/src/notes.txt b/pd/src/notes.txt
index 0cf0ee61..f9bf2dd8 100644
--- a/pd/src/notes.txt
+++ b/pd/src/notes.txt
@@ -1,6 +1,13 @@
+font courier not found?
+carriage returns after posting
+lose makesfx.bat, etc. from msw (and move out personal stuff?)
+control C control
+window titles wrong on Macintosh
---------------- dolist --------------------
+portaudio: put call to PA_Terminate back in where appropriate
+ (first test situation on windows)
compile on various versions of linux
windows:
modal dialogs confuse watchdog
diff --git a/pd/src/pd.ico b/pd/src/pd.ico
new file mode 100755
index 00000000..2da5c243
--- /dev/null
+++ b/pd/src/pd.ico
Binary files differ
diff --git a/pd/src/pd.rc b/pd/src/pd.rc
new file mode 100644
index 00000000..a51d9462
--- /dev/null
+++ b/pd/src/pd.rc
@@ -0,0 +1,25 @@
+id ICON "pd.ico"
+1 VERSIONINFO
+FILEVERSION 0,43,0,0
+PRODUCTVERSION 0,43,0,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "puredata.info"
+ VALUE "FileDescription", "Pure Data Application"
+ VALUE "FileVersion", "0.43"
+ VALUE "InternalName", "pd.exe"
+ VALUE "LegalCopyright", "Miller Puckette, et al."
+ VALUE "OriginalFilename", "pd.exe"
+ VALUE "ProductName", "Pure Data"
+ VALUE "ProductVersion", "0.43"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c
index 2f274fc6..bff3c3ab 100644
--- a/pd/src/s_audio.c
+++ b/pd/src/s_audio.c
@@ -9,17 +9,18 @@
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
-#ifdef HAVE_UNISTD_H
+#ifdef _WIN32
+#include <time.h>
+#else
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
-#endif
+#endif /* _WIN32 */
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define SYS_DEFAULTCH 2
-#define SYS_MAXCH 100
typedef long t_pa_sample;
#define SYS_SAMPLEWIDTH sizeof(t_pa_sample)
#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH)
@@ -37,7 +38,6 @@ static void audio_getdevs(char *indevlist, int *nindevs,
int sys_inchannels;
int sys_outchannels;
int sys_advance_samples; /* scheduler advance in samples */
-int sys_blocksize = 0; /* audio I/O block size in sample frames */
int sys_audioapi = API_DEFAULT;
int sys_audioapiopened = -1; /* save last API opened for later closing */
static int sys_meters; /* true if we're metering */
@@ -64,8 +64,9 @@ static int audio_naudiooutdev = -1;
static int audio_audiooutdev[MAXAUDIOOUTDEV];
static int audio_audiochoutdev[MAXAUDIOOUTDEV];
static int audio_rate;
-static int audio_advance;
+static int audio_advance = -1;
static int audio_callback;
+static int audio_blocksize;
static int audio_callback_is_open; /* reflects true actual state */
static int audio_nextinchans, audio_nextoutchans;
@@ -82,7 +83,7 @@ static int audio_isopen(void)
void sys_get_audio_params(
int *pnaudioindev, int *paudioindev, int *chindev,
int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
- int *prate, int *padvance, int *pcallback)
+ int *prate, int *padvance, int *pcallback, int *pblocksize)
{
int i;
*pnaudioindev = audio_naudioindev;
@@ -96,12 +97,13 @@ void sys_get_audio_params(
*prate = audio_rate;
*padvance = audio_advance;
*pcallback = audio_callback;
+ *pblocksize = audio_blocksize;
}
void sys_save_audio_params(
int naudioindev, int *audioindev, int *chindev,
int naudiooutdev, int *audiooutdev, int *choutdev,
- int rate, int advance, int callback)
+ int rate, int advance, int callback, int blocksize)
{
int i;
audio_naudioindev = naudioindev;
@@ -115,6 +117,7 @@ void sys_save_audio_params(
audio_rate = rate;
audio_advance = advance;
audio_callback = callback;
+ audio_blocksize = blocksize;
}
/* init routines for any API which needs to set stuff up before
@@ -156,8 +159,8 @@ void sys_setchsr(int chin, int chout, int sr)
sys_outchannels = chout;
sys_dacsr = sr;
sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.);
- if (sys_advance_samples < 3 * DEFDACBLKSIZE)
- sys_advance_samples = 3 * DEFDACBLKSIZE;
+ if (sys_advance_samples < DEFDACBLKSIZE)
+ sys_advance_samples = DEFDACBLKSIZE;
sys_soundin = (t_sample *)getbytes(inbytes);
memset(sys_soundin, 0, inbytes);
@@ -180,7 +183,7 @@ void sys_setchsr(int chin, int chout, int sr)
void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate, int advance, int callback)
+ int *choutdev, int rate, int advance, int callback, int blocksize)
{
int i, *ip;
int defaultchannels = SYS_DEFAULTCH;
@@ -195,8 +198,10 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
if (rate < 1)
rate = DEFAULTSRATE;
- if (advance <= 0)
+ if (advance < 0)
advance = DEFAULTADVANCE;
+ if (blocksize != (1 << ilog2(blocksize)) || blocksize < DEFDACBLKSIZE)
+ blocksize = DEFDACBLKSIZE;
audio_init();
/* Since the channel vector might be longer than the
audio device vector, or vice versa, we fill the shorter one
@@ -324,7 +329,8 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
audio_nextinchans = inchans;
audio_nextoutchans = outchans;
sys_save_audio_params(nrealindev, realindev, realinchans,
- nrealoutdev, realoutdev, realoutchans, rate, advance, callback);
+ nrealoutdev, realoutdev, realoutchans, rate, advance, callback,
+ blocksize);
}
void sys_close_audio(void)
@@ -360,12 +366,29 @@ void sys_close_audio(void)
mmio_close_audio();
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapiopened == API_AUDIOUNIT)
+ audiounit_close_audio();
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapiopened == API_ESD)
+ esd_close_audio();
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapiopened == API_DUMMY)
+ dummy_close_audio();
+ else
+#endif
post("sys_close_audio: unknown API %d", sys_audioapiopened);
sys_inchannels = sys_outchannels = 0;
sys_audioapiopened = -1;
sched_set_using_audio(SCHED_AUDIO_NONE);
audio_state = 0;
audio_callback_is_open = 0;
+
+ sys_vgui("set pd_whichapi 0\n");
}
/* open audio using whatever parameters were last used */
@@ -373,9 +396,10 @@ void sys_reopen_audio( void)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int rate, advance, callback, outcome = 0;
+ int rate, advance, callback, blocksize, outcome = 0;
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
if (!naudioindev && !naudiooutdev)
{
@@ -385,7 +409,9 @@ void sys_reopen_audio( void)
#ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO)
{
- int blksize = (sys_blocksize ? sys_blocksize : 64);
+ int blksize = (audio_blocksize ? audio_blocksize : 64);
+ if (sys_verbose)
+ fprintf(stderr, "blksize %d, advance %d\n", blksize, sys_advance_samples/blksize);
outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
(naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
sys_soundout, blksize, sys_advance_samples/blksize,
@@ -398,14 +424,16 @@ void sys_reopen_audio( void)
#ifdef USEAPI_JACK
if (sys_audioapi == API_JACK)
outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
- (naudioindev > 0 ? choutdev[0] : 0), rate);
+ (naudioindev > 0 ? choutdev[0] : 0), rate,
+ (callback ? sched_audio_callbackfn : 0));
else
#endif
#ifdef USEAPI_OSS
if (sys_audioapi == API_OSS)
outcome = oss_open_audio(naudioindev, audioindev, naudioindev,
- chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+ chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+ audio_blocksize);
else
#endif
#ifdef USEAPI_ALSA
@@ -413,13 +441,32 @@ void sys_reopen_audio( void)
be open for both input and output. */
if (sys_audioapi == API_ALSA)
outcome = alsa_open_audio(naudioindev, audioindev, naudioindev,
- chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+ chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+ audio_blocksize);
else
#endif
#ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO)
outcome = mmio_open_audio(naudioindev, audioindev, naudioindev,
+ chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+ audio_blocksize);
+ else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0),
+ (naudioindev > 0 ? choutdev[0] : 0), rate);
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ALSA)
+ outcome = esd_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ outcome = dummy_open_audio(naudioindev, naudiooutdev, rate);
else
#endif
if (sys_audioapi == API_NONE)
@@ -493,6 +540,21 @@ int sys_send_dacs(void)
return (mmio_send_dacs());
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ return (audiounit_send_dacs());
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ESD)
+ return (esd_send_dacs());
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ return (dummy_send_dacs());
+ else
+#endif
post("unknown API");
return (0);
}
@@ -549,6 +611,7 @@ static void audio_getdevs(char *indevlist, int *nindevs,
{
jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
+ *cancallback = 1;
}
else
#endif
@@ -576,6 +639,28 @@ static void audio_getdevs(char *indevlist, int *nindevs,
}
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ {
+ }
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ESD)
+ {
+ esd_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+ maxndev, devdescsize);
+ }
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ {
+ dummy_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+ maxndev, devdescsize);
+ }
+ else
+#endif
{
/* this shouldn't happen once all the above get filled in. */
int i;
@@ -635,7 +720,7 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
audioinchan1, audioinchan2, audioinchan3, audioinchan4,
audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4;
- int rate, advance, callback;
+ int rate, advance, callback, blocksize;
/* these are all the devices on your system: */
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i;
@@ -654,7 +739,8 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
outdevlist + i * DEVDESCSIZE);
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
/* post("naudioindev %d naudiooutdev %d longform %f",
naudioindev, naudiooutdev, flongform); */
@@ -681,13 +767,13 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
"pdtk_audio_dialog %%s \
%d %d %d %d %d %d %d %d \
%d %d %d %d %d %d %d %d \
-%d %d %d %d %d\n",
+%d %d %d %d %d %d\n",
audioindev1, audioindev2, audioindev3, audioindev4,
audioinchan1, audioinchan2, audioinchan3, audioinchan4,
audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4,
rate, advance, canmulti, (cancallback ? callback : -1),
- (flongform != 0));
+ (flongform != 0), blocksize);
gfxstub_deleteforkey(0);
gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf);
}
@@ -706,6 +792,7 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
int newrate = atom_getintarg(16, argc, argv);
int newadvance = atom_getintarg(17, argc, argv);
int newcallback = atom_getintarg(18, argc, argv);
+ int newblocksize = atom_getintarg(19, argc, argv);
for (i = 0; i < 4; i++)
{
@@ -738,14 +825,27 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
}
}
- if (newcallback < 0)
- newcallback = 0;
- if (!audio_callback_is_open && !newcallback)
- sys_close_audio();
- sys_set_audio_settings(nindev, newaudioindev, nindev, newaudioinchan,
+ sys_set_audio_settings_reopen(nindev, newaudioindev, nindev, newaudioinchan,
noutdev, newaudiooutdev, noutdev, newaudiooutchan,
- newrate, newadvance, (newcallback >= 0 ? newcallback : 0));
- if (!audio_callback_is_open && !newcallback)
+ newrate, newadvance, newcallback, newblocksize);
+}
+
+void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, int nchindev,
+ int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+ int *choutdev, int rate, int advance, int callback, int newblocksize)
+{
+ if (callback < 0)
+ callback = 0;
+ if (newblocksize != (1<<ilog2(newblocksize)) ||
+ newblocksize < DEFDACBLKSIZE || newblocksize > 2048)
+ newblocksize = DEFDACBLKSIZE;
+
+ if (!audio_callback_is_open && !callback)
+ sys_close_audio();
+ sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
+ naudiooutdev, audiooutdev, nchoutdev, choutdev,
+ rate, advance, (callback >= 0 ? callback : 0), newblocksize);
+ if (!audio_callback_is_open && !callback)
sys_reopen_audio();
else sched_reopenmeplease();
}
@@ -777,19 +877,34 @@ void sys_listdevs(void )
sys_listaudiodevs();
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ sys_listaudiodevs();
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ESD)
+ sys_listaudiodevs();
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ sys_listaudiodevs();
+ else
+#endif
post("unknown API");
sys_listmididevs();
}
-void sys_setblocksize(int n)
+void sys_get_audio_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
+ int maxndev, int devdescsize)
{
- if (n < 1)
- n = 1;
- if (n != (1 << ilog2(n)))
- post("warning: adjusting blocksize to power of 2: %d",
- (n = (1 << ilog2(n))));
- sys_blocksize = n;
+ audio_getdevs(indevlist, nindevs,
+ outdevlist, noutdevs,
+ canmulti, cancallback,
+ maxndev, devdescsize);
}
void sys_set_audio_api(int which)
@@ -872,6 +987,15 @@ void sys_get_audio_apis(char *buf)
#ifdef USEAPI_JACK
sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++;
#endif
+#ifdef USEAPI_AUDIOUNIT
+ sprintf(buf + strlen(buf), "{AudioUnit %d} ", API_AUDIOUNIT); n++;
+#endif
+#ifdef USEAPI_ESD
+ sprintf(buf + strlen(buf), "{ESD %d} ", API_ESD); n++;
+#endif
+#ifdef USEAPI_DUMMY
+ sprintf(buf + strlen(buf), "{dummy %d} ", API_DUMMY); n++;
+#endif
strcat(buf, "}");
/* then again, if only one API (or none) we don't offer any choice. */
if (n < 2)
diff --git a/pd/src/s_audio_alsa.c b/pd/src/s_audio_alsa.c
index a5034c8d..cf731109 100644
--- a/pd/src/s_audio_alsa.c
+++ b/pd/src/s_audio_alsa.c
@@ -90,9 +90,17 @@ static int alsaio_canmmap(t_alsa_dev *dev)
return ((err1 < 0) && (err2 >= 0));
}
+static void check_setup_error(int err, int out, const char *why) {
+ char bf[256];
+ snprintf(bf, sizeof bf, "%s (%s)", why, out ? "output" : "input");
+ check_error(err, bf);
+}
+
static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
int nfrags, int frag_size)
{
+#define CHECK_ERROR(why_) check_setup_error(err, out, why_)
+
int bufsizeforthis, err;
snd_pcm_hw_params_t* hw_params;
unsigned int tmp_uint;
@@ -110,14 +118,14 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
/* get the default params */
err = snd_pcm_hw_params_any(dev->a_handle, hw_params);
- check_error(err, "snd_pcm_hw_params_any");
+ CHECK_ERROR("snd_pcm_hw_params_any");
/* try to set interleaved access */
err = snd_pcm_hw_params_set_access(dev->a_handle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
return (-1);
- check_error(err, "snd_pcm_hw_params_set_access");
+ CHECK_ERROR("snd_pcm_hw_params_set_access");
#if 0 /* enable this to print out which formats are available */
{
int i;
@@ -141,7 +149,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
"PD-ALSA: 32/24 bit format not available - using 16\n"); */
err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
SND_PCM_FORMAT_S16);
- check_error(err, "snd_pcm_hw_params_set_format");
+ CHECK_ERROR("_pcm_hw_params_set_format");
dev->a_sampwidth = 2;
}
else dev->a_sampwidth = 3;
@@ -154,22 +162,22 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
/* set the subformat */
err = snd_pcm_hw_params_set_subformat(dev->a_handle,
hw_params, SND_PCM_SUBFORMAT_STD);
- check_error(err, "snd_pcm_hw_params_set_subformat");
+ CHECK_ERROR("snd_pcm_hw_params_set_subformat");
/* set the number of channels */
tmp_uint = *channels;
err = snd_pcm_hw_params_set_channels_min(dev->a_handle,
hw_params, &tmp_uint);
- check_error(err, "snd_pcm_hw_params_set_channels");
+ CHECK_ERROR("snd_pcm_hw_params_set_channels");
if (tmp_uint != (unsigned)*channels)
post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint);
*channels = tmp_uint;
dev->a_channels = *channels;
/* set the sampling rate */
- err = snd_pcm_hw_params_set_rate_min(dev->a_handle, hw_params,
+ err = snd_pcm_hw_params_set_rate_near(dev->a_handle, hw_params,
(unsigned int *)rate, 0);
- check_error(err, "snd_pcm_hw_params_set_rate_min (input)");
+ CHECK_ERROR("snd_pcm_hw_params_set_rate_min");
#if 0
err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
post("input sample rate %d", err);
@@ -185,7 +193,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
err = snd_pcm_hw_params_set_period_size_near(dev->a_handle,
hw_params, &tmp_snd_pcm_uframes, 0);
#endif
- check_error(err, "snd_pcm_hw_params_set_period_size_near (input)");
+ CHECK_ERROR("snd_pcm_hw_params_set_period_size_near");
/* set the buffer size */
#ifdef ALSAAPI9
@@ -196,10 +204,10 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle,
hw_params, &tmp_snd_pcm_uframes);
#endif
- check_error(err, "snd_pcm_hw_params_set_buffer_size_near (input)");
+ CHECK_ERROR("snd_pcm_hw_params_set_buffer_size_near");
err = snd_pcm_hw_params(dev->a_handle, hw_params);
- check_error(err, "snd_pcm_hw_params (input)");
+ CHECK_ERROR("snd_pcm_hw_params");
/* set up the buffer */
bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels;
@@ -227,18 +235,19 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
alsa_snd_bufsize = bufsizeforthis;
}
return (1);
+#undef CHECK_ERROR
}
/* return 0 on success */
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate)
+ int *choutdev, int rate, int blocksize)
{
int err, inchans = 0, outchans = 0, subunitdir;
char devname[512];
snd_output_t* out;
- int frag_size = (sys_blocksize ? sys_blocksize : ALSA_DEFFRAGSIZE);
+ int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE);
int nfrags, i, iodev, dev2;
int wantinchans, wantoutchans, device;
@@ -292,7 +301,7 @@ int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
if (alsa_usemmap)
{
post("using mmap audio interface");
- if (alsamm_open_audio(rate))
+ if (alsamm_open_audio(rate, blocksize))
goto blewit;
else return (0);
}
@@ -469,7 +478,7 @@ int alsa_send_dacs(void)
((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
- fprintf(stderr("big endian 24-bit not supported");
+ fprintf(stderr, "big endian 24-bit not supported");
#endif
}
for (; i < thisdevchans; i++, ch++)
@@ -581,7 +590,7 @@ int alsa_send_dacs(void)
* (1./ INT32_MAX);
}
#else
- fprintf(stderr("big endian 24-bit not supported");
+ fprintf(stderr, "big endian 24-bit not supported");
#endif
}
else
diff --git a/pd/src/s_audio_alsa.h b/pd/src/s_audio_alsa.h
index 813be211..f59cff3c 100644
--- a/pd/src/s_audio_alsa.h
+++ b/pd/src/s_audio_alsa.h
@@ -35,6 +35,6 @@ extern t_alsa_dev alsa_outdev[ALSA_MAXDEV];
extern int alsa_nindev;
extern int alsa_noutdev;
-int alsamm_open_audio(int rate);
+int alsamm_open_audio(int rate, int blocksize);
void alsamm_close_audio(void);
int alsamm_send_dacs(void);
diff --git a/pd/src/s_audio_alsamm.c b/pd/src/s_audio_alsamm.c
index 3bc4b369..abcb0a85 100644
--- a/pd/src/s_audio_alsamm.c
+++ b/pd/src/s_audio_alsamm.c
@@ -182,7 +182,7 @@ static void check_error(int err, const char *why)
error("%s: %s\n", why, snd_strerror(err));
}
-int alsamm_open_audio(int rate)
+int alsamm_open_audio(int rate, int blocksize)
{
int err;
char devname[80];
@@ -238,16 +238,16 @@ int alsamm_open_audio(int rate)
/* set the asked buffer time (alsa buffertime in us)*/
alsamm_buffertime = alsamm_buffersize = 0;
- if(sys_blocksize == 0)
+ if(blocksize == 0)
alsamm_buffertime = sys_schedadvance;
else
- alsamm_buffersize = sys_blocksize;
+ alsamm_buffersize = blocksize;
if(sys_verbose)
post("syschedadvance=%d us(%d Samples)so buffertime max should be this=%d"
"or sys_blocksize=%d (samples) to use buffersize=%d",
sys_schedadvance,sys_advance_samples,alsamm_buffertime,
- sys_blocksize,alsamm_buffersize);
+ blocksize,alsamm_buffersize);
alsamm_periods = 0; /* no one wants periods setting from command line ;-) */
diff --git a/pd/src/s_audio_audiounit.c b/pd/src/s_audio_audiounit.c
new file mode 100644
index 00000000..d9d7f667
--- /dev/null
+++ b/pd/src/s_audio_audiounit.c
@@ -0,0 +1,43 @@
+
+/* ------------- routines for Apple AudioUnit in AudioToolbox -------------- */
+#ifdef USEAPI_AUDIOUNIT
+
+/* this is currently a placeholder file while we decide which one of three implementations of this API we use */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "m_pd.h"
+#include "s_stuff.h"
+#include <AudioToolbox/AudioToolbox.h>
+
+pthread_mutex_t audiounit_mutex;
+pthread_cond_t audiounit_sem;
+
+int audiounit_open_audio(int inchans, int outchans, int rate)
+{
+ return 0;
+}
+
+void audiounit_close_audio(void)
+{
+}
+
+int audiounit_send_dacs(void)
+{
+ return 0;
+}
+
+void audiounit_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize)
+{
+ post("device getting not implemented for AudioUnit yet\n");
+}
+
+void audiounit_listdevs( void)
+{
+ post("device listing not implemented for AudioUnit yet\n");
+}
+
+#endif /* AUDIOUNIT */
diff --git a/pd/src/s_audio_dummy.c b/pd/src/s_audio_dummy.c
new file mode 100644
index 00000000..5ea1dd9f
--- /dev/null
+++ b/pd/src/s_audio_dummy.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ */
+
+#ifdef USEAPI_DUMMY
+
+#include <stdio.h>
+
+int dummy_open_audio(int nin, int nout, int sr) {
+ return 0;
+}
+
+int dummy_close_audio() {
+ return 0;
+}
+
+int dummy_send_dacs() {
+ return 0;
+}
+
+void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist,
+ int *noutdevs, int *canmulti, int maxndev, int devdescsize) {
+ sprintf(indevlist, "NONE");
+ sprintf(outdevlist, "NONE");
+ *nindevs = *noutdevs = 1;
+ *canmulti = 0;
+}
+
+void dummy_listdevs() {
+ // do nothing
+}
+
+#endif
+
diff --git a/pd/src/s_audio_esd.c b/pd/src/s_audio_esd.c
new file mode 100644
index 00000000..eb08815d
--- /dev/null
+++ b/pd/src/s_audio_esd.c
@@ -0,0 +1,135 @@
+/* Copyright (c) 2006 Guenter Geiger,
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#ifdef USEAPI_ESD
+
+#include <stdio.h>
+#include <string.h> /* memset */
+#include <esd.h>
+#include "m_pd.h"
+#include "s_stuff.h"
+#include "m_fixed.h"
+
+/* exported variables */
+
+float sys_dacsr;
+
+
+/* private data */
+
+static int esd_socket_out;
+static int esd_channels_out;
+
+static int esd_socket_in;
+static int esd_channels_in;
+
+
+int esd_open_audio(int nindev, int *indev, int nchin, int *chin,
+ int noutdev, int *outdev, int nchout, int *chout, int rate)
+{
+
+ esd_format_t format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_PLAY;
+
+ indev[0] = 0;
+ nindev = 1;
+
+ outdev[0] = 0;
+ noutdev = 1;
+
+ rate = sys_dacsr = ESD_DEFAULT_RATE;
+
+ if (*chout == 2) {
+ esd_socket_out = esd_play_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd");
+ if (esd_socket_out <= 0) {
+ fprintf (stderr, "Error at esd open: %d\n", esd_socket_out);
+ esd_channels_out = *chout = 0;
+ return 0;
+ }
+ esd_channels_out = *chout = 2;
+ }
+
+ if (*chin == 2) {
+ esd_socket_in = esd_record_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd-in");
+ if (esd_socket_in <= 0) {
+ fprintf (stderr, "Error at esd open: %d\n", esd_socket_in);
+ esd_channels_in = *chin = 0;
+ return 0;
+ }
+ esd_channels_in = *chin = 2;
+ }
+ return (0);
+}
+
+void esd_close_audio( void)
+{
+ close(esd_socket_out);
+ close(esd_socket_in);
+}
+
+
+#define DEFDACBLKSIZE 64
+#define MAXCHANS 2
+
+static short buf[DEFDACBLKSIZE*MAXCHANS];
+
+int esd_send_dacs(void)
+{
+ t_sample* fp1,*fp2;
+ short* sp;
+ int i,j;
+
+ /* Do input */
+
+ if (esd_channels_in) {
+ read(esd_socket_in,buf,DEFDACBLKSIZE*esd_channels_out*2);
+ for (i = DEFDACBLKSIZE, fp1 = sys_soundin,
+ sp = (short *)buf; i--; fp1++, sp += esd_channels_in) {
+ for (j=0, fp2 = fp1; j<esd_channels_in; j++, fp2 += DEFDACBLKSIZE)
+ {
+ int s = INVSCALE16(sp[j]);
+ *fp2 = s;
+ }
+ }
+ }
+
+ /* Do output */
+
+ if (esd_channels_out) {
+ for (i = DEFDACBLKSIZE, fp1 = sys_soundout,
+ sp = (short *)buf; i--; fp1++, sp += esd_channels_out) {
+ for (j=0, fp2 = fp1; j<esd_channels_out; j++, fp2 += DEFDACBLKSIZE)
+ {
+ int s = SCALE16(*fp2);
+ if (s > 32767) s = 32767;
+ else if (s < -32767) s = -32767;
+ sp[j] = s;
+ }
+ }
+
+ write(esd_socket_out,buf,DEFDACBLKSIZE*esd_channels_out*2);
+ }
+
+ memset(sys_soundin,0,DEFDACBLKSIZE*esd_channels_out*2);
+ memset(sys_soundout,0,DEFDACBLKSIZE*esd_channels_out*4);
+
+ return (SENDDACS_YES);
+}
+
+void esd_listdevs( void)
+{
+ post("device listing not implemented for ESD yet\n");
+}
+
+void esd_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize)
+{
+ int i, ndev;
+ *canmulti = 1; /* supports multiple devices */
+ sprintf(indevlist, "ESD device");
+ sprintf(outdevlist, "ESD device");
+ *nindevs = *noutdevs = 1;
+}
+
+#endif
diff --git a/pd/src/s_audio_jack.c b/pd/src/s_audio_jack.c
index 990a7a8c..79d4692e 100644
--- a/pd/src/s_audio_jack.c
+++ b/pd/src/s_audio_jack.c
@@ -11,25 +11,24 @@
#include <jack/jack.h>
#include <regex.h>
-
#define MAX_CLIENTS 100
-#define NUM_JACK_PORTS 128 /* seems like higher values give bad xrun problems */
+#define MAX_JACK_PORTS 128 /* seems like higher values give bad xrun problems */
#define BUF_JACK 4096
static jack_nframes_t jack_out_max;
#define JACK_OUT_MAX 64
static jack_nframes_t jack_filled = 0;
-static t_sample jack_outbuf[NUM_JACK_PORTS*BUF_JACK];
-static t_sample jack_inbuf[NUM_JACK_PORTS*BUF_JACK];
+static t_sample *jack_outbuf;
+static t_sample *jack_inbuf;
static int jack_started = 0;
-static jack_port_t *input_port[NUM_JACK_PORTS];
-static jack_port_t *output_port[NUM_JACK_PORTS];
+static jack_port_t *input_port[MAX_JACK_PORTS];
+static jack_port_t *output_port[MAX_JACK_PORTS];
static int outport_count = 0;
static jack_client_t *jack_client = NULL;
char *jack_client_names[MAX_CLIENTS];
static int jack_dio_error;
-
+static t_audiocallback jack_callback;
pthread_mutex_t jack_mutex;
pthread_cond_t jack_sem;
@@ -38,56 +37,114 @@ pthread_cond_t jack_sem;
static int
process (jack_nframes_t nframes, void *arg)
{
- int j;
- jack_default_audio_sample_t *out, *in;
-
- if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
- else jack_out_max = JACK_OUT_MAX;
- if (jack_filled >= nframes) {
- if (jack_filled != nframes) fprintf(stderr,"Partial read");
- /* hmm, how to find out whether 't_sample' and 'jack_default_audio_sample_t' are actually the same type??? */
- if(sizeof(t_sample)==sizeof(jack_default_audio_sample_t))
+ int j;
+ jack_default_audio_sample_t *out, *in;
+
+ pthread_mutex_lock(&jack_mutex);
+ if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
+ else jack_out_max = JACK_OUT_MAX;
+ if (jack_filled >= nframes)
+ {
+ if (jack_filled != nframes)
+ fprintf(stderr,"Partial read\n");
+ /* hmm, how to find out whether 't_sample' and
+ 'jack_default_audio_sample_t' are actually the same type??? */
+ if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t))
+ {
+ for (j = 0; j < sys_outchannels; j++)
+ {
+ out = jack_port_get_buffer (output_port[j], nframes);
+ memcpy(out, jack_outbuf + (j * BUF_JACK),
+ sizeof (jack_default_audio_sample_t) * nframes);
+ }
+ for (j = 0; j < sys_inchannels; j++)
+ {
+ in = jack_port_get_buffer( input_port[j], nframes);
+ memcpy(jack_inbuf + (j * BUF_JACK), in,
+ sizeof (jack_default_audio_sample_t) * nframes);
+ }
+ }
+ else
+ {
+ unsigned int frame=0;
+ t_sample*data;
+ for (j = 0; j < sys_outchannels; j++)
+ {
+ out = jack_port_get_buffer (output_port[j], nframes);
+ data = jack_outbuf + (j * BUF_JACK);
+ for(frame=0; frame<nframes; frame++)
{
- for (j = 0; j < sys_outchannels; j++) {
- out = jack_port_get_buffer (output_port[j], nframes);
- memcpy(out, jack_outbuf + (j * BUF_JACK), sizeof (jack_default_audio_sample_t) * nframes);
- }
- for (j = 0; j < sys_inchannels; j++) {
- in = jack_port_get_buffer( input_port[j], nframes);
- memcpy(jack_inbuf + (j * BUF_JACK), in, sizeof (jack_default_audio_sample_t) * nframes);
- }
- }
- else
+ *out++=*data++;
+ }
+ }
+ for (j = 0; j < sys_inchannels; j++)
+ {
+ in = jack_port_get_buffer( input_port[j], nframes);
+ data = jack_inbuf + (j * BUF_JACK);
+ for(frame=0; frame<nframes; frame++)
{
- unsigned int frame=0;
- t_sample*data;
- for (j = 0; j < sys_outchannels; j++) {
- out = jack_port_get_buffer (output_port[j], nframes);
- data=jack_outbuf + (j * BUF_JACK);
- for(frame=0; frame<nframes; frame++) {
- *out++=*data++;
- }
- }
- for (j = 0; j < sys_inchannels; j++) {
- in = jack_port_get_buffer( input_port[j], nframes);
- data=jack_inbuf+(j*BUF_JACK);
- for(frame=0; frame<nframes; frame++) {
- *data++=*in++;
- }
- }
+ *data++=*in++;
}
- jack_filled -= nframes;
- } else { /* PD could not keep up ! */
- if (jack_started) jack_dio_error = 1;
- for (j = 0; j < outport_count; j++) {
- out = jack_port_get_buffer (output_port[j], nframes);
- memset(out, 0, sizeof (float) * nframes);
- }
- memset(jack_outbuf,0,sizeof(jack_outbuf));
- jack_filled = 0;
+ }
}
- pthread_cond_broadcast(&jack_sem);
- return 0;
+ jack_filled -= nframes;
+ }
+ else
+ { /* PD could not keep up ! */
+ if (jack_started) jack_dio_error = 1;
+ for (j = 0; j < outport_count; j++)
+ {
+ out = jack_port_get_buffer (output_port[j], nframes);
+ memset(out, 0, sizeof (float) * nframes);
+ memset(jack_outbuf + j * BUF_JACK, 0, BUF_JACK * sizeof(t_sample));
+ }
+ jack_filled = 0;
+ }
+ pthread_cond_broadcast(&jack_sem);
+ pthread_mutex_unlock(&jack_mutex);
+ return 0;
+}
+
+static int callbackprocess(jack_nframes_t nframes, void *arg)
+{
+ int chan, j, k;
+ unsigned int n;
+ jack_default_audio_sample_t *out[MAX_JACK_PORTS], *in[MAX_JACK_PORTS], *jp;
+
+ if (nframes % DEFDACBLKSIZE)
+ {
+ fprintf(stderr, "jack: nframes %d not a multiple of blocksize %d\n",
+ nframes, DEFDACBLKSIZE);
+ nframes -= (nframes % DEFDACBLKSIZE);
+ }
+ for (chan = 0; chan < sys_inchannels; chan++)
+ in[chan] = jack_port_get_buffer(input_port[chan], nframes);
+ for (chan = 0; chan < sys_outchannels; chan++)
+ out[chan] = jack_port_get_buffer(output_port[chan], nframes);
+ for (n = 0; n < nframes; n += DEFDACBLKSIZE)
+ {
+ t_sample *fp;
+ for (chan = 0; chan < sys_inchannels; chan++)
+ {
+ for (fp = sys_soundin + chan*DEFDACBLKSIZE,
+ jp = in[chan] + n, j=0; j < DEFDACBLKSIZE; j++)
+ *fp++ = *jp++;
+ }
+ for (chan = 0; chan < sys_outchannels; chan++)
+ {
+ for (fp = sys_soundout + chan*DEFDACBLKSIZE,
+ j = 0; j < DEFDACBLKSIZE; j++)
+ *fp++ = 0;
+ }
+ (*jack_callback)();
+ for (chan = 0; chan < sys_outchannels; chan++)
+ {
+ for (fp = sys_soundout + chan*DEFDACBLKSIZE, jp = out[chan] + n,
+ j=0; j < DEFDACBLKSIZE; j++)
+ *jp++ = *fp++;
+ }
+ }
+ return 0;
}
static int
@@ -97,11 +154,19 @@ jack_srate (jack_nframes_t srate, void *arg)
return 0;
}
+
+void glob_audio_setapi(void *dummy, t_floatarg f);
+
static void
jack_shutdown (void *arg)
{
- /* Ignore for now */
- // exit (1);
+ error("JACK: server shut down");
+
+ jack_deactivate (jack_client);
+ //jack_client_close(jack_client); /* likely to hang if the server shut down */
+ jack_client = NULL;
+
+ glob_audio_setapi(NULL, API_NONE); // set pd_whichapi 0
}
static int jack_xrun(void* arg) {
@@ -128,6 +193,9 @@ static char** jack_get_clients(void)
regmatch_t match_info;
char tmp_client_name[100];
+ if(num_clients>=MAX_CLIENTS)break;
+
+
/* extract the client name from the port name, using a regex
* that parses the clientname:portname syntax */
regexec( &port_regex, jack_ports[i], 1, &match_info, 0 );
@@ -166,7 +234,6 @@ static char** jack_get_clients(void)
strcpy( jack_client_names[ num_clients ], tmp_client_name );
}
num_clients++;
-
}
}
@@ -196,7 +263,7 @@ static int jack_connect_ports(char* client)
if (jack_ports)
for (i=0;jack_ports[i] != NULL && i < sys_inchannels;i++)
if (jack_connect (jack_client, jack_ports[i], jack_port_name (input_port[i])))
- fprintf (stderr, "cannot connect input ports %s -> %s\n", jack_ports[i],jack_port_name (input_port[i]));
+ error ("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i]));
@@ -205,7 +272,7 @@ static int jack_connect_ports(char* client)
if (jack_ports)
for (i=0;jack_ports[i] != NULL && i < sys_outchannels;i++)
if (jack_connect (jack_client, jack_port_name (output_port[i]), jack_ports[i]))
- fprintf (stderr, "cannot connect output ports %s -> %s\n", jack_port_name (output_port[i]),jack_ports[i]);
+ error( "JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]);
@@ -214,172 +281,244 @@ static int jack_connect_ports(char* client)
}
-void pd_jack_error_callback(const char *desc) {
+static void pd_jack_error_callback(const char *desc) {
+ error("JACKerror: %s", desc);
return;
}
-
int
-jack_open_audio(int inchans, int outchans, int rate)
-
+jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback)
{
- int j;
- char port_name[80] = "";
- int client_iterator = 0;
- int new_jack = 0;
- int srate;
+ int j;
+ char port_name[80] = "";
+ char client_name[80] = "";
- jack_dio_error = 0;
-
- if ((inchans == 0) && (outchans == 0)) return 0;
+ int client_iterator = 0;
+ int new_jack = 0;
+ int srate;
+ jack_status_t status;
- if (outchans > NUM_JACK_PORTS) {
- fprintf(stderr,"%d output ports not supported, setting to %d\n",outchans, NUM_JACK_PORTS);
- outchans = NUM_JACK_PORTS;
- }
+ if (NULL==jack_client_new)
+ {
+ fprintf(stderr,"JACK framework not available\n");
+ return 1;
+ }
+
+ jack_dio_error = 0;
+
+ if ((inchans == 0) && (outchans == 0)) return 0;
- if (inchans > NUM_JACK_PORTS) {
- fprintf(stderr,"%d input ports not supported, setting to %d\n",inchans, NUM_JACK_PORTS);
- inchans = NUM_JACK_PORTS;
+ if (outchans > MAX_JACK_PORTS) {
+ error("JACK: %d output ports not supported, setting to %d",
+ outchans, MAX_JACK_PORTS);
+ outchans = MAX_JACK_PORTS;
+ }
+
+ if (inchans > MAX_JACK_PORTS) {
+ error("JACK: %d input ports not supported, setting to %d",
+ inchans, MAX_JACK_PORTS);
+ inchans = MAX_JACK_PORTS;
+ }
+ /* try to become a client of the JACK server */
+ /* if no JACK server exists, start a default one (jack_client_open() does that for us... */
+ if (!jack_client) {
+ do {
+ sprintf(client_name,"pure_data_%d",client_iterator);
+ client_iterator++;
+ jack_client = jack_client_open (client_name, JackNullOption, &status, NULL);
+ if (status & JackServerFailed) {
+ error("JACK: unable to connect to JACK server");
+ jack_client=NULL;
+ break;
+ }
+ } while (status & JackNameNotUnique);
+
+ if(status) {
+ if (status & JackServerStarted) {
+ verbose(1, "JACK: started server");
+ } else {
+ error("JACK: server returned status %d", status);
+ }
}
+ verbose(1, "JACK: started server as '%s'", client_name);
- /* try to become a client of the JACK server (we allow two pd's)*/
if (!jack_client) {
- do {
- sprintf(port_name,"pure_data_%d",client_iterator);
- client_iterator++;
- } while (((jack_client = jack_client_new (port_name)) == 0) && client_iterator < 2);
-
-
- if (!jack_client) { // jack spits out enough messages already, do not warn
+ /* jack spits out enough messages already, do not warn */
sys_inchannels = sys_outchannels = 0;
return 1;
- }
-
- jack_get_clients();
-
- /* tell the JACK server to call `process()' whenever
- there is work to be done.
- */
-
- jack_set_process_callback (jack_client, process, 0);
-
- jack_set_error_function (pd_jack_error_callback);
-
+ }
+
+ sys_inchannels = inchans;
+ sys_outchannels = outchans;
+ if (jack_inbuf)
+ free(jack_inbuf);
+ if (sys_inchannels)
+ jack_inbuf = calloc(sizeof(t_sample), sys_inchannels * BUF_JACK);
+ if (jack_outbuf)
+ free(jack_outbuf);
+ if (sys_outchannels)
+ jack_outbuf = calloc(sizeof(t_sample), sys_outchannels * BUF_JACK);
+
+ jack_get_clients();
+
+ /* tell the JACK server to call `process()' whenever
+ there is work to be done.
+ */
+ jack_callback = callback;
+ jack_set_process_callback (jack_client,
+ (callback? callbackprocess : process), 0);
+
+ jack_set_error_function (pd_jack_error_callback);
+
#ifdef JACK_XRUN
- jack_set_xrun_callback (jack_client, jack_xrun, NULL);
+ jack_set_xrun_callback (jack_client, jack_xrun, NULL);
#endif
-
- /* tell the JACK server to call `srate()' whenever
- the sample rate of the system changes.
- */
-
- jack_set_sample_rate_callback (jack_client, jack_srate, 0);
-
-
- /* tell the JACK server to call `jack_shutdown()' if
- it ever shuts down, either entirely, or if it
- just decides to stop calling us.
- */
-
- jack_on_shutdown (jack_client, jack_shutdown, 0);
-
- for (j=0;j<NUM_JACK_PORTS;j++) {
- input_port[j]=NULL;
- output_port[j] = NULL;
- }
-
- new_jack = 1;
- }
- /* display the current sample rate. once the client is activated
- (see below), you should rely on your own sample rate
- callback (see above) for this value.
+ /* tell the JACK server to call `srate()' whenever
+ the sample rate of the system changes.
*/
-
- srate = jack_get_sample_rate (jack_client);
- sys_dacsr = srate;
-
- /* create the ports */
-
- for (j = 0; j < inchans; j++) {
- sprintf(port_name, "input%d", j);
- if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+
+ jack_set_sample_rate_callback (jack_client, jack_srate, 0);
+
+
+ /* tell the JACK server to call `jack_shutdown()' if
+ it ever shuts down, either entirely, or if it
+ just decides to stop calling us.
+ */
+
+ jack_on_shutdown (jack_client, jack_shutdown, 0);
+
+ for (j=0; j<sys_inchannels; j++)
+ input_port[j]=NULL;
+ for (j=0; j<sys_outchannels; j++)
+ output_port[j] = NULL;
+
+ new_jack = 1;
+ }
+
+ /* display the current sample rate. once the client is activated
+ (see below), you should rely on your own sample rate
+ callback (see above) for this value.
+ */
+
+ srate = jack_get_sample_rate (jack_client);
+ sys_dacsr = srate;
+
+ /* create the ports */
+
+ for (j = 0; j < inchans; j++) {
+ sprintf(port_name, "input%d", j);
+ if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ if (!input_port[j]) {
+ error("JACK: can only register %d input ports (instead of requested %d)", j, inchans);
+ sys_inchannels = inchans = j;
+ break;
}
+ }
- for (j = 0; j < outchans; j++) {
- sprintf(port_name, "output%d", j);
- if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- }
- outport_count = outchans;
+ for (j = 0; j < outchans; j++) {
+ sprintf(port_name, "output%d", j);
+ if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ if (!output_port[j]) {
+ error("JACK: can only register %d output ports (instead of requested %d)", j, outchans);
+ sys_outchannels = outchans = j;
+ break;
+ }
+ }
+ outport_count = outchans;
- /* tell the JACK server that we are ready to roll */
-
- if (new_jack) {
- if (jack_activate (jack_client)) {
- fprintf (stderr, "cannot activate client\n");
+ /* tell the JACK server that we are ready to roll */
+
+ if (new_jack) {
+ if (jack_activate (jack_client)) {
+ error("cannot activate client");
sys_inchannels = sys_outchannels = 0;
return 1;
- }
-
- memset(jack_outbuf,0,sizeof(jack_outbuf));
-
- if (jack_client_names[0])
+ }
+
+ for (j = 0; j < outchans; j++)
+ memset(jack_outbuf + j * BUF_JACK, 0,
+ BUF_JACK * sizeof(t_sample));
+
+ if (jack_client_names[0])
jack_connect_ports(jack_client_names[0]);
- pthread_mutex_init(&jack_mutex,NULL);
- pthread_cond_init(&jack_sem,NULL);
- }
- return 0;
+ pthread_mutex_init(&jack_mutex, NULL);
+ pthread_cond_init(&jack_sem, NULL);
+ }
+ return 0;
}
void jack_close_audio(void)
-
{
- jack_started = 0;
+ if (jack_client){
+ jack_deactivate (jack_client);
+ jack_client_close(jack_client);
+ }
+
+ jack_client=NULL;
+ jack_started = 0;
+
+ pthread_cond_broadcast(&jack_sem);
+
+ pthread_cond_destroy(&jack_sem);
+ pthread_mutex_destroy(&jack_mutex);
+ if (jack_inbuf)
+ free(jack_inbuf), jack_inbuf = 0;
+ if (jack_outbuf)
+ free(jack_outbuf), jack_outbuf = 0;
+
}
int jack_send_dacs(void)
{
- t_sample * fp;
- int j;
- int rtnval = SENDDACS_YES;
- int timenow;
- int timeref = sys_getrealtime();
-
- if (!jack_client) return SENDDACS_NO;
-
- if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO);
-
- if (jack_dio_error) {
- sys_log_error(ERR_RESYNC);
- jack_dio_error = 0;
- }
- if (jack_filled >= jack_out_max)
- pthread_cond_wait(&jack_sem,&jack_mutex);
-
- jack_started = 1;
-
- fp = sys_soundout;
- for (j = 0; j < sys_outchannels; j++) {
- memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled,fp, DEFDACBLKSIZE*sizeof(t_sample));
- fp += DEFDACBLKSIZE;
- }
- fp = sys_soundin;
- for (j = 0; j < sys_inchannels; j++) {
- memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(t_sample));
- fp += DEFDACBLKSIZE;
- }
+ t_sample * fp;
+ int j;
+ int rtnval = SENDDACS_YES;
+ int timenow;
+ int timeref = sys_getrealtime();
+ if (!jack_client) return SENDDACS_NO;
+ if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO);
+ if (jack_dio_error)
+ {
+ sys_log_error(ERR_RESYNC);
+ jack_dio_error = 0;
+ }
+ pthread_mutex_lock(&jack_mutex);
+ if (jack_filled >= jack_out_max)
+ pthread_cond_wait(&jack_sem,&jack_mutex);
- if ((timenow = sys_getrealtime()) - timeref > 0.002)
- {
- rtnval = SENDDACS_SLEPT;
- }
+ if (!jack_client)
+ {
+ pthread_mutex_unlock(&jack_mutex);
+ return SENDDACS_NO;
+ }
+ jack_started = 1;
- memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
- jack_filled += DEFDACBLKSIZE;
- return rtnval;
+ fp = sys_soundout;
+ for (j = 0; j < sys_outchannels; j++)
+ {
+ memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp,
+ DEFDACBLKSIZE*sizeof(t_sample));
+ fp += DEFDACBLKSIZE;
+ }
+ fp = sys_soundin;
+ for (j = 0; j < sys_inchannels; j++)
+ {
+ memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled,
+ DEFDACBLKSIZE*sizeof(t_sample));
+ fp += DEFDACBLKSIZE;
+ }
+ jack_filled += DEFDACBLKSIZE;
+ pthread_mutex_unlock(&jack_mutex);
+
+ if ((timenow = sys_getrealtime()) - timeref > 0.002)
+ {
+ rtnval = SENDDACS_SLEPT;
+ }
+ memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
+ return rtnval;
}
void jack_getdevs(char *indevlist, int *nindevs,
diff --git a/pd/src/s_audio_mmio.c b/pd/src/s_audio_mmio.c
index fd17a1ce..0324c941 100644
--- a/pd/src/s_audio_mmio.c
+++ b/pd/src/s_audio_mmio.c
@@ -696,11 +696,11 @@ idle:
int mmio_open_audio(int naudioindev, int *audioindev,
int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
- int nchoutdev, int *choutdev, int rate)
+ int nchoutdev, int *choutdev, int rate, int blocksize)
{
int nbuf;
- nt_realdacblksize = (sys_blocksize ? sys_blocksize : DEFREALDACBLKSIZE);
+ nt_realdacblksize = (blocksize ? blocksize : DEFREALDACBLKSIZE);
nbuf = sys_advance_samples/nt_realdacblksize;
if (nbuf >= MAXBUFFER)
{
diff --git a/pd/src/s_audio_oss.c b/pd/src/s_audio_oss.c
index 73f916ce..10329fed 100644
--- a/pd/src/s_audio_oss.c
+++ b/pd/src/s_audio_oss.c
@@ -5,7 +5,11 @@
/* this file inputs and outputs audio using the OSS API available on linux. */
-#include <linux/soundcard.h>
+#if defined(__FreeBSD_kernel__)
+# include <sys/soundcard.h>
+#else
+# include <linux/soundcard.h>
+#endif
#include "m_pd.h"
#include "s_stuff.h"
@@ -45,7 +49,7 @@ static int linux_meters; /* true if we're metering */
static t_sample linux_inmax; /* max input amplitude */
static t_sample linux_outmax; /* max output amplitude */
static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
-
+extern int audio_blocksize; /* stolen from s_audio.c */
/* our device handles */
typedef struct _oss_dev
@@ -121,7 +125,8 @@ int oss_reset(int fd) {
return err;
}
-void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
+void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize,
+ int suggestedblocksize)
{
int orig, param, nblk, fd = dev->d_fd, wantformat;
int nchannels = dev->d_nchannels;
@@ -153,7 +158,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
{
int fragbytes, logfragsize, nfragment;
/* setting fragment count and size. */
- linux_fragsize = sys_blocksize;
+ linux_fragsize = suggestedblocksize;
if (!linux_fragsize)
{
linux_fragsize = OSS_DEFFRAGSIZE;
@@ -256,7 +261,8 @@ whynot:
#define O_AUDIOFLAG O_NDELAY
int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
- int noutdev, int *outdev, int nchout, int *chout, int rate)
+ int noutdev, int *outdev, int nchout, int *chout, int rate,
+ int blocksize)
{
int capabilities = 0;
int inchannels = 0, outchannels = 0;
@@ -358,7 +364,7 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
{
linux_dacs[linux_noutdevs].d_nchannels = gotchans;
linux_dacs[linux_noutdevs].d_fd = fd;
- oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
+ oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize);
linux_noutdevs++;
outchannels += gotchans;
@@ -433,7 +439,8 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
linux_adcs[linux_nindevs].d_nchannels = gotchans;
- oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
+ oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened,
+ blocksize);
inchannels += gotchans;
linux_nindevs++;
diff --git a/pd/src/s_audio_pa.c b/pd/src/s_audio_pa.c
index de5fe711..3f9ca51c 100644
--- a/pd/src/s_audio_pa.c
+++ b/pd/src/s_audio_pa.c
@@ -6,18 +6,29 @@
the main way in for Mac OS and, with Michael Casey's help, also into
ASIO in Windows. */
+/* dolist...
+ put in a real FIFO (compare to Zmoelnig and keep FIFO if OK)
+ switch to usleep in s_inter.c
+ try blocking and nonblocking calls here
+ for blocking, offer pthreads or usleep method
+ (see if pthreads is still inefficient with FIFO?)
+*/
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
#include <portaudio.h>
-#include "s_audio_pablio.h"
#ifdef MSW
#include <malloc.h>
+#include <windows.h>
#else
#include <alloca.h>
+#include <unistd.h>
#endif
+#include "s_audio_paring.h"
/* LATER try to figure out how to handle default devices in portaudio;
the way s_audio.c handles them isn't going to work here. */
@@ -25,16 +36,24 @@
/* public interface declared in m_imp.h */
/* implementation */
-static PABLIO_Stream *pa_stream;
+static PaStream *pa_stream;
static int pa_inchans, pa_outchans;
static float *pa_soundin, *pa_soundout;
static t_audiocallback pa_callback;
-int pa_foo;
+static float *pa_outbuf;
+static sys_ringbuf pa_outring;
+static float *pa_inbuf;
+static sys_ringbuf pa_inring;
+static int pa_started = 0;
+static int pa_dio_error;
+
+pthread_mutex_t pa_mutex;
+pthread_cond_t pa_sem;
+
+/* define this to enable thread signaling instead of polling */
+/* #define THREADSIGNAL */
-#ifndef MSW
-#include <unistd.h>
-#endif
static void pa_init(void)
{
static int initialized;
@@ -68,54 +87,117 @@ static void pa_init(void)
}
static int pa_lowlevel_callback(const void *inputBuffer,
- void *outputBuffer, unsigned long framesPerBuffer,
+ void *outputBuffer, unsigned long nframes,
const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
void *userData)
{
int i;
- unsigned int j;
+ unsigned int n, j;
float *fbuf, *fp2, *fp3, *soundiop;
- if (pa_foo)
- fprintf(stderr, "pa_lowlevel_callback\n");
- if (framesPerBuffer != DEFDACBLKSIZE)
+ if (nframes % DEFDACBLKSIZE)
{
- fprintf(stderr, "ignoring buffer size %d\n", (int)framesPerBuffer);
- return 0;
+ fprintf(stderr, "portaudio: nframes %ld not a multiple of blocksize %d\n",
+ nframes, (int)DEFDACBLKSIZE);
+ nframes -= (nframes % DEFDACBLKSIZE);
}
- if (inputBuffer != NULL)
+ for (n = 0; n < nframes; n += DEFDACBLKSIZE)
{
- fbuf = (float *)inputBuffer;
- soundiop = pa_soundin;
- for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
- for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans)
- *soundiop++ = *fp3;
+ if (inputBuffer != NULL)
+ {
+ fbuf = ((float *)inputBuffer) + n*pa_inchans;
+ soundiop = pa_soundin;
+ for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
+ for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
+ j++, fp3 += pa_inchans)
+ *soundiop++ = *fp3;
+ }
+ else memset((void *)pa_soundin, 0,
+ DEFDACBLKSIZE * pa_inchans * sizeof(float));
+ memset((void *)pa_soundout, 0,
+ DEFDACBLKSIZE * pa_outchans * sizeof(float));
+ (*pa_callback)();
+ if (outputBuffer != NULL)
+ {
+ fbuf = ((float *)outputBuffer) + n*pa_outchans;
+ soundiop = pa_soundout;
+ for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
+ for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
+ j++, fp3 += pa_outchans)
+ *fp3 = *soundiop++;
+ }
}
- else memset((void *)pa_soundin, 0,
- framesPerBuffer * pa_inchans * sizeof(float));
- memset((void *)pa_soundout, 0,
- framesPerBuffer * pa_outchans * sizeof(float));
- (*pa_callback)();
- if (outputBuffer != NULL)
+ return 0;
+}
+
+ /* callback for "non-callback" case where we communicate with the
+ main thread via FIFO. Here we first read the sudio output FIFO (which
+ we sync on, not waiting for it but supplying zeros to the audio output if
+ there aren't enough samples in the FIFO when we are called), then write
+ to the audio input FIFO. The main thread will wait for the input fifo.
+ We can either throw it a pthreads condition or just allow the main thread
+ to poll for us; so far polling seems to work better. */
+static int pa_fifo_callback(const void *inputBuffer,
+ void *outputBuffer, unsigned long nframes,
+ const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
+ void *userData)
+{
+ /* callback routine for non-callback client... throw samples into
+ and read them out of a FIFO */
+ int ch;
+ long fiforoom;
+ float *fbuf;
+
+#if CHECKFIFOS
+ if (pa_inchans * sys_ringbuf_GetReadAvailable(&pa_outring) !=
+ pa_outchans * sys_ringbuf_GetWriteAvailable(&pa_inring))
+ fprintf(stderr, "warning: in and out rings unequal (%d, %d)\n",
+ sys_ringbuf_GetReadAvailable(&pa_outring),
+ sys_ringbuf_GetWriteAvailable(&pa_inring));
+#endif
+ fiforoom = sys_ringbuf_GetReadAvailable(&pa_outring);
+ if ((unsigned)fiforoom >= nframes*pa_outchans*sizeof(float))
{
- fbuf = (float *)outputBuffer;
- soundiop = pa_soundout;
- for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
- for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_outchans)
- *fp3 = *soundiop++;
+ if (outputBuffer)
+ sys_ringbuf_Read(&pa_outring, outputBuffer,
+ nframes*pa_outchans*sizeof(float));
+ else if (pa_outchans)
+ fprintf(stderr, "no outputBuffer but output channels\n");
+ if (inputBuffer)
+ sys_ringbuf_Write(&pa_inring, inputBuffer,
+ nframes*pa_inchans*sizeof(float));
+ else if (pa_inchans)
+ fprintf(stderr, "no inputBuffer but input channels\n");
}
- if (pa_foo)
- fprintf(stderr, "done pa_lowlevel_callback\n");
+ else
+ { /* PD could not keep up; generate zeros */
+ if (pa_started)
+ pa_dio_error = 1;
+ if (outputBuffer)
+ {
+ for (ch = 0; ch < pa_outchans; ch++)
+ {
+ unsigned long frame;
+ fbuf = ((float *)outputBuffer) + ch;
+ for (frame = 0; frame < nframes; frame++, fbuf += pa_outchans)
+ *fbuf = 0;
+ }
+ }
+ }
+#ifdef THREADSIGNAL
+ pthread_mutex_lock(&pa_mutex);
+ pthread_cond_signal(&pa_sem);
+ pthread_mutex_unlock(&pa_mutex);
+#endif
return 0;
}
PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
- int framesperbuf, int nbuffers, int indeviceno, int outdeviceno)
+ int framesperbuf, int nbuffers, int indeviceno, int outdeviceno, PaStreamCallback *callbackfn)
{
long bytesPerSample;
PaError err;
- PABLIO_Stream *pastream;
- long numFrames;
PaStreamParameters instreamparams, outstreamparams;
+ PaStreamParameters*p_instreamparams=0, *p_outstreamparams=0;
if (indeviceno < 0)
{
@@ -130,58 +212,84 @@ PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
/* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
nchannels, flags, nbuffers, framesperbuf); */
- /* Allocate PABLIO_Stream structure for caller. */
- pastream = (PABLIO_Stream *)malloc( sizeof(PABLIO_Stream));
- if (pastream == NULL)
- return (1);
- memset(pastream, 0, sizeof(PABLIO_Stream));
-
- /* Determine size of a sample. */
- bytesPerSample = Pa_GetSampleSize(paFloat32);
- if (bytesPerSample < 0)
- {
- err = (PaError) bytesPerSample;
- goto error;
- }
- pastream->insamplesPerFrame = inchannels;
- pastream->inbytesPerFrame = bytesPerSample * pastream->insamplesPerFrame;
- pastream->outsamplesPerFrame = outchannels;
- pastream->outbytesPerFrame = bytesPerSample * pastream->outsamplesPerFrame;
-
- numFrames = nbuffers * framesperbuf;
-
instreamparams.device = indeviceno;
instreamparams.channelCount = inchannels;
instreamparams.sampleFormat = paFloat32;
- instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
+ instreamparams.suggestedLatency = 0; /* was nbuffers*framesperbuf/sampleRate */
instreamparams.hostApiSpecificStreamInfo = 0;
outstreamparams.device = outdeviceno;
outstreamparams.channelCount = outchannels;
outstreamparams.sampleFormat = paFloat32;
- outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
+ outstreamparams.suggestedLatency = 0;
outstreamparams.hostApiSpecificStreamInfo = 0;
+ if(inchannels>0)
+ p_instreamparams=&instreamparams;
+ if(outchannels>0)
+ p_outstreamparams=&outstreamparams;
+
+ err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams, sampleRate);
+
+ if (paFormatIsSupported != err)
+ {
+ /* check whether we have to change the numbers of channel and/or samplerate */
+ const PaDeviceInfo* info = 0;
+ double inRate=0, outRate=0;
+
+ if (inchannels>0)
+ {
+ if (NULL != (info = Pa_GetDeviceInfo( instreamparams.device )))
+ {
+ inRate=info->defaultSampleRate;
+
+ if(info->maxInputChannels<inchannels)
+ instreamparams.channelCount=info->maxInputChannels;
+ }
+ }
+
+ if (outchannels>0)
+ {
+ if (NULL != (info = Pa_GetDeviceInfo( outstreamparams.device )))
+ {
+ outRate=info->defaultSampleRate;
+
+ if(info->maxOutputChannels<outchannels)
+ outstreamparams.channelCount=info->maxOutputChannels;
+ }
+ }
+
+ if (err == paInvalidSampleRate)
+ {
+ sampleRate=outRate;
+ }
+
+ err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams,
+ sampleRate);
+ if (paFormatIsSupported != err)
+ goto error;
+ }
+
err = Pa_OpenStream(
- &pastream->stream,
- (inchannels ? &instreamparams : 0),
- (outchannels ? &outstreamparams : 0),
+ &pa_stream,
+ p_instreamparams,
+ p_outstreamparams,
sampleRate,
- DEFDACBLKSIZE,
+ framesperbuf,
paNoFlag, /* portaudio will clip for us */
- pa_lowlevel_callback,
- pastream);
+ callbackfn,
+ 0);
if (err != paNoError)
goto error;
- err = Pa_StartStream(pastream->stream);
+ err = Pa_StartStream(pa_stream);
if (err != paNoError)
{
fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
- CloseAudioStream( pastream );
+ pa_close_audio();
goto error;
}
- pa_stream = pastream;
+ sys_dacsr=sampleRate;
return paNoError;
error:
pa_stream = NULL;
@@ -200,6 +308,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
pa_init();
/* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
+ if (pa_stream)
+ pa_close_audio();
+
if (inchans > 0)
{
for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++)
@@ -209,6 +320,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
{
if (devno == indeviceno)
{
+ if (inchans > info->maxInputChannels)
+ inchans = info->maxInputChannels;
+
pa_indev = j;
break;
}
@@ -226,6 +340,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
{
if (devno == outdeviceno)
{
+ if (outchans > info->maxOutputChannels)
+ outchans = info->maxOutputChannels;
+
pa_outdev = j;
break;
}
@@ -240,23 +357,42 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
post("output device %d, channels %d", pa_outdev, outchans);
post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
}
- pa_inchans = inchans;
- pa_outchans = outchans;
+ pa_inchans = sys_inchannels = inchans;
+ pa_outchans = sys_outchannels = outchans;
pa_soundin = soundin;
pa_soundout = soundout;
+
+ if (pa_inbuf)
+ free(pa_inbuf), pa_inbuf = 0;
+ if (pa_outbuf)
+ free(pa_outbuf), pa_outbuf = 0;
+
if (! inchans && !outchans)
- return(0);
+ return (0);
+
if (callbackfn)
{
pa_callback = callbackfn;
err = pa_open_callback(rate, inchans, outchans,
- framesperbuf, nbuffers, pa_indev, pa_outdev);
+ framesperbuf, nbuffers, pa_indev, pa_outdev, pa_lowlevel_callback);
}
else
{
- err = OpenAudioStream( &pa_stream, rate, paFloat32,
- inchans, outchans, framesperbuf, nbuffers,
- pa_indev, pa_outdev);
+ if (pa_inchans)
+ {
+ pa_inbuf = malloc(nbuffers*framesperbuf*pa_inchans*sizeof(float));
+ sys_ringbuf_Init(&pa_inring,
+ nbuffers*framesperbuf*pa_inchans*sizeof(float), pa_inbuf,
+ nbuffers*framesperbuf*pa_inchans*sizeof(float));
+ }
+ if (pa_outchans)
+ {
+ pa_outbuf = malloc(nbuffers*framesperbuf*pa_outchans*sizeof(float));
+ sys_ringbuf_Init(&pa_outring,
+ nbuffers*framesperbuf*pa_outchans*sizeof(float), pa_outbuf, 0);
+ }
+ err = pa_open_callback(rate, inchans, outchans,
+ framesperbuf, nbuffers, pa_indev, pa_outdev, pa_fifo_callback);
}
if ( err != paNoError )
{
@@ -273,95 +409,117 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
void pa_close_audio( void)
{
- /* fprintf(stderr, "close\n"); */
- if (pa_inchans || pa_outchans)
- CloseAudioStream( pa_stream );
- pa_inchans = pa_outchans = 0;
+ if (pa_stream)
+ {
+ Pa_AbortStream(pa_stream);
+ Pa_CloseStream(pa_stream);
+ }
+ pa_stream = 0;
+ if (pa_inbuf)
+ free(pa_inbuf), pa_inbuf = 0;
+ if (pa_outbuf)
+ free(pa_outbuf), pa_outbuf = 0;
+
}
int pa_send_dacs(void)
{
- unsigned int framesize = (sizeof(float) * DEFDACBLKSIZE) *
- (pa_inchans > pa_outchans ? pa_inchans:pa_outchans);
- float *samples, *fp1, *fp2;
- int i, j;
- double timebefore;
-
-
- samples = alloca(framesize);
-
- timebefore = sys_getrealtime();
- if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
- (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
+ t_sample *fp;
+ float *fp2, *fp3;
+ float *conversionbuf;
+ int j, k;
+ int rtnval = SENDDACS_YES;
+ int timenow;
+ int timeref = sys_getrealtime();
+ if (!sys_inchannels && !sys_outchannels)
+ return (SENDDACS_NO);
+#if CHECKFIFOS
+ if (sys_outchannels * sys_ringbuf_GetReadAvailable(&pa_inring) !=
+ sys_inchannels * sys_ringbuf_GetWriteAvailable(&pa_outring))
+ fprintf(stderr, "warning (2): in and out rings unequal (%d, %d)\n",
+ sys_ringbuf_GetReadAvailable(&pa_inring),
+ sys_ringbuf_GetWriteAvailable(&pa_outring));
+#endif
+ conversionbuf = (float *)alloca((sys_inchannels > sys_outchannels?
+ sys_inchannels:sys_outchannels) * DEFDACBLKSIZE * sizeof(float));
+ if (pa_dio_error)
{
- if (pa_inchans && pa_outchans)
- {
- int synced = 0;
- while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
- {
- for (j = 0; j < pa_outchans; j++)
- for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
- fp2 += pa_outchans)
- {
- *fp2 = 0;
- }
- synced = 1;
- WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
- }
- while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
- {
- synced = 1;
- ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
- }
- /* if (synced)
- post("sync"); */
- }
- return (SENDDACS_NO);
+ sys_log_error(ERR_RESYNC);
+ pa_dio_error = 0;
}
- if (pa_inchans)
+
+ if (!sys_inchannels) /* if no input channels sync on output */
{
- ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
- for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += DEFDACBLKSIZE)
- for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
- fp2 += pa_inchans)
- {
- fp1[i] = *fp2;
- }
+#ifdef THREADSIGNAL
+ pthread_mutex_lock(&pa_mutex);
+#endif
+ while (sys_ringbuf_GetWriteAvailable(&pa_outring) <
+ (long)(sys_outchannels * DEFDACBLKSIZE * sizeof(float)))
+#ifdef THREADSIGNAL
+ pthread_cond_wait(&pa_sem, &pa_mutex);
+#else
+#ifdef MSW
+ Sleep(1);
+#else
+ usleep(1000);
+#endif /* MSW */
+#endif /* THREADSIGNAL */
+#ifdef THREADSIGNAL
+ pthread_mutex_unlock(&pa_mutex);
+#endif
}
-#if 0
- {
- static int nread;
- if (nread == 0)
- {
- post("it's %f %f %f %f",
- pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
- nread = 1000;
- }
- nread--;
- }
+ /* write output */
+ if (sys_outchannels)
+ {
+ for (j = 0, fp = sys_soundout, fp2 = conversionbuf;
+ j < sys_outchannels; j++, fp2++)
+ for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+ k++, fp++, fp3 += sys_outchannels)
+ *fp3 = *fp;
+ sys_ringbuf_Write(&pa_outring, conversionbuf,
+ sys_outchannels*(DEFDACBLKSIZE*sizeof(float)));
+ }
+ if (sys_inchannels) /* if there is input sync on it */
+ {
+#ifdef THREADSIGNAL
+ pthread_mutex_lock(&pa_mutex);
#endif
- if (pa_outchans)
+ while (sys_ringbuf_GetReadAvailable(&pa_inring) <
+ (long)(sys_inchannels * DEFDACBLKSIZE * sizeof(float)))
+#ifdef THREADSIGNAL
+ pthread_cond_wait(&pa_sem, &pa_mutex);
+#else
+#ifdef MSW
+ Sleep(1);
+#else
+ usleep(1000);
+#endif /* MSW */
+#endif /* THREADSIGNAL */
+#ifdef THREADSIGNAL
+ pthread_mutex_unlock(&pa_mutex);
+#endif
+ }
+ pa_started = 1;
+
+ if (sys_inchannels)
{
- for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
- fp1 += DEFDACBLKSIZE)
- for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
- fp2 += pa_outchans)
- {
- *fp2 = fp1[i];
- fp1[i] = 0;
- }
- WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
+ sys_ringbuf_Read(&pa_inring, conversionbuf,
+ sys_inchannels*(DEFDACBLKSIZE*sizeof(float)));
+ for (j = 0, fp = sys_soundin, fp2 = conversionbuf;
+ j < sys_inchannels; j++, fp2++)
+ for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+ k++, fp++, fp3 += sys_inchannels)
+ *fp = *fp3;
}
- if (sys_getrealtime() > timebefore + 0.002)
+ if ((timenow = sys_getrealtime()) - timeref > 0.002)
{
- /* post("slept"); */
- return (SENDDACS_SLEPT);
+ rtnval = SENDDACS_SLEPT;
}
- else return (SENDDACS_YES);
+ memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
+ return rtnval;
}
-
void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
{
int i,j;
diff --git a/pd/src/s_audio_pablio.c b/pd/src/s_audio_pablio.c
deleted file mode 100644
index 0873f269..00000000
--- a/pd/src/s_audio_pablio.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
-
- * pablio.c
- * Portable Audio Blocking Input/Output utility.
- *
- * Author: Phil Burk, http://www.softsynth.com
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.audiomulch.com/portaudio/
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
- /* changes by Miller Puckette to support Pd: device selection,
- settable audio buffer size, and settable number of channels.
- LATER also fix it to poll for input and output fifo fill points. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "portaudio.h"
-#include "s_audio_paring.h"
-#include "s_audio_pablio.h" /* MSP */
-#include <string.h>
-
- /* MSP -- FRAMES_PER_BUFFER constant removed */
-static void NPa_Sleep(int n) /* MSP wrapper to check we never stall... */
-{
-#if 0
- fprintf(stderr, "sleep\n");
-#endif
- Pa_Sleep(n);
-}
-
-/************************************************************************/
-/******** Prototypes ****************************************************/
-/************************************************************************/
-
-static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /*MSP */
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo *outTime,
- PaStreamCallbackFlags myflags,
- void *userData );
-static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame );
-static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf );
-
-/************************************************************************/
-/******** Functions *****************************************************/
-/************************************************************************/
-
-/* Called from PortAudio.
- * Read and write data only if there is room in FIFOs.
- */
-static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /* MSP */
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo *outTime,
- PaStreamCallbackFlags myflags,
- void *userData )
-{
- PABLIO_Stream *data = (PABLIO_Stream*)userData;
- (void) outTime;
-
- /* This may get called with NULL inputBuffer during initial setup. */
- if( inputBuffer != NULL )
- {
- sys_ringbuf_Write( &data->inFIFO, inputBuffer,
- data->inbytesPerFrame * framesPerBuffer );
- }
- if( outputBuffer != NULL )
- {
- int i;
- int numBytes = data->outbytesPerFrame * framesPerBuffer;
- int numRead = sys_ringbuf_Read( &data->outFIFO, outputBuffer,
- numBytes);
- /* Zero out remainder of buffer if we run out of data. */
- for( i=numRead; i<numBytes; i++ )
- {
- ((char *)outputBuffer)[i] = 0;
- }
- }
-
- return 0;
-}
-
-/* Allocate buffer. */
-static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame )
-{
- long numBytes = numFrames * bytesPerFrame;
- char *buffer = (char *) malloc( numBytes );
- if( buffer == NULL ) return paInsufficientMemory;
- memset( buffer, 0, numBytes );
- return (PaError) sys_ringbuf_Init( rbuf, numBytes, buffer );
-}
-
-/* Free buffer. */
-static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf )
-{
- if( rbuf->buffer ) free( rbuf->buffer );
- rbuf->buffer = NULL;
- return paNoError;
-}
-
-/************************************************************
- * Write data to ring buffer.
- * Will not return until all the data has been written.
- */
-long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
-{
- long bytesWritten;
- char *p = (char *) data;
- long numBytes = aStream->outbytesPerFrame * numFrames;
- while( numBytes > 0)
- {
- bytesWritten = sys_ringbuf_Write( &aStream->outFIFO, p, numBytes );
- numBytes -= bytesWritten;
- p += bytesWritten;
- if( numBytes > 0) NPa_Sleep(10); /* MSP */
- }
- return numFrames;
-}
-
-/************************************************************
- * Read data from ring buffer.
- * Will not return until all the data has been read.
- */
-long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
-{
- long bytesRead;
- char *p = (char *) data;
- long numBytes = aStream->inbytesPerFrame * numFrames;
- while( numBytes > 0)
- {
- bytesRead = sys_ringbuf_Read( &aStream->inFIFO, p, numBytes );
- numBytes -= bytesRead;
- p += bytesRead;
- if( numBytes > 0) NPa_Sleep(10); /* MSP */
- }
- return numFrames;
-}
-
-/************************************************************
- * Return the number of frames that could be written to the stream without
- * having to wait.
- */
-long GetAudioStreamWriteable( PABLIO_Stream *aStream )
-{
- int bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- return bytesEmpty / aStream->outbytesPerFrame;
-}
-
-/************************************************************
- * Return the number of frames that are available to be read from the
- * stream without having to wait.
- */
-long GetAudioStreamReadable( PABLIO_Stream *aStream )
-{
- int bytesFull = sys_ringbuf_GetReadAvailable( &aStream->inFIFO );
- return bytesFull / aStream->inbytesPerFrame;
-}
-
-/************************************************************/
-static unsigned long RoundUpToNextPowerOf2( unsigned long n )
-{
- long numBits = 0;
- if( ((n-1) & n) == 0) return n; /* Already Power of two. */
- while( n > 0 )
- {
- n= n>>1;
- numBits++;
- }
- return (1<<numBits);
-}
-
-/************************************************************
- * Opens a PortAudio stream with default characteristics.
- * Allocates PABLIO_Stream structure.
- *
- * flags parameter can be an ORed combination of:
- * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE
- */
-PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate,
- PaSampleFormat format, int inchannels,
- int outchannels, int framesperbuf, int nbuffers,
- int indeviceno, int outdeviceno) /* MSP */
-{
- long bytesPerSample;
- long doRead = 0;
- long doWrite = 0;
- PaError err;
- PABLIO_Stream *aStream;
- long numFrames;
- PaStreamParameters instreamparams, outstreamparams; /* MSP */
-
- /* fprintf(stderr,
- "open %lf fmt %d flags %d ch: %d fperbuf: %d nbuf: %d devs: %d %d\n",
- sampleRate, format, flags, nchannels,
- framesperbuf, nbuffers, indeviceno, outdeviceno); */
-
- if (indeviceno < 0) /* MSP... */
- {
- indeviceno = Pa_GetDefaultInputDevice();
- fprintf(stderr, "using default input device number: %d\n", indeviceno);
- }
- if (outdeviceno < 0)
- {
- outdeviceno = Pa_GetDefaultOutputDevice();
- fprintf(stderr, "using default output device number: %d\n", outdeviceno);
- }
- /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
- nchannels, flags, nbuffers, framesperbuf); */
- /* ...MSP */
-
- /* Allocate PABLIO_Stream structure for caller. */
- aStream = (PABLIO_Stream *) malloc( sizeof(PABLIO_Stream) );
- if( aStream == NULL ) return paInsufficientMemory;
- memset( aStream, 0, sizeof(PABLIO_Stream) );
-
- /* Determine size of a sample. */
- bytesPerSample = Pa_GetSampleSize( format );
- if( bytesPerSample < 0 )
- {
- err = (PaError) bytesPerSample;
- goto error;
- }
- aStream->insamplesPerFrame = inchannels; /* MSP */
- aStream->inbytesPerFrame = bytesPerSample * aStream->insamplesPerFrame;
- aStream->outsamplesPerFrame = outchannels;
- aStream->outbytesPerFrame = bytesPerSample * aStream->outsamplesPerFrame;
-
- /* Initialize PortAudio */
- err = Pa_Initialize();
- if( err != paNoError ) goto error;
-
- numFrames = nbuffers * framesperbuf; /* ...MSP */
-
- instreamparams.device = indeviceno; /* MSP... */
- instreamparams.channelCount = inchannels;
- instreamparams.sampleFormat = format;
- instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
- instreamparams.hostApiSpecificStreamInfo = 0;
-
- outstreamparams.device = outdeviceno;
- outstreamparams.channelCount = outchannels;
- outstreamparams.sampleFormat = format;
- outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
- outstreamparams.hostApiSpecificStreamInfo = 0; /* ... MSP */
-
- numFrames = nbuffers * framesperbuf;
- /* fprintf(stderr, "numFrames %d\n", numFrames); */
- /* Initialize Ring Buffers */
- doRead = (inchannels != 0);
- doWrite = (outchannels != 0);
- if(doRead)
- {
- err = PABLIO_InitFIFO( &aStream->inFIFO, numFrames,
- aStream->inbytesPerFrame );
- if( err != paNoError ) goto error;
- }
- if(doWrite)
- {
- long numBytes;
- err = PABLIO_InitFIFO( &aStream->outFIFO, numFrames,
- aStream->outbytesPerFrame );
- if( err != paNoError ) goto error;
- /* Make Write FIFO appear full initially. */
- numBytes = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- sys_ringbuf_AdvanceWriteIndex( &aStream->outFIFO, numBytes );
- }
-
- /* Open a PortAudio stream that we will use to communicate with the underlying
- * audio drivers. */
- err = Pa_OpenStream(
- &aStream->stream,
- (doRead ? &instreamparams : 0), /* MSP */
- (doWrite ? &outstreamparams : 0), /* MSP */
- sampleRate,
- framesperbuf, /* MSP */
- paNoFlag, /* MSP -- portaudio will clip for us */
- blockingIOCallback,
- aStream );
- if( err != paNoError ) goto error;
-
- err = Pa_StartStream( aStream->stream );
- if( err != paNoError ) /* MSP */
- {
- fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
- CloseAudioStream( aStream );
- goto error;
- }
-
- *rwblPtr = aStream;
- return paNoError;
-
-error:
- *rwblPtr = NULL;
- return err;
-}
-
-/************************************************************/
-PaError CloseAudioStream( PABLIO_Stream *aStream )
-{
- PaError err;
- int bytesEmpty;
- int byteSize = aStream->outFIFO.bufferSize;
-
- /* If we are writing data, make sure we play everything written. */
- if( byteSize > 0 )
- {
- bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- while( bytesEmpty < byteSize )
- {
- NPa_Sleep( 10 ); /* MSP */
- bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- }
- }
-
- err = Pa_StopStream( aStream->stream );
- if( err != paNoError ) goto error;
- err = Pa_CloseStream( aStream->stream );
- if( err != paNoError ) goto error;
- Pa_Terminate();
-
-error:
- PABLIO_TermFIFO( &aStream->inFIFO );
- PABLIO_TermFIFO( &aStream->outFIFO );
- free( aStream );
- return err;
-}
diff --git a/pd/src/s_audio_pablio.h b/pd/src/s_audio_pablio.h
deleted file mode 100644
index f4d32614..00000000
--- a/pd/src/s_audio_pablio.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef _PABLIO_H
-#define _PABLIO_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-/*
- * PABLIO.h
- * Portable Audio Blocking read/write utility.
- *
- * Author: Phil Burk, http://www.softsynth.com/portaudio/
- *
- * Include file for PABLIO, the Portable Audio Blocking I/O Library.
- * PABLIO is built on top of PortAudio, the Portable Audio Library.
- * For more information see: http://www.audiomulch.com/portaudio/
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "portaudio.h"
-#include "s_audio_paring.h"
-#include <string.h>
-
-typedef struct
-{
- sys_ringbuf inFIFO;
- sys_ringbuf outFIFO;
- PaStream *stream;
- int inbytesPerFrame;
- int insamplesPerFrame;
- int outbytesPerFrame;
- int outsamplesPerFrame;
-}
-PABLIO_Stream;
-
-/* Values for flags for OpenAudioStream(). */
-#define PABLIO_READ (1<<0)
-#define PABLIO_WRITE (1<<1)
-#define PABLIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
-#define PABLIO_MONO (1<<2)
-#define PABLIO_STEREO (1<<3)
-
-/************************************************************
- * Write data to ring buffer.
- * Will not return until all the data has been written.
- */
-long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames );
-
-/************************************************************
- * Read data from ring buffer.
- * Will not return until all the data has been read.
- */
-long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames );
-
-/************************************************************
- * Return the number of frames that could be written to the stream without
- * having to wait.
- */
-long GetAudioStreamWriteable( PABLIO_Stream *aStream );
-
-/************************************************************
- * Return the number of frames that are available to be read from the
- * stream without having to wait.
- */
-long GetAudioStreamReadable( PABLIO_Stream *aStream );
-
-/************************************************************
- * Opens a PortAudio stream with default characteristics.
- * Allocates PABLIO_Stream structure.
- *
- * flags parameter can be an ORed combination of:
- * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
- */
-PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate,
- PaSampleFormat format, int inchannels,
- int outchannels, int framesperbuf, int nbuffers,
- int indeviceno, int outdeviceno); /* MSP */
-
-PaError CloseAudioStream( PABLIO_Stream *aStream );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* _PABLIO_H */
diff --git a/pd/src/s_audio_paring.c b/pd/src/s_audio_paring.c
index 6e645e45..af2771ff 100644
--- a/pd/src/s_audio_paring.c
+++ b/pd/src/s_audio_paring.c
@@ -46,11 +46,11 @@
/***************************************************************************
* Initialize FIFO.
*/
-long sys_ringbuf_Init( sys_ringbuf *rbuf, long numBytes, void *dataPtr )
+long sys_ringbuf_Init(sys_ringbuf *rbuf, long numBytes, void *dataPtr, long nfill)
{
rbuf->bufferSize = numBytes;
rbuf->buffer = (char *)dataPtr;
- sys_ringbuf_Flush( rbuf );
+ sys_ringbuf_Flush(rbuf, dataPtr, nfill);
return 0;
}
/***************************************************************************
@@ -74,9 +74,14 @@ long sys_ringbuf_GetWriteAvailable( sys_ringbuf *rbuf )
/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
-void sys_ringbuf_Flush( sys_ringbuf *rbuf )
+void sys_ringbuf_Flush(sys_ringbuf *rbuf, void *dataPtr, long nfill)
{
- rbuf->writeIndex = rbuf->readIndex = 0;
+ char *s;
+ long n;
+ rbuf->readIndex = 0;
+ rbuf->writeIndex = nfill;
+ for (n = nfill, s = dataPtr; n--; s++)
+ *s = 0;
}
/***************************************************************************
diff --git a/pd/src/s_audio_paring.h b/pd/src/s_audio_paring.h
index e5e5e6b2..8c417cd9 100644
--- a/pd/src/s_audio_paring.h
+++ b/pd/src/s_audio_paring.h
@@ -58,12 +58,11 @@ typedef struct
sys_ringbuf;
/*
* Initialize Ring Buffer.
- * numBytes must be power of 2, returns -1 if not.
*/
-long sys_ringbuf_Init( sys_ringbuf *rbuf, long numBytes, void *dataPtr );
+long sys_ringbuf_Init(sys_ringbuf *rbuf, long numBytes, void *dataPtr, long nfill);
/* Clear buffer. Should only be called when buffer is NOT being read. */
-void sys_ringbuf_Flush( sys_ringbuf *rbuf );
+void sys_ringbuf_Flush(sys_ringbuf *rbuf, void *dataPtr, long nfill);
/* Return number of bytes available for writing. */
long sys_ringbuf_GetWriteAvailable( sys_ringbuf *rbuf );
diff --git a/pd/src/s_file.c b/pd/src/s_file.c
index e5510011..c5a4f763 100644
--- a/pd/src/s_file.c
+++ b/pd/src/s_file.c
@@ -24,7 +24,7 @@
#include <fcntl.h>
#include <unistd.h>
#endif
-#ifdef MSW
+#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#endif
@@ -36,7 +36,7 @@ int sys_defeatrt;
t_symbol *sys_flags = &s_;
void sys_doflags( void);
-#ifdef UNIX
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD_kernel__) || defined(__GNU__) || defined(ANDROID)
static char *sys_prefbuf;
static int sys_prefbufsize;
@@ -159,9 +159,9 @@ static void sys_donesavepreferences( void)
}
}
-#endif /* UNIX */
+#endif /* __linux__ || __CYGWIN__ || __FreeBSD_kernel__ || __GNU__ */
-#ifdef MSW
+#ifdef _WIN32
static void sys_initloadpreferences( void)
{
@@ -203,12 +203,12 @@ static void sys_putpreference(const char *key, const char *value)
NULL, &hkey, NULL);
if (err != ERROR_SUCCESS)
{
- post("unable to create registry entry: %s\n", key);
+ error("unable to create registry entry: %s\n", key);
return;
}
- err = RegSetValueEx(hkey, key, 0, REG_SZ, value, strlen(value)+1);
+ err = RegSetValueEx(hkey, key, 0, REG_EXPAND_SZ, value, strlen(value)+1);
if (err != ERROR_SUCCESS)
- post("unable to set registry entry: %s\n", key);
+ error("unable to set registry entry: %s\n", key);
RegCloseKey(hkey);
}
@@ -216,7 +216,7 @@ static void sys_donesavepreferences( void)
{
}
-#endif /* MSW */
+#endif /* _WIN32 */
#ifdef __APPLE__
@@ -291,7 +291,8 @@ void sys_loadpreferences( void)
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
- int i, rate = 0, advance = 0, callback = 0, api, nolib, maxi;
+ int i, rate = 0, advance = -1, callback = 0, blocksize = 0,
+ api, nolib, maxi;
char prefbuf[MAXPDSTRING], keybuf[80];
sys_initloadpreferences();
@@ -342,9 +343,11 @@ void sys_loadpreferences( void)
sscanf(prefbuf, "%d", &advance);
if (sys_getpreference("callback", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &callback);
+ if (sys_getpreference("blocksize", prefbuf, MAXPDSTRING))
+ sscanf(prefbuf, "%d", &blocksize);
sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev,
naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
- callback);
+ callback, blocksize);
/* load MIDI preferences */
/* JMZ/MB: brackets for initializing */
@@ -414,10 +417,10 @@ void sys_loadpreferences( void)
if (sys_defeatrt)
sys_hipriority = 0;
else
-#ifdef UNIX
- sys_hipriority = !geteuid();
+#if defined(__linux__) || defined(__CYGWIN__)
+ sys_hipriority = 1;
#else
-#ifdef MSW
+#if defined(_WIN32) || defined(ANDROID)
sys_hipriority = 0;
#else
sys_hipriority = 1;
@@ -429,7 +432,7 @@ void glob_savepreferences(t_pd *dummy)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int i, rate, advance, callback;
+ int i, rate, advance, callback, blocksize;
char buf1[MAXPDSTRING], buf2[MAXPDSTRING];
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
@@ -442,7 +445,8 @@ void glob_savepreferences(t_pd *dummy)
sys_putpreference("audioapi", buf1);
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False"));
for (i = 0; i < naudioindev; i++)
@@ -468,6 +472,9 @@ void glob_savepreferences(t_pd *dummy)
sprintf(buf1, "%d", callback);
sys_putpreference("callback", buf1);
+ sprintf(buf1, "%d", blocksize);
+ sys_putpreference("blocksize", buf1);
+
/* MIDI settings */
sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev);
sys_putpreference("nomidiin", (nmidiindev <= 0 ? "True" : "False"));
diff --git a/pd/src/s_inter.c b/pd/src/s_inter.c
index 1549f9de..6efa098c 100644
--- a/pd/src/s_inter.c
+++ b/pd/src/s_inter.c
@@ -9,7 +9,7 @@ that didn't really belong anywhere. */
#include "s_stuff.h"
#include "m_imp.h"
#include "g_canvas.h" /* for GUI queueing stuff */
-#ifndef MSW
+#ifndef _WIN32
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -59,15 +59,15 @@ typedef int socklen_t;
#define PDBINDIR "bin/"
#endif
-#ifndef PDTCLDIR
-#define PDTCLDIR "tcl/"
+#ifndef PDGUIDIR
+#define PDGUIDIR "tcl/"
#endif
#ifndef WISHAPP
#define WISHAPP "wish84.exe"
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#define LOCALHOST "127.0.0.1"
#else
#define LOCALHOST "localhost"
@@ -93,7 +93,6 @@ struct _socketreceiver
t_socketreceivefn sr_socketreceivefn;
};
-extern char *pd_version;
extern int sys_guisetportnumber;
static int sys_nfdpoll;
@@ -104,10 +103,13 @@ static int sys_guisock;
static t_binbuf *inbinbuf;
static t_socketreceiver *sys_socketreceiver;
extern int sys_addhist(int phase);
+void sys_set_searchpath(void);
+void sys_set_extrapath(void);
+void sys_set_startup(void);
/* ----------- functions for timing, signals, priorities, etc --------- */
-#ifdef MSW
+#ifdef _WIN32
static LARGE_INTEGER nt_inittime;
static double nt_freq = 0;
@@ -136,13 +138,13 @@ double nt_tixtotime(LARGE_INTEGER *dumbass)
return (((double)(dumbass->QuadPart - nt_inittime.QuadPart)) / nt_freq);
}
#endif
-#endif /* MSW */
+#endif /* _WIN32 */
/* get "real time" in seconds; take the
first time we get called as a reference time of zero. */
double sys_getrealtime(void)
{
-#ifndef MSW
+#ifndef _WIN32
static struct timeval then;
struct timeval now;
gettimeofday(&now, 0);
@@ -174,7 +176,7 @@ static int sys_domicrosleep(int microsec, int pollem)
FD_ZERO(&exceptset);
for (fp = sys_fdpoll, i = sys_nfdpoll; i--; fp++)
FD_SET(fp->fdp_fd, &readset);
-#ifdef MSW
+#ifdef _WIN32
if (sys_maxfd == 0)
Sleep(microsec/1000);
else
@@ -196,7 +198,7 @@ static int sys_domicrosleep(int microsec, int pollem)
}
else
{
-#ifdef MSW
+#ifdef _WIN32
if (sys_maxfd == 0)
Sleep(microsec/1000);
else
@@ -211,10 +213,8 @@ void sys_microsleep(int microsec)
sys_domicrosleep(microsec, 1);
}
-#ifdef HAVE_UNISTD_H
-typedef void (*sighandler_t)(int);
-
-static void sys_signal(int signo, sighandler_t sigfun)
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+static void sys_signal(int signo, sig_t sigfun)
{
struct sigaction action;
action.sa_flags = 0;
@@ -270,9 +270,9 @@ void sys_setalarm(int microsec)
setitimer(ITIMER_REAL, &gonzo, 0);
}
-#endif
+#endif /* NOT _WIN32 && NOT __CYGWIN__ */
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#if defined(_POSIX_PRIORITY_SCHEDULING) || defined(_POSIX_MEMLOCK)
#include <sched.h>
@@ -346,7 +346,7 @@ void sys_set_priority(int higher)
void sys_sockerror(char *s)
{
-#ifdef MSW
+#ifdef _WIN32
int err = WSAGetLastError();
if (err == 10054) return;
else if (err == 10044)
@@ -562,7 +562,7 @@ void sys_closesocket(int fd)
#ifdef HAVE_UNISTD_H
close(fd);
#endif
-#ifdef MSW
+#ifdef _WIN32
closesocket(fd);
#endif
}
@@ -844,7 +844,7 @@ int sys_pollgui(void)
static int sys_watchfd;
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
void glob_watchdog(t_pd *dummy)
{
if (write(sys_watchfd, "\n", 1) < 1)
@@ -873,24 +873,25 @@ int sys_startgui(const char *libdir)
int len = sizeof(server);
int ntry = 0, portno = FIRSTPORTNUM;
int xsock = -1;
-#ifdef MSW
+#ifdef _WIN32
short version = MAKEWORD(2, 0);
WSADATA nobby;
-#endif
-#ifdef HAVE_UNISTD_H
+#else
int stdinpipe[2];
-#endif
+#endif /* _WIN32 */
/* create an empty FD poll list */
sys_fdpoll = (t_fdpoll *)t_getbytes(0);
sys_nfdpoll = 0;
inbinbuf = binbuf_new();
-#ifdef HAVE_UNISTD_H
+#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);
@@ -900,10 +901,11 @@ int sys_startgui(const char *libdir)
#if 0 /* GG says: don't use that */
signal(SIGSTKFLT, sys_exithandler);
#endif
-#endif
-#ifdef MSW
+#endif /* NOT _WIN32 && NOT __CYGWIN__ */
+
+#ifdef _WIN32
if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup");
-#endif
+#endif /* _WIN32 */
if (sys_nogui)
{
@@ -911,11 +913,10 @@ int sys_startgui(const char *libdir)
skip starting the GUI up. */
t_atom zz[NDEFAULTFONT+2];
int i;
-#ifdef MSW
+#ifdef _WIN32
if (GetCurrentDirectory(MAXPDSTRING, cmdbuf) == 0)
strcpy(cmdbuf, ".");
-#endif
-#ifdef HAVE_UNISTD_H
+#else
if (!getcwd(cmdbuf, MAXPDSTRING))
strcpy(cmdbuf, ".");
@@ -961,12 +962,9 @@ int sys_startgui(const char *libdir)
}
else /* default behavior: start up the GUI ourselves. */
{
-#ifdef MSW
+#ifdef _WIN32
char scriptbuf[MAXPDSTRING+30], wishbuf[MAXPDSTRING+30], portbuf[80];
int spawnret;
-
-#endif
-#ifdef MSW
char intarg;
#else
int intarg;
@@ -988,7 +986,7 @@ int sys_startgui(const char *libdir)
intarg = 1;
if (setsockopt(xsock, IPPROTO_TCP, TCP_NODELAY,
&intarg, sizeof(intarg)) < 0)
-#ifndef MSW
+#ifndef _WIN32
post("setsockopt (TCP_NODELAY) failed\n")
#endif
;
@@ -1003,7 +1001,7 @@ int sys_startgui(const char *libdir)
/* name the socket */
while (bind(xsock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
-#ifdef MSW
+#ifdef _WIN32
int err = WSAGetLastError();
#else
int err = errno;
@@ -1024,7 +1022,7 @@ int sys_startgui(const char *libdir)
if (sys_verbose) fprintf(stderr, "port %d\n", portno);
-#ifdef HAVE_UNISTD_H
+#ifndef _WIN32
if (!sys_guicmd)
{
#ifdef __APPLE__
@@ -1063,14 +1061,13 @@ int sys_startgui(const char *libdir)
if (stat(wish_paths[i], &statbuf) >= 0)
break;
}
- sprintf(cmdbuf,"\"%s\" %s/tcl/pd-gui.tcl %d\n", wish_paths[i],
- libdir, portno);
-#else
+ sprintf(cmdbuf,"\"%s\" %d\n", wish_paths[i], portno);
+#else /* __APPLE__ */
sprintf(cmdbuf,
"TCL_LIBRARY=\"%s/lib/tcl/library\" TK_LIBRARY=\"%s/lib/tk/library\" \
- wish \"%s/tcl/pd-gui.tcl\" %d\n",
+ wish \"%s/" PDGUIDIR "/pd-gui.tcl\" %d\n",
libdir, libdir, libdir, portno);
-#endif
+#endif /* __APPLE__ */
sys_guicmd = cmdbuf;
}
@@ -1104,19 +1101,17 @@ int sys_startgui(const char *libdir)
close(stdinpipe[0]);
}
}
-#endif
+#endif /* NOT __APPLE__ */
execl("/bin/sh", "sh", "-c", sys_guicmd, (char*)0);
perror("pd: exec");
_exit(1);
}
-#endif /* UNISTD */
-
-#ifdef MSW
+#else /* NOT _WIN32 */
/* fprintf(stderr, "%s\n", libdir); */
strcpy(scriptbuf, "\"");
strcat(scriptbuf, libdir);
- strcat(scriptbuf, "/" PDTCLDIR "pd-gui.tcl\"");
+ strcat(scriptbuf, "/" PDGUIDIR "pd-gui.tcl\"");
sys_bashfilename(scriptbuf, scriptbuf);
sprintf(portbuf, "%d", portno);
@@ -1133,18 +1128,23 @@ int sys_startgui(const char *libdir)
exit(1);
}
-#endif /* MSW */
+#endif /* NOT _WIN32 */
}
-#if defined(__linux__) || defined(IRIX)
+#if defined(__linux__) || defined(IRIX) || defined(__FreeBSD_kernel__)
/* 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 check root status. This misses the case where we might
- have permission from a "security module" (linux 2.6) -- I don't
- know how to test for that. The "-rt" flag must b eset in that
- case. */
+ (-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:
+ @audio - rtprio 99
+ @audio - memlock unlimited
+ in the system limits file, perhaps /etc/limits.conf or
+ /etc/security/limits.conf */
+ fprintf(stderr, "was... %d\n", sys_hipriority);
if (sys_hipriority == -1)
- sys_hipriority = (!getuid() || !geteuid());
+ sys_hipriority = 1;
if (sys_hipriority)
{
@@ -1205,7 +1205,7 @@ int sys_startgui(const char *libdir)
setuid(getuid()); /* lose setuid priveliges */
#endif /* __linux__ */
-#ifdef MSW
+#ifdef _WIN32
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
fprintf(stderr, "pd: couldn't set high priority class\n");
#endif
@@ -1246,14 +1246,20 @@ int sys_startgui(const char *libdir)
sys_socketreceiver);
/* here is where we start the pinging. */
-#if defined(__linux__) || defined(IRIX)
+#if defined(__linux__) || defined(IRIX) || defined(__FreeBSD_kernel__)
if (sys_hipriority)
sys_gui("pdtk_watchdog\n");
#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);
+ sys_set_searchpath(); /* tell GUI about path and startup flags */
+ sys_set_extrapath();
+ sys_set_startup();
+ /* ... and about font, medio APIS, etc */
+ sys_vgui("pdtk_pd_startup %d %d %d {%s} %s %s {%s} %s\n",
+ PD_MAJOR_VERSION, PD_MINOR_VERSION,
+ PD_BUGFIX_VERSION, PD_TEST_VERSION,
+ buf, buf2, sys_font, sys_fontweight);
}
return (0);
@@ -1270,7 +1276,7 @@ void sys_bail(int n)
if (!reentered)
{
reentered = 1;
-#ifndef __linux__ /* sys_close_audio() hangs if you're in a signal? */
+#if !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) /* sys_close_audio() hangs if you're in a signal? */
fprintf(stderr, "closing audio...\n");
sys_close_audio();
fprintf(stderr, "closing MIDI...\n");
diff --git a/pd/src/s_loader.c b/pd/src/s_loader.c
index b708961c..c3e2d3a0 100644
--- a/pd/src/s_loader.c
+++ b/pd/src/s_loader.c
@@ -38,23 +38,22 @@ a fat binary or an indication of the instruction set. */
#ifdef __FreeBSD__
static char sys_dllextent[] = ".b_i386", sys_dllextent2[] = ".pd_freebsd";
-#endif
-#ifdef __linux__
-#ifdef __x86_64__
+#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+# ifdef __x86_64__
static char sys_dllextent[] = ".l_ia64", sys_dllextent2[] = ".pd_linux";
-#else
+# else
static char sys_dllextent[] = ".l_i386", sys_dllextent2[] = ".pd_linux";
-#endif
-#endif
-#ifdef __APPLE__
-#ifndef MACOSX3
+# endif
+#elif defined(__APPLE__)
+# ifndef MACOSX3
static char sys_dllextent[] = ".d_fat", sys_dllextent2[] = ".pd_darwin";
-#else
+# else
static char sys_dllextent[] = ".d_ppc", sys_dllextent2[] = ".pd_darwin";
-#endif
-#endif
-#ifdef MSW
+# endif
+#elif defined(_WIN32) || defined(__CYGWIN__)
static char sys_dllextent[] = ".m_i386", sys_dllextent2[] = ".dll";
+#elif defined(ANDROID)
+static char sys_dllextent[] = ".l_arm", sys_dllextent2[] = ".pd_linux";
#endif
/* maintain list of loaded modules to avoid repeating loads */
@@ -178,7 +177,7 @@ gotone:
return (0);
}
makeout = (t_xxx)dlsym(dlobj, symname);
- fprintf(stderr, "symbol %s\n", symname);
+ /* fprintf(stderr, "symbol %s\n", symname); */
#endif
#ifdef MSW
sys_bashfilename(filename, filename);
@@ -218,8 +217,10 @@ void sys_register_loader(loader_t loader)
{
loader_queue_t *q = &loaders;
while (1)
- {
- if (q->next)
+ {
+ if (q->loader == loader) /* already loaded - nothing to do */
+ return;
+ else if (q->next)
q = q->next;
else
{
diff --git a/pd/src/s_main.c b/pd/src/s_main.c
index a1e5af2a..24b5860e 100644
--- a/pd/src/s_main.c
+++ b/pd/src/s_main.c
@@ -25,7 +25,11 @@
#define snprintf sprintf_s
#endif
-char *pd_version;
+
+#define stringify(s) str(s)
+#define str(s) #s
+
+char *pd_version = "Pd-" stringify(PD_MAJOR_VERSION) "." stringify(PD_MINOR_VERSION) "." stringify(PD_BUGFIX_VERSION) " (" stringify(PD_TEST_VERSION) ")";
char pd_compiletime[] = __TIME__;
char pd_compiledate[] = __DATE__;
@@ -61,16 +65,17 @@ int sys_nmidiin = -1;
int sys_midiindevlist[MAXMIDIINDEV] = {1};
int sys_midioutdevlist[MAXMIDIOUTDEV] = {1};
-char sys_font[100] =
#ifdef __APPLE__
- "Monaco";
+char sys_font[100] = "Monaco";
+char sys_fontweight[10] = "normal";
#else
- "Courier";
+char sys_font[100] = "Courier";
+char sys_fontweight[10] = "bold";
#endif
-char sys_fontweight[] = "bold ";
static int sys_main_srate;
static int sys_main_advance;
static int sys_main_callback;
+static int sys_main_blocksize;
static int sys_listplease;
int sys_externalschedlib;
@@ -258,15 +263,6 @@ void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv)
static void sys_afterargparse(void);
-static void pd_makeversion(void)
-{
- char foo[100];
- sprintf(foo, "Pd version %d.%d-%d%s\n",PD_MAJOR_VERSION,
- PD_MINOR_VERSION,PD_BUGFIX_VERSION,PD_TEST_VERSION);
- pd_version = malloc(strlen(foo)+1);
- strcpy(pd_version, foo);
-}
-
/* this is called from main() in s_entry.c */
int sys_main(int argc, char **argv)
{
@@ -290,9 +286,7 @@ int sys_main(int argc, char **argv)
if (sys_argparse(argc-1, argv+1)) /* parse cmd line */
return (1);
sys_afterargparse(); /* post-argparse settings */
- /* build version string from defines in m_pd.h */
- pd_makeversion();
- if (sys_verbose || sys_version) fprintf(stderr, "%scompiled %s %s\n",
+ if (sys_verbose || sys_version) fprintf(stderr, "%s compiled %s %s\n",
pd_version, pd_compiletime, pd_compiledate);
if (sys_version) /* if we were just asked our version, exit here. */
return (0);
@@ -356,6 +350,15 @@ static char *(usagemessage[]) = {
#ifdef USEAPI_MMIO
"-mmio -- use MMIO audio API (default for Windows)\n",
#endif
+
+#ifdef USEAPI_AUDIOUNIT
+"-audiounit -- use Apple AudioUnit API\n",
+#endif
+
+#ifdef USEAPI_ESD
+"-esd -- use Enlightenment Sound Daemon (ESD) API\n",
+#endif
+
" (default audio API for this platform: ", API_DEFSTRING, ")\n\n",
"\nMIDI configuration flags:\n",
@@ -440,20 +443,19 @@ void sys_findprogdir(char *progname)
{
char sbuf[MAXPDSTRING], sbuf2[MAXPDSTRING], *sp;
char *lastslash;
-#ifdef HAVE_UNISTD_H
+#ifndef _WIN32
struct stat statbuf;
-#endif
+#endif /* NOT _WIN32 */
/* find out by what string Pd was invoked; put answer in "sbuf". */
-#ifdef MSW
+#ifdef _WIN32
GetModuleFileName(NULL, sbuf2, sizeof(sbuf2));
sbuf2[MAXPDSTRING-1] = 0;
sys_unbashfilename(sbuf2, sbuf);
-#endif /* MSW */
-#ifdef HAVE_UNISTD_H
+#else
strncpy(sbuf, progname, MAXPDSTRING);
sbuf[MAXPDSTRING-1] = 0;
-#endif
+#endif /* _WIN32 */
lastslash = strrchr(sbuf, '/');
if (lastslash)
{
@@ -483,12 +485,12 @@ void sys_findprogdir(char *progname)
"gui" directory. In "simple" unix installations, the layout is
.../bin/pd
.../bin/pd-watchdog (etc)
- .../tcl/pd-gui.tcl
+ .../bin/pd-gui.tcl
.../doc
and in "complicated" unix installations, it's:
.../bin/pd
.../lib/pd/bin/pd-watchdog
- .../lib/tcl/pd-gui.tcl
+ .../lib/pd/bin/pd-gui.tcl
.../lib/pd/doc
To decide which, we stat .../lib/pd; if that exists, we assume it's
the complicated layout. In MSW, it's the "simple" layout, but
@@ -578,7 +580,7 @@ int sys_argparse(int argc, char **argv)
}
else if (!strcmp(*argv, "-blocksize"))
{
- sys_setblocksize(atoi(argv[1]));
+ sys_main_blocksize = atoi(argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-sleepgrain") && (argc > 1))
@@ -657,6 +659,20 @@ int sys_argparse(int argc, char **argv)
argc--; argv++;
}
#endif
+#ifdef USEAPI_AUDIOUNIT
+ else if (!strcmp(*argv, "-audiounit"))
+ {
+ sys_set_audio_api(API_AUDIOUNIT);
+ argc--; argv++;
+ }
+#endif
+#ifdef USEAPI_ESD
+ else if (!strcmp(*argv, "-esd"))
+ {
+ sys_set_audio_api(API_ESD);
+ argc--; argv++;
+ }
+#endif
else if (!strcmp(*argv, "-nomidiin"))
{
sys_nmidiin = 0;
@@ -909,7 +925,7 @@ static void sys_afterargparse(void)
int i;
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int nchindev, nchoutdev, rate, advance, callback;
+ int nchindev, nchoutdev, rate, advance, callback, blocksize;
int nmidiindev = 0, midiindev[MAXMIDIINDEV];
int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV];
/* add "extra" library to path */
@@ -945,7 +961,8 @@ static void sys_afterargparse(void)
else are the default. Overwrite them with any results
of argument parsing, and store them again. */
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance,
+ &callback, &blocksize);
if (sys_nchin >= 0)
{
nchindev = sys_nchin;
@@ -993,9 +1010,11 @@ static void sys_afterargparse(void)
rate = sys_main_srate;
if (sys_main_callback)
callback = sys_main_callback;
+ if (sys_main_blocksize)
+ blocksize = sys_main_blocksize;
sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance,
- callback);
+ callback, blocksize);
sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0);
}
diff --git a/pd/src/s_midi.c b/pd/src/s_midi.c
index 11669366..5ed54d8b 100644
--- a/pd/src/s_midi.c
+++ b/pd/src/s_midi.c
@@ -14,7 +14,7 @@
#include <bstring.h>
#endif
#endif
-#ifdef MSW
+#ifdef _WIN32
#include <winsock.h>
#include <sys/types.h>
#include <sys/timeb.h>
@@ -762,3 +762,17 @@ void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
}
}
+
+void sys_get_midi_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs,
+ int maxndevs, int devdescsize)
+{
+
+#ifdef USEAPI_ALSA
+ if (sys_midiapi == API_ALSA)
+ midi_alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs,
+ maxndevs, devdescsize);
+ else
+#endif /* ALSA */
+ midi_getdevs(indevlist, nindevs, outdevlist, noutdevs, maxndevs, devdescsize);
+}
diff --git a/pd/src/s_midi_alsa.c b/pd/src/s_midi_alsa.c
index d0d82f30..d6d1525e 100644
--- a/pd/src/s_midi_alsa.c
+++ b/pd/src/s_midi_alsa.c
@@ -28,16 +28,6 @@ static snd_seq_t *midi_handle;
static snd_midi_event_t *midiev;
-
-static unsigned short CombineBytes(unsigned char First, unsigned char Second)
-{
- unsigned short _14bit;
- _14bit = (unsigned short)Second;
- _14bit <<= 7;
- _14bit |= (unsigned short)First;
- return(_14bit);
-}
-
void sys_alsa_do_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec)
{
@@ -193,7 +183,7 @@ void sys_alsa_putmidimess(int portno, int a, int b, int c)
if (a >= 224) // pitchbend
{
channel = a-224;
- snd_seq_ev_set_pitchbend(&ev,channel,CombineBytes(b,c));
+ snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192)); /* b and c are already correct but alsa needs to recalculate them */
}
else if (a >= 208) // touch
{
diff --git a/pd/src/s_midi_dummy.c b/pd/src/s_midi_dummy.c
new file mode 100644
index 00000000..0ab463ef
--- /dev/null
+++ b/pd/src/s_midi_dummy.c
@@ -0,0 +1,34 @@
+/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
+* Winfried Ritsch, Karl MacMillan, and others.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+
+ this file is a dummy for systems without any MIDI support
+
+*/
+
+void sys_do_open_midi(int nmidiin, int *midiinvec,
+ int nmidiout, int *midioutvec)
+{
+}
+
+void sys_close_midi( void)
+{
+}
+
+void sys_putmidimess(int portno, int a, int b, int c)
+{
+}
+
+void sys_putmidibyte(int portno, int byte)
+{
+}
+
+void sys_poll_midi(void)
+{
+}
+
+void midi_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int maxndev, int devdescsize)
+{
+}
diff --git a/pd/src/s_midi_pm.c b/pd/src/s_midi_pm.c
index e1c05b1a..fe123ff1 100644
--- a/pd/src/s_midi_pm.c
+++ b/pd/src/s_midi_pm.c
@@ -18,7 +18,6 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include "portaudio.h"
#include "portmidi.h"
#include "porttime.h"
diff --git a/pd/src/s_path.c b/pd/src/s_path.c
index f9c232a3..020db14a 100644
--- a/pd/src/s_path.c
+++ b/pd/src/s_path.c
@@ -20,6 +20,10 @@
#endif
#ifdef MSW
#include <io.h>
+#include <windows.h>
+#endif
+#ifdef _WIN32
+#include <malloc.h>
#endif
#include <string.h>
@@ -39,6 +43,7 @@
t_namelist *sys_externlist;
t_namelist *sys_searchpath;
+t_namelist *sys_staticpath;
t_namelist *sys_helppath;
/* change '/' characters to the system's native file separator */
@@ -86,6 +91,39 @@ int sys_isabsolutepath(const char *dir)
}
}
+/* expand env vars and ~ at the beginning of a path and make a copy to return */
+static void sys_expandpath(const char *from, char *to, int bufsize)
+{
+ if ((strlen(from) == 1 && from[0] == '~') || (strncmp(from,"~/", 2) == 0))
+ {
+#ifdef _WIN32
+ const char *home = getenv("USERPROFILE");
+#else
+ const char *home = getenv("HOME");
+#endif
+ if (home)
+ {
+ strncpy(to, home, bufsize);
+ to[bufsize-1] = 0;
+ strncpy(to + strlen(to), from + 1, bufsize - strlen(to));
+ to[bufsize-1] = 0;
+ }
+ }
+ else
+ {
+ strncpy(to, from, bufsize);
+ to[bufsize-1] = 0;
+ }
+#ifdef _WIN32
+ {
+ char *buf = alloca(bufsize);
+ ExpandEnvironmentStrings(to, buf, bufsize-1);
+ buf[bufsize-1] = 0;
+ strncpy(to, buf, bufsize);
+ to[bufsize-1] = 0;
+ }
+#endif
+}
/******************* Utility functions used below ******************/
@@ -187,14 +225,33 @@ char *namelist_get(t_namelist *namelist, int n)
return (nl ? nl->nl_string : 0);
}
-static t_namelist *pd_extrapath;
-
int sys_usestdpath = 1;
void sys_setextrapath(const char *p)
{
- namelist_free(pd_extrapath);
- pd_extrapath = namelist_append(0, p, 0);
+ char pathbuf[MAXPDSTRING];
+ namelist_free(sys_staticpath);
+ /* add standard place for users to install stuff first */
+#ifdef __gnu_linux__
+ sys_expandpath("~/pd-externals", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(0, pathbuf, 0);
+ sys_staticpath = namelist_append(sys_staticpath, "/usr/local/lib/pd-externals", 0);
+#endif
+
+#ifdef __APPLE__
+ sys_expandpath("~/Library/Pd", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(0, pathbuf, 0);
+ sys_staticpath = namelist_append(sys_staticpath, "/Library/Pd", 0);
+#endif
+
+#ifdef _WIN32
+ sys_expandpath("%ProgramFiles%/Common Files/Pd", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(0, pathbuf, 0);
+ sys_expandpath("%UserProfile%/Application Data/Pd", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(sys_staticpath, pathbuf, 0);
+#endif
+ /* add built-in "extra" path last so its checked last */
+ sys_staticpath = namelist_append(sys_staticpath, p, 0);
}
#ifdef MSW
@@ -214,9 +271,11 @@ int sys_trytoopenone(const char *dir, const char *name, const char* ext,
char *dirresult, char **nameresult, unsigned int size, int bin)
{
int fd;
+ char buf[MAXPDSTRING];
if (strlen(dir) + strlen(name) + strlen(ext) + 4 > size)
return (-1);
- strcpy(dirresult, dir);
+ sys_expandpath(dir, buf, MAXPDSTRING);
+ strcpy(dirresult, buf);
if (*dirresult && dirresult[strlen(dirresult)-1] != '/')
strcat(dirresult, "/");
strcat(dirresult, name);
@@ -319,11 +378,12 @@ static int do_open_via_path(const char *dir, const char *name,
dirresult, nameresult, size, bin)) >= 0)
return (fd);
- /* next look in "extra" */
- if (sys_usestdpath &&
- (fd = sys_trytoopenone(pd_extrapath->nl_string, name, ext,
- dirresult, nameresult, size, bin)) >= 0)
- return (fd);
+ /* next look in built-in paths like "extra" */
+ if (sys_usestdpath)
+ for (nl = sys_staticpath; nl; nl = nl->nl_next)
+ if ((fd = sys_trytoopenone(nl->nl_string, name, ext,
+ dirresult, nameresult, size, bin)) >= 0)
+ return (fd);
*dirresult = 0;
*nameresult = dirresult;
@@ -338,6 +398,15 @@ int open_via_path(const char *dir, const char *name, const char *ext,
size, bin, sys_searchpath));
}
+ /* close a previsouly opened file
+ this is needed on platforms where you cannot open/close ressources
+ across dll-boundaries */
+int sys_close(int fd)
+{
+ return close(fd);
+}
+
+
/* Open a help file using the help search path. We expect the ".pd"
suffix here, even though we have to tear it back off for one of the
search attempts. */
@@ -450,7 +519,7 @@ int sys_rcfile(void)
}
if (sys_argparse(rcargc-1, rcargv+1))
{
- post("error parsing RC arguments");
+ error("error parsing RC arguments");
goto cleanup;
}
@@ -472,7 +541,7 @@ void sys_doflags( void)
char *rcargv[MAXPDSTRING];
if (len > MAXPDSTRING)
{
- post("flags: %s: too long", sys_flags->s_name);
+ error("flags: %s: too long", sys_flags->s_name);
return;
}
for (i = 0; i < len+1; i++)
@@ -504,7 +573,7 @@ void sys_doflags( void)
}
}
if (sys_argparse(rcargc, rcargv))
- post("error parsing startup arguments");
+ error("error parsing startup arguments");
}
/* undo pdtl_encodedialog. This allows dialogs to send spaces, commas,
@@ -540,17 +609,36 @@ t_symbol *sys_decodedialog(t_symbol *s)
return (gensym(buf));
}
-
- /* start a search path dialog window */
-void glob_start_path_dialog(t_pd *dummy)
+ /* send the user-specified search path to pd-gui */
+void sys_set_searchpath( void)
{
- char buf[MAXPDSTRING];
int i;
t_namelist *nl;
- sys_gui("global pd_path; set pd_path {}\n");
+ sys_gui("set ::tmp_path {}\n");
for (nl = sys_searchpath, i = 0; nl; nl = nl->nl_next, i++)
- sys_vgui("lappend pd_path {%s}\n", nl->nl_string);
+ sys_vgui("lappend ::tmp_path {%s}\n", nl->nl_string);
+ sys_gui("set ::sys_searchpath $::tmp_path\n");
+}
+
+ /* send the hard-coded search path to pd-gui */
+void sys_set_extrapath( void)
+{
+ int i;
+ t_namelist *nl;
+
+ sys_gui("set ::tmp_path {}\n");
+ for (nl = sys_staticpath, i = 0; nl; nl = nl->nl_next, i++)
+ sys_vgui("lappend ::tmp_path {%s}\n", nl->nl_string);
+ sys_gui("set ::sys_staticpath $::tmp_path\n");
+}
+
+ /* start a search path dialog window */
+void glob_start_path_dialog(t_pd *dummy)
+{
+ char buf[MAXPDSTRING];
+
+ sys_set_searchpath();
sprintf(buf, "pdtk_path_dialog %%s %d %d\n", sys_usestdpath, sys_verbose);
gfxstub_new(&glob_pdobject, (void *)glob_start_path_dialog, buf);
}
@@ -571,16 +659,24 @@ void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
}
}
- /* start a startup dialog window */
-void glob_start_startup_dialog(t_pd *dummy)
+ /* set the global list vars for startup libraries and flags */
+void sys_set_startup( void)
{
- char buf[MAXPDSTRING];
int i;
t_namelist *nl;
- sys_gui("global pd_startup; set pd_startup {}\n");
+ sys_vgui("set ::startup_flags {%s}\n", sys_flags->s_name);
+ sys_gui("set ::startup_libraries {}\n");
for (nl = sys_externlist, i = 0; nl; nl = nl->nl_next, i++)
- sys_vgui("lappend pd_startup {%s}\n", nl->nl_string);
+ sys_vgui("lappend ::startup_libraries {%s}\n", nl->nl_string);
+}
+
+ /* start a startup dialog window */
+void glob_start_startup_dialog(t_pd *dummy)
+{
+ char buf[MAXPDSTRING];
+
+ sys_set_startup();
sprintf(buf, "pdtk_startup_dialog %%s %d \"%s\"\n", sys_defeatrt,
sys_flags->s_name);
gfxstub_new(&glob_pdobject, (void *)glob_start_startup_dialog, buf);
diff --git a/pd/src/s_print.c b/pd/src/s_print.c
index 3aacd188..c82601a1 100644
--- a/pd/src/s_print.c
+++ b/pd/src/s_print.c
@@ -9,10 +9,43 @@
#include <string.h>
#include <errno.h>
#include "s_stuff.h"
+#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
+#define snprintf sprintf_s
+#endif
t_printhook sys_printhook;
int sys_printtostderr;
+/* escape characters for tcl/tk */
+static char* strnescape(char *dest, const char *src, size_t len)
+{
+ int ptin = 0;
+ unsigned ptout = 0;
+ for(; ptout < len; ptin++, ptout++)
+ {
+ int c = src[ptin];
+ if (c == '\\' || c == '{' || c == '}' || c == ';')
+ dest[ptout++] = '\\';
+ dest[ptout] = src[ptin];
+ if (c==0) break;
+ }
+
+ if(ptout < len)
+ dest[ptout]=0;
+ else
+ dest[len-1]=0;
+
+ return dest;
+}
+
+static char* strnpointerid(char *dest, const void *pointer, size_t len)
+{
+ *dest=0;
+ if(pointer)
+ snprintf(dest, len, ".x%lx", pointer);
+ return dest;
+}
+
static void dopost(const char *s)
{
if (sys_printhook)
@@ -22,25 +55,90 @@ static void dopost(const char *s)
else
{
char upbuf[MAXPDSTRING];
- int ptin = 0, ptout = 0, len = strlen(s);
- static int heldcr = 0;
- if (heldcr)
- upbuf[ptout++] = '\n', heldcr = 0;
- for (; ptin < len && ptout < MAXPDSTRING-3;
- ptin++, ptout++)
- {
- int c = s[ptin];
- if (c == '\\' || c == '{' || c == '}' || c == ';')
- upbuf[ptout++] = '\\';
- upbuf[ptout] = s[ptin];
- }
- if (ptout && upbuf[ptout-1] == '\n')
- upbuf[--ptout] = 0, heldcr = 1;
- upbuf[ptout] = 0;
- sys_vgui("pdtk_post {%s}\n", upbuf);
+ sys_vgui("::pdwindow::post {%s}\n", strnescape(upbuf, s, MAXPDSTRING));
}
}
+static void doerror(const void *object, const char *s)
+{
+ char upbuf[MAXPDSTRING];
+ upbuf[MAXPDSTRING-1]=0;
+
+ // what about sys_printhook_error ?
+ if (sys_printhook)
+ {
+ snprintf(upbuf, MAXPDSTRING-1, "error: %s", s);
+ (*sys_printhook)(upbuf);
+ }
+ else if (sys_printtostderr)
+ fprintf(stderr, "error: %s", s);
+ else
+ {
+ char obuf[MAXPDSTRING];
+ sys_vgui("::pdwindow::logpost {%s} 1 {%s}\n",
+ strnpointerid(obuf, object, MAXPDSTRING),
+ strnescape(upbuf, s, MAXPDSTRING));
+ }
+}
+
+static void dologpost(const void *object, const int level, const char *s)
+{
+ char upbuf[MAXPDSTRING];
+ upbuf[MAXPDSTRING-1]=0;
+
+ // what about sys_printhook_verbose ?
+ if (sys_printhook)
+ {
+ snprintf(upbuf, MAXPDSTRING-1, "verbose(%d): %s", level, s);
+ (*sys_printhook)(upbuf);
+ }
+ else if (sys_printtostderr)
+ {
+ fprintf(stderr, "verbose(%d): %s", level, s);
+ }
+ else
+ {
+ char obuf[MAXPDSTRING];
+ sys_vgui("::pdwindow::logpost {%s} %d {%s}\n",
+ strnpointerid(obuf, object, MAXPDSTRING),
+ level, strnescape(upbuf, s, MAXPDSTRING));
+ }
+}
+
+static void dobug(const char *s)
+{
+ char upbuf[MAXPDSTRING];
+ upbuf[MAXPDSTRING-1]=0;
+
+ // what about sys_printhook_bug ?
+ if (sys_printhook)
+ {
+ snprintf(upbuf, MAXPDSTRING-1, "consistency check failed: %s", s);
+ (*sys_printhook)(upbuf);
+ }
+ else if (sys_printtostderr)
+ fprintf(stderr, "consistency check failed: %s", s);
+ else
+ {
+ char upbuf[MAXPDSTRING];
+ sys_vgui("::pdwindow::bug {%s}\n", strnescape(upbuf, s, MAXPDSTRING));
+ }
+}
+
+void logpost(const void *object, const int level, const char *fmt, ...)
+{
+ char buf[MAXPDSTRING];
+ va_list ap;
+ t_int arg[8];
+ int i;
+ va_start(ap, fmt);
+ vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
+ va_end(ap);
+ strcat(buf, "\n");
+
+ dologpost(object, level, buf);
+}
+
void post(const char *fmt, ...)
{
char buf[MAXPDSTRING];
@@ -51,6 +149,7 @@ void post(const char *fmt, ...)
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
strcat(buf, "\n");
+
dopost(buf);
}
@@ -63,12 +162,14 @@ void startpost(const char *fmt, ...)
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
+
dopost(buf);
}
void poststring(const char *s)
{
dopost(" ");
+
dopost(s);
}
@@ -88,12 +189,17 @@ void postfloat(t_float f)
char buf[80];
t_atom a;
SETFLOAT(&a, f);
+
postatom(1, &a);
}
void endpost(void)
{
- dopost("\n");
+ if (sys_printhook)
+ (*sys_printhook)("\n");
+ else if (sys_printtostderr)
+ fprintf(stderr, "\n");
+ else post("");
}
void error(const char *fmt, ...)
@@ -102,12 +208,13 @@ void error(const char *fmt, ...)
va_list ap;
t_int arg[8];
int i;
- dopost("error: ");
+
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+
+ doerror(NULL, buf);
+ endpost();
}
void verbose(int level, const char *fmt, ...)
@@ -116,16 +223,15 @@ void verbose(int level, const char *fmt, ...)
va_list ap;
t_int arg[8];
int i;
+
if(level>sys_verbose)return;
- dopost("verbose(");
- postfloat((t_float)level);
- dopost("):");
-
+
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+ dologpost(NULL, level+4, buf);
+
+ endpost();
}
/* here's the good way to log errors -- keep a pointer to the
@@ -143,16 +249,19 @@ void pd_error(void *object, const char *fmt, ...)
t_int arg[8];
int i;
static int saidit;
- dopost("error: ");
+
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+
+ doerror(object, buf);
+ endpost();
+
error_object = object;
if (!saidit)
{
- post("... you might be able to track this down from the Find menu.");
+ logpost(NULL, 4,
+ "... you might be able to track this down from the Find menu.");
saidit = 1;
}
}
@@ -169,18 +278,29 @@ void glob_finderror(t_pd *dummy)
}
}
+void glob_findinstance(t_pd *dummy, t_symbol*s)
+{
+ // revert s to (potential) pointer to object
+ void*obj=NULL;
+ if(sscanf(s->s_name, ".x%lx", &obj)) {
+ if(obj) {
+ canvas_finderror(obj);
+ }
+ }
+}
+
void bug(const char *fmt, ...)
{
char buf[MAXPDSTRING];
va_list ap;
t_int arg[8];
int i;
- dopost("consistency check failed: ");
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+
+ dobug(buf);
+ endpost();
}
/* this isn't worked out yet. */
@@ -203,4 +323,5 @@ void sys_ouch(void)
{
if (*errobject) error("%s: %s", errobject, errstring);
else error("%s", errstring);
+ sys_gui("bell\n");
}
diff --git a/pd/src/s_stuff.h b/pd/src/s_stuff.h
index 0fb2497e..b37b161a 100644
--- a/pd/src/s_stuff.h
+++ b/pd/src/s_stuff.h
@@ -75,12 +75,17 @@ extern int sys_blocksize; /* audio I/O block size in sample frames */
extern t_float sys_dacsr;
extern int sys_schedadvance;
extern int sys_sleepgrain;
-void sys_set_audio_settings(int naudioindev, int *audioindev,
+EXTERN void sys_set_audio_settings(int naudioindev, int *audioindev,
int nchindev, int *chindev,
int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
- int srate, int advance, int callback);
-void sys_reopen_audio( void);
-void sys_close_audio(void);
+ int srate, int advance, int callback, int blocksize);
+/* the same as above, but reopens the audio subsystem if needed */
+EXTERN void sys_set_audio_settings_reopen(int naudioindev, int *audioindev,
+ int nchindev, int *chindev,
+ int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
+ int srate, int advance, int callback, int blocksize);
+EXTERN void sys_reopen_audio( void);
+EXTERN void sys_close_audio(void);
int sys_send_dacs(void);
@@ -91,23 +96,32 @@ void sys_getmeters(t_sample *inmax, t_sample *outmax);
void sys_listdevs(void);
void sys_setblocksize(int n);
+EXTERN void sys_get_audio_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
+ int maxndev, int devdescsize);
+EXTERN void sys_get_audio_apis(char *buf);
+
/* s_midi.c */
#define MAXMIDIINDEV 16 /* max. number of input ports */
#define MAXMIDIOUTDEV 16 /* max. number of output ports */
+extern int sys_midiapi;
extern int sys_nmidiin;
extern int sys_nmidiout;
extern int sys_midiindevlist[];
extern int sys_midioutdevlist[];
-void sys_open_midi(int nmidiin, int *midiinvec,
+EXTERN void sys_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec, int enable);
-void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
- int *pnmidioutdev, int *pmidioutdev);
-void sys_get_midi_apis(char *buf);
+EXTERN void sys_get_midi_apis(char *buf);
+EXTERN void sys_get_midi_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs,
+ int maxndev, int devdescsize);
+EXTERN void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
+ int *pnmidioutdev, int *pmidioutdev);
-void sys_reopen_midi( void);
-void sys_close_midi( void);
+EXTERN void sys_reopen_midi( void);
+EXTERN void sys_close_midi( void);
EXTERN void sys_putmidimess(int portno, int a, int b, int c);
EXTERN void sys_putmidibyte(int portno, int a);
EXTERN void sys_poll_midi(void);
@@ -171,9 +185,8 @@ EXTERN void sys_closesocket(int fd);
typedef void (*t_fdpollfn)(void *ptr, int fd);
EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
EXTERN void sys_rmpollfn(int fd);
-#ifdef UNIX
+#if defined(USEAPI_OSS) || defined(USEAPI_ALSA)
void sys_setalarm(int microsec);
-void sys_setvirtualalarm( void);
#endif
#define API_NONE 0
@@ -183,23 +196,41 @@ void sys_setvirtualalarm( void);
#define API_PORTAUDIO 4
#define API_JACK 5
#define API_SGI 6
+#define API_AUDIOUNIT 7
+#define API_ESD 8
+#define API_DUMMY 9
-#ifdef __linux__
-#define API_DEFAULT API_OSS
-#define API_DEFSTRING "OSS"
+#ifdef USEAPI_DUMMY
+#define API_DEFAULT API_DUMMY
+#define API_DEFSTRING "dummy audio"
+#else
+#if defined(__linux__) || defined(__FreeBSD_kernel__)
+# define API_DEFAULT API_OSS
+# define API_DEFSTRING "OSS"
#endif
-#ifdef MSW
-#define API_DEFAULT API_MMIO
-#define API_DEFSTRING "MMIO"
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define API_DEFAULT API_MMIO
+# define API_DEFSTRING "MMIO"
#endif
#ifdef __APPLE__
-#define API_DEFAULT API_PORTAUDIO
-#define API_DEFSTRING "portaudio"
+# ifdef __arm__
+# define API_DEFAULT API_AUDIOUNIT
+# define API_DEFSTRING "AudioUnit"
+# else
+# define API_DEFAULT API_PORTAUDIO
+# define API_DEFSTRING "portaudio"
+# endif /* __arm__ */
#endif
#ifdef IRIX
-#define API_DEFAULT API_SGI
-#define API_DEFSTRING "SGI Digital Media"
+# define API_DEFAULT API_SGI
+# define API_DEFSTRING "SGI Digital Media"
+#endif
+#ifdef __GNU__
+# define API_DEFAULT API_JACK
+# define API_DEFSTRING "Jack audio connection kit"
+#endif
#endif
+
#define DEFAULTAUDIODEV 0
#define MAXAUDIOINDEV 4
@@ -211,7 +242,7 @@ void sys_setvirtualalarm( void);
#ifdef MSW
#define DEFAULTADVANCE 70
#else
-#define DEFAULTADVANCE 50
+#define DEFAULTADVANCE 25
#endif
typedef void (*t_audiocallback)(void);
@@ -229,7 +260,7 @@ void pa_getdevs(char *indevlist, int *nindevs,
int oss_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate);
+ int *choutdev, int rate, int blocksize);
void oss_close_audio(void);
int oss_send_dacs(void);
void oss_reportidle(void);
@@ -239,7 +270,7 @@ void oss_getdevs(char *indevlist, int *nindevs,
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate);
+ int *choutdev, int rate, int blocksize);
void alsa_close_audio(void);
int alsa_send_dacs(void);
void alsa_reportidle(void);
@@ -247,7 +278,8 @@ void alsa_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize);
-int jack_open_audio(int wantinchans, int wantoutchans, int srate);
+int jack_open_audio(int wantinchans, int wantoutchans, int srate,
+ t_audiocallback callback);
void jack_close_audio(void);
int jack_send_dacs(void);
void jack_reportidle(void);
@@ -266,25 +298,51 @@ void mmio_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize);
+int audiounit_open_audio(int naudioindev, int *audioindev, int nchindev,
+ int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+ int *choutdev, int rate);
+void audiounit_close_audio(void);
+int audiounit_send_dacs(void);
+void audiounit_listdevs(void);
+void audiounit_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize);
+
+int esd_open_audio(int naudioindev, int *audioindev, int nchindev,
+ int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+ int *choutdev, int rate);
+void esd_close_audio(void);
+int esd_send_dacs(void);
+void esd_listdevs(void);
+void esd_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize);
+
+int dummy_open_audio(int nin, int nout, int sr);
+int dummy_close_audio( void);
+int dummy_send_dacs( void);
+void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist,
+ int *noutdevs, int *canmulti, int maxndev, int devdescsize);
+void dummy_listdevs( void);
+
void sys_listmididevs(void);
-void sys_set_midi_api(int whichapi);
-void sys_set_audio_api(int whichapi);
-void sys_get_audio_apis(char *buf);
+EXTERN void sys_set_midi_api(int whichapi);
+EXTERN void sys_set_audio_api(int whichapi);
extern int sys_audioapi;
-void sys_set_audio_state(int onoff);
+EXTERN void sys_set_audio_state(int onoff);
/* API dependent audio flags and settings */
void oss_set32bit( void);
void linux_alsa_devname(char *devname);
-void sys_get_audio_params(
+EXTERN void sys_get_audio_params(
int *pnaudioindev, int *paudioindev, int *chindev,
int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
- int *prate, int *padvance, int *callback);
+ int *prate, int *padvance, int *callback, int *blocksize);
void sys_save_audio_params(
int naudioindev, int *audioindev, int *chindev,
int naudiooutdev, int *audiooutdev, int *choutdev,
- int rate, int advance, int callback);
+ int rate, int advance, int callback, int blocksize);
/* s_file.c */
diff --git a/pd/src/s_utf8.c b/pd/src/s_utf8.c
new file mode 100644
index 00000000..b50d0929
--- /dev/null
+++ b/pd/src/s_utf8.c
@@ -0,0 +1,280 @@
+/*
+ Basic UTF-8 manipulation routines
+ by Jeff Bezanson
+ placed in the public domain Fall 2005
+
+ This code is designed to provide the utilities you need to manipulate
+ UTF-8 as an internal string encoding. These functions do not perform the
+ error checking normally needed when handling UTF-8 data, so if you happen
+ to be from the Unicode Consortium you will want to flay me alive.
+ I do this because error checking can be performed at the boundaries (I/O),
+ with these routines reserved for higher performance on data known to be
+ valid.
+
+ modified by Bryan Jurish (moo) March 2009
+ + removed some unneeded functions (escapes, printf etc), added others
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef WIN32
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+#include "s_utf8.h"
+
+static const u_int32_t offsetsFromUTF8[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+};
+
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+
+/* returns length of next utf-8 sequence */
+int u8_seqlen(char *s)
+{
+ return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1;
+}
+
+/* conversions without error checking
+ only works for valid UTF-8, i.e. no 5- or 6-byte sequences
+ srcsz = source size in bytes, or -1 if 0-terminated
+ sz = dest size in # of wide characters
+
+ returns # characters converted
+ dest will always be L'\0'-terminated, even if there isn't enough room
+ for all the characters.
+ if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space.
+*/
+int u8_toucs(u_int32_t *dest, int sz, char *src, int srcsz)
+{
+ u_int32_t ch;
+ char *src_end = src + srcsz;
+ int nb;
+ int i=0;
+
+ while (i < sz-1) {
+ nb = trailingBytesForUTF8[(unsigned char)*src];
+ if (srcsz == -1) {
+ if (*src == 0)
+ goto done_toucs;
+ }
+ else {
+ if (src + nb >= src_end)
+ goto done_toucs;
+ }
+ ch = 0;
+ switch (nb) {
+ /* these fall through deliberately */
+#if UTF8_SUPPORT_FULL_UCS4
+ case 5: ch += (unsigned char)*src++; ch <<= 6;
+ case 4: ch += (unsigned char)*src++; ch <<= 6;
+#endif
+ case 3: ch += (unsigned char)*src++; ch <<= 6;
+ case 2: ch += (unsigned char)*src++; ch <<= 6;
+ case 1: ch += (unsigned char)*src++; ch <<= 6;
+ case 0: ch += (unsigned char)*src++;
+ }
+ ch -= offsetsFromUTF8[nb];
+ dest[i++] = ch;
+ }
+ done_toucs:
+ dest[i] = 0;
+ return i;
+}
+
+/* srcsz = number of source characters, or -1 if 0-terminated
+ sz = size of dest buffer in bytes
+
+ returns # characters converted
+ dest will only be '\0'-terminated if there is enough space. this is
+ for consistency; imagine there are 2 bytes of space left, but the next
+ character requires 3 bytes. in this case we could NUL-terminate, but in
+ general we can't when there's insufficient space. therefore this function
+ only NUL-terminates if all the characters fit, and there's space for
+ the NUL as well.
+ the destination string will never be bigger than the source string.
+*/
+int u8_toutf8(char *dest, int sz, u_int32_t *src, int srcsz)
+{
+ u_int32_t ch;
+ int i = 0;
+ char *dest_end = dest + sz;
+
+ while (srcsz<0 ? src[i]!=0 : i < srcsz) {
+ ch = src[i];
+ if (ch < 0x80) {
+ if (dest >= dest_end)
+ return i;
+ *dest++ = (char)ch;
+ }
+ else if (ch < 0x800) {
+ if (dest >= dest_end-1)
+ return i;
+ *dest++ = (ch>>6) | 0xC0;
+ *dest++ = (ch & 0x3F) | 0x80;
+ }
+ else if (ch < 0x10000) {
+ if (dest >= dest_end-2)
+ return i;
+ *dest++ = (ch>>12) | 0xE0;
+ *dest++ = ((ch>>6) & 0x3F) | 0x80;
+ *dest++ = (ch & 0x3F) | 0x80;
+ }
+ else if (ch < 0x110000) {
+ if (dest >= dest_end-3)
+ return i;
+ *dest++ = (ch>>18) | 0xF0;
+ *dest++ = ((ch>>12) & 0x3F) | 0x80;
+ *dest++ = ((ch>>6) & 0x3F) | 0x80;
+ *dest++ = (ch & 0x3F) | 0x80;
+ }
+ i++;
+ }
+ if (dest < dest_end)
+ *dest = '\0';
+ return i;
+}
+
+/* moo: get byte length of character number, or 0 if not supported */
+int u8_wc_nbytes(u_int32_t ch)
+{
+ if (ch < 0x80) return 1;
+ if (ch < 0x800) return 2;
+ if (ch < 0x10000) return 3;
+ if (ch < 0x200000) return 4;
+#if UTF8_SUPPORT_FULL_UCS4
+ /*-- moo: support full UCS-4 range? --*/
+ if (ch < 0x4000000) return 5;
+ if (ch < 0x7fffffffUL) return 6;
+#endif
+ return 0; /*-- bad input --*/
+}
+
+int u8_wc_toutf8(char *dest, u_int32_t ch)
+{
+ if (ch < 0x80) {
+ dest[0] = (char)ch;
+ return 1;
+ }
+ if (ch < 0x800) {
+ dest[0] = (ch>>6) | 0xC0;
+ dest[1] = (ch & 0x3F) | 0x80;
+ return 2;
+ }
+ if (ch < 0x10000) {
+ dest[0] = (ch>>12) | 0xE0;
+ dest[1] = ((ch>>6) & 0x3F) | 0x80;
+ dest[2] = (ch & 0x3F) | 0x80;
+ return 3;
+ }
+ if (ch < 0x110000) {
+ dest[0] = (ch>>18) | 0xF0;
+ dest[1] = ((ch>>12) & 0x3F) | 0x80;
+ dest[2] = ((ch>>6) & 0x3F) | 0x80;
+ dest[3] = (ch & 0x3F) | 0x80;
+ return 4;
+ }
+ return 0;
+}
+
+/*-- moo --*/
+int u8_wc_toutf8_nul(char *dest, u_int32_t ch)
+{
+ int sz = u8_wc_toutf8(dest,ch);
+ dest[sz] = '\0';
+ return sz;
+}
+
+/* charnum => byte offset */
+int u8_offset(char *str, int charnum)
+{
+ int offs=0;
+
+ while (charnum > 0 && str[offs]) {
+ (void)(isutf(str[++offs]) || isutf(str[++offs]) ||
+ isutf(str[++offs]) || ++offs);
+ charnum--;
+ }
+ return offs;
+}
+
+/* byte offset => charnum */
+int u8_charnum(char *s, int offset)
+{
+ int charnum = 0, offs=0;
+
+ while (offs < offset && s[offs]) {
+ (void)(isutf(s[++offs]) || isutf(s[++offs]) ||
+ isutf(s[++offs]) || ++offs);
+ charnum++;
+ }
+ return charnum;
+}
+
+/* reads the next utf-8 sequence out of a string, updating an index */
+u_int32_t u8_nextchar(char *s, int *i)
+{
+ u_int32_t ch = 0;
+ int sz = 0;
+
+ do {
+ ch <<= 6;
+ ch += (unsigned char)s[(*i)++];
+ sz++;
+ } while (s[*i] && !isutf(s[*i]));
+ ch -= offsetsFromUTF8[sz-1];
+
+ return ch;
+}
+
+/* number of characters */
+int u8_strlen(char *s)
+{
+ int count = 0;
+ int i = 0;
+
+ while (u8_nextchar(s, &i) != 0)
+ count++;
+
+ return count;
+}
+
+void u8_inc(char *s, int *i)
+{
+ (void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) ||
+ isutf(s[++(*i)]) || ++(*i));
+}
+
+void u8_dec(char *s, int *i)
+{
+ (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) ||
+ isutf(s[--(*i)]) || --(*i));
+}
+
+/*-- moo --*/
+void u8_inc_ptr(char **sp)
+{
+ (void)(isutf(*(++(*sp))) || isutf(*(++(*sp))) ||
+ isutf(*(++(*sp))) || ++(*sp));
+}
+
+/*-- moo --*/
+void u8_dec_ptr(char **sp)
+{
+ (void)(isutf(*(--(*sp))) || isutf(*(--(*sp))) ||
+ isutf(*(--(*sp))) || --(*sp));
+}
diff --git a/pd/src/s_utf8.h b/pd/src/s_utf8.h
new file mode 100644
index 00000000..56c40d48
--- /dev/null
+++ b/pd/src/s_utf8.h
@@ -0,0 +1,88 @@
+#ifndef S_UTF8_H
+#define S_UTF8_H
+
+/*--moo--*/
+#ifndef u_int32_t
+# define u_int32_t unsigned int
+#endif
+
+#ifndef UCS4
+# define UCS4 u_int32_t
+#endif
+
+/* UTF8_SUPPORT_FULL_UCS4
+ * define this to support the full potential range of UCS-4 codepoints
+ * (in anticipation of a future UTF-8 standard)
+ */
+/*#define UTF8_SUPPORT_FULL_UCS4 1*/
+#undef UTF8_SUPPORT_FULL_UCS4
+
+/* UTF8_MAXBYTES
+ * maximum number of bytes required to represent a single character in UTF-8
+ *
+ * UTF8_MAXBYTES1 = UTF8_MAXBYTES+1
+ * maximum bytes per character including NUL terminator
+ */
+#ifdef UTF8_SUPPORT_FULL_UCS4
+# ifndef UTF8_MAXBYTES
+# define UTF8_MAXBYTES 6
+# endif
+# ifndef UTF8_MAXBYTES1
+# define UTF8_MAXBYTES1 7
+# endif
+#else
+# ifndef UTF8_MAXBYTES
+# define UTF8_MAXBYTES 4
+# endif
+# ifndef UTF8_MAXBYTES1
+# define UTF8_MAXBYTES1 5
+# endif
+#endif
+/*--/moo--*/
+
+/* is c the start of a utf8 sequence? */
+#define isutf(c) (((c)&0xC0)!=0x80)
+
+/* convert UTF-8 data to wide character */
+int u8_toucs(u_int32_t *dest, int sz, char *src, int srcsz);
+
+/* the opposite conversion */
+int u8_toutf8(char *dest, int sz, u_int32_t *src, int srcsz);
+
+/* moo: get byte length of character number, or 0 if not supported */
+int u8_wc_nbytes(u_int32_t ch);
+
+/* moo: compute required storage for UTF-8 encoding of 's[0..n-1]' */
+int u8_wcs_nbytes(u_int32_t *ucs, int size);
+
+/* single character to UTF-8, no NUL termination */
+int u8_wc_toutf8(char *dest, u_int32_t ch);
+
+/* moo: single character to UTF-8, with NUL termination */
+int u8_wc_toutf8_nul(char *dest, u_int32_t ch);
+
+/* character number to byte offset */
+int u8_offset(char *str, int charnum);
+
+/* byte offset to character number */
+int u8_charnum(char *s, int offset);
+
+/* return next character, updating an index variable */
+u_int32_t u8_nextchar(char *s, int *i);
+
+/* move to next character */
+void u8_inc(char *s, int *i);
+
+/* move to previous character */
+void u8_dec(char *s, int *i);
+
+/* moo: move pointer to next character */
+void u8_inc_ptr(char **sp);
+
+/* moo: move pointer to previous character */
+void u8_dec_ptr(char **sp);
+
+/* returns length of next utf-8 sequence */
+int u8_seqlen(char *s);
+
+#endif /* S_UTF8_H */
diff --git a/pd/src/u_pdreceive.c b/pd/src/u_pdreceive.c
index e61397ed..8a193292 100644
--- a/pd/src/u_pdreceive.c
+++ b/pd/src/u_pdreceive.c
@@ -128,7 +128,7 @@ static void addport(int fd)
nfdpoll++;
if (fd >= maxfd) maxfd = fd + 1;
fp->fdp_outlen = fp->fdp_discard = fp->fdp_gotsemi = 0;
- if (!(fp->fdp_outbuf = malloc(BUFSIZE)))
+ if (!(fp->fdp_outbuf = (char*) malloc(BUFSIZE)))
{
fprintf(stderr, "out of memory");
exit(1);
diff --git a/pd/src/x_arithmetic.c b/pd/src/x_arithmetic.c
index 0dd19937..d89530f6 100644
--- a/pd/src/x_arithmetic.c
+++ b/pd/src/x_arithmetic.c
@@ -10,19 +10,6 @@ inputs to int and their outputs back to float. */
#include <math.h>
-/* MSW and OSX don't appear to have single-precision ANSI math */
-#if defined(MSW) || defined(__APPLE__)
-#define sinf sin
-#define cosf cos
-#define atanf atan
-#define atan2f atan2
-#define sqrtf sqrt
-#define logf log
-#define expf exp
-#define fabsf fabs
-#define powf pow
-#endif
-
typedef struct _binop
{
t_object x_obj;
diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
index b9093f46..abd09317 100644
--- a/pd/src/x_connective.c
+++ b/pd/src/x_connective.c
@@ -508,6 +508,8 @@ static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
{
t_float f;
if (!argc) return;
+ if (argv->a_type != A_FLOAT)
+ goto rejected;
f = atom_getfloat(argv);
for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
if (e->e_w.w_float == f)
@@ -569,6 +571,7 @@ static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
}
}
}
+ rejected:
outlet_list(x->x_rejectout, 0, argc, argv);
}
@@ -600,6 +603,12 @@ static void *route_new(t_symbol *s, int argc, t_atom *argv)
e->e_w.w_float = atom_getfloatarg(n, argc, argv);
else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv);
}
+ if (argc == 1)
+ {
+ if (argv->a_type == A_FLOAT)
+ floatinlet_new(&x->x_obj, &x->x_vec->e_w.w_float);
+ else symbolinlet_new(&x->x_obj, &x->x_vec->e_w.w_symbol);
+ }
x->x_rejectout = outlet_new(&x->x_obj, &s_list);
return (x);
}
@@ -1002,8 +1011,7 @@ static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv)
outlet_bang(u->u_outlet);
else if (u->u_type == TR_ANYTHING)
outlet_anything(u->u_outlet, s, argc, argv);
- else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'",
- s->s_name);
+ else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'");
}
}
@@ -1260,12 +1268,15 @@ static void makefilename_float(t_makefilename *x, t_floatarg f)
char buf[MAXPDSTRING];
if (x->x_accept == A_FLOAT) {
if (x->x_intconvert)
- sprintf(buf, x->x_format->s_name, (int)f);
- else
- sprintf(buf, x->x_format->s_name, f);
+ sprintf(buf, x->x_format->s_name, (int)f);
+ else sprintf(buf, x->x_format->s_name, f);
}
else
- sprintf(buf, x->x_format->s_name, "");
+ {
+ char buf2[MAXPDSTRING];
+ sprintf(buf2, "%g", f);
+ sprintf(buf, x->x_format->s_name, buf2);
+ }
if (buf[0]!=0)
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
}
diff --git a/pd/src/x_gui.c b/pd/src/x_gui.c
index e83981bb..2409ca41 100644
--- a/pd/src/x_gui.c
+++ b/pd/src/x_gui.c
@@ -46,6 +46,9 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
{
char buf[4*MAXPDSTRING];
char namebuf[80];
+ char sprintfbuf[MAXPDSTRING];
+ char *afterpercent;
+ t_int afterpercentlen;
t_gfxstub *x;
t_symbol *s;
/* if any exists with matching key, burn it. */
@@ -55,7 +58,7 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
if (strlen(cmd) + 50 > 4*MAXPDSTRING)
{
bug("audio dialog too long");
- bug("%x", cmd);
+ bug("%s", cmd);
return;
}
x = (t_gfxstub *)pd_new(gfxstub_class);
@@ -68,7 +71,13 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
x->x_key = key;
x->x_next = gfxstub_list;
gfxstub_list = x;
- sprintf(buf, cmd, s->s_name);
+ /* only replace first %s so sprintf() doesn't crash */
+ afterpercent = strchr(cmd, '%') + 2;
+ afterpercentlen = afterpercent - cmd;
+ strncpy(sprintfbuf, cmd, afterpercentlen);
+ sprintfbuf[afterpercentlen] = '\0';
+ sprintf(buf, sprintfbuf, s->s_name);
+ strncat(buf, afterpercent, (4*MAXPDSTRING) - afterpercentlen);
sys_gui(buf);
}
diff --git a/pd/src/x_interface.c b/pd/src/x_interface.c
index 044961b1..ce685e57 100644
--- a/pd/src/x_interface.c
+++ b/pd/src/x_interface.c
@@ -19,12 +19,28 @@ typedef struct _print
static void *print_new(t_symbol *sel, int argc, t_atom *argv)
{
t_print *x = (t_print *)pd_new(print_class);
- t_symbol *s = atom_getsymbolarg(0, argc, argv);
- if (!*s->s_name)
+ if (argc == 0)
x->x_sym = gensym("print");
- else if (!strcmp(s->s_name, "-n"))
- x->x_sym = &s_;
- else x->x_sym = s;
+ else if (argc == 1 && argv->a_type == A_SYMBOL)
+ {
+ t_symbol *s = atom_getsymbolarg(0, argc, argv);
+ if (!strcmp(s->s_name, "-n"))
+ x->x_sym = &s_;
+ else x->x_sym = s;
+ }
+ else
+ {
+ int bufsize;
+ char *buf;
+ t_binbuf *bb = binbuf_new();
+ binbuf_add(bb, argc, argv);
+ binbuf_gettext(bb, &buf, &bufsize);
+ buf = resizebytes(buf, bufsize, bufsize+1);
+ buf[bufsize] = 0;
+ x->x_sym = gensym(buf);
+ freebytes(buf, bufsize+1);
+ binbuf_free(bb);
+ }
return (x);
}
diff --git a/pd/src/x_misc.c b/pd/src/x_misc.c
index 2d7860d9..13090f0d 100644
--- a/pd/src/x_misc.c
+++ b/pd/src/x_misc.c
@@ -9,24 +9,28 @@
#include <math.h>
#include <stdio.h>
#include <string.h>
-#ifdef HAVE_UNISTD_H
+#ifdef _WIN32
+#include <wtypes.h>
+#include <time.h>
+#else
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/param.h>
#include <unistd.h>
-#endif
-#ifdef MSW
-#include <wtypes.h>
-#include <time.h>
-#endif
+#endif /* _WIN32 */
#if defined (__APPLE__) || defined (__FreeBSD__)
#define CLOCKHZ CLK_TCK
#endif
-#if defined (__linux__)
+#if defined (__linux__) || defined (__CYGWIN__) || defined (ANDROID)
#define CLOCKHZ sysconf(_SC_CLK_TCK)
#endif
+#if defined (__FreeBSD_kernel__) || defined(__GNU__)
+#include <time.h>
+#define CLOCKHZ CLOCKS_PER_SEC
+#endif
+
/* -------------------------- random ------------------------------ */
/* this is strictly homebrew and untested. */
@@ -145,7 +149,7 @@ static void namecanvas_setup(void)
sizeof(t_namecanvas), CLASS_NOINLET, A_DEFSYM, 0);
}
-/* ---------------serial ports (MSW only -- hack) ------------------------- */
+/* ---------------serial ports (_WIN32 only -- hack) ------------------------- */
#define MAXSERIAL 100
static t_class *serial_class;
@@ -194,22 +198,18 @@ static t_class *cputime_class;
typedef struct _cputime
{
t_object x_obj;
-#ifdef HAVE_UNISTD_H
- struct tms x_setcputime;
-#endif
-#ifdef MSW
+#ifdef _WIN32
LARGE_INTEGER x_kerneltime;
LARGE_INTEGER x_usertime;
int x_warned;
-#endif
+#else
+ struct tms x_setcputime;
+#endif /* _WIN32 */
} t_cputime;
static void cputime_bang(t_cputime *x)
{
-#ifdef HAVE_UNISTD_H
- times(&x->x_setcputime);
-#endif
-#ifdef MSW
+#ifdef _WIN32
FILETIME ignorethis, ignorethat;
BOOL retval;
retval = GetProcessTimes(GetCurrentProcess(), &ignorethis, &ignorethat,
@@ -222,12 +222,14 @@ static void cputime_bang(t_cputime *x)
x->x_kerneltime.QuadPart = 0;
x->x_usertime.QuadPart = 0;
}
-#endif
+#else
+ times(&x->x_setcputime);
+#endif /* _WIN32 */
}
static void cputime_bang2(t_cputime *x)
{
-#ifdef HAVE_UNISTD_H
+#ifndef _WIN32
t_float elapsedcpu;
struct tms newcputime;
times(&newcputime);
@@ -235,8 +237,7 @@ static void cputime_bang2(t_cputime *x)
newcputime.tms_utime + newcputime.tms_stime -
x->x_setcputime.tms_utime - x->x_setcputime.tms_stime) / CLOCKHZ;
outlet_float(x->x_obj.ob_outlet, elapsedcpu);
-#endif
-#ifdef MSW
+#else
t_float elapsedcpu;
FILETIME ignorethis, ignorethat;
LARGE_INTEGER usertime, kerneltime;
@@ -250,7 +251,7 @@ static void cputime_bang2(t_cputime *x)
(usertime.QuadPart - x->x_usertime.QuadPart));
else elapsedcpu = 0;
outlet_float(x->x_obj.ob_outlet, elapsedcpu);
-#endif
+#endif /* NOT _WIN32 */
}
static void *cputime_new(void)
@@ -259,7 +260,7 @@ static void *cputime_new(void)
outlet_new(&x->x_obj, gensym("float"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
-#ifdef MSW
+#ifdef _WIN32
x->x_warned = 0;
#endif
cputime_bang(x);
diff --git a/pd/src/x_net.c b/pd/src/x_net.c
index 9d1aee0b..7e0d0be4 100644
--- a/pd/src/x_net.c
+++ b/pd/src/x_net.c
@@ -76,6 +76,10 @@ static void netsend_connect(t_netsend *x, t_symbol *hostname,
&intarg, sizeof(intarg)) < 0)
post("setsockopt (SO_RCVBUF) failed\n");
#endif
+ intarg = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+ (const void *)&intarg, sizeof(intarg)) < 0)
+ post("setting SO_BROADCAST");
/* for stream (TCP) sockets, specify "nodelay" */
if (x->x_protocol == SOCK_STREAM)
{
@@ -282,6 +286,10 @@ static void *netreceive_new(t_symbol *compatflag,
&intarg, sizeof(intarg)) < 0)
post("setsockopt (SO_RCVBUF) failed\n");
#endif
+ intarg = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+ (const void *)&intarg, sizeof(intarg)) < 0)
+ post("setting SO_BROADCAST");
/* Stream (TCP) sockets are set NODELAY */
if (!udp)
{
diff --git a/pd/src/x_time.c b/pd/src/x_time.c
index 5dc9d37f..c81c1ed1 100644
--- a/pd/src/x_time.c
+++ b/pd/src/x_time.c
@@ -139,6 +139,7 @@ static void metro_setup(void)
}
/* -------------------------- line ------------------------------ */
+#define DEFAULTLINEGRAIN 20
static t_class *line_class;
typedef struct _line
@@ -168,6 +169,8 @@ static void line_tick(t_line *x)
outlet_float(x->x_obj.ob_outlet,
x->x_setval + x->x_1overtimediff * (timenow - x->x_prevtime)
* (x->x_targetval - x->x_setval));
+ if (x->x_grain <= 0)
+ x->x_grain = DEFAULTLINEGRAIN;
clock_delay(x->x_clock,
(x->x_grain > msectogo ? msectogo : x->x_grain));
}
@@ -188,6 +191,8 @@ static void line_float(t_line *x, t_float f)
line_tick(x);
x->x_gotinlet = 0;
x->x_1overtimediff = 1./ (x->x_targettime - timenow);
+ if (x->x_grain <= 0)
+ x->x_grain = DEFAULTLINEGRAIN;
clock_delay(x->x_clock,
(x->x_grain > x->x_in1val ? x->x_in1val : x->x_grain));
@@ -232,10 +237,10 @@ static void *line_new(t_floatarg f, t_floatarg grain)
x->x_1overtimediff = 1;
x->x_clock = clock_new(x, (t_method)line_tick);
x->x_targettime = x->x_prevtime = clock_getsystime();
- if (grain <= 0) grain = 20;
x->x_grain = grain;
outlet_new(&x->x_obj, gensym("float"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
+ floatinlet_new(&x->x_obj, &x->x_grain);
return (x);
}