From 21c068f1916330e90f814bed461fe0821d1665ec Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 9 Oct 2011 16:36:37 +0000 Subject: checked in pd-0.43-0.src.tar.gz svn path=/trunk/; revision=15557 --- pd/src/Makefile.am | 145 +++++++++++++ pd/src/configure.in | 31 +-- pd/src/d_array.c | 56 ++--- pd/src/d_ctl.c | 2 +- pd/src/d_delay.c | 32 ++- pd/src/d_fft_fftw.c | 138 +++++++++--- pd/src/d_fftroutine.c | 41 ++-- pd/src/d_math.c | 23 +- pd/src/d_osc.c | 57 ++--- pd/src/d_soundfile.c | 6 +- pd/src/d_ugen.c | 2 +- pd/src/g_all_guis.c | 13 +- pd/src/g_array.c | 53 +++-- pd/src/g_bang.c | 8 +- pd/src/g_canvas.c | 89 +++----- pd/src/g_canvas.h | 5 +- pd/src/g_editor.c | 201 +++++++++--------- pd/src/g_graph.c | 32 ++- pd/src/g_hdial.c | 8 +- pd/src/g_hslider.c | 13 +- pd/src/g_mycanvas.c | 2 +- pd/src/g_numbox.c | 8 +- pd/src/g_readwrite.c | 9 +- pd/src/g_rtext.c | 187 +++++++++++----- pd/src/g_template.c | 28 ++- pd/src/g_text.c | 42 ++-- pd/src/g_toggle.c | 8 +- pd/src/g_vdial.c | 8 +- pd/src/g_vslider.c | 8 +- pd/src/g_vumeter.c | 14 +- pd/src/m_atom.c | 2 +- pd/src/m_binbuf.c | 164 +++++++++++--- pd/src/m_class.c | 10 +- pd/src/m_glob.c | 5 +- pd/src/m_obj.c | 28 +++ pd/src/m_pd.h | 25 ++- pd/src/m_sched.c | 18 +- pd/src/makefile.in | 3 +- pd/src/makefile.mingw | 297 ++++++++++++++++++++++++++ pd/src/makefile.nt | 23 +- pd/src/notes.txt | 7 + pd/src/pd.ico | Bin 0 -> 25214 bytes pd/src/pd.rc | 25 +++ pd/src/s_audio.c | 196 +++++++++++++---- pd/src/s_audio_alsa.c | 39 ++-- pd/src/s_audio_alsa.h | 2 +- pd/src/s_audio_alsamm.c | 8 +- pd/src/s_audio_audiounit.c | 43 ++++ pd/src/s_audio_dummy.c | 37 ++++ pd/src/s_audio_esd.c | 135 ++++++++++++ pd/src/s_audio_jack.c | 517 ++++++++++++++++++++++++++++----------------- pd/src/s_audio_mmio.c | 4 +- pd/src/s_audio_oss.c | 21 +- pd/src/s_audio_pa.c | 450 ++++++++++++++++++++++++++------------- pd/src/s_audio_pablio.c | 350 ------------------------------ pd/src/s_audio_pablio.h | 111 ---------- pd/src/s_audio_paring.c | 13 +- pd/src/s_audio_paring.h | 5 +- pd/src/s_file.c | 37 ++-- pd/src/s_inter.c | 124 +++++------ pd/src/s_loader.c | 31 +-- pd/src/s_main.c | 77 ++++--- pd/src/s_midi.c | 16 +- pd/src/s_midi_alsa.c | 12 +- pd/src/s_midi_dummy.c | 34 +++ pd/src/s_midi_pm.c | 1 - pd/src/s_path.c | 144 ++++++++++--- pd/src/s_print.c | 187 +++++++++++++--- pd/src/s_stuff.h | 124 ++++++++--- pd/src/s_utf8.c | 280 ++++++++++++++++++++++++ pd/src/s_utf8.h | 88 ++++++++ pd/src/u_pdreceive.c | 2 +- pd/src/x_arithmetic.c | 13 -- pd/src/x_connective.c | 23 +- pd/src/x_gui.c | 13 +- pd/src/x_interface.c | 26 ++- pd/src/x_misc.c | 47 +++-- pd/src/x_net.c | 8 + pd/src/x_time.c | 7 +- 79 files changed, 3422 insertions(+), 1679 deletions(-) create mode 100644 pd/src/Makefile.am create mode 100644 pd/src/makefile.mingw create mode 100755 pd/src/pd.ico create mode 100644 pd/src/pd.rc create mode 100644 pd/src/s_audio_audiounit.c create mode 100644 pd/src/s_audio_dummy.c create mode 100644 pd/src/s_audio_esd.c delete mode 100644 pd/src/s_audio_pablio.c delete mode 100644 pd/src/s_audio_pablio.h create mode 100644 pd/src/s_midi_dummy.c create mode 100644 pd/src/s_utf8.c create mode 100644 pd/src/s_utf8.h (limited to 'pd/src') 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 #endif -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) #include #endif -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(ANDROID) #include #endif -#if defined(__unix__) || defined(__APPLE__) +#ifdef __MINGW32__ +#include +#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 -#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 /* 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 -#else -#include -#endif - -#error oops -- I'm talking to the old fftw. Apparently it's still changing. +/* changes and additions for FFTW3 by Thomas Grill */ -#include +#include "m_pd.h" +#include int ilog2(int n); -#define MINFFT 5 +#define MINFFT 0 #define MAXFFT 30 /* from the FFTW website: - fftw_complex in[N], out[N]; + #include + ... + { + 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 -#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 /* 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 #endif -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) #include #endif -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(ANDROID) #include #endif -#if defined(__unix__) || defined(__APPLE__) +#ifdef __MINGW32__ +#include +#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 -#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 /* 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<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 +#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 ), 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 #include +#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; ja_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 /* 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. +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 Binary files /dev/null and b/pd/src/pd.ico 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 -#ifdef HAVE_UNISTD_H +#ifdef _WIN32 +#include +#else #include #include #include -#endif +#endif /* _WIN32 */ #include #include #include #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) @@ -359,6 +365,21 @@ void sys_close_audio(void) if (sys_audioapiopened == API_MMIO) 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; @@ -366,6 +387,8 @@ void sys_close_audio(void) 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) @@ -492,6 +539,21 @@ int sys_send_dacs(void) if (sys_audioapi == API_MMIO) 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 @@ -575,6 +638,28 @@ static void audio_getdevs(char *indevlist, int *nindevs, maxndev, devdescsize); } 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. */ @@ -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< 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(); } @@ -776,20 +876,35 @@ void sys_listdevs(void ) if (sys_audioapi == API_MMIO) 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) @@ -871,6 +986,15 @@ void sys_get_audio_apis(char *buf) #endif #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. */ 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 +#include +#include +#include "m_pd.h" +#include "s_stuff.h" +#include + +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 + +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 +#include /* memset */ +#include +#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 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 #include - #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=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= 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 +#if defined(__FreeBSD_kernel__) +# include +#else +# include +#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 #include +#include +#include #include -#include "s_audio_pablio.h" #ifdef MSW #include +#include #else #include +#include #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 -#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->maxInputChannelsmaxInputChannels; + } + } + + if (outchannels>0) + { + if (NULL != (info = Pa_GetDeviceInfo( outstreamparams.device ))) + { + outRate=info->defaultSampleRate; + + if(info->maxOutputChannelsmaxOutputChannels; + } + } + + 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 -#include -#include -#include "portaudio.h" -#include "s_audio_paring.h" -#include "s_audio_pablio.h" /* MSP */ -#include - - /* 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; ibuffer ) 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<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 -#include -#include -#include "portaudio.h" -#include "s_audio_paring.h" -#include - -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 #include #endif -#ifdef MSW +#ifdef _WIN32 #include #include #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 #include #include @@ -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 @@ -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)) @@ -656,6 +658,20 @@ int sys_argparse(int argc, char **argv) sys_mmio = 1; 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")) { @@ -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 #endif #endif -#ifdef MSW +#ifdef _WIN32 #include #include #include @@ -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 #include #include -#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 +#include +#endif +#ifdef _WIN32 +#include #endif #include @@ -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 #include #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 +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#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 -/* 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 #include #include -#ifdef HAVE_UNISTD_H +#ifdef _WIN32 +#include +#include +#else #include #include #include #include #include -#endif -#ifdef MSW -#include -#include -#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 +#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); } -- cgit v1.2.1