From 4cbd55491dd86ea99e1ea8190a20bd13e0f328ae Mon Sep 17 00:00:00 2001 From: Miller Puckette Date: Sat, 16 Jul 2005 01:43:18 +0000 Subject: fixed bugs, adopted some patches. svn path=/trunk/; revision=3347 --- pd/src/configure.in | 25 ++++- pd/src/g_all_guis.c | 3 - pd/src/g_numbox.c | 2 +- pd/src/m_glob.c | 3 + pd/src/makefile | 18 ++-- pd/src/makefile.dependencies | 33 ++++++ pd/src/notes.txt | 7 +- pd/src/s_inter.c | 10 +- pd/src/s_main.c | 11 +- pd/src/s_midi.c | 141 ++++++++++++++++++++++++-- pd/src/s_midi_alsa.c | 233 +++++++++++++++++++++++++++++++++++++++++++ pd/src/s_stuff.h | 19 ++++ pd/src/u_main.tk | 193 +++++++++++++++++++++++++++++++---- pd/src/u_pdsend.c | 3 +- pd/src/x_connective.c | 16 ++- 15 files changed, 670 insertions(+), 47 deletions(-) create mode 100644 pd/src/s_midi_alsa.c (limited to 'pd/src') diff --git a/pd/src/configure.in b/pd/src/configure.in index 5e0d6474..84ab18c4 100644 --- a/pd/src/configure.in +++ b/pd/src/configure.in @@ -13,6 +13,7 @@ AC_SUBST(OPT_CFLAGS) AC_SUBST(USE_DEBUG_CFLAGS, no) AC_SUBST(SYSSRC) AC_SUBST(TCLTK_FRAMEWORKS_PATH) +AC_SUBST(TCLTK_FRAMEWORKS_PATH) AC_SUBST(STRIPFLAG) AC_SUBST(GUINAME) AC_SUBST(GUIFLAGS) @@ -169,10 +170,12 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate. SYSSRC="s_midi_oss.c s_audio_oss.c" if test x$alsa == "xyes"; then - SYSSRC=$SYSSRC" s_audio_alsa.c s_audio_alsamm.c" + SYSSRC=$SYSSRC" s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c" MORECFLAGS=$MORECFLAGS" -DPA_USE_ALSA -DUSEAPI_ALSA" LDFLAGS=$LDFLAGS" -lasound" fi + + if test x$portaudio == "xyes"; @@ -210,6 +213,24 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate. OPT_CFLAGS="-g" else OPT_CFLAGS="-O6 -funroll-loops -fomit-frame-pointer" + + if test x$jack == "xyes"; + then + LDFLAGS=$LDFLAGS" -lrt -ljack" + fi + if test x$jack == "xrun"; + then + LDFLAGS=$LDFLAGS" -lrt -ljack" + fi + fi + + if test x$jack == "xyes"; + then + LDFLAGS=$LDFLAGS" -lrt -ljack" + fi + if test x$jack == "xrun"; + then + LDFLAGS=$LDFLAGS" -lrt -ljack" fi echo OPT_CFLAGS --------------- $OPT_CFLAGS OSNUMBER=0 @@ -244,7 +265,7 @@ then -I../portmidi/pm_common -I../portmidi/pm_mac \ -I../portmidi/porttime \ -Wno-error \ - -DUSEAPI_PORTAUDIO -DPA_BIG_ENDIAN -DPA19" + -DUSEAPI_PORTAUDIO -DPA_BIG_ENDIAN -DPA19 -DPA_USE_COREAUDIO" SYSSRC="s_midi_pm.c s_audio_pa.c \ s_audio_pablio.c \ s_audio_paring.c \ diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c index da83c2ab..f2df4a4b 100644 --- a/pd/src/g_all_guis.c +++ b/pd/src/g_all_guis.c @@ -353,9 +353,6 @@ void iemgui_send(void *x, t_iemgui *iemgui, t_symbol *s) snd = iemgui_raute2dollar(s); iemgui->x_snd_unexpanded = snd; iemgui->x_snd = snd = canvas_realizedollar(iemgui->x_glist, snd); - post("send: before %s, after %s", iemgui->x_snd_unexpanded->s_name, - iemgui->x_snd->s_name); - iemgui->x_fsf.x_snd_able = sndable; iemgui_verify_snd_ne_rcv(iemgui); (*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_IO + oldsndrcvable); diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c index 79fd3e9d..547641c5 100644 --- a/pd/src/g_numbox.c +++ b/pd/src/g_numbox.c @@ -36,7 +36,7 @@ static t_class *my_numbox_class; static void my_numbox_tick_reset(t_my_numbox *x) { - if(x->x_gui.x_fsf.x_change && x->x_gui.x_glist) + if(x->x_gui.x_fsf.x_change && x->x_gui.x_glist) { x->x_gui.x_fsf.x_change = 0; (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c index 12cfb9b6..bcd9d6f3 100644 --- a/pd/src/m_glob.c +++ b/pd/src/m_glob.c @@ -23,6 +23,7 @@ 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); void glob_midi_properties(t_pd *dummy, t_floatarg flongform); void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); +void glob_midi_setapi(t_pd *dummy, t_floatarg f); void glob_start_path_dialog(t_pd *dummy, t_floatarg flongform); void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv); void glob_start_startup_dialog(t_pd *dummy, t_floatarg flongform); @@ -93,6 +94,8 @@ void glob_init(void) gensym("audio-dialog"), A_GIMME, 0); class_addmethod(glob_pdobject, (t_method)glob_audio_setapi, gensym("audio-setapi"), A_FLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_midi_setapi, + gensym("midi-setapi"), A_FLOAT, 0); class_addmethod(glob_pdobject, (t_method)glob_midi_properties, gensym("midi-properties"), A_DEFFLOAT, 0); class_addmethod(glob_pdobject, (t_method)glob_midi_dialog, diff --git a/pd/src/makefile b/pd/src/makefile index 188977c1..f69e9a00 100644 --- a/pd/src/makefile +++ b/pd/src/makefile @@ -28,7 +28,7 @@ CFLAGS = -Werror $(ARCH_CFLAGS) $(WARN_CFLAGS) $(OPT_CFLAGS) $(MORECFLAGS) # the sources -SYSSRC += s_midi_oss.c s_audio_oss.c s_audio_alsa.c s_audio_alsamm.c +SYSSRC += s_midi_oss.c s_audio_oss.c s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c 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 \ @@ -97,11 +97,17 @@ $(BIN_DIR)/pd.tk: u_main.tk cp u_main.tk $(BIN_DIR)/pd.tk #this is for Max OSX only... -$(BIN_DIR)/pdtcl: $(GOBJ) $(GSRC) - cd ../obj; libtool -dynamic -o $(BIN_DIR)/pdtcl $(GOBJ) \ - ../../Frameworks/Tk.framework/Versions/Current/Tk \ - ../../Frameworks/Tcl.framework/Versions/Current/Tcl \ - /usr/lib/libSystem.B.dylib +$(BIN_DIR)/libPdTcl.dylib: $(GOBJ) $(GSRC) + cd ../obj && $(CC) -dynamiclib -read_only_relocs warning \ + -o $(BIN_DIR)/libPdTcl.dylib $(GOBJ) \ + -F \ + -framework Tcl -framework Tk -framework System \ + -Wl,-install_name,@executable_path/../Resources/bin/libPdTcl.dylib + install_name_tool -change /Tcl.framework/Versions/8.4/Tcl\ + @executable_path/../Frameworks/Tcl.framework/Versions/8.4/Tcl \ + -change /Tk.framework/Versions/8.4/Tk \ + @executable_path/../Frameworks/Tk.framework/Versions/8.4/Tk \ + ../bin/libPdTcl.dylib externs: cd ../extra/bonk~;make diff --git a/pd/src/makefile.dependencies b/pd/src/makefile.dependencies index 3b0b06e6..79c847aa 100644 --- a/pd/src/makefile.dependencies +++ b/pd/src/makefile.dependencies @@ -1034,3 +1034,36 @@ s_audio_alsamm.o: s_audio_alsamm.c /usr/include/alsa/asoundlib.h \ /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \ /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h \ /usr/include/sched.h s_audio_alsa.h +s_midi_alsa.o: s_midi_alsa.c /usr/include/stdio.h /usr/include/features.h \ + /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \ + /usr/lib/gcc-lib/i386-redhat-linux/3.3.3/include/stddef.h \ + /usr/include/bits/types.h /usr/include/bits/wordsize.h \ + /usr/include/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h /usr/include/bits/wchar.h \ + /usr/include/gconv.h \ + /usr/lib/gcc-lib/i386-redhat-linux/3.3.3/include/stdarg.h \ + /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \ + /usr/include/bits/stdio.h /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \ + /usr/include/getopt.h /usr/include/stdlib.h /usr/include/sys/types.h \ + /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/bits/time.h \ + /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \ + /usr/include/bits/sched.h /usr/include/alloca.h /usr/include/sys/stat.h \ + /usr/include/bits/stat.h /usr/include/fcntl.h /usr/include/bits/fcntl.h \ + /usr/include/errno.h /usr/include/bits/errno.h \ + /usr/include/linux/errno.h /usr/include/asm/errno.h \ + /usr/include/alsa/asoundlib.h /usr/include/string.h \ + /usr/include/bits/string.h /usr/include/bits/string2.h \ + /usr/include/assert.h /usr/include/sys/poll.h /usr/include/bits/poll.h \ + /usr/include/alsa/asoundef.h /usr/include/alsa/version.h \ + /usr/include/alsa/global.h /usr/include/alsa/input.h \ + /usr/include/alsa/output.h /usr/include/alsa/error.h \ + /usr/include/alsa/conf.h /usr/include/alsa/pcm.h \ + /usr/include/alsa/rawmidi.h /usr/include/alsa/timer.h \ + /usr/include/alsa/hwdep.h /usr/include/alsa/control.h \ + /usr/include/alsa/mixer.h /usr/include/alsa/seq_event.h \ + /usr/include/alsa/seq.h /usr/include/alsa/seqmid.h \ + /usr/include/alsa/seq_midi_event.h /usr/include/alsa/conv.h \ + /usr/include/alsa/instr.h m_pd.h s_stuff.h diff --git a/pd/src/notes.txt b/pd/src/notes.txt index 2faef8a0..038c2a94 100644 --- a/pd/src/notes.txt +++ b/pd/src/notes.txt @@ -16,11 +16,10 @@ GOP font depends on abstraction, not parent ------------ 0.39 --------- problems: -array dimension change gives TK erro (doesn't update) -throwing new array on canvas makes red rectangle? -dialog doesn't start array dialog, just canvas one +TK commands to nonexistent windows? (maybe fixed) +array name changes don't show up on parent arrays that don't fit in bounds don't update (same as red rectangle problem?) - +what about upsampling inlet~s? ask Pd list... flag for array to suppress printing name diff --git a/pd/src/s_inter.c b/pd/src/s_inter.c index f95dbc50..5eb931ec 100644 --- a/pd/src/s_inter.c +++ b/pd/src/s_inter.c @@ -851,7 +851,7 @@ int sys_startgui(const char *guidir) #ifdef UNISTD int stdinpipe[2]; #endif - + fprintf(stderr, "gui; %s\n", guidir); /* create an empty FD poll list */ sys_fdpoll = (t_fdpoll *)t_getbytes(0); sys_nfdpoll = 0; @@ -1029,6 +1029,9 @@ int sys_startgui(const char *guidir) #ifdef MACOSX char *homedir = getenv("HOME"), filename[250]; struct stat statbuf; + sprintf(filename, "%s/../../MacOS/Pd", guidir); + if (stat(filename, &statbuf) >= 0) + goto foundit; if (!homedir || strlen(homedir) > 150) goto nohomedir; sprintf(filename, @@ -1196,7 +1199,7 @@ int sys_startgui(const char *guidir) } if (!sys_nogui) { - char buf[256]; + char buf[256], buf2[256]; sys_socketreceiver = socketreceiver_new(0, 0, 0, 0); sys_addpollfn(sys_guisock, (t_fdpollfn)socketreceiver_read, sys_socketreceiver); @@ -1207,7 +1210,8 @@ int sys_startgui(const char *guidir) sys_gui("pdtk_watchdog\n"); #endif sys_get_audio_apis(buf); - sys_vgui("pdtk_pd_startup {%s} %s {%s}\n", pd_version, buf, + sys_get_midi_apis(buf2); + sys_vgui("pdtk_pd_startup {%s} %s %s {%s}\n", pd_version, buf, buf2, sys_font); } return (0); diff --git a/pd/src/s_main.c b/pd/src/s_main.c index a8030f40..1aa106d6 100644 --- a/pd/src/s_main.c +++ b/pd/src/s_main.c @@ -2,7 +2,7 @@ * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ -char pd_version[] = "Pd version 0.39 TEST 3\n"; +char pd_version[] = "Pd version 0.39 TEST 4\n"; char pd_compiletime[] = __TIME__; char pd_compiledate[] = __DATE__; @@ -346,6 +346,10 @@ static char *(usagemessage[]) = { "-nomidiin -- suppress MIDI input\n", "-nomidiout -- suppress MIDI output\n", "-nomidi -- suppress MIDI input and output\n", +#ifdef USEAPI_ALSA +"-alsamidi -- use ALSA midi API\n", +#endif + "\nother flags:\n", "-path -- add to file search path\n", @@ -604,6 +608,11 @@ int sys_argparse(int argc, char **argv) else goto usage; argc -= 2; argv +=2; } + else if (!strcmp(*argv, "-alsamidi")) + { + sys_set_midi_api(API_ALSA); + argc--; argv++; + } #endif #ifdef USEAPI_JACK else if (!strcmp(*argv, "-jack")) diff --git a/pd/src/s_midi.c b/pd/src/s_midi.c index fbab4283..77943121 100644 --- a/pd/src/s_midi.c +++ b/pd/src/s_midi.c @@ -42,6 +42,8 @@ t_midiqelem midi_inqueue[MIDIQSIZE]; int midi_inhead, midi_intail; static double sys_midiinittime; +int sys_midiapi = API_DEFAULT; + /* this is our current estimate for at what "system" real time the current logical time's output should occur. */ static double sys_dactimeminusrealtime; @@ -99,11 +101,24 @@ static double sys_getmidiinrealtime( void) static void sys_putnext( void) { int portno = midi_outqueue[midi_outtail].q_portno; - if (midi_outqueue[midi_outtail].q_onebyte) - sys_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1); - else sys_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1, - midi_outqueue[midi_outtail].q_byte2, - midi_outqueue[midi_outtail].q_byte3); +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + { + if (midi_outqueue[midi_outtail].q_onebyte) + sys_alsa_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1); + else sys_alsa_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1, + midi_outqueue[midi_outtail].q_byte2, + midi_outqueue[midi_outtail].q_byte3); + } + else +#endif /* ALSA */ + { + if (midi_outqueue[midi_outtail].q_onebyte) + sys_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1); + else sys_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1, + midi_outqueue[midi_outtail].q_byte2, + midi_outqueue[midi_outtail].q_byte3); + } midi_outtail = (midi_outtail + 1 == MIDIQSIZE ? 0 : midi_outtail + 1); } @@ -441,6 +456,11 @@ void sys_pollmidiqueue( void) post("delay %d", (int)(1000 * (newtime - lasttime))); lasttime = newtime; #endif +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sys_alsa_poll_midi(); + else +#endif /* ALSA */ sys_poll_midi(); /* OS dependent poll for MIDI input */ sys_pollmidioutqueue(); sys_pollmidiinqueue(); @@ -448,6 +468,9 @@ void sys_pollmidiqueue( void) /******************** dialog window and device listing ********************/ +#ifdef USEAPI_ALSA +void midi_alsa_init( void); +#endif #ifdef USEAPI_OSS void midi_oss_init( void); #endif @@ -458,6 +481,21 @@ static int midi_midiindev[MAXMIDIINDEV]; static int midi_nmidioutdev; static int midi_midioutdev[MAXMIDIOUTDEV]; + +void sys_get_midi_apis(char *buf) +{ + int n = 0; + strcpy(buf, "{ "); + sprintf(buf + strlen(buf), "{default-MIDI %d} ", API_DEFAULT); n++; +#ifdef USEAPI_ALSA + sprintf(buf + strlen(buf), "{ALSA-MIDI %d} ", API_ALSA); n++; +#endif + strcat(buf, "}"); + /* then again, if only one API (or none) we don't offer any choice. */ + if (n < 2) + strcpy(buf, "{}"); + +} void sys_get_midi_params(int *pnmidiindev, int *pmidiindev, int *pnmidioutdev, int *pmidioutdev) { @@ -486,13 +524,24 @@ static void sys_save_midi_params( void sys_open_midi(int nmidiindev, int *midiindev, int nmidioutdev, int *midioutdev, int enable) { +#ifdef USEAPI_ALSA + midi_alsa_init(); +#endif #ifdef USEAPI_OSS midi_oss_init(); #endif if (enable) +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sys_alsa_do_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev); + else +#endif /* ALSA */ sys_do_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev); sys_save_midi_params(nmidiindev, midiindev, nmidioutdev, midioutdev); + + sys_vgui("set pd_whichmidiapi %d\n", sys_midiapi); + } /* open midi using whatever parameters were last used */ @@ -514,6 +563,12 @@ void sys_listmididevs(void ) char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE]; int nindevs = 0, noutdevs = 0, i; +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + midi_alsa_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, + MAXNDEV, DEVDESCSIZE); + else +#endif /* ALSA */ midi_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, MAXNDEV, DEVDESCSIZE); @@ -535,6 +590,50 @@ void sys_listmididevs(void ) } } +void sys_set_midi_api(int which) +{ + sys_midiapi = which; + if (sys_verbose) + post("sys_midiapi %d", sys_midiapi); +} + +void glob_midi_properties(t_pd *dummy, t_floatarg flongform); + +void glob_midi_setapi(void *dummy, t_floatarg f) +{ + int newapi = f; + if (newapi) + { + if (newapi == sys_midiapi) + { + //if (!midi_isopen()) + // s_reopen_midi(); + } + else + { +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sys_alsa_close_midi(); + else +#endif + sys_close_midi(); + sys_midiapi = newapi; + /* bash device params back to default */ + midi_nmidiindev = midi_nmidioutdev = 1; + //midi_midiindev[0] = midi_midioutdev[0] = DEFAULTMIDIDEV; + //midi_midichindev[0] = midi_midichoutdev[0] = SYS_DEFAULTCH; + sys_reopen_midi(); + } + + glob_midi_properties(0, 0); + } + else //if (midi_isopen()) + { + sys_close_midi(); + //midi_state = 0; + } +} + extern t_class *glob_pdobject; /* start an midi settings dialog window */ @@ -589,6 +688,19 @@ void glob_midi_properties(t_pd *dummy, t_floatarg flongform) midioutdev3 = (noutdev > 2 && midioutdev[2]>=0 ? midioutdev[2]+1 : 0); midioutdev4 = (noutdev > 3 && midioutdev[3]>=0 ? midioutdev[3]+1 : 0); +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + sprintf(buf, +"pdtk_alsa_midi_dialog %%s \ +%s %d %d %d %d %s %d %d %d %d \ +%d 1\n", + indevliststring, + midiindev1, midiindev2, midiindev3, midiindev4, + outdevliststring, + midioutdev1, midioutdev2, midioutdev3, midioutdev4, + (flongform != 0)); + else +#endif sprintf(buf, "pdtk_midi_dialog %%s \ %s %d %d %d %d %s %d %d %d %d \ @@ -598,6 +710,7 @@ void glob_midi_properties(t_pd *dummy, t_floatarg flongform) outdevliststring, midioutdev1, midioutdev2, midioutdev3, midioutdev4, (flongform != 0)); + gfxstub_deleteforkey(0); gfxstub_new(&glob_pdobject, (void *)glob_midi_properties, buf); } @@ -609,6 +722,7 @@ void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) int nmidioutdev, midioutdev[MAXMIDIOUTDEV]; int i, nindev, noutdev; int newmidiindev[4], newmidioutdev[4]; + int alsadevin, alsadevout; for (i = 0; i < 4; i++) { @@ -632,7 +746,20 @@ void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) noutdev++; } } + alsadevin = atom_getintarg(8, argc, argv); + alsadevout = atom_getintarg(9, argc, argv); + +#ifdef USEAPI_ALSA + if (sys_midiapi == API_ALSA) + { + sys_alsa_close_midi(); + sys_open_midi(alsadevin, newmidiindev, alsadevout, newmidioutdev, 1); + } + else +#endif + { + sys_close_midi(); + sys_open_midi(nindev, newmidiindev, noutdev, newmidioutdev, 1); + } - sys_close_midi(); - sys_open_midi(nindev, newmidiindev, noutdev, newmidioutdev, 1); } diff --git a/pd/src/s_midi_alsa.c b/pd/src/s_midi_alsa.c new file mode 100644 index 00000000..437ac792 --- /dev/null +++ b/pd/src/s_midi_alsa.c @@ -0,0 +1,233 @@ +/* Copyright (c) 1997-1999 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. */ + +/* MIDI I/O for Linux using ALSA */ + +#include +#ifdef UNISTD +#include +#endif +#include +#include +#include +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" + +static int alsa_nmidiin; +static int alsa_midiinfd[MAXMIDIINDEV]; +static int alsa_nmidiout; +static int alsa_midioutfd[MAXMIDIOUTDEV]; + +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) +{ + + char portname[50]; + int err = 0; + int client; + int i; + alsa_nmidiin = 0; + alsa_nmidiout = 0; + + if (nmidiin>0 && nmidiout>0) + err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_DUPLEX,0); + else if (nmidiin > 0) + err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0); + else if (nmidiout > 0) + err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_OUTPUT,0); + + if (err!=0) + { + sys_setalarm(1000000); + post("couldn't open alsa sequencer"); + return; + } + for (i=0;i= 0 && portno < alsa_nmidiout) + { + if (a >= 224) // pitchbend + { + channel = a-224; + snd_seq_ev_set_pitchbend(&ev,channel,CombineBytes(b,c)); + } + else if (a >= 208) // touch + { + channel = a-208; + snd_seq_ev_set_chanpress(&ev,channel,b); + } + else if (a >= 192) // program + { + channel = a-192; + snd_seq_ev_set_pgmchange(&ev,channel,b); + } + else if (a >= 176) // controller + { + channel = a-176; + snd_seq_ev_set_controller(&ev,channel,b,c); + } + else if (a >= 160) // polytouch + { + channel = a-160; + snd_seq_ev_set_keypress(&ev,channel,b,c); + } + else if (a >= 144) // note + { + channel = a-144; + if (c) + snd_seq_ev_set_noteon(&ev,channel,b,c); + else + snd_seq_ev_set_noteoff(&ev,channel,b,c); + } + snd_seq_ev_set_direct(&ev); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_source(&ev,alsa_midioutfd[portno]); + snd_seq_event_output_direct(midi_handle,&ev); + } + //post("%d %d %d\n",a,b,c); +} + +void sys_alsa_putmidibyte(int portno, int byte) +{ + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + if (portno >= 0 && portno < alsa_nmidiout) + { + // repack into 1 byte char and put somewhere to point at + unsigned char data = (unsigned char)byte; + unsigned char *dataptr = malloc(1); + memcpy(dataptr,&byte,1); + + snd_seq_ev_set_sysex(&ev,1,dataptr); //...set_variable *should* have worked but didn't + snd_seq_ev_set_direct(&ev); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_source(&ev,alsa_midioutfd[portno]); + snd_seq_event_output_direct(midi_handle,&ev); + } +} + + + /* this version uses the asynchronous "read()" ... */ +void sys_alsa_poll_midi(void) +{ + char buf[20]; + int count, alsa_source; + int i; + snd_seq_event_t *midievent = NULL; + + if (alsa_nmidiout == 0 && alsa_nmidiin == 0) return; + + snd_midi_event_init(midiev); + + if (!alsa_nmidiout && !alsa_nmidiin) return; + count = snd_seq_event_input_pending(midi_handle,1); + if (count != 0) + count = snd_seq_event_input(midi_handle,&midievent); + if (midievent != NULL) + { + count = snd_midi_event_decode(midiev,buf,20,midievent); + alsa_source = midievent->dest.port; + for(i=0;i maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + sprintf(indevlist + i * devdescsize, "ALSA MIDI device #%d", i+1); + *nindevs = ndev; + + if ((ndev = alsa_nmidioutdevs) > maxndev) + ndev = maxndev; + for (i = 0; i < ndev; i++) + sprintf(outdevlist + i * devdescsize, "ALSA MIDI device #%d", i+1); + *noutdevs = ndev; +} diff --git a/pd/src/s_stuff.h b/pd/src/s_stuff.h index b03ce4e6..4304f288 100644 --- a/pd/src/s_stuff.h +++ b/pd/src/s_stuff.h @@ -95,6 +95,8 @@ void sys_open_midi(int nmidiin, int *midiinvec, void sys_get_midi_params(int *pnmidiindev, int *pmidiindev, int *pnmidioutdev, int *pmidioutdev); +void sys_get_midi_apis(char *buf); + void sys_reopen_midi( void); void sys_close_midi( void); EXTERN void sys_putmidimess(int portno, int a, int b, int c); @@ -109,6 +111,22 @@ void midi_getdevs(char *indevlist, int *nindevs, void sys_do_open_midi(int nmidiindev, int *midiindev, int nmidioutdev, int *midioutdev); +#ifdef USEAPI_ALSA +EXTERN void sys_alsa_putmidimess(int portno, int a, int b, int c); +EXTERN void sys_alsa_putmidibyte(int portno, int a); +EXTERN void sys_alsa_poll_midi(void); +EXTERN void sys_alsa_setmiditimediff(double inbuftime, double outbuftime); +EXTERN void sys_alsa_midibytein(int portno, int byte); +EXTERN void sys_alsa_close_midi( void); + + + /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */ +void midi_alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize); +void sys_alsa_do_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev); +#endif + /* m_sched.c */ EXTERN void sys_log_error(int type); #define ERR_NOTHING 0 @@ -233,6 +251,7 @@ void mmio_getdevs(char *indevlist, int *nindevs, int maxndev, int devdescsize); 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 int sys_audioapi; diff --git a/pd/src/u_main.tk b/pd/src/u_main.tk index f6233efa..8da41f7a 100644 --- a/pd/src/u_main.tk +++ b/pd/src/u_main.tk @@ -44,6 +44,12 @@ if {$pd_nt == 1} { if {$pd_nt == 2} { # turn on James Tittle II's fast drawing (wait until I can test this...): # set tk::mac::useCGDrawing 1 + # set minimum line size for anti-aliasing. If set to 1 or 0, then every + # line will be anti-aliased. While this makes connections and circles in + # [bng] and such look really good, it makes boxes and messages look out of + # focus. Setting this to 2 makes it so the thick audio rate connections + # are anti-aliased. 2005-06-09 + set tk::mac::CGAntialiasLimit 2 global pd_guidir global pd_tearoff set pd_gui2 [string range $argv0 0 [expr [string last / $argv0 ] - 1]] @@ -338,10 +344,10 @@ proc menu_opentext {filename} { global doc_number global pd_guidir global pd_myversion - global pd_font3 +# global pd_font3 set name [format ".help%d" $doc_number] toplevel $name - text $name.text -relief raised -bd 2 -font $pd_font3 \ + text $name.text -relief raised -bd 2 -font -*-times-regular--normal--14-* \ -yscrollcommand "$name.scroll set" -background white scrollbar $name.scroll -command "$name.text yview" pack $name.scroll -side right -fill y @@ -451,7 +457,7 @@ proc doc_submenu {helpmenu subdir} { ############# routine to add media, help, and apple menu items ############### proc menu_addstd {mbar} { - global pd_apilist pd_nt pd_tearoff + global pd_apilist pd_midiapilist pd_nt pd_tearoff # the "Audio" menu $mbar.audio add command -label {audio ON} -accelerator [accel_munge "Ctrl+/"] \ -command {menu_audio 1} @@ -462,6 +468,12 @@ proc menu_addstd {mbar} { -command {menu_audio 0} -variable pd_whichapi \ -value [lindex [lindex $pd_apilist $x] 1]\ -command {pd [concat pd audio-setapi $pd_whichapi \;]} + } + for {set x 0} {$x<[llength $pd_midiapilist]} {incr x} { + $mbar.audio add radiobutton -label [lindex [lindex $pd_midiapilist $x] 0] \ + -command {menu_midi 0} -variable pd_whichmidiapi \ + -value [lindex [lindex $pd_midiapilist $x] 1]\ + -command {pd [concat pd midi-setapi $pd_whichmidiapi \;]} } if {$pd_nt != 2} { $mbar.audio add command -label {Audio settings...} \ @@ -3112,7 +3124,7 @@ proc pdtk_data_dialog {name stuff} { pack $name.buttonframe.ok -side left -expand 1 text $name.text -relief raised -bd 2 -height 40 -width 60 \ - -yscrollcommand "$name.scroll set" -font pd_font3 + -yscrollcommand "$name.scroll set" -font $pd_font3 scrollbar $name.scroll -command "$name.text yview" pack $name.scroll -side right -fill y pack $name.text -side left -fill both -expand 1 @@ -3182,20 +3194,21 @@ proc pdtk_pd_ctrlkey {name key shift} { # font sizes 8, 10, 12, 14, 16, and 24. # tb: user defined typefaces -proc pdtk_pd_startup {version apilist fontname} { +proc pdtk_pd_startup {version apilist midiapilist fontname} { # puts stderr [concat $version $apilist $fontname] - global pd_myversion pd_apilist + global pd_myversion pd_apilist pd_midiapilist set pd_myversion $version set pd_apilist $apilist - global pd_font1 pd_font2 pd_font3 pd_font4 pd_font5 pd_font6 pd_font7 + set pd_midiapilist $midiapilist + global pd_font1 pd_font2 pd_font3 pd_font4 pd_font5 pd_font6 pd_font7 - set pd_font1 [format -*-%s-bold--normal--8-* $fontname] - set pd_font2 [format -*-%s-bold--normal--10-* $fontname] - set pd_font3 [format -*-%s-bold--normal--12-* $fontname] - set pd_font4 [format -*-%s-bold--normal--14-* $fontname] - set pd_font5 [format -*-%s-bold--normal--16-* $fontname] - set pd_font6 [format -*-%s-bold--normal--24-* $fontname] - set pd_font7 [format -*-%s-bold--normal--36-* $fontname] + set pd_font1 [format -*-%s-bold--normal--8-* $fontname] + set pd_font2 [format -*-%s-bold--normal--10-* $fontname] + set pd_font3 [format -*-%s-bold--normal--12-* $fontname] + set pd_font4 [format -*-%s-bold--normal--14-* $fontname] + set pd_font5 [format -*-%s-bold--normal--16-* $fontname] + set pd_font6 [format -*-%s-bold--normal--24-* $fontname] + set pd_font7 [format -*-%s-bold--normal--36-* $fontname] set width1 [font measure $pd_font1 x] set height1 [lindex [font metrics $pd_font1] 5] @@ -3676,11 +3689,11 @@ proc pdtk_audio_dialog {id indevlist indev1 indev2 indev3 indev4 \ pdtk_standardkeybindings $id.out1f.x2 } -####################### midi dialog ##################3 +####################### midi dialog ################## proc midi_apply {id} { global midi_indev1 midi_indev2 midi_indev3 midi_indev4 - global midi_outdev1 midi_outdev2 midi_outdev3 midi_outdev4 + global midi_outdev1 midi_outdev2 midi_outdev3 midi_outdev4 midi_alsain midi_alsaout pd [concat pd midi-dialog \ $midi_indev1 \ @@ -3691,6 +3704,8 @@ proc midi_apply {id} { $midi_outdev2 \ $midi_outdev3 \ $midi_outdev4 \ + $midi_alsain \ + $midi_alsaout \ \;] } @@ -3727,12 +3742,12 @@ proc midi_popup {name buttonname varname devlist} { # start a dialog window to select midi devices. "longform" asks us to make # controls for opening several devices; if not, we get an extra button to # turn longform on and restart the dialog. - proc pdtk_midi_dialog {id indevlist indev1 indev2 indev3 indev4 \ outdevlist outdev1 outdev2 outdev3 outdev4 longform} { global midi_indev1 midi_indev2 midi_indev3 midi_indev4 global midi_outdev1 midi_outdev2 midi_outdev3 midi_outdev4 global midi_indevlist midi_outdevlist + global midi_alsain midi_alsaout set midi_indev1 $indev1 set midi_indev2 $indev2 @@ -3744,6 +3759,8 @@ proc pdtk_midi_dialog {id indevlist indev1 indev2 indev3 indev4 \ set midi_outdev4 $outdev4 set midi_indevlist $indevlist set midi_outdevlist $outdevlist + set midi_alsain [llength $indevlist] + set midi_alsaout [llength $outdevlist] toplevel $id wm title $id {midi} @@ -3857,6 +3874,148 @@ proc pdtk_midi_dialog {id indevlist indev1 indev2 indev3 indev4 \ } } +proc pdtk_alsa_midi_dialog {id indevlist indev1 indev2 indev3 indev4 \ + outdevlist outdev1 outdev2 outdev3 outdev4 longform alsa} { + global midi_indev1 midi_indev2 midi_indev3 midi_indev4 + global midi_outdev1 midi_outdev2 midi_outdev3 midi_outdev4 + global midi_indevlist midi_outdevlist + global midi_alsain midi_alsaout + + set midi_indev1 $indev1 + set midi_indev2 $indev2 + set midi_indev3 $indev3 + set midi_indev4 $indev4 + set midi_outdev1 $outdev1 + set midi_outdev2 $outdev2 + set midi_outdev3 $outdev3 + set midi_outdev4 $outdev4 + set midi_indevlist $indevlist + set midi_outdevlist $outdevlist + set midi_alsain [llength $indevlist] + set midi_alsaout [llength $outdevlist] + + toplevel $id + wm title $id {midi} + wm protocol $id WM_DELETE_WINDOW [concat midi_cancel $id] + + frame $id.buttonframe + pack $id.buttonframe -side bottom -fill x -pady 2m + button $id.buttonframe.cancel -text {Cancel}\ + -command "midi_cancel $id" + button $id.buttonframe.apply -text {Apply}\ + -command "midi_apply $id" + button $id.buttonframe.ok -text {OK}\ + -command "midi_ok $id" + pack $id.buttonframe.cancel -side left -expand 1 + pack $id.buttonframe.apply -side left -expand 1 + pack $id.buttonframe.ok -side left -expand 1 + + frame $id.in1f + pack $id.in1f -side top + + if {$alsa == 0} { + # input device 1 + label $id.in1f.l1 -text "input device 1:" + button $id.in1f.x1 -text [lindex $indevlist $midi_indev1] \ + -command [list midi_popup $id $id.in1f.x1 midi_indev1 $indevlist] + pack $id.in1f.l1 $id.in1f.x1 -side left + + # input device 2 + if {$longform && [llength $indevlist] > 2} { + frame $id.in2f + pack $id.in2f -side top + + label $id.in2f.l1 -text "input device 2:" + button $id.in2f.x1 -text [lindex $indevlist $midi_indev2] \ + -command [list midi_popup $id $id.in2f.x1 midi_indev2 $indevlist] + pack $id.in2f.l1 $id.in2f.x1 -side left + } + + # input device 3 + if {$longform && [llength $indevlist] > 3} { + frame $id.in3f + pack $id.in3f -side top + + label $id.in3f.l1 -text "input device 3:" + button $id.in3f.x1 -text [lindex $indevlist $midi_indev3] \ + -command [list midi_popup $id $id.in3f.x1 midi_indev3 $indevlist] + pack $id.in3f.l1 $id.in3f.x1 -side left + } + + # input device 4 + if {$longform && [llength $indevlist] > 4} { + frame $id.in4f + pack $id.in4f -side top + + label $id.in4f.l1 -text "input device 4:" + button $id.in4f.x1 -text [lindex $indevlist $midi_indev4] \ + -command [list midi_popup $id $id.in4f.x1 midi_indev4 $indevlist] + pack $id.in4f.l1 $id.in4f.x1 -side left + } + + # output device 1 + + frame $id.out1f + pack $id.out1f -side top + label $id.out1f.l1 -text "output device 1:" + button $id.out1f.x1 -text [lindex $outdevlist $midi_outdev1] \ + -command [list midi_popup $id $id.out1f.x1 midi_outdev1 $outdevlist] + pack $id.out1f.l1 $id.out1f.x1 -side left + + # output device 2 + if {$longform && [llength $indevlist] > 2} { + frame $id.out2f + pack $id.out2f -side top + label $id.out2f.l1 -text "output device 2:" + button $id.out2f.x1 -text [lindex $outdevlist $midi_outdev2] \ + -command \ + [list midi_popup $id $id.out2f.x1 midi_outdev2 $outdevlist] + pack $id.out2f.l1 $id.out2f.x1 -side left + } + + # output device 3 + if {$longform && [llength $indevlist] > 3} { + frame $id.out3f + pack $id.out3f -side top + label $id.out3f.l1 -text "output device 3:" + button $id.out3f.x1 -text [lindex $outdevlist $midi_outdev3] \ + -command \ + [list midi_popup $id $id.out3f.x1 midi_outdev3 $outdevlist] + pack $id.out3f.l1 $id.out3f.x1 -side left + } + + # output device 4 + if {$longform && [llength $indevlist] > 4} { + frame $id.out4f + pack $id.out4f -side top + label $id.out4f.l1 -text "output device 4:" + button $id.out4f.x1 -text [lindex $outdevlist $midi_outdev4] \ + -command \ + [list midi_popup $id $id.out4f.x1 midi_outdev4 $outdevlist] + pack $id.out4f.l1 $id.out4f.x1 -side left + } + + # if not the "long form" make a button to + # restart with longform set. + + if {$longform == 0} { + frame $id.longbutton + pack $id.longbutton -side top + button $id.longbutton.b -text {use multiple alsa devices} \ + -command {pd pd midi-properties 1 \;} + pack $id.longbutton.b + } + } + if {$alsa} { + label $id.in1f.l1 -text "In Channels:" + entry $id.in1f.x1 -textvariable midi_alsain -width 4 + pack $id.in1f.l1 $id.in1f.x1 -side left + label $id.in1f.l2 -text "Out Channels:" + entry $id.in1f.x2 -textvariable midi_alsaout -width 4 + pack $id.in1f.l2 $id.in1f.x2 -side left + } +} + ############ pdtk_path_dialog -- dialog window for search path ######### proc path_apply {id} { diff --git a/pd/src/u_pdsend.c b/pd/src/u_pdsend.c index 7b464cad..663889cc 100644 --- a/pd/src/u_pdsend.c +++ b/pd/src/u_pdsend.c @@ -105,7 +105,8 @@ connected: ; /* now loop reading stdin and sending it to socket */ while (1) { - char buf[BUFSIZE], *bp, nsent, nsend; + char buf[BUFSIZE], *bp; + int nsent, nsend; if (!fgets(buf, BUFSIZE, stdin)) break; nsend = strlen(buf); diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c index 3d62b319..ad6219cd 100644 --- a/pd/src/x_connective.c +++ b/pd/src/x_connective.c @@ -505,7 +505,11 @@ static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv) if (x->x_type == A_FLOAT) { float f; - if (!argc) return; + if (!argc) /* empty lists go out reject outlet */ + { + outlet_bang(x->x_rejectout); + return; + } f = atom_getfloat(argv); for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) if (e->e_w.w_float == f) @@ -580,7 +584,8 @@ static void *route_new(t_symbol *s, int argc, t_atom *argv) { int n; t_routeelement *e; - t_route *x = (t_route *)pd_new(route_class); + t_route *x; + t_atom a; if (argc == 0) { @@ -588,6 +593,13 @@ static void *route_new(t_symbol *s, int argc, t_atom *argv) SETFLOAT(&a, 0); argv = &a; } + for (n = 1; n < argc; n++) + if (argv[n].a_type != argv[0].a_type) + { + error("route: creation with mixed argument types failed"); + return (0); + } + x = (t_route *)pd_new(route_class); x->x_type = argv[0].a_type; x->x_nelement = argc; x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec)); -- cgit v1.2.1