From 513389b4c1bc8afe4b2dc9947c534bfeb105e3da Mon Sep 17 00:00:00 2001 From: Peter D'Hoye Date: Fri, 22 May 2009 21:58:48 +0000 Subject: Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin project of Wincent Balin. Stripped some non-sourcefiles and added a rockbox readme that needs a bit more info from Wincent. Is added to CATEGORIES and viewers, but not yet to SUBDIRS (ie doesn't build yet) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21044 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/pdbox/PDa/CHANGELOG.PDa | 118 + apps/plugins/pdbox/PDa/LICENSE.txt | 60 + apps/plugins/pdbox/PDa/README.PDa | 106 + apps/plugins/pdbox/PDa/README.txt | 88 + apps/plugins/pdbox/PDa/extra/OSC-client.h | 376 ++ apps/plugins/pdbox/PDa/extra/OSC.pd | 26 + apps/plugins/pdbox/PDa/extra/OSCroute.c | 1204 +++++ apps/plugins/pdbox/PDa/extra/README | 24 + apps/plugins/pdbox/PDa/extra/bandpass-help.pd | 34 + apps/plugins/pdbox/PDa/extra/bandpass.c | 172 + apps/plugins/pdbox/PDa/extra/dumpOSC.c | 1998 ++++++++ apps/plugins/pdbox/PDa/extra/equalizer.c | 178 + apps/plugins/pdbox/PDa/extra/fatom.h | 970 ++++ apps/plugins/pdbox/PDa/extra/filters.h | 148 + apps/plugins/pdbox/PDa/extra/g_canvas.h | 1204 +++++ apps/plugins/pdbox/PDa/extra/gcanvas-help.pd | 16 + apps/plugins/pdbox/PDa/extra/gcanvas.c | 758 +++ apps/plugins/pdbox/PDa/extra/highpass.c | 174 + apps/plugins/pdbox/PDa/extra/highshelf.c | 180 + apps/plugins/pdbox/PDa/extra/hlshelf.c | 452 ++ apps/plugins/pdbox/PDa/extra/image.c | 434 ++ apps/plugins/pdbox/PDa/extra/lowpass.c | 178 + apps/plugins/pdbox/PDa/extra/lowshelf.c | 182 + apps/plugins/pdbox/PDa/extra/m_pd.h | 1300 +++++ apps/plugins/pdbox/PDa/extra/makefile | 66 + apps/plugins/pdbox/PDa/extra/moog~.c | 366 ++ apps/plugins/pdbox/PDa/extra/notch.c | 178 + apps/plugins/pdbox/PDa/extra/s_stuff.h | 430 ++ apps/plugins/pdbox/PDa/extra/sendOSC.c | 2922 +++++++++++ apps/plugins/pdbox/PDa/extra/sformat.h | 110 + apps/plugins/pdbox/PDa/extra/shell.c | 624 +++ apps/plugins/pdbox/PDa/extra/slider.c | 106 + apps/plugins/pdbox/PDa/extra/sliderh.c | 126 + apps/plugins/pdbox/PDa/extra/test-clip.pd | 26 + apps/plugins/pdbox/PDa/extra/test-vcf.pd | 36 + apps/plugins/pdbox/PDa/extra/zerox~.c | 114 + apps/plugins/pdbox/PDa/intern/biquad~.c | 252 + apps/plugins/pdbox/PDa/intern/bp~.c | 276 + apps/plugins/pdbox/PDa/intern/clip~.c | 116 + apps/plugins/pdbox/PDa/intern/cos_table.h | 6 + apps/plugins/pdbox/PDa/intern/cos~.c | 122 + apps/plugins/pdbox/PDa/intern/dbtopow~.c | 104 + apps/plugins/pdbox/PDa/intern/dbtorms~.c | 106 + apps/plugins/pdbox/PDa/intern/delay.h | 84 + apps/plugins/pdbox/PDa/intern/delread~.c | 200 + apps/plugins/pdbox/PDa/intern/delwrite~.c | 168 + apps/plugins/pdbox/PDa/intern/env~.c | 254 + apps/plugins/pdbox/PDa/intern/ftom~.c | 88 + apps/plugins/pdbox/PDa/intern/hip~.c | 184 + apps/plugins/pdbox/PDa/intern/intern_setup.c | 94 + apps/plugins/pdbox/PDa/intern/line~.c | 202 + apps/plugins/pdbox/PDa/intern/lop~.c | 180 + apps/plugins/pdbox/PDa/intern/makefile | 48 + apps/plugins/pdbox/PDa/intern/mtof~.c | 98 + apps/plugins/pdbox/PDa/intern/noise~.c | 110 + apps/plugins/pdbox/PDa/intern/osc~.c | 174 + apps/plugins/pdbox/PDa/intern/phasor~.c | 138 + apps/plugins/pdbox/PDa/intern/powtodb~.c | 106 + apps/plugins/pdbox/PDa/intern/print~.c | 156 + apps/plugins/pdbox/PDa/intern/rmstodb~.c | 104 + apps/plugins/pdbox/PDa/intern/rsqrt~.c | 210 + apps/plugins/pdbox/PDa/intern/samphold~.c | 150 + apps/plugins/pdbox/PDa/intern/sformat.h | 110 + apps/plugins/pdbox/PDa/intern/sfread~.c | 576 +++ apps/plugins/pdbox/PDa/intern/sfwrite~.c | 480 ++ apps/plugins/pdbox/PDa/intern/sig~.c | 134 + apps/plugins/pdbox/PDa/intern/snapshot~.c | 114 + apps/plugins/pdbox/PDa/intern/sqrt~.c | 154 + apps/plugins/pdbox/PDa/intern/tabosc4~.c | 264 + apps/plugins/pdbox/PDa/intern/tabplay~.c | 264 + apps/plugins/pdbox/PDa/intern/tabread.c | 104 + apps/plugins/pdbox/PDa/intern/tabread4~.c | 210 + apps/plugins/pdbox/PDa/intern/tabread~.c | 194 + apps/plugins/pdbox/PDa/intern/tabreceive~.c | 122 + apps/plugins/pdbox/PDa/intern/tabsend~.c | 196 + apps/plugins/pdbox/PDa/intern/tabwrite.c | 168 + apps/plugins/pdbox/PDa/intern/tabwrite~.c | 264 + apps/plugins/pdbox/PDa/intern/threshold~.c | 270 + apps/plugins/pdbox/PDa/intern/vcf~.c | 238 + apps/plugins/pdbox/PDa/intern/vd~.c | 184 + apps/plugins/pdbox/PDa/intern/vline~.c | 368 ++ apps/plugins/pdbox/PDa/intern/vsnapshot~.c | 176 + apps/plugins/pdbox/PDa/intern/wrap~.c | 104 + apps/plugins/pdbox/PDa/src/build.ipod | 10 + apps/plugins/pdbox/PDa/src/d_arithmetic.c | 1684 +++++++ apps/plugins/pdbox/PDa/src/d_array.c | 2148 ++++++++ apps/plugins/pdbox/PDa/src/d_ctl.c | 1568 ++++++ apps/plugins/pdbox/PDa/src/d_dac.c | 368 ++ apps/plugins/pdbox/PDa/src/d_delay.c | 638 +++ apps/plugins/pdbox/PDa/src/d_fft.c | 688 +++ apps/plugins/pdbox/PDa/src/d_fftroutine.c | 2002 ++++++++ apps/plugins/pdbox/PDa/src/d_filter.c | 1094 ++++ apps/plugins/pdbox/PDa/src/d_global.c | 616 +++ apps/plugins/pdbox/PDa/src/d_imayer_fft.c | 1032 ++++ apps/plugins/pdbox/PDa/src/d_imayer_tables.h | 100 + apps/plugins/pdbox/PDa/src/d_math.c | 1146 +++++ apps/plugins/pdbox/PDa/src/d_mayer_fft.c | 838 +++ apps/plugins/pdbox/PDa/src/d_misc.c | 524 ++ apps/plugins/pdbox/PDa/src/d_osc.c | 1070 ++++ apps/plugins/pdbox/PDa/src/d_resample.c | 450 ++ apps/plugins/pdbox/PDa/src/d_soundfile.c | 4734 +++++++++++++++++ apps/plugins/pdbox/PDa/src/d_ugen.c | 2252 +++++++++ apps/plugins/pdbox/PDa/src/delme.pd | 16 + apps/plugins/pdbox/PDa/src/g_all_guis.c | 1324 +++++ apps/plugins/pdbox/PDa/src/g_all_guis.h | 658 +++ apps/plugins/pdbox/PDa/src/g_array.c | 2734 ++++++++++ apps/plugins/pdbox/PDa/src/g_bang.c | 1108 ++++ apps/plugins/pdbox/PDa/src/g_canvas.c | 2952 +++++++++++ apps/plugins/pdbox/PDa/src/g_canvas.h | 1204 +++++ apps/plugins/pdbox/PDa/src/g_editor.c | 4548 +++++++++++++++++ apps/plugins/pdbox/PDa/src/g_graph.c | 2224 ++++++++ apps/plugins/pdbox/PDa/src/g_guiconnect.c | 188 + apps/plugins/pdbox/PDa/src/g_hdial.c | 1470 ++++++ apps/plugins/pdbox/PDa/src/g_hslider.c | 1308 +++++ apps/plugins/pdbox/PDa/src/g_io.c | 1224 +++++ apps/plugins/pdbox/PDa/src/g_mycanvas.c | 770 +++ apps/plugins/pdbox/PDa/src/g_numbox.c | 1814 +++++++ apps/plugins/pdbox/PDa/src/g_readwrite.c | 1446 ++++++ apps/plugins/pdbox/PDa/src/g_rtext.c | 972 ++++ apps/plugins/pdbox/PDa/src/g_scalar.c | 802 +++ apps/plugins/pdbox/PDa/src/g_template.c | 3358 ++++++++++++ apps/plugins/pdbox/PDa/src/g_text.c | 2632 ++++++++++ apps/plugins/pdbox/PDa/src/g_toggle.c | 948 ++++ apps/plugins/pdbox/PDa/src/g_traversal.c | 2168 ++++++++ apps/plugins/pdbox/PDa/src/g_vdial.c | 1432 ++++++ apps/plugins/pdbox/PDa/src/g_vslider.c | 1254 +++++ apps/plugins/pdbox/PDa/src/g_vumeter.c | 1426 ++++++ apps/plugins/pdbox/PDa/src/m_atom.c | 258 + apps/plugins/pdbox/PDa/src/m_binbuf.c | 2438 +++++++++ apps/plugins/pdbox/PDa/src/m_class.c | 1648 ++++++ apps/plugins/pdbox/PDa/src/m_conf.c | 202 + apps/plugins/pdbox/PDa/src/m_fixed.c | 252 + apps/plugins/pdbox/PDa/src/m_fixed.h | 110 + apps/plugins/pdbox/PDa/src/m_glob.c | 210 + apps/plugins/pdbox/PDa/src/m_imp.h | 156 + apps/plugins/pdbox/PDa/src/m_memory.c | 178 + apps/plugins/pdbox/PDa/src/m_obj.c | 1394 +++++ apps/plugins/pdbox/PDa/src/m_pd.c | 612 +++ apps/plugins/pdbox/PDa/src/m_pd.h | 1300 +++++ apps/plugins/pdbox/PDa/src/m_sched.c | 1162 +++++ apps/plugins/pdbox/PDa/src/makecostab.c | 50 + apps/plugins/pdbox/PDa/src/makefile | 354 ++ apps/plugins/pdbox/PDa/src/s_audio.c | 1746 +++++++ apps/plugins/pdbox/PDa/src/s_audio_alsa.c | 1890 +++++++ apps/plugins/pdbox/PDa/src/s_audio_mmio.c | 1588 ++++++ apps/plugins/pdbox/PDa/src/s_audio_oss.c | 1688 +++++++ apps/plugins/pdbox/PDa/src/s_audio_pa.c | 584 +++ apps/plugins/pdbox/PDa/src/s_entry.c | 102 + apps/plugins/pdbox/PDa/src/s_file.c | 110 + apps/plugins/pdbox/PDa/src/s_inter.c | 2000 ++++++++ apps/plugins/pdbox/PDa/src/s_loader.c | 338 ++ apps/plugins/pdbox/PDa/src/s_main.c | 1676 ++++++ apps/plugins/pdbox/PDa/src/s_midi.c | 1282 +++++ apps/plugins/pdbox/PDa/src/s_midi_oss.c | 718 +++ apps/plugins/pdbox/PDa/src/s_midi_pm.c | 332 ++ apps/plugins/pdbox/PDa/src/s_midi_sgi.c | 376 ++ apps/plugins/pdbox/PDa/src/s_path.c | 820 +++ apps/plugins/pdbox/PDa/src/s_print.c | 300 ++ apps/plugins/pdbox/PDa/src/s_stuff.h | 430 ++ apps/plugins/pdbox/PDa/src/s_watchdog.c | 94 + apps/plugins/pdbox/PDa/src/t_main.c | 240 + apps/plugins/pdbox/PDa/src/t_tk.h | 20 + apps/plugins/pdbox/PDa/src/t_tkcmd.c | 796 +++ apps/plugins/pdbox/PDa/src/u_main.tk | 6734 +++++++++++++++++++++++++ apps/plugins/pdbox/PDa/src/u_pdreceive.c | 650 +++ apps/plugins/pdbox/PDa/src/u_pdsend.c | 314 ++ apps/plugins/pdbox/PDa/src/x_acoustics.c | 386 ++ apps/plugins/pdbox/PDa/src/x_arithmetic.c | 1792 +++++++ apps/plugins/pdbox/PDa/src/x_connective.c | 2904 +++++++++++ apps/plugins/pdbox/PDa/src/x_gui.c | 754 +++ apps/plugins/pdbox/PDa/src/x_interface.c | 156 + apps/plugins/pdbox/PDa/src/x_midi.c | 2626 ++++++++++ apps/plugins/pdbox/PDa/src/x_misc.c | 642 +++ apps/plugins/pdbox/PDa/src/x_net.c | 726 +++ apps/plugins/pdbox/PDa/src/x_qlist.c | 690 +++ apps/plugins/pdbox/PDa/src/x_time.c | 1040 ++++ 176 files changed, 133718 insertions(+) create mode 100644 apps/plugins/pdbox/PDa/CHANGELOG.PDa create mode 100644 apps/plugins/pdbox/PDa/LICENSE.txt create mode 100644 apps/plugins/pdbox/PDa/README.PDa create mode 100644 apps/plugins/pdbox/PDa/README.txt create mode 100644 apps/plugins/pdbox/PDa/extra/OSC-client.h create mode 100644 apps/plugins/pdbox/PDa/extra/OSC.pd create mode 100644 apps/plugins/pdbox/PDa/extra/OSCroute.c create mode 100644 apps/plugins/pdbox/PDa/extra/README create mode 100644 apps/plugins/pdbox/PDa/extra/bandpass-help.pd create mode 100644 apps/plugins/pdbox/PDa/extra/bandpass.c create mode 100644 apps/plugins/pdbox/PDa/extra/dumpOSC.c create mode 100644 apps/plugins/pdbox/PDa/extra/equalizer.c create mode 100644 apps/plugins/pdbox/PDa/extra/fatom.h create mode 100644 apps/plugins/pdbox/PDa/extra/filters.h create mode 100644 apps/plugins/pdbox/PDa/extra/g_canvas.h create mode 100644 apps/plugins/pdbox/PDa/extra/gcanvas-help.pd create mode 100644 apps/plugins/pdbox/PDa/extra/gcanvas.c create mode 100644 apps/plugins/pdbox/PDa/extra/highpass.c create mode 100644 apps/plugins/pdbox/PDa/extra/highshelf.c create mode 100644 apps/plugins/pdbox/PDa/extra/hlshelf.c create mode 100644 apps/plugins/pdbox/PDa/extra/image.c create mode 100644 apps/plugins/pdbox/PDa/extra/lowpass.c create mode 100644 apps/plugins/pdbox/PDa/extra/lowshelf.c create mode 100644 apps/plugins/pdbox/PDa/extra/m_pd.h create mode 100644 apps/plugins/pdbox/PDa/extra/makefile create mode 100644 apps/plugins/pdbox/PDa/extra/moog~.c create mode 100644 apps/plugins/pdbox/PDa/extra/notch.c create mode 100644 apps/plugins/pdbox/PDa/extra/s_stuff.h create mode 100644 apps/plugins/pdbox/PDa/extra/sendOSC.c create mode 100644 apps/plugins/pdbox/PDa/extra/sformat.h create mode 100644 apps/plugins/pdbox/PDa/extra/shell.c create mode 100644 apps/plugins/pdbox/PDa/extra/slider.c create mode 100644 apps/plugins/pdbox/PDa/extra/sliderh.c create mode 100644 apps/plugins/pdbox/PDa/extra/test-clip.pd create mode 100644 apps/plugins/pdbox/PDa/extra/test-vcf.pd create mode 100644 apps/plugins/pdbox/PDa/extra/zerox~.c create mode 100644 apps/plugins/pdbox/PDa/intern/biquad~.c create mode 100644 apps/plugins/pdbox/PDa/intern/bp~.c create mode 100644 apps/plugins/pdbox/PDa/intern/clip~.c create mode 100644 apps/plugins/pdbox/PDa/intern/cos_table.h create mode 100644 apps/plugins/pdbox/PDa/intern/cos~.c create mode 100644 apps/plugins/pdbox/PDa/intern/dbtopow~.c create mode 100644 apps/plugins/pdbox/PDa/intern/dbtorms~.c create mode 100644 apps/plugins/pdbox/PDa/intern/delay.h create mode 100644 apps/plugins/pdbox/PDa/intern/delread~.c create mode 100644 apps/plugins/pdbox/PDa/intern/delwrite~.c create mode 100644 apps/plugins/pdbox/PDa/intern/env~.c create mode 100644 apps/plugins/pdbox/PDa/intern/ftom~.c create mode 100644 apps/plugins/pdbox/PDa/intern/hip~.c create mode 100644 apps/plugins/pdbox/PDa/intern/intern_setup.c create mode 100644 apps/plugins/pdbox/PDa/intern/line~.c create mode 100644 apps/plugins/pdbox/PDa/intern/lop~.c create mode 100644 apps/plugins/pdbox/PDa/intern/makefile create mode 100644 apps/plugins/pdbox/PDa/intern/mtof~.c create mode 100644 apps/plugins/pdbox/PDa/intern/noise~.c create mode 100644 apps/plugins/pdbox/PDa/intern/osc~.c create mode 100644 apps/plugins/pdbox/PDa/intern/phasor~.c create mode 100644 apps/plugins/pdbox/PDa/intern/powtodb~.c create mode 100644 apps/plugins/pdbox/PDa/intern/print~.c create mode 100644 apps/plugins/pdbox/PDa/intern/rmstodb~.c create mode 100644 apps/plugins/pdbox/PDa/intern/rsqrt~.c create mode 100644 apps/plugins/pdbox/PDa/intern/samphold~.c create mode 100644 apps/plugins/pdbox/PDa/intern/sformat.h create mode 100644 apps/plugins/pdbox/PDa/intern/sfread~.c create mode 100644 apps/plugins/pdbox/PDa/intern/sfwrite~.c create mode 100644 apps/plugins/pdbox/PDa/intern/sig~.c create mode 100644 apps/plugins/pdbox/PDa/intern/snapshot~.c create mode 100644 apps/plugins/pdbox/PDa/intern/sqrt~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabosc4~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabplay~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabread.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabread4~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabread~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabreceive~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabsend~.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabwrite.c create mode 100644 apps/plugins/pdbox/PDa/intern/tabwrite~.c create mode 100644 apps/plugins/pdbox/PDa/intern/threshold~.c create mode 100644 apps/plugins/pdbox/PDa/intern/vcf~.c create mode 100644 apps/plugins/pdbox/PDa/intern/vd~.c create mode 100644 apps/plugins/pdbox/PDa/intern/vline~.c create mode 100644 apps/plugins/pdbox/PDa/intern/vsnapshot~.c create mode 100644 apps/plugins/pdbox/PDa/intern/wrap~.c create mode 100644 apps/plugins/pdbox/PDa/src/build.ipod create mode 100644 apps/plugins/pdbox/PDa/src/d_arithmetic.c create mode 100644 apps/plugins/pdbox/PDa/src/d_array.c create mode 100644 apps/plugins/pdbox/PDa/src/d_ctl.c create mode 100644 apps/plugins/pdbox/PDa/src/d_dac.c create mode 100644 apps/plugins/pdbox/PDa/src/d_delay.c create mode 100644 apps/plugins/pdbox/PDa/src/d_fft.c create mode 100644 apps/plugins/pdbox/PDa/src/d_fftroutine.c create mode 100644 apps/plugins/pdbox/PDa/src/d_filter.c create mode 100644 apps/plugins/pdbox/PDa/src/d_global.c create mode 100644 apps/plugins/pdbox/PDa/src/d_imayer_fft.c create mode 100644 apps/plugins/pdbox/PDa/src/d_imayer_tables.h create mode 100644 apps/plugins/pdbox/PDa/src/d_math.c create mode 100644 apps/plugins/pdbox/PDa/src/d_mayer_fft.c create mode 100644 apps/plugins/pdbox/PDa/src/d_misc.c create mode 100644 apps/plugins/pdbox/PDa/src/d_osc.c create mode 100644 apps/plugins/pdbox/PDa/src/d_resample.c create mode 100644 apps/plugins/pdbox/PDa/src/d_soundfile.c create mode 100644 apps/plugins/pdbox/PDa/src/d_ugen.c create mode 100644 apps/plugins/pdbox/PDa/src/delme.pd create mode 100644 apps/plugins/pdbox/PDa/src/g_all_guis.c create mode 100644 apps/plugins/pdbox/PDa/src/g_all_guis.h create mode 100644 apps/plugins/pdbox/PDa/src/g_array.c create mode 100644 apps/plugins/pdbox/PDa/src/g_bang.c create mode 100644 apps/plugins/pdbox/PDa/src/g_canvas.c create mode 100644 apps/plugins/pdbox/PDa/src/g_canvas.h create mode 100644 apps/plugins/pdbox/PDa/src/g_editor.c create mode 100644 apps/plugins/pdbox/PDa/src/g_graph.c create mode 100644 apps/plugins/pdbox/PDa/src/g_guiconnect.c create mode 100644 apps/plugins/pdbox/PDa/src/g_hdial.c create mode 100644 apps/plugins/pdbox/PDa/src/g_hslider.c create mode 100644 apps/plugins/pdbox/PDa/src/g_io.c create mode 100644 apps/plugins/pdbox/PDa/src/g_mycanvas.c create mode 100644 apps/plugins/pdbox/PDa/src/g_numbox.c create mode 100644 apps/plugins/pdbox/PDa/src/g_readwrite.c create mode 100644 apps/plugins/pdbox/PDa/src/g_rtext.c create mode 100644 apps/plugins/pdbox/PDa/src/g_scalar.c create mode 100644 apps/plugins/pdbox/PDa/src/g_template.c create mode 100644 apps/plugins/pdbox/PDa/src/g_text.c create mode 100644 apps/plugins/pdbox/PDa/src/g_toggle.c create mode 100644 apps/plugins/pdbox/PDa/src/g_traversal.c create mode 100644 apps/plugins/pdbox/PDa/src/g_vdial.c create mode 100644 apps/plugins/pdbox/PDa/src/g_vslider.c create mode 100644 apps/plugins/pdbox/PDa/src/g_vumeter.c create mode 100644 apps/plugins/pdbox/PDa/src/m_atom.c create mode 100644 apps/plugins/pdbox/PDa/src/m_binbuf.c create mode 100644 apps/plugins/pdbox/PDa/src/m_class.c create mode 100644 apps/plugins/pdbox/PDa/src/m_conf.c create mode 100644 apps/plugins/pdbox/PDa/src/m_fixed.c create mode 100644 apps/plugins/pdbox/PDa/src/m_fixed.h create mode 100644 apps/plugins/pdbox/PDa/src/m_glob.c create mode 100644 apps/plugins/pdbox/PDa/src/m_imp.h create mode 100644 apps/plugins/pdbox/PDa/src/m_memory.c create mode 100644 apps/plugins/pdbox/PDa/src/m_obj.c create mode 100644 apps/plugins/pdbox/PDa/src/m_pd.c create mode 100644 apps/plugins/pdbox/PDa/src/m_pd.h create mode 100644 apps/plugins/pdbox/PDa/src/m_sched.c create mode 100644 apps/plugins/pdbox/PDa/src/makecostab.c create mode 100644 apps/plugins/pdbox/PDa/src/makefile create mode 100644 apps/plugins/pdbox/PDa/src/s_audio.c create mode 100644 apps/plugins/pdbox/PDa/src/s_audio_alsa.c create mode 100644 apps/plugins/pdbox/PDa/src/s_audio_mmio.c create mode 100644 apps/plugins/pdbox/PDa/src/s_audio_oss.c create mode 100644 apps/plugins/pdbox/PDa/src/s_audio_pa.c create mode 100644 apps/plugins/pdbox/PDa/src/s_entry.c create mode 100644 apps/plugins/pdbox/PDa/src/s_file.c create mode 100644 apps/plugins/pdbox/PDa/src/s_inter.c create mode 100644 apps/plugins/pdbox/PDa/src/s_loader.c create mode 100644 apps/plugins/pdbox/PDa/src/s_main.c create mode 100644 apps/plugins/pdbox/PDa/src/s_midi.c create mode 100644 apps/plugins/pdbox/PDa/src/s_midi_oss.c create mode 100644 apps/plugins/pdbox/PDa/src/s_midi_pm.c create mode 100644 apps/plugins/pdbox/PDa/src/s_midi_sgi.c create mode 100644 apps/plugins/pdbox/PDa/src/s_path.c create mode 100644 apps/plugins/pdbox/PDa/src/s_print.c create mode 100644 apps/plugins/pdbox/PDa/src/s_stuff.h create mode 100644 apps/plugins/pdbox/PDa/src/s_watchdog.c create mode 100644 apps/plugins/pdbox/PDa/src/t_main.c create mode 100644 apps/plugins/pdbox/PDa/src/t_tk.h create mode 100644 apps/plugins/pdbox/PDa/src/t_tkcmd.c create mode 100644 apps/plugins/pdbox/PDa/src/u_main.tk create mode 100644 apps/plugins/pdbox/PDa/src/u_pdreceive.c create mode 100644 apps/plugins/pdbox/PDa/src/u_pdsend.c create mode 100644 apps/plugins/pdbox/PDa/src/x_acoustics.c create mode 100644 apps/plugins/pdbox/PDa/src/x_arithmetic.c create mode 100644 apps/plugins/pdbox/PDa/src/x_connective.c create mode 100644 apps/plugins/pdbox/PDa/src/x_gui.c create mode 100644 apps/plugins/pdbox/PDa/src/x_interface.c create mode 100644 apps/plugins/pdbox/PDa/src/x_midi.c create mode 100644 apps/plugins/pdbox/PDa/src/x_misc.c create mode 100644 apps/plugins/pdbox/PDa/src/x_net.c create mode 100644 apps/plugins/pdbox/PDa/src/x_qlist.c create mode 100644 apps/plugins/pdbox/PDa/src/x_time.c (limited to 'apps/plugins/pdbox/PDa') diff --git a/apps/plugins/pdbox/PDa/CHANGELOG.PDa b/apps/plugins/pdbox/PDa/CHANGELOG.PDa new file mode 100644 index 0000000000..f8afc2bd89 --- /dev/null +++ b/apps/plugins/pdbox/PDa/CHANGELOG.PDa @@ -0,0 +1,118 @@ +0.6: + - added compilation for blackfin architecture (blackfin.uclinux.org) + - added third outlet for mouseup to gcanvas. + - debian package support (for maemo) + - don't ask quit question + +0.5: + - fixed a crasher bug in sfread~.c + +0.4: + - added ipod gui communication in m_pd.c (pd_bind) and m_fixed.c + - moved the pd internal objects in a folder called interns + - restructuring of the makefile, you can build a static binary + now with "make static", needed for the iPod part mainly. + - the oscillator tables are precalculated now (faster startup). + see src/makecostable.c for that + - the scheduler is simplified (added an additional scheduler called + m_scheduler_pda(), this is a lot faster now + - changed the "look" of PDa + - The menubar in the patcher window is now optional, its off by default. + - stdin interface added. It is now possible to communicate with pd via the + keyboard even in -nogui mode + - fixed loading and saving of arrays (g_array.c) + - corrected rounding when calculation phase update osc~ and phasor~ + (there are better methods to do this, but they are slower) + - fixed tabosc4~ + - enabled array drawing + - fixed array saving in subpatch + + +0.3test2: + - added the O_CREAT flag to sfwrite + - removed the OSC stuff (now in PDa-externals) + +0.3test1: + - moved all objects into the extra dir + + + d_arithmetic: t_float -> t_sample .. exchanged * with mult / with divide + d_fft: t_float -> t_sample + d_global: t_float -> t_sample + d_misc: put print~ into extra folder + d_resample: t_float -> t_sample + g_array: disable editing + fixtof() + t_float -> t_sample (check out the savefn thingy) + + g_graph: 1 t_float -> t_sample + g_io: t_float -> t_sample + m_conf: remove calls to setup routines + m_obj.c ftofix + m_pd.h definition of t_sample + double -> t_time + ... and more + m_sched.c + double t_time + s_inter: check !!! + s_main: check !!! + +0.6: + - added compilation for blackfin architecture (blackfin.uclinux.org) + - added third outlet for mouseup to gcanvas. + - debian package support (for maemo) + - don't ask quit question + +0.5: + - fixed a crasher bug in sfread~.c + +0.4: + - added ipod gui communication in m_pd.c (pd_bind) and m_fixed.c + - moved the pd internal objects in a folder called interns + - restructuring of the makefile, you can build a static binary + now with "make static", needed for the iPod part mainly. + - the oscillator tables are precalculated now (faster startup). + see src/makecostable.c for that + - the scheduler is simplified (added an additional scheduler called + m_scheduler_pda(), this is a lot faster now + - changed the "look" of PDa + - The menubar in the patcher window is now optional, its off by default. + - stdin interface added. It is now possible to communicate with pd via the + keyboard even in -nogui mode + - fixed loading and saving of arrays (g_array.c) + - corrected rounding when calculation phase update osc~ and phasor~ + (there are better methods to do this, but they are slower) + - fixed tabosc4~ + - enabled array drawing + - fixed array saving in subpatch + + +0.3test2: + - added the O_CREAT flag to sfwrite + - removed the OSC stuff (now in PDa-externals) + +0.3test1: + - moved all objects into the extra dir + + + d_arithmetic: t_float -> t_sample .. exchanged * with mult / with divide + d_fft: t_float -> t_sample + d_global: t_float -> t_sample + d_misc: put print~ into extra folder + d_resample: t_float -> t_sample + g_array: disable editing + fixtof() + t_float -> t_sample (check out the savefn thingy) + + g_graph: 1 t_float -> t_sample + g_io: t_float -> t_sample + m_conf: remove calls to setup routines + m_obj.c ftofix + m_pd.h definition of t_sample + double -> t_time + ... and more + m_sched.c + double t_time + s_inter: check !!! + s_main: check !!! + diff --git a/apps/plugins/pdbox/PDa/LICENSE.txt b/apps/plugins/pdbox/PDa/LICENSE.txt new file mode 100644 index 0000000000..3e104c77a2 --- /dev/null +++ b/apps/plugins/pdbox/PDa/LICENSE.txt @@ -0,0 +1,60 @@ +This software is copyrighted by Miller Puckette and others. The following +terms (the "Standard Improved BSD License") apply to all files associated with +the software unless explicitly disclaimed in individual files: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. +This software is copyrighted by Miller Puckette and others. The following +terms (the "Standard Improved BSD License") apply to all files associated with +the software unless explicitly disclaimed in individual files: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/apps/plugins/pdbox/PDa/README.PDa b/apps/plugins/pdbox/PDa/README.PDa new file mode 100644 index 0000000000..7c567d70c2 --- /dev/null +++ b/apps/plugins/pdbox/PDa/README.PDa @@ -0,0 +1,106 @@ +PDa - Pure Data for Personal Digital Assistants +=============================================== + +Based on pd-0.37-4. + +This version of Pure Data is based on the original sources by +Miller Puckette, but several part have been changed in order +to run on embedded systems. Most of the changed objects are in +the folder "intern". + +This means, that all the signal processing is done with fixed-point +math. The control processing is still in floating point, therefor this +might be a bit slow. + +The package is compilable under Linux. I would be glad if someone would +make a version for windows or OSX, but I unfortunately don't have the +time or resource to do so. + +In order to compile: +cd src/ +make + +The default compilation flags are very conservative, you can add +optimization flags through the CFLAGS variable. +e.g + +make CFLAGS="-O6" + +Will turn on maximum optimization (almost). + +If you have tcl/tk installed in the right place this should work out, +if you have problems with that, either adapt the makefile or ask me. +On Debian you just have to install tk8.4-dev to get it going. + +Have fun ! + +Guenter + + +Additional information: +--------------------------- + +Instructions for compiling for iPods, using arm-elf-tools-20030314: + +cd src +./build.ipod + +The tcl/tk interface will not be built for iPods, you can interface with +Pd from the podzilla console or with this GUI for PDa on iPod: + +http://ipodlinux.org/Pdpod + + +PDa - Pure Data for Personal Digital Assistants +=============================================== + +Based on pd-0.37-4. + +This version of Pure Data is based on the original sources by +Miller Puckette, but several part have been changed in order +to run on embedded systems. Most of the changed objects are in +the folder "intern". + +This means, that all the signal processing is done with fixed-point +math. The control processing is still in floating point, therefor this +might be a bit slow. + +The package is compilable under Linux. I would be glad if someone would +make a version for windows or OSX, but I unfortunately don't have the +time or resource to do so. + +In order to compile: +cd src/ +make + +The default compilation flags are very conservative, you can add +optimization flags through the CFLAGS variable. +e.g + +make CFLAGS="-O6" + +Will turn on maximum optimization (almost). + +If you have tcl/tk installed in the right place this should work out, +if you have problems with that, either adapt the makefile or ask me. +On Debian you just have to install tk8.4-dev to get it going. + +Have fun ! + +Guenter + + +Additional information: +--------------------------- + +Instructions for compiling for iPods, using arm-elf-tools-20030314: + +cd src +./build.ipod + +The tcl/tk interface will not be built for iPods, you can interface with +Pd from the podzilla console or with this GUI for PDa on iPod: + +http://ipodlinux.org/Pdpod + + diff --git a/apps/plugins/pdbox/PDa/README.txt b/apps/plugins/pdbox/PDa/README.txt new file mode 100644 index 0000000000..856ccaad62 --- /dev/null +++ b/apps/plugins/pdbox/PDa/README.txt @@ -0,0 +1,88 @@ +This is the README file for Pd, a free real-time computer music software +package resembling Max. You can get Pd for Linux, Windows, Mac OSX, or IRIX +from http://www.crca.ucsd.edu/~msp/software.html or ftp://felix.ucsd.edu. +Installation instructions are in the HTML DOCUMENTATION at: + + http://www.crca.ucsd.edu/~msp/Pd_documentation/index.htm + +If you download and unpack Pd, you will also find the html documentation +locally in the file, .../pd-whatever/doc/1.manual/index.htm. To unpack Pd: + +LINUX (or freeBSD). Download Pd, which will be a ".tar.gz" file; to unpack it, +type "zcat [name].tar.gz | tar xf -" to a shell. This creates a directory with +a name like "pd-0.35". There are also RPMs available. + +Microsoft Windows. Pd is distributed as a "zip" file. Unzip this, +creating a directory such as \pd. + +IRIX. Download Pd, which will be a "tar.Z" file. You can unpack this by +typing "zcat [name].tar.Z | tar xf -" to a shell. + +Macintosh. The web browser will automatically unpack the distributions +into a folder such as "pd-0.35" on your desktop. + +If you have qustions about Pd, or if you wish to be notified of releases, +check the Pd mailing list: http://iem.mhsg.ac.at/mailinglists/pd-list/ + +Many extensions to Pd are available, notably for handling video and 3D +graphics; see the html documentation for pointers. + +COPYRIGHT. Except as otherwise noted, all files in the Pd distribution are + + Copyright (c) 1997-2001 Miller Puckette and others. + +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "LICENSE.txt," included in the Pd distribution. +(Note that tcl/tk, expr, and some other files are copyrighted separately). + +ACKNOWLEDGEMENTS. Thanks to Harry Castle, Krzysztof Czaja, Mark Danks, +Christian Feldbauer, Guenter Geiger, Kerry Hagan, Trevor Johnson, Fernando +Lopez-Lezcano, Adam Lindsay, Karl MacMillan, Thomas Musil, Toshinori Ohkouchi, +Winfried Ritsch, Vibeke Sorensen, Rand Steiger, Shahrokh Yadegari, David +Zicarelli, Iohannes Zmoelnig, and probably many others for contributions of +code, documentation, ideas, and expertise. This work has received generous +support from the Intel Research Council. +This is the README file for Pd, a free real-time computer music software +package resembling Max. You can get Pd for Linux, Windows, Mac OSX, or IRIX +from http://www.crca.ucsd.edu/~msp/software.html or ftp://felix.ucsd.edu. +Installation instructions are in the HTML DOCUMENTATION at: + + http://www.crca.ucsd.edu/~msp/Pd_documentation/index.htm + +If you download and unpack Pd, you will also find the html documentation +locally in the file, .../pd-whatever/doc/1.manual/index.htm. To unpack Pd: + +LINUX (or freeBSD). Download Pd, which will be a ".tar.gz" file; to unpack it, +type "zcat [name].tar.gz | tar xf -" to a shell. This creates a directory with +a name like "pd-0.35". There are also RPMs available. + +Microsoft Windows. Pd is distributed as a "zip" file. Unzip this, +creating a directory such as \pd. + +IRIX. Download Pd, which will be a "tar.Z" file. You can unpack this by +typing "zcat [name].tar.Z | tar xf -" to a shell. + +Macintosh. The web browser will automatically unpack the distributions +into a folder such as "pd-0.35" on your desktop. + +If you have qustions about Pd, or if you wish to be notified of releases, +check the Pd mailing list: http://iem.mhsg.ac.at/mailinglists/pd-list/ + +Many extensions to Pd are available, notably for handling video and 3D +graphics; see the html documentation for pointers. + +COPYRIGHT. Except as otherwise noted, all files in the Pd distribution are + + Copyright (c) 1997-2001 Miller Puckette and others. + +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "LICENSE.txt," included in the Pd distribution. +(Note that tcl/tk, expr, and some other files are copyrighted separately). + +ACKNOWLEDGEMENTS. Thanks to Harry Castle, Krzysztof Czaja, Mark Danks, +Christian Feldbauer, Guenter Geiger, Kerry Hagan, Trevor Johnson, Fernando +Lopez-Lezcano, Adam Lindsay, Karl MacMillan, Thomas Musil, Toshinori Ohkouchi, +Winfried Ritsch, Vibeke Sorensen, Rand Steiger, Shahrokh Yadegari, David +Zicarelli, Iohannes Zmoelnig, and probably many others for contributions of +code, documentation, ideas, and expertise. This work has received generous +support from the Intel Research Council. diff --git a/apps/plugins/pdbox/PDa/extra/OSC-client.h b/apps/plugins/pdbox/PDa/extra/OSC-client.h new file mode 100644 index 0000000000..196143f8e7 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/OSC-client.h @@ -0,0 +1,376 @@ +/* +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +/* + + OSC-client.h: library for constructing OpenSoundControl messages. + Derived from SynthControl.h + Author: Matt Wright + Version 0.1: 6/13/97 + Version 0.2: 7/21/2000: Support for type-tagged messages + + + General notes: + + This library abstracts away the data format for the OpenSoundControl + protocol. Users of this library can construct OpenSoundControl packets + with a function call interface instead of knowing how to lay out the bits. + + All issues of memory allocation are deferred to the user of this library. + There are two data structures that the user must allocate. The first + is the actual buffer that the message will be written into. This buffer + can be any size, but if it's too small there's a possibility that it + will become overfull. The other data structure is called an OSCbuf, + and it holds all the state used by the library as it's constructing + a buffer. + + All procedures that have the possibility of an error condition return int, + with 0 indicating no error and nonzero indicating an error. The variable + OSC_errorMessage will be set to point to a string containing an error + message explaining what the problem is. + +*/ + + + +/* The int4byte type has to be a 4-byte integer. You may have to + change this to long or something else on your system. */ +#ifdef __MWERKS__ + /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is + always 4 bytes */ + typedef long int4byte; +#else + typedef int int4byte; +#endif + +/* OSC_timetag.h */ + + typedef struct { + int seconds; + int fraction; + } OSCTimeTag; + +OSCTimeTag OSCTT_Immediately(void); +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset); +OSCTimeTag OSCTT_CurrentTime(void); + + + +/* The maximum depth of bundles within bundles within bundles within... + This is the size of a static array. If you exceed this limit you'll + get an error message. */ +#define MAX_BUNDLE_NESTING 32 + + +/* Don't ever manipulate the data in the OSCbuf struct directly. (It's + declared here in the header file only so your program will be able to + declare variables of type OSCbuf and have the right amount of memory + be allocated.) */ + +typedef struct OSCbuf_struct { + char *buffer; /* The buffer to hold the OSC packet */ + int size; /* Size of the buffer */ + char *bufptr; /* Current position as we fill the buffer */ + int state; /* State of partially-constructed message */ + int4byte *thisMsgSize; /* Pointer to count field before + currently-being-written message */ + int4byte *prevCounts[MAX_BUNDLE_NESTING]; + /* Pointers to count field before each currently + open bundle */ + int bundleDepth; /* How many sub-sub-bundles are we in now? */ + char *typeStringPtr; /* This pointer advances through the type + tag string as you add arguments. */ + int gettingFirstUntypedArg; /* nonzero if this message doesn't have + a type tag and we're waiting for the 1st arg */ +} OSCbuf; + + + +/* Initialize the given OSCbuf. The user of this module must pass in the + block of memory that this OSCbuf will use for a buffer, and the number of + bytes in that block. (It's the user's job to allocate the memory because + you do it differently in different systems.) */ +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray); + + +/* Reset the given OSCbuf. Do this after you send out the contents of + the buffer and want to start writing new data into it. */ +void OSC_resetBuffer(OSCbuf *buf); + + +/* Is the buffer empty? (I.e., would it be stupid to send the buffer + contents to the synth?) */ +int OSC_isBufferEmpty(OSCbuf *buf); + + +/* How much space is left in the buffer? */ +int OSC_freeSpaceInBuffer(OSCbuf *buf); + +/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */ +int OSC_isBufferDone(OSCbuf *buf); + +/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone() + returns true), call these two procedures to get the OSC packet that's been + assembled and its size in bytes. (And then call OSC_resetBuffer() if you + want to re-use this OSCbuf for the next packet.) */ +char *OSC_getPacket(OSCbuf *buf); +int OSC_packetSize(OSCbuf *buf); + + + +/* Here's the basic model for building up OSC messages in an OSCbuf: + + - Make sure the OSCbuf has been initialized with OSC_initBuffer(). + + - To open a bundle, call OSC_openBundle(). You can then write + messages or open new bundles within the bundle you opened. + Call OSC_closeBundle() to close the bundle. Note that a packet + does not have to have a bundle; it can instead consist of just a + single message. + + + - For each message you want to send: + + - Call OSC_writeAddress() with the name of your message. (In + addition to writing your message name into the buffer, this + procedure will also leave space for the size count of this message.) + + - Alternately, call OSC_writeAddressAndTypes() with the name of + your message and with a type string listing the types of all the + arguments you will be putting in this message. + + - Now write each of the arguments into the buffer, by calling one of: + OSC_writeFloatArg() + OSC_writeFloatArgs() + OSC_writeIntArg() + OSC_writeStringArg() + + - Now your message is complete; you can send out the buffer or you can + add another message to it. +*/ + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt); +int OSC_closeBundle(OSCbuf *buf); +int OSC_closeAllBundles(OSCbuf *buf); + +int OSC_writeAddress(OSCbuf *buf, char *name); +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types); +int OSC_writeFloatArg(OSCbuf *buf, float arg); +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args); +int OSC_writeIntArg(OSCbuf *buf, int4byte arg); +int OSC_writeStringArg(OSCbuf *buf, char *arg); + +extern char *OSC_errorMessage; + +/* How many bytes will be needed in the OSC format to hold the given + string? The length of the string, plus the null char, plus any padding + needed for 4-byte alignment. */ +int OSC_effectiveStringLength(char *string); +/* +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +/* + + OSC-client.h: library for constructing OpenSoundControl messages. + Derived from SynthControl.h + Author: Matt Wright + Version 0.1: 6/13/97 + Version 0.2: 7/21/2000: Support for type-tagged messages + + + General notes: + + This library abstracts away the data format for the OpenSoundControl + protocol. Users of this library can construct OpenSoundControl packets + with a function call interface instead of knowing how to lay out the bits. + + All issues of memory allocation are deferred to the user of this library. + There are two data structures that the user must allocate. The first + is the actual buffer that the message will be written into. This buffer + can be any size, but if it's too small there's a possibility that it + will become overfull. The other data structure is called an OSCbuf, + and it holds all the state used by the library as it's constructing + a buffer. + + All procedures that have the possibility of an error condition return int, + with 0 indicating no error and nonzero indicating an error. The variable + OSC_errorMessage will be set to point to a string containing an error + message explaining what the problem is. + +*/ + + + +/* The int4byte type has to be a 4-byte integer. You may have to + change this to long or something else on your system. */ +#ifdef __MWERKS__ + /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is + always 4 bytes */ + typedef long int4byte; +#else + typedef int int4byte; +#endif + +/* OSC_timetag.h */ + + typedef struct { + int seconds; + int fraction; + } OSCTimeTag; + +OSCTimeTag OSCTT_Immediately(void); +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset); +OSCTimeTag OSCTT_CurrentTime(void); + + + +/* The maximum depth of bundles within bundles within bundles within... + This is the size of a static array. If you exceed this limit you'll + get an error message. */ +#define MAX_BUNDLE_NESTING 32 + + +/* Don't ever manipulate the data in the OSCbuf struct directly. (It's + declared here in the header file only so your program will be able to + declare variables of type OSCbuf and have the right amount of memory + be allocated.) */ + +typedef struct OSCbuf_struct { + char *buffer; /* The buffer to hold the OSC packet */ + int size; /* Size of the buffer */ + char *bufptr; /* Current position as we fill the buffer */ + int state; /* State of partially-constructed message */ + int4byte *thisMsgSize; /* Pointer to count field before + currently-being-written message */ + int4byte *prevCounts[MAX_BUNDLE_NESTING]; + /* Pointers to count field before each currently + open bundle */ + int bundleDepth; /* How many sub-sub-bundles are we in now? */ + char *typeStringPtr; /* This pointer advances through the type + tag string as you add arguments. */ + int gettingFirstUntypedArg; /* nonzero if this message doesn't have + a type tag and we're waiting for the 1st arg */ +} OSCbuf; + + + +/* Initialize the given OSCbuf. The user of this module must pass in the + block of memory that this OSCbuf will use for a buffer, and the number of + bytes in that block. (It's the user's job to allocate the memory because + you do it differently in different systems.) */ +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray); + + +/* Reset the given OSCbuf. Do this after you send out the contents of + the buffer and want to start writing new data into it. */ +void OSC_resetBuffer(OSCbuf *buf); + + +/* Is the buffer empty? (I.e., would it be stupid to send the buffer + contents to the synth?) */ +int OSC_isBufferEmpty(OSCbuf *buf); + + +/* How much space is left in the buffer? */ +int OSC_freeSpaceInBuffer(OSCbuf *buf); + +/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */ +int OSC_isBufferDone(OSCbuf *buf); + +/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone() + returns true), call these two procedures to get the OSC packet that's been + assembled and its size in bytes. (And then call OSC_resetBuffer() if you + want to re-use this OSCbuf for the next packet.) */ +char *OSC_getPacket(OSCbuf *buf); +int OSC_packetSize(OSCbuf *buf); + + + +/* Here's the basic model for building up OSC messages in an OSCbuf: + + - Make sure the OSCbuf has been initialized with OSC_initBuffer(). + + - To open a bundle, call OSC_openBundle(). You can then write + messages or open new bundles within the bundle you opened. + Call OSC_closeBundle() to close the bundle. Note that a packet + does not have to have a bundle; it can instead consist of just a + single message. + + + - For each message you want to send: + + - Call OSC_writeAddress() with the name of your message. (In + addition to writing your message name into the buffer, this + procedure will also leave space for the size count of this message.) + + - Alternately, call OSC_writeAddressAndTypes() with the name of + your message and with a type string listing the types of all the + arguments you will be putting in this message. + + - Now write each of the arguments into the buffer, by calling one of: + OSC_writeFloatArg() + OSC_writeFloatArgs() + OSC_writeIntArg() + OSC_writeStringArg() + + - Now your message is complete; you can send out the buffer or you can + add another message to it. +*/ + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt); +int OSC_closeBundle(OSCbuf *buf); +int OSC_closeAllBundles(OSCbuf *buf); + +int OSC_writeAddress(OSCbuf *buf, char *name); +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types); +int OSC_writeFloatArg(OSCbuf *buf, float arg); +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args); +int OSC_writeIntArg(OSCbuf *buf, int4byte arg); +int OSC_writeStringArg(OSCbuf *buf, char *arg); + +extern char *OSC_errorMessage; + +/* How many bytes will be needed in the OSC format to hold the given + string? The length of the string, plus the null char, plus any padding + needed for 4-byte alignment. */ +int OSC_effectiveStringLength(char *string); diff --git a/apps/plugins/pdbox/PDa/extra/OSC.pd b/apps/plugins/pdbox/PDa/extra/OSC.pd new file mode 100644 index 0000000000..8873f308da --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/OSC.pd @@ -0,0 +1,26 @@ +#N canvas 0 0 240 300 10; +#X obj 32 185 dumpOSC 5550; +#X obj 32 217 OSCroute /hello; +#X obj 32 239 print; +#X obj 133 238 print; +#X obj 26 87 sendOSC; +#X msg 50 43 connect localhost 5550; +#X msg 21 13 send /hello PDa; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 1 1 3 0; +#X connect 5 0 4 0; +#X connect 6 0 4 0; +#N canvas 0 0 240 300 10; +#X obj 32 185 dumpOSC 5550; +#X obj 32 217 OSCroute /hello; +#X obj 32 239 print; +#X obj 133 238 print; +#X obj 26 87 sendOSC; +#X msg 50 43 connect localhost 5550; +#X msg 21 13 send /hello PDa; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 1 1 3 0; +#X connect 5 0 4 0; +#X connect 6 0 4 0; diff --git a/apps/plugins/pdbox/PDa/extra/OSCroute.c b/apps/plugins/pdbox/PDa/extra/OSCroute.c new file mode 100644 index 0000000000..437d34dc68 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/OSCroute.c @@ -0,0 +1,1204 @@ +/* +Written by Adrian Freed, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + +The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl +*/ + + /* OSC-route.c + Max object for OSC-style dispatching + + To-do: + + Match a pattern against a pattern? + Declare outlet types / distinguish leaf nodes from other children + More sophisticated (2-pass?) allmessages scheme + set message? + + + pd + ------------- + -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 + + + */ + +#ifdef WIN32 + #include + #include +#endif +#ifdef __APPLE__ + #include +#endif +#ifdef UNIX + #include +#endif + +/* structure definition of your object */ + +#define MAX_NUM 20 +#define OSC_ROUTE_VERSION "1.05" +#define OSCWarning(x...) post(x) + +/* the required include files */ +#include "m_pd.h" + + +#ifndef TRUE +typedef int Boolean; +#define TRUE 1 +#define FALSE 0 +#endif + + +/* Fixed byte width types */ +typedef int int4; /* 4 byte int */ + +Boolean PatternMatch (const char *pattern, const char *test); + + + +/* Version 1.04: Allows #1 thru #9 as typed-in arguments + Version 1.05: Allows "list" messages as well as "message" messages. +*/ + +static t_class *OSCroute_class; + +typedef struct _OSCroute +{ + t_object x_obj; // required header + t_int x_num; // Number of address prefixes we store + t_int x_complainmode; // Do we print a message if no match? + t_int x_sendmode; // use pd internal sends instead of outlets + char *x_prefixes[MAX_NUM]; + void *x_outlets[MAX_NUM+1]; +} t_OSCroute; + +t_symbol *ps_list, *ps_complain, *ps_emptySymbol; + +/* prototypes */ + +void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); +void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); +void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); +/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */ +void *OSCroute_new(t_symbol *s, int argc, t_atom *argv); +void OSCroute_version (t_OSCroute *x); +/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */ +/* char *dstString); */ +void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); + +static char *NextSlashOrNull(char *p); +static void StrCopyUntilSlash(char *target, const char *source); + + +// free +static void OSCroute_free(t_OSCroute *x) +{ + // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); +} + +/* initialization routine */ + +// setup +#ifdef WIN32 + OSC_API void OSCroute_setup(void) { +#else +void OSCroute_setup(void) { +#endif + OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new, + (t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0); + class_addlist(OSCroute_class, OSCroute_list); + class_addanything(OSCroute_class, OSCroute_anything); + class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0); + class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd")); + + /* + class_addmethod(OSCroute_class, (t_method)OSCroute_connect, + gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect, + gensym("disconnect"), 0); + class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"), + A_GIMME, 0); + */ +/* ps_list = gensym("list"); */ +/* ps_complain = gensym("complain"); */ + ps_emptySymbol = gensym(""); + + post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf."); + post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved."); +} + + + +/* instance creation routine */ + +void *OSCroute_new(t_symbol *s, int argc, t_atom *argv) +{ + + t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize + + int i; //{{raf}} n not used + + // EnterCallback(); + + if (argc > MAX_NUM) { + post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM); + // ExitCallback(); + return 0; + } + + x->x_complainmode = 0; + x->x_num = 0; + for (i = 0; i < argc; ++i) { + if (argv[i].a_type == A_SYMBOL) { + if (argv[i].a_w.w_symbol->s_name[0] == '/') { + /* Now that's a nice prefix */ + x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name; + ++(x->x_num); + } else if (argv[i].a_w.w_symbol->s_name[0] == '#' && + argv[i].a_w.w_symbol->s_name[1] >= '1' && + argv[i].a_w.w_symbol->s_name[1] <= '9') { + /* The Max programmer is trying to make a patch that will be + a subpatch with arguments. We have to make an outlet for this + argument. */ + x->x_prefixes[i] = "dummy"; + ++(x->x_num); + } else { + /* Maybe this is an option we support */ + +/* if (argv[i].a_w.w_sym == ps_complain) { */ +/* x->x_complainmode = 1; */ +/* } else { */ +/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */ +/* } */ + + } + + // no LONG + +/* } else if (argv[i].a_type == A_FLOAD) { */ +/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */ +/* char *string = getbytes(12); */ +/* // I can't be bothered to plug this 12 byte memory leak */ +/* if (string == 0) { */ +/* post("* OSC-route: out of memory!"); */ +/* // ExitCallback(); */ +/* return 0; */ +/* } */ +/* sprintf(string, "%d", argv[i].a_w.w_long); */ +/* x->x_prefixes[i] = string; */ +/* ++(x->x_num); */ + + } else if (argv[i].a_type == A_FLOAT) { + post("* OSC-route: float arguments are not OK."); + // ExitCallback(); + return 0; + } else { + post("* OSC-route: unrecognized argument type!"); + // ExitCallback(); + return 0; + } + } + + + /* Have to create the outlets in reverse order */ + /* well, not in pd ? */ + // for (i = x->x_num-1; i >= 0; --i) { + // for (i = 0; i <= x->x_num-1; i++) { + for (i = 0; i <= x->x_num; i++) { + // x->x_outlets[i] = listout(x); + x->x_outlets[i] = outlet_new(&x->x_obj, &s_list); + } + + // ExitCallback(); + return (x); +} + + +void OSCroute_version (t_OSCroute *x) { + // EnterCallback(); + post("OSCroute Version " OSC_ROUTE_VERSION + ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__); + // ExitCallback(); +} + +/* I don't know why these aren't defined in some Max #include file. */ +#define ASSIST_INLET 1 +#define ASSIST_OUTLET 2 + +void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg, + char *dstString) { + // EnterCallback(); + + if (msg==ASSIST_INLET) { + sprintf(dstString, "Incoming OSC messages"); + } else if (msg==ASSIST_OUTLET) { + if (arg < 0 || arg >= x->x_num) { + post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg); + } else { + sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]); + } + } else { + post("* OSCroute_assist: unrecognized message %ld", msg); + } + + // ExitCallback(); +} + +void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + // EnterCallback(); + if (argc > 0 && argv[0].a_type == A_SYMBOL) { + /* Ignore the fact that this is a "list" */ + OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1); + } else { + // post("* OSC-route: invalid list beginning with a number"); + // output on unmatched outlet jdl 20020908 + if (argv[0].a_type == A_FLOAT) { + outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float); + } else { + post("* OSC-route: unrecognized atom type!"); + } + } + // ExitCallback(); +} + + +void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + // EnterCallback(); + OSCroute_doanything(x, s, argc, argv); + // ExitCallback(); +} + + + + +void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + char *pattern, *nextSlash; + int i; + int matchedAnything; + // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc); + + pattern = s->s_name; + if (pattern[0] != '/') { + post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name); + outlet_anything(x->x_outlets[x->x_num], s, argc, argv); + return; + } + + matchedAnything = 0; + + nextSlash = NextSlashOrNull(pattern+1); + if (*nextSlash == '\0') { + /* last level of the address, so we'll output the argument list */ + + +#ifdef NULL_IS_DIFFERENT_FROM_BANG + if (argc==0) { + post("* OSC-route: why are you matching one level pattern %s with no args?", + pattern); + return; + } +#endif + + for (i = 0; i < x->x_num; ++i) { + if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) { + ++matchedAnything; + + // I hate stupid Max lists with a special first element + if (argc == 0) { + outlet_bang(x->x_outlets[i]); + } else if (argv[0].a_type == A_SYMBOL) { + // Promote the symbol that was argv[0] to the special symbol + outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1); + } else if (argc > 1) { + // Multiple arguments starting with a number, so naturally we have + // to use a special function to output this "list", since it's what + // Max originally meant by "list". + outlet_list(x->x_outlets[i], 0L, argc, argv); + } else { + // There was only one argument, and it was a number, so we output it + // not as a list +/* if (argv[0].a_type == A_LONG) { */ + +/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */ + // } else + if (argv[0].a_type == A_FLOAT) { + + outlet_float(x->x_outlets[i], argv[0].a_w.w_float); + } else { + post("* OSC-route: unrecognized atom type!"); + } + } + } + } + } else { + /* There's more address after this part, so our output list will begin with + the next slash. */ + t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */ + char patternBegin[1000]; + + + /* Get the first level of the incoming pattern to match against all our prefixes */ + StrCopyUntilSlash(patternBegin, pattern+1); + + for (i = 0; i < x->x_num; ++i) { + if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) { + ++matchedAnything; + if (restOfPattern == 0) { + restOfPattern = gensym(nextSlash); + } + outlet_anything(x->x_outlets[i], restOfPattern, argc, argv); + } + } + } + + if (x->x_complainmode) { + if (!matchedAnything) { + post("* OSC-route: pattern %s did not match any prefixes", pattern); + } + } + + // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908 + if (!matchedAnything) { + outlet_anything(x->x_outlets[x->x_num], s, argc, argv); + } + + +} + +static char *NextSlashOrNull(char *p) { + while (*p != '/' && *p != '\0') { + p++; + } + return p; +} + +static void StrCopyUntilSlash(char *target, const char *source) { + while (*source != '/' && *source != '\0') { + *target = *source; + ++target; + ++source; + } + *target = 0; +} + +static int MyStrCopy(char *target, const char *source) { + int i = 0; + while (*source != '\0') { + *target = *source; + ++target; + ++source; + ++i; + } + *target = 0; + return i; +} + + + +void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + int i; + t_symbol *prefixSymbol = 0; + char prefixBuf[1000]; + char *endOfPrefix; + t_atom a[1]; + + if (argc >= 1 && argv[0].a_type == A_SYMBOL) { + prefixSymbol = argv[0].a_w.w_symbol; + endOfPrefix = prefixBuf + MyStrCopy(prefixBuf, + prefixSymbol->s_name); + } else { + prefixSymbol = ps_emptySymbol; + prefixBuf[0] = '\0'; + endOfPrefix = prefixBuf; + } + + + for (i = 0; i < x->x_num; ++i) { + post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]); + MyStrCopy(endOfPrefix, x->x_prefixes[i]); + SETSYMBOL(a, gensym(prefixBuf)); + outlet_anything(x->x_outlets[i], s, 1, a); + } +} + + +/* --------------------------------------------------- */ + + + +static const char *theWholePattern; /* Just for warning messages */ + +static Boolean MatchBrackets (const char *pattern, const char *test); +static Boolean MatchList (const char *pattern, const char *test); + +Boolean PatternMatch (const char * pattern, const char * test) { + theWholePattern = pattern; + + if (pattern == 0 || pattern[0] == 0) { + return test[0] == 0; + } + + if (test[0] == 0) { + if (pattern[0] == '*') + return PatternMatch (pattern+1,test); + else + return FALSE; + } + + switch (pattern[0]) { + case 0 : return test[0] == 0; + case '?' : return PatternMatch (pattern + 1, test + 1); + case '*' : + if (PatternMatch (pattern+1, test)) { + return TRUE; + } else { + return PatternMatch (pattern, test+1); + } + case ']' : + case '}' : + OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern); + return FALSE; + case '[' : + return MatchBrackets (pattern,test); + case '{' : + return MatchList (pattern,test); + case '\\' : + if (pattern[1] == 0) { + return test[0] == 0; + } else if (pattern[1] == test[0]) { + return PatternMatch (pattern+2,test+1); + } else { + return FALSE; + } + default : + if (pattern[0] == test[0]) { + return PatternMatch (pattern+1,test+1); + } else { + return FALSE; + } + } +} + + +/* we know that pattern[0] == '[' and test[0] != 0 */ + +static Boolean MatchBrackets (const char *pattern, const char *test) { + Boolean result; + Boolean negated = FALSE; + const char *p = pattern; + + if (pattern[1] == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + + if (pattern[1] == '!') { + negated = TRUE; + p++; + } + + while (*p != ']') { + if (*p == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + if (p[1] == '-' && p[2] != 0) { + if (test[0] >= p[0] && test[0] <= p[2]) { + result = !negated; + goto advance; + } + } + if (p[0] == test[0]) { + result = !negated; + goto advance; + } + p++; + } + + result = negated; + +advance: + + if (!result) + return FALSE; + + while (*p != ']') { + if (*p == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + p++; + } + + return PatternMatch (p+1,test+1); +} + +static Boolean MatchList (const char *pattern, const char *test) { + + const char *restOfPattern, *tp = test; + + + for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) { + if (*restOfPattern == 0) { + OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + } + + restOfPattern++; /* skip close curly brace */ + + + pattern++; /* skip open curly brace */ + + while (1) { + + if (*pattern == ',') { + if (PatternMatch (restOfPattern, tp)) { + return TRUE; + } else { + tp = test; + ++pattern; + } + } else if (*pattern == '}') { + return PatternMatch (restOfPattern, tp); + } else if (*pattern == *tp) { + ++pattern; + ++tp; + } else { + tp = test; + while (*pattern != ',' && *pattern != '}') { + pattern++; + } + if (*pattern == ',') { + pattern++; + } + } + } + +} + + + +/* +Written by Adrian Freed, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + +The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl +*/ + + /* OSC-route.c + Max object for OSC-style dispatching + + To-do: + + Match a pattern against a pattern? + Declare outlet types / distinguish leaf nodes from other children + More sophisticated (2-pass?) allmessages scheme + set message? + + + pd + ------------- + -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 + + + */ + +#ifdef WIN32 + #include + #include +#endif +#ifdef __APPLE__ + #include +#endif +#ifdef UNIX + #include +#endif + +/* structure definition of your object */ + +#define MAX_NUM 20 +#define OSC_ROUTE_VERSION "1.05" +#define OSCWarning(x...) post(x) + +/* the required include files */ +#include "m_pd.h" + + +#ifndef TRUE +typedef int Boolean; +#define TRUE 1 +#define FALSE 0 +#endif + + +/* Fixed byte width types */ +typedef int int4; /* 4 byte int */ + +Boolean PatternMatch (const char *pattern, const char *test); + + + +/* Version 1.04: Allows #1 thru #9 as typed-in arguments + Version 1.05: Allows "list" messages as well as "message" messages. +*/ + +static t_class *OSCroute_class; + +typedef struct _OSCroute +{ + t_object x_obj; // required header + t_int x_num; // Number of address prefixes we store + t_int x_complainmode; // Do we print a message if no match? + t_int x_sendmode; // use pd internal sends instead of outlets + char *x_prefixes[MAX_NUM]; + void *x_outlets[MAX_NUM+1]; +} t_OSCroute; + +t_symbol *ps_list, *ps_complain, *ps_emptySymbol; + +/* prototypes */ + +void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); +void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); +void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); +/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */ +void *OSCroute_new(t_symbol *s, int argc, t_atom *argv); +void OSCroute_version (t_OSCroute *x); +/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */ +/* char *dstString); */ +void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv); + +static char *NextSlashOrNull(char *p); +static void StrCopyUntilSlash(char *target, const char *source); + + +// free +static void OSCroute_free(t_OSCroute *x) +{ + // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); +} + +/* initialization routine */ + +// setup +#ifdef WIN32 + OSC_API void OSCroute_setup(void) { +#else +void OSCroute_setup(void) { +#endif + OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new, + (t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0); + class_addlist(OSCroute_class, OSCroute_list); + class_addanything(OSCroute_class, OSCroute_anything); + class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0); + class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd")); + + /* + class_addmethod(OSCroute_class, (t_method)OSCroute_connect, + gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect, + gensym("disconnect"), 0); + class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"), + A_GIMME, 0); + */ +/* ps_list = gensym("list"); */ +/* ps_complain = gensym("complain"); */ + ps_emptySymbol = gensym(""); + + post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf."); + post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved."); +} + + + +/* instance creation routine */ + +void *OSCroute_new(t_symbol *s, int argc, t_atom *argv) +{ + + t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize + + int i; //{{raf}} n not used + + // EnterCallback(); + + if (argc > MAX_NUM) { + post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM); + // ExitCallback(); + return 0; + } + + x->x_complainmode = 0; + x->x_num = 0; + for (i = 0; i < argc; ++i) { + if (argv[i].a_type == A_SYMBOL) { + if (argv[i].a_w.w_symbol->s_name[0] == '/') { + /* Now that's a nice prefix */ + x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name; + ++(x->x_num); + } else if (argv[i].a_w.w_symbol->s_name[0] == '#' && + argv[i].a_w.w_symbol->s_name[1] >= '1' && + argv[i].a_w.w_symbol->s_name[1] <= '9') { + /* The Max programmer is trying to make a patch that will be + a subpatch with arguments. We have to make an outlet for this + argument. */ + x->x_prefixes[i] = "dummy"; + ++(x->x_num); + } else { + /* Maybe this is an option we support */ + +/* if (argv[i].a_w.w_sym == ps_complain) { */ +/* x->x_complainmode = 1; */ +/* } else { */ +/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */ +/* } */ + + } + + // no LONG + +/* } else if (argv[i].a_type == A_FLOAD) { */ +/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */ +/* char *string = getbytes(12); */ +/* // I can't be bothered to plug this 12 byte memory leak */ +/* if (string == 0) { */ +/* post("* OSC-route: out of memory!"); */ +/* // ExitCallback(); */ +/* return 0; */ +/* } */ +/* sprintf(string, "%d", argv[i].a_w.w_long); */ +/* x->x_prefixes[i] = string; */ +/* ++(x->x_num); */ + + } else if (argv[i].a_type == A_FLOAT) { + post("* OSC-route: float arguments are not OK."); + // ExitCallback(); + return 0; + } else { + post("* OSC-route: unrecognized argument type!"); + // ExitCallback(); + return 0; + } + } + + + /* Have to create the outlets in reverse order */ + /* well, not in pd ? */ + // for (i = x->x_num-1; i >= 0; --i) { + // for (i = 0; i <= x->x_num-1; i++) { + for (i = 0; i <= x->x_num; i++) { + // x->x_outlets[i] = listout(x); + x->x_outlets[i] = outlet_new(&x->x_obj, &s_list); + } + + // ExitCallback(); + return (x); +} + + +void OSCroute_version (t_OSCroute *x) { + // EnterCallback(); + post("OSCroute Version " OSC_ROUTE_VERSION + ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__); + // ExitCallback(); +} + +/* I don't know why these aren't defined in some Max #include file. */ +#define ASSIST_INLET 1 +#define ASSIST_OUTLET 2 + +void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg, + char *dstString) { + // EnterCallback(); + + if (msg==ASSIST_INLET) { + sprintf(dstString, "Incoming OSC messages"); + } else if (msg==ASSIST_OUTLET) { + if (arg < 0 || arg >= x->x_num) { + post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg); + } else { + sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]); + } + } else { + post("* OSCroute_assist: unrecognized message %ld", msg); + } + + // ExitCallback(); +} + +void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + // EnterCallback(); + if (argc > 0 && argv[0].a_type == A_SYMBOL) { + /* Ignore the fact that this is a "list" */ + OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1); + } else { + // post("* OSC-route: invalid list beginning with a number"); + // output on unmatched outlet jdl 20020908 + if (argv[0].a_type == A_FLOAT) { + outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float); + } else { + post("* OSC-route: unrecognized atom type!"); + } + } + // ExitCallback(); +} + + +void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + // EnterCallback(); + OSCroute_doanything(x, s, argc, argv); + // ExitCallback(); +} + + + + +void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + char *pattern, *nextSlash; + int i; + int matchedAnything; + // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc); + + pattern = s->s_name; + if (pattern[0] != '/') { + post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name); + outlet_anything(x->x_outlets[x->x_num], s, argc, argv); + return; + } + + matchedAnything = 0; + + nextSlash = NextSlashOrNull(pattern+1); + if (*nextSlash == '\0') { + /* last level of the address, so we'll output the argument list */ + + +#ifdef NULL_IS_DIFFERENT_FROM_BANG + if (argc==0) { + post("* OSC-route: why are you matching one level pattern %s with no args?", + pattern); + return; + } +#endif + + for (i = 0; i < x->x_num; ++i) { + if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) { + ++matchedAnything; + + // I hate stupid Max lists with a special first element + if (argc == 0) { + outlet_bang(x->x_outlets[i]); + } else if (argv[0].a_type == A_SYMBOL) { + // Promote the symbol that was argv[0] to the special symbol + outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1); + } else if (argc > 1) { + // Multiple arguments starting with a number, so naturally we have + // to use a special function to output this "list", since it's what + // Max originally meant by "list". + outlet_list(x->x_outlets[i], 0L, argc, argv); + } else { + // There was only one argument, and it was a number, so we output it + // not as a list +/* if (argv[0].a_type == A_LONG) { */ + +/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */ + // } else + if (argv[0].a_type == A_FLOAT) { + + outlet_float(x->x_outlets[i], argv[0].a_w.w_float); + } else { + post("* OSC-route: unrecognized atom type!"); + } + } + } + } + } else { + /* There's more address after this part, so our output list will begin with + the next slash. */ + t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */ + char patternBegin[1000]; + + + /* Get the first level of the incoming pattern to match against all our prefixes */ + StrCopyUntilSlash(patternBegin, pattern+1); + + for (i = 0; i < x->x_num; ++i) { + if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) { + ++matchedAnything; + if (restOfPattern == 0) { + restOfPattern = gensym(nextSlash); + } + outlet_anything(x->x_outlets[i], restOfPattern, argc, argv); + } + } + } + + if (x->x_complainmode) { + if (!matchedAnything) { + post("* OSC-route: pattern %s did not match any prefixes", pattern); + } + } + + // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908 + if (!matchedAnything) { + outlet_anything(x->x_outlets[x->x_num], s, argc, argv); + } + + +} + +static char *NextSlashOrNull(char *p) { + while (*p != '/' && *p != '\0') { + p++; + } + return p; +} + +static void StrCopyUntilSlash(char *target, const char *source) { + while (*source != '/' && *source != '\0') { + *target = *source; + ++target; + ++source; + } + *target = 0; +} + +static int MyStrCopy(char *target, const char *source) { + int i = 0; + while (*source != '\0') { + *target = *source; + ++target; + ++source; + ++i; + } + *target = 0; + return i; +} + + + +void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { + int i; + t_symbol *prefixSymbol = 0; + char prefixBuf[1000]; + char *endOfPrefix; + t_atom a[1]; + + if (argc >= 1 && argv[0].a_type == A_SYMBOL) { + prefixSymbol = argv[0].a_w.w_symbol; + endOfPrefix = prefixBuf + MyStrCopy(prefixBuf, + prefixSymbol->s_name); + } else { + prefixSymbol = ps_emptySymbol; + prefixBuf[0] = '\0'; + endOfPrefix = prefixBuf; + } + + + for (i = 0; i < x->x_num; ++i) { + post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]); + MyStrCopy(endOfPrefix, x->x_prefixes[i]); + SETSYMBOL(a, gensym(prefixBuf)); + outlet_anything(x->x_outlets[i], s, 1, a); + } +} + + +/* --------------------------------------------------- */ + + + +static const char *theWholePattern; /* Just for warning messages */ + +static Boolean MatchBrackets (const char *pattern, const char *test); +static Boolean MatchList (const char *pattern, const char *test); + +Boolean PatternMatch (const char * pattern, const char * test) { + theWholePattern = pattern; + + if (pattern == 0 || pattern[0] == 0) { + return test[0] == 0; + } + + if (test[0] == 0) { + if (pattern[0] == '*') + return PatternMatch (pattern+1,test); + else + return FALSE; + } + + switch (pattern[0]) { + case 0 : return test[0] == 0; + case '?' : return PatternMatch (pattern + 1, test + 1); + case '*' : + if (PatternMatch (pattern+1, test)) { + return TRUE; + } else { + return PatternMatch (pattern, test+1); + } + case ']' : + case '}' : + OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern); + return FALSE; + case '[' : + return MatchBrackets (pattern,test); + case '{' : + return MatchList (pattern,test); + case '\\' : + if (pattern[1] == 0) { + return test[0] == 0; + } else if (pattern[1] == test[0]) { + return PatternMatch (pattern+2,test+1); + } else { + return FALSE; + } + default : + if (pattern[0] == test[0]) { + return PatternMatch (pattern+1,test+1); + } else { + return FALSE; + } + } +} + + +/* we know that pattern[0] == '[' and test[0] != 0 */ + +static Boolean MatchBrackets (const char *pattern, const char *test) { + Boolean result; + Boolean negated = FALSE; + const char *p = pattern; + + if (pattern[1] == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + + if (pattern[1] == '!') { + negated = TRUE; + p++; + } + + while (*p != ']') { + if (*p == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + if (p[1] == '-' && p[2] != 0) { + if (test[0] >= p[0] && test[0] <= p[2]) { + result = !negated; + goto advance; + } + } + if (p[0] == test[0]) { + result = !negated; + goto advance; + } + p++; + } + + result = negated; + +advance: + + if (!result) + return FALSE; + + while (*p != ']') { + if (*p == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + p++; + } + + return PatternMatch (p+1,test+1); +} + +static Boolean MatchList (const char *pattern, const char *test) { + + const char *restOfPattern, *tp = test; + + + for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) { + if (*restOfPattern == 0) { + OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + } + + restOfPattern++; /* skip close curly brace */ + + + pattern++; /* skip open curly brace */ + + while (1) { + + if (*pattern == ',') { + if (PatternMatch (restOfPattern, tp)) { + return TRUE; + } else { + tp = test; + ++pattern; + } + } else if (*pattern == '}') { + return PatternMatch (restOfPattern, tp); + } else if (*pattern == *tp) { + ++pattern; + ++tp; + } else { + tp = test; + while (*pattern != ',' && *pattern != '}') { + pattern++; + } + if (*pattern == ',') { + pattern++; + } + } + } + +} + + + diff --git a/apps/plugins/pdbox/PDa/extra/README b/apps/plugins/pdbox/PDa/extra/README new file mode 100644 index 0000000000..6e0b4a1e67 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/README @@ -0,0 +1,24 @@ +PDa - externals +=============== + +This is a collection of selected externals for PDa. The externals are +all copyright by their authors, check out the copyright notice in +each of the files. + +I have changed some of the files a bit, so the bugs are most likely my +fault. Send feedback and wishes to + +geiger xdv dot org + +PDa - externals +=============== + +This is a collection of selected externals for PDa. The externals are +all copyright by their authors, check out the copyright notice in +each of the files. + +I have changed some of the files a bit, so the bugs are most likely my +fault. Send feedback and wishes to + +geiger xdv dot org + diff --git a/apps/plugins/pdbox/PDa/extra/bandpass-help.pd b/apps/plugins/pdbox/PDa/extra/bandpass-help.pd new file mode 100644 index 0000000000..65d41eafad --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/bandpass-help.pd @@ -0,0 +1,34 @@ +#N canvas 428 285 240 300 8; +#X obj 24 78 noise~; +#X obj 15 215 dac~; +#X obj 24 167 biquad~; +#X floatatom 67 76 5 0 0 0 - - -; +#X floatatom 83 111 5 0 0 0 - - -; +#X obj 67 138 bandpass 600 10; +#X text 77 97 bandwidth: 100 = 1 octave; +#X text 67 58 frequency; +#X text 8 11 Calculation of biquad coefficients; +#X text 7 21 ==================================; +#X connect 0 0 2 0; +#X connect 2 0 1 0; +#X connect 2 0 1 1; +#X connect 3 0 5 0; +#X connect 4 0 5 1; +#X connect 5 0 2 0; +#N canvas 428 285 240 300 8; +#X obj 24 78 noise~; +#X obj 15 215 dac~; +#X obj 24 167 biquad~; +#X floatatom 67 76 5 0 0 0 - - -; +#X floatatom 83 111 5 0 0 0 - - -; +#X obj 67 138 bandpass 600 10; +#X text 77 97 bandwidth: 100 = 1 octave; +#X text 67 58 frequency; +#X text 8 11 Calculation of biquad coefficients; +#X text 7 21 ==================================; +#X connect 0 0 2 0; +#X connect 2 0 1 0; +#X connect 2 0 1 1; +#X connect 3 0 5 0; +#X connect 4 0 5 1; +#X connect 5 0 2 0; diff --git a/apps/plugins/pdbox/PDa/extra/bandpass.c b/apps/plugins/pdbox/PDa/extra/bandpass.c new file mode 100644 index 0000000000..6de56d6174 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/bandpass.c @@ -0,0 +1,172 @@ + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + +/* ------------------- bandpass ----------------------------*/ + +static t_class *bandpass_class; + +void bandpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = 0.; + t_float b0 = alpha; + t_float b2 = -alpha; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("bandpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void bandpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + bandpass_bang(x); +} + + +static void *bandpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void bandpass_setup(void) +{ + bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(bandpass_class,bandpass_bang); + class_addfloat(bandpass_class,bandpass_float); +} + + + + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + +/* ------------------- bandpass ----------------------------*/ + +static t_class *bandpass_class; + +void bandpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = 0.; + t_float b0 = alpha; + t_float b2 = -alpha; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("bandpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void bandpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + bandpass_bang(x); +} + + +static void *bandpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void bandpass_setup(void) +{ + bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(bandpass_class,bandpass_bang); + class_addfloat(bandpass_class,bandpass_float); +} + + + diff --git a/apps/plugins/pdbox/PDa/extra/dumpOSC.c b/apps/plugins/pdbox/PDa/extra/dumpOSC.c new file mode 100644 index 0000000000..37767c2b03 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/dumpOSC.c @@ -0,0 +1,1998 @@ +/* +Written by Matt Wright and Adrian Freed, The Center for New Music and +Audio Technologies, University of California, Berkeley. Copyright (c) +1992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of +California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + +The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl +*/ + + + /* + + dumpOSC.c + server that displays OpenSoundControl messages sent to it + for debugging client udp and UNIX protocol + + by Matt Wright, 6/3/97 + modified from dumpSC.c, by Matt Wright and Adrian Freed + + version 0.2: Added "-silent" option a.k.a. "-quiet" + + version 0.3: Incorporated patches from Nicola Bernardini to make + things Linux-friendly. Also added ntohl() in the right places + to support little-endian architectures. + + + + compile: + cc -o dumpOSC dumpOSC.c + + to-do: + + More robustness in saying exactly what's wrong with ill-formed + messages. (If they don't make sense, show exactly what was + received.) + + Time-based features: print time-received for each packet + + Clean up to separate OSC parsing code from socket/select stuff + + pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c + ------------- + -- added pd functions + -- socket is made differently than original via pd mechanisms + -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 + -- the OSX changes from cnmat didnt make it here yet but this compiles + on OSX anyway. + +*/ + +#if HAVE_CONFIG_H +#include +#endif + +#include "m_pd.h" +//#include "m_imp.h" +#include "s_stuff.h" + +/* declarations */ + +// typedef void (*t_fdpollfn)(void *ptr, int fd); +void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); + + +#if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__) + +#ifdef WIN32 + #include "OSC-common.h" + #include + #include + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + //#include + + #ifdef NEED_SCHEDCTL_AND_LOCK + #include + #include + #endif +#endif + + +char *htm_error_string; +typedef int Boolean; +typedef void *OBJ; + +typedef struct ClientAddressStruct { + struct sockaddr_in cl_addr; + int clilen; + int sockfd; +} *ClientAddr; + +typedef unsigned long long osc_time_t; + +Boolean ShowBytes = FALSE; +Boolean Silent = FALSE; + +/* Declarations */ +#ifndef WIN32 +static int unixinitudp(int chan); +#endif + +static int initudp(int chan); +static void closeudp(int sockfd); +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength); +void sgi_CleanExit(void); +Boolean sgi_HaveToQuit(void); +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy); +static void catch_sigint(); +static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ; +char *DataAfterAlignedString(char *string, char *boundary) ; +Boolean IsNiceString(char *string, char *boundary) ; +void complain(char *s, ...); + +#define MAXMESG 32768 +static char mbuf[MAXMESG]; + +/* ----------------------------- dumpOSC ------------------------- */ + +#define MAXOUTAT 50 + +static t_class *dumpOSC_class; + +typedef struct _dumpOSC +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_connectout; + t_atom x_outat[MAXOUTAT]; + int x_outatc; + t_binbuf *x_b; + int x_connectsocket; + int x_nconnections; + int x_udp; + struct sockaddr_in x_server; + int x_clilen; +} t_dumpOSC; + +void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr); +Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd); +static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr); +static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n); +static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma); + +static void dumpOSC_read(t_dumpOSC *x, int sockfd) { + int clilen = x->x_clilen; + int n; + struct ClientAddressStruct ras; + ClientAddr ra = &ras; + + //catchupflag= FALSE; + +/* if (ShowBytes) { */ +/* int i; */ +/* printf("%d byte message:\n", n); */ +/* for (i = 0; i < n; ++i) { */ +/* printf(" %x (%c)\t", m[i], m[i]); */ +/* if (i%4 == 3) printf("\n"); */ +/* } */ +/* printf("\n"); */ +/* } */ + + // return catchupflag; + //struct sockaddr_in x->x_server; + //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0) + // while(( + + #ifdef WIN32 + if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0) + #else + if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0) + #endif + { + //int r; + ras.cl_addr = *((struct sockaddr_in *) &x->x_server); + ras.clilen = x->x_clilen; + ras.sockfd = x->x_connectsocket; + + #ifdef DEBUG + printf("dumpOSC_read: received UDP packet of length %d\n", n); + #endif + + if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd)) + { + dumpOSC_ParsePacket(x, mbuf, n, ra); + } + //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd); + //post ("%d", r); + //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + // emsg-msg-1, at + msg + 1); + // outlet_list(x->x_msgout, 0, n, mbuf); + //if( sgi_HaveToQuit()) goto out; + //if(r>0) goto back; + //clilen = maxclilen; + } +} + +static void *dumpOSC_new(t_symbol *compatflag, + t_floatarg fportno) { + t_dumpOSC *x; + struct sockaddr_in server; + int clilen=sizeof(server); + int sockfd; + int portno=fportno; + int udp = 1; + + //x->x_b = binbuf_new(); + //x->x_outat = binbuf_getvec(x->x_b); + + //{{raf}} pointer not valid yet...moving this down + //x->x_outatc = 0; {{raf}} + + /* create a socket */ + if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1) + { + sys_sockerror("socket"); + return (0); + } + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + /* assign server port number */ + server.sin_port = htons((u_short)portno); + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("bind"); + sys_closesocket(sockfd); + return (0); + } + + x = (t_dumpOSC *)pd_new(dumpOSC_class); + x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid) + + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + + // if (udp) /* datagram protocol */ + { + + sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x); + x->x_connectout = 0; + } + // else /* streaming protocol */ + /* { */ + /* if (listen(sockfd, 5) < 0) */ + /* { */ + /* sys_sockerror("listen"); */ + /* sys_closesocket(sockfd); */ + /* sockfd = -1; */ + /* } */ + /* else */ + /* { */ + /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */ + /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */ + /* } */ + /* } */ + + x->x_connectsocket = sockfd; + x->x_server = server; + x->x_clilen = clilen; + x->x_nconnections = 0; + x->x_udp = udp; + + return (x); +} + +static void dumpOSC_free(t_dumpOSC *x) +{ + /* LATER make me clean up open connections */ + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } +} + +#ifdef WIN32 +OSC_API void dumpOSC_setup(void) +#else +void dumpOSC_setup(void) +#endif +{ + dumpOSC_class = class_new(gensym("dumpOSC"), + (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free, + sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, + A_DEFSYM, 0); + class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd")); +} + + +#ifndef WIN32 + #define UNIXDG_PATH "/tmp/htm" + #define UNIXDG_TMP "/tmp/htm.XXXXXX" + static int unixinitudp(int chan) + { + struct sockaddr_un serv_addr; + int sockfd; + + if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, UNIXDG_PATH); + sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan); + unlink(serv_addr.sun_path); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; + } +#endif // #ifndef WIN32 + + + +static int initudp(int chan) +{ + +#ifdef WIN32 + struct sockaddr_in serv_addr; + unsigned int sockfd; + ULONG nonBlocking = (ULONG) TRUE; + + if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) { + ZeroMemory((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) { + // set for non-blocking mode + if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) { + perror("unable to set non-blocking\n"); + return -1; + } + } + else { perror("unable to bind\n"); return -1; } + } + return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd); +#else + struct sockaddr_in serv_addr; + int sockfd; + + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; +#endif +} + + + + + + + + +static void closeudp(int sockfd) { + #ifdef WIN32 + closesocket(sockfd); + #else + close(sockfd); + #endif +} + +static Boolean catchupflag=FALSE; +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength) +{ + if(!clientaddresspointer) return FALSE; + catchupflag= TRUE; + return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength); +} + +static Boolean exitflag= FALSE; +void sgi_CleanExit(void) { + exitflag = TRUE; +} + +Boolean sgi_HaveToQuit(void) { + return exitflag; +} + + +/* file descriptor poll table */ +static int npolldevs =0; +typedef struct polldev +{ + int fd; + void (*callbackfunction)(int , void *); + void *dummy; +} polldev; +#define TABMAX 8 +static polldev polldevs[TABMAX]; + + +/* Register a device (referred to by a file descriptor that the caller + should have already successfully obtained from a system call) to be + polled as real-time constraints allowed. + + When a select(2) call indicates activity on the file descriptor, the + callback function is called with the file descripter as first + argument and the given dummy argument (presumably a pointer to the + instance variables associated with the device). +*/ +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy) +{ + if(npolldevscl_addr.sin_addr.s_addr; + printf("Client address %p:\n", CA); + printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd); + printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family, + CA->cl_addr.sin_port); + printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr)); + + printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n", + CA->cl_addr.sin_zero[0], + CA->cl_addr.sin_zero[1], + CA->cl_addr.sin_zero[2], + CA->cl_addr.sin_zero[3], + CA->cl_addr.sin_zero[4], + CA->cl_addr.sin_zero[5], + CA->cl_addr.sin_zero[6], + CA->cl_addr.sin_zero[7]); + + printf("\n"); +} + +//******************* + +void WriteTime(char* dst, osc_time_t osctime) +{ + *(int32_t*)dst = htonl((int32_t)(osctime >> 32)); + *(int32_t*)(dst+4) = htonl((int32_t)osctime); +} + +void WriteMode(char* dst) +{ + *(int32_t*)dst = htonl(0); +} + +osc_time_t ReadTime(const char* src) +{ + osc_time_t osctime = ntohl(*(int32_t*)src); + return (osctime << 32) + ntohl(*(int32_t*)(src+4)); +} + +double TimeToSeconds(osc_time_t osctime) +{ + return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */; +} + +int timeRound(double x) +{ + return x >= 0.0 ? x+0.5 : x-0.5; +} +/* +void WriteLogicalTime(char* dst) +{ + static double startTime = -1.0; + double sTime; + + // Initialisierung der Startzeit. + // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren. + // Knnte wahrscheinlich auch 0.0 sein. + if (startTime < 0.0) { + startTime = clock_getlogicaltime(); + } + + sTime = clock_gettimesince(startTime) * 0.001; + *(int32_t*)dst = hton'K l((int32_t)sTime); + *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime)); +} +*/ + +void WriteLogicalTime(char* dst) +{ + double sTime = clock_gettimesince(19230720) / 1000.0; + double tau = sTime - timeRound(sTime); + + //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau); + + *(int32_t*)dst = htonl((int32_t)(sTime)); + *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau)); +} + +Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd) +{ + if((n == 24) && (strcmp(buf, "#time") == 0)) + { + osc_time_t t0, t1, t2; + double dt0, dt1, dt2; + + WriteMode(buf+6); + + t0 = ReadTime(buf+8); + + WriteLogicalTime(buf+16); + t1 = ReadTime(buf+16); // reverse + dt0 = TimeToSeconds(t0); // client time + dt1 = TimeToSeconds(t1); // server time + + // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1); + + sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght); + return TRUE; + } + else + { + return FALSE; + } +} + +//********************** + +void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) { + // t_dumpOSC *x; + int size, messageLen, i; + char *messageName; + char *args; + + //#ifdef PRINTADDRS + #ifdef DEBUG + //PrintClientAddr(returnAddr); + #endif + + + if ((n%4) != 0) { + complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n); + return; + } + + if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { + /* This is a bundle message. */ + #ifdef DEBUG + printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n"); + #endif + + if (n < 16) { + complain("Bundle message too small (%d bytes) for time tag", n); + return; + } + + /* Print the time tag */ + #ifdef DEBUG + printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12)))); + #endif + + /* Note: if we wanted to actually use the time tag as a little-endian + 64-bit int, we'd have to word-swap the two 32-bit halves of it */ + + i = 16; /* Skip "#group\0" and time tag */ + + while(i n) { + complain("Bad size count %d in bundle (only %d bytes left in entire bundle)", + size, n-i-4); + return; + } + + /* Recursively handle element of bundle */ + dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr); + i += 4 + size; + } + + if (i != n) { + complain("This can't happen"); + } + #ifdef DEBUG + printf("]\n"); + #endif + + } + else if ((n == 24) && (strcmp(buf, "#time") == 0)) + { + complain("Time message: %s\n :).\n", htm_error_string); + return; + + } + else + { + /* This is not a bundle message */ + + messageName = buf; + args = DataAfterAlignedString(messageName, buf+n); + if (args == 0) { + complain("Bad message name string: %s\nDropping entire message.\n", + htm_error_string); + return; + } + messageLen = args-messageName; + dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr); + } +} + +#define SMALLEST_POSITIVE_FLOAT 0.000001f + +static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) { + char *chars = v; + t_atom at; + //t_atom myargv[50]; + + int myargc = x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + +#ifdef DEBUG + printf("%s ", address); +#endif + + // ztoln+cvt from envgen.c, ggee-0.18 .. + // outlet_anything's 'symbol' gets set to address + // so we dont need to append address to the atomlist + /* + SETSYMBOL(mya,gensym(address));myargc++; + x->x_outatc = myargc; + */ + + if (n != 0) { + if (chars[0] == ',') { + if (chars[1] != ',') { + /* This message begins with a type-tag string */ + dumpOSC_PrintTypeTaggedArgs(x, v, n); + } else { + /* Double comma means an escaped real comma, not a type string */ + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1); + } + } else { + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + } + } + + outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat); + x->x_outatc = 0; +#ifdef DEBUG + printf("\n"); +#endif + fflush(stdout); /* Added for Sami 5/21/98 */ +} + +static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) { + char *typeTags, *thisType; + char *p; + + int myargc = x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + + typeTags = v; + + if (!IsNiceString(typeTags, typeTags+n)) { + /* No null-termination, so maybe it wasn't a type tag + string after all */ + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + return; + } + + p = DataAfterAlignedString(typeTags, typeTags+n); + + + for (thisType = typeTags + 1; *thisType != 0; ++thisType) { + switch (*thisType) { + case 'i': case 'r': case 'm': case 'c': +#ifdef DEBUG + //post("integer: %d", ntohl(*((int *) p))); +#endif + /* Martin Peach fix for negative floats: + * was: SETFLOAT(mya+myargc,ntohl(*((int *) p))); + * now is: + */ + SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p))); + myargc++; + + p += 4; + break; + + case 'f': { + int i = ntohl(*((int *) p)); + float *floatp = ((float *) (&i)); +#ifdef DEBUG + post("float: %f", *floatp); +#endif + SETFLOAT(mya+myargc,*floatp); + myargc++; + + p += 4; + } + break; + + case 'h': case 't': +#ifdef DEBUG + printf("[A 64-bit int] "); +#endif + post("[A 64-bit int] not implemented"); + + p += 8; + break; + + case 'd': +#ifdef DEBUG + printf("[A 64-bit float] "); +#endif + post("[A 64-bit float] not implemented"); + + p += 8; + break; + + case 's': case 'S': + if (!IsNiceString(p, typeTags+n)) { + post("Type tag said this arg is a string but it's not!\n"); + return; + } else { +#ifdef DEBUG + post("string: \"%s\"", p); +#endif + SETSYMBOL(mya+myargc,gensym(p)); + myargc++; + //outlet_list(x->x_msgout, 0,sizeof(p), p); + //outlet_anything(x->x_msgout, 0, sizeof(p), p); + p = DataAfterAlignedString(p, typeTags+n); + // append to output vector .. + } + break; + + case 'T': +#ifdef DEBUG + printf("[True] "); +#endif + SETFLOAT(mya+myargc,1.); + myargc++; + break; + case 'F': +#ifdef DEBUG + printf("[False] "); +#endif + SETFLOAT(mya+myargc,0.); + myargc++; + break; + case 'N': +#ifdef DEBUG + printf("[Nil]"); +#endif + post("sendOSC: [Nil] not implemented"); + break; + case 'I': +#ifdef DEBUG + printf("[Infinitum]"); +#endif + post("sendOSC: [Infinitum] not implemented"); + break; + + default: + post("sendOSC: [Unrecognized type tag %c]", *thisType); + // return; + } + } + x->x_outatc = myargc; +} + +static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) { + int i, thisi; + float thisf; + int *ints; + char *chars; + char *string, *nextString; + + int myargc= x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + + + /* Go through the arguments 32 bits at a time */ + ints = v; + chars = v; + + for (i = 0; i= -1000 && thisi <= 1000000) { +#ifdef DEBUG + printf("%d ", thisi); +#endif + // append to output vector .. + SETFLOAT(mya+myargc,(t_float) (thisi)); + myargc++; + // outlet_float(x->x_msgout, thisi); + i++; + } else if (thisf >= -1000.f && thisf <= 1000000.f && + (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) { +#ifdef DEBUG + printf("%f ", thisf); +#endif + // append to output vector .. + SETFLOAT(mya+myargc,thisf); + myargc++; + //outlet_float(x->x_msgout, thisf); + i++; + } else if (IsNiceString(string, chars+n)) { + nextString = DataAfterAlignedString(string, chars+n); +#ifdef DEBUG + printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string); +#endif + // append to output vector .. + SETSYMBOL(mya+myargc,gensym(string)); + myargc++; + //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string)); + i += (nextString-string) / 4; + } else { + // unhandled .. ;) +#ifdef DEBUG + printf("0x%x xx", ints[i]); +#endif + i++; + } + x->x_outatc = myargc; + } +} + + +#define STRING_ALIGN_PAD 4 + +char *DataAfterAlignedString(char *string, char *boundary) +{ + /* The argument is a block of data beginning with a string. The + string has (presumably) been padded with extra null characters + so that the overall length is a multiple of STRING_ALIGN_PAD + bytes. Return a pointer to the next byte after the null + byte(s). The boundary argument points to the character after + the last valid character in the buffer---if the string hasn't + ended by there, something's wrong. + + If the data looks wrong, return 0, and set htm_error_string */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + } + + /* Now string[i] is the first null character */ + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + if (string[i] != '\0') { + htm_error_string = "DataAfterAlignedString: Incorrectly padded string."; + return 0; + } + } + + return string+i; +} + +Boolean IsNiceString(char *string, char *boundary) +{ + /* Arguments same as DataAfterAlignedString(). Is the given "string" + really a string? I.e., is it a sequence of isprint() characters + terminated with 1-4 null characters to align on a 4-byte boundary? */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: IsNiceString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (!isprint(string[i])) return FALSE; + if (string + i >= boundary) return FALSE; + } + + /* If we made it this far, it's a null-terminated sequence of printing characters + in the given boundary. Now we just make sure it's null padded... */ + + /* Now string[i] is the first null character */ + i++; + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string[i] != '\0') return FALSE; + } + + return TRUE; +} + + + + + + + + + +#include +void complain(char *s, ...) { + va_list ap; + va_start(ap, s); + fprintf(stderr, "*** ERROR: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +#endif /* __sgi or LINUX or WIN32 */ +/* +Written by Matt Wright and Adrian Freed, The Center for New Music and +Audio Technologies, University of California, Berkeley. Copyright (c) +1992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of +California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + +The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl +*/ + + + /* + + dumpOSC.c + server that displays OpenSoundControl messages sent to it + for debugging client udp and UNIX protocol + + by Matt Wright, 6/3/97 + modified from dumpSC.c, by Matt Wright and Adrian Freed + + version 0.2: Added "-silent" option a.k.a. "-quiet" + + version 0.3: Incorporated patches from Nicola Bernardini to make + things Linux-friendly. Also added ntohl() in the right places + to support little-endian architectures. + + + + compile: + cc -o dumpOSC dumpOSC.c + + to-do: + + More robustness in saying exactly what's wrong with ill-formed + messages. (If they don't make sense, show exactly what was + received.) + + Time-based features: print time-received for each packet + + Clean up to separate OSC parsing code from socket/select stuff + + pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c + ------------- + -- added pd functions + -- socket is made differently than original via pd mechanisms + -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 + -- the OSX changes from cnmat didnt make it here yet but this compiles + on OSX anyway. + +*/ + +#if HAVE_CONFIG_H +#include +#endif + +#include "m_pd.h" +//#include "m_imp.h" +#include "s_stuff.h" + +/* declarations */ + +// typedef void (*t_fdpollfn)(void *ptr, int fd); +void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); + + +#if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__) + +#ifdef WIN32 + #include "OSC-common.h" + #include + #include + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + //#include + + #ifdef NEED_SCHEDCTL_AND_LOCK + #include + #include + #endif +#endif + + +char *htm_error_string; +typedef int Boolean; +typedef void *OBJ; + +typedef struct ClientAddressStruct { + struct sockaddr_in cl_addr; + int clilen; + int sockfd; +} *ClientAddr; + +typedef unsigned long long osc_time_t; + +Boolean ShowBytes = FALSE; +Boolean Silent = FALSE; + +/* Declarations */ +#ifndef WIN32 +static int unixinitudp(int chan); +#endif + +static int initudp(int chan); +static void closeudp(int sockfd); +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength); +void sgi_CleanExit(void); +Boolean sgi_HaveToQuit(void); +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy); +static void catch_sigint(); +static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ; +char *DataAfterAlignedString(char *string, char *boundary) ; +Boolean IsNiceString(char *string, char *boundary) ; +void complain(char *s, ...); + +#define MAXMESG 32768 +static char mbuf[MAXMESG]; + +/* ----------------------------- dumpOSC ------------------------- */ + +#define MAXOUTAT 50 + +static t_class *dumpOSC_class; + +typedef struct _dumpOSC +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_connectout; + t_atom x_outat[MAXOUTAT]; + int x_outatc; + t_binbuf *x_b; + int x_connectsocket; + int x_nconnections; + int x_udp; + struct sockaddr_in x_server; + int x_clilen; +} t_dumpOSC; + +void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr); +Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd); +static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr); +static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n); +static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma); + +static void dumpOSC_read(t_dumpOSC *x, int sockfd) { + int clilen = x->x_clilen; + int n; + struct ClientAddressStruct ras; + ClientAddr ra = &ras; + + //catchupflag= FALSE; + +/* if (ShowBytes) { */ +/* int i; */ +/* printf("%d byte message:\n", n); */ +/* for (i = 0; i < n; ++i) { */ +/* printf(" %x (%c)\t", m[i], m[i]); */ +/* if (i%4 == 3) printf("\n"); */ +/* } */ +/* printf("\n"); */ +/* } */ + + // return catchupflag; + //struct sockaddr_in x->x_server; + //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0) + // while(( + + #ifdef WIN32 + if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0) + #else + if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0) + #endif + { + //int r; + ras.cl_addr = *((struct sockaddr_in *) &x->x_server); + ras.clilen = x->x_clilen; + ras.sockfd = x->x_connectsocket; + + #ifdef DEBUG + printf("dumpOSC_read: received UDP packet of length %d\n", n); + #endif + + if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd)) + { + dumpOSC_ParsePacket(x, mbuf, n, ra); + } + //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd); + //post ("%d", r); + //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + // emsg-msg-1, at + msg + 1); + // outlet_list(x->x_msgout, 0, n, mbuf); + //if( sgi_HaveToQuit()) goto out; + //if(r>0) goto back; + //clilen = maxclilen; + } +} + +static void *dumpOSC_new(t_symbol *compatflag, + t_floatarg fportno) { + t_dumpOSC *x; + struct sockaddr_in server; + int clilen=sizeof(server); + int sockfd; + int portno=fportno; + int udp = 1; + + //x->x_b = binbuf_new(); + //x->x_outat = binbuf_getvec(x->x_b); + + //{{raf}} pointer not valid yet...moving this down + //x->x_outatc = 0; {{raf}} + + /* create a socket */ + if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1) + { + sys_sockerror("socket"); + return (0); + } + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + /* assign server port number */ + server.sin_port = htons((u_short)portno); + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("bind"); + sys_closesocket(sockfd); + return (0); + } + + x = (t_dumpOSC *)pd_new(dumpOSC_class); + x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid) + + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + + // if (udp) /* datagram protocol */ + { + + sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x); + x->x_connectout = 0; + } + // else /* streaming protocol */ + /* { */ + /* if (listen(sockfd, 5) < 0) */ + /* { */ + /* sys_sockerror("listen"); */ + /* sys_closesocket(sockfd); */ + /* sockfd = -1; */ + /* } */ + /* else */ + /* { */ + /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */ + /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */ + /* } */ + /* } */ + + x->x_connectsocket = sockfd; + x->x_server = server; + x->x_clilen = clilen; + x->x_nconnections = 0; + x->x_udp = udp; + + return (x); +} + +static void dumpOSC_free(t_dumpOSC *x) +{ + /* LATER make me clean up open connections */ + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } +} + +#ifdef WIN32 +OSC_API void dumpOSC_setup(void) +#else +void dumpOSC_setup(void) +#endif +{ + dumpOSC_class = class_new(gensym("dumpOSC"), + (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free, + sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, + A_DEFSYM, 0); + class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd")); +} + + +#ifndef WIN32 + #define UNIXDG_PATH "/tmp/htm" + #define UNIXDG_TMP "/tmp/htm.XXXXXX" + static int unixinitudp(int chan) + { + struct sockaddr_un serv_addr; + int sockfd; + + if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, UNIXDG_PATH); + sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan); + unlink(serv_addr.sun_path); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; + } +#endif // #ifndef WIN32 + + + +static int initudp(int chan) +{ + +#ifdef WIN32 + struct sockaddr_in serv_addr; + unsigned int sockfd; + ULONG nonBlocking = (ULONG) TRUE; + + if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) { + ZeroMemory((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) { + // set for non-blocking mode + if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) { + perror("unable to set non-blocking\n"); + return -1; + } + } + else { perror("unable to bind\n"); return -1; } + } + return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd); +#else + struct sockaddr_in serv_addr; + int sockfd; + + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; +#endif +} + + + + + + + + +static void closeudp(int sockfd) { + #ifdef WIN32 + closesocket(sockfd); + #else + close(sockfd); + #endif +} + +static Boolean catchupflag=FALSE; +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength) +{ + if(!clientaddresspointer) return FALSE; + catchupflag= TRUE; + return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength); +} + +static Boolean exitflag= FALSE; +void sgi_CleanExit(void) { + exitflag = TRUE; +} + +Boolean sgi_HaveToQuit(void) { + return exitflag; +} + + +/* file descriptor poll table */ +static int npolldevs =0; +typedef struct polldev +{ + int fd; + void (*callbackfunction)(int , void *); + void *dummy; +} polldev; +#define TABMAX 8 +static polldev polldevs[TABMAX]; + + +/* Register a device (referred to by a file descriptor that the caller + should have already successfully obtained from a system call) to be + polled as real-time constraints allowed. + + When a select(2) call indicates activity on the file descriptor, the + callback function is called with the file descripter as first + argument and the given dummy argument (presumably a pointer to the + instance variables associated with the device). +*/ +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy) +{ + if(npolldevscl_addr.sin_addr.s_addr; + printf("Client address %p:\n", CA); + printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd); + printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family, + CA->cl_addr.sin_port); + printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr)); + + printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n", + CA->cl_addr.sin_zero[0], + CA->cl_addr.sin_zero[1], + CA->cl_addr.sin_zero[2], + CA->cl_addr.sin_zero[3], + CA->cl_addr.sin_zero[4], + CA->cl_addr.sin_zero[5], + CA->cl_addr.sin_zero[6], + CA->cl_addr.sin_zero[7]); + + printf("\n"); +} + +//******************* + +void WriteTime(char* dst, osc_time_t osctime) +{ + *(int32_t*)dst = htonl((int32_t)(osctime >> 32)); + *(int32_t*)(dst+4) = htonl((int32_t)osctime); +} + +void WriteMode(char* dst) +{ + *(int32_t*)dst = htonl(0); +} + +osc_time_t ReadTime(const char* src) +{ + osc_time_t osctime = ntohl(*(int32_t*)src); + return (osctime << 32) + ntohl(*(int32_t*)(src+4)); +} + +double TimeToSeconds(osc_time_t osctime) +{ + return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */; +} + +int timeRound(double x) +{ + return x >= 0.0 ? x+0.5 : x-0.5; +} +/* +void WriteLogicalTime(char* dst) +{ + static double startTime = -1.0; + double sTime; + + // Initialisierung der Startzeit. + // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren. + // Knnte wahrscheinlich auch 0.0 sein. + if (startTime < 0.0) { + startTime = clock_getlogicaltime(); + } + + sTime = clock_gettimesince(startTime) * 0.001; + *(int32_t*)dst = hton'K l((int32_t)sTime); + *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime)); +} +*/ + +void WriteLogicalTime(char* dst) +{ + double sTime = clock_gettimesince(19230720) / 1000.0; + double tau = sTime - timeRound(sTime); + + //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau); + + *(int32_t*)dst = htonl((int32_t)(sTime)); + *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau)); +} + +Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd) +{ + if((n == 24) && (strcmp(buf, "#time") == 0)) + { + osc_time_t t0, t1, t2; + double dt0, dt1, dt2; + + WriteMode(buf+6); + + t0 = ReadTime(buf+8); + + WriteLogicalTime(buf+16); + t1 = ReadTime(buf+16); // reverse + dt0 = TimeToSeconds(t0); // client time + dt1 = TimeToSeconds(t1); // server time + + // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1); + + sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght); + return TRUE; + } + else + { + return FALSE; + } +} + +//********************** + +void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) { + // t_dumpOSC *x; + int size, messageLen, i; + char *messageName; + char *args; + + //#ifdef PRINTADDRS + #ifdef DEBUG + //PrintClientAddr(returnAddr); + #endif + + + if ((n%4) != 0) { + complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n); + return; + } + + if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { + /* This is a bundle message. */ + #ifdef DEBUG + printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n"); + #endif + + if (n < 16) { + complain("Bundle message too small (%d bytes) for time tag", n); + return; + } + + /* Print the time tag */ + #ifdef DEBUG + printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12)))); + #endif + + /* Note: if we wanted to actually use the time tag as a little-endian + 64-bit int, we'd have to word-swap the two 32-bit halves of it */ + + i = 16; /* Skip "#group\0" and time tag */ + + while(i n) { + complain("Bad size count %d in bundle (only %d bytes left in entire bundle)", + size, n-i-4); + return; + } + + /* Recursively handle element of bundle */ + dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr); + i += 4 + size; + } + + if (i != n) { + complain("This can't happen"); + } + #ifdef DEBUG + printf("]\n"); + #endif + + } + else if ((n == 24) && (strcmp(buf, "#time") == 0)) + { + complain("Time message: %s\n :).\n", htm_error_string); + return; + + } + else + { + /* This is not a bundle message */ + + messageName = buf; + args = DataAfterAlignedString(messageName, buf+n); + if (args == 0) { + complain("Bad message name string: %s\nDropping entire message.\n", + htm_error_string); + return; + } + messageLen = args-messageName; + dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr); + } +} + +#define SMALLEST_POSITIVE_FLOAT 0.000001f + +static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) { + char *chars = v; + t_atom at; + //t_atom myargv[50]; + + int myargc = x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + +#ifdef DEBUG + printf("%s ", address); +#endif + + // ztoln+cvt from envgen.c, ggee-0.18 .. + // outlet_anything's 'symbol' gets set to address + // so we dont need to append address to the atomlist + /* + SETSYMBOL(mya,gensym(address));myargc++; + x->x_outatc = myargc; + */ + + if (n != 0) { + if (chars[0] == ',') { + if (chars[1] != ',') { + /* This message begins with a type-tag string */ + dumpOSC_PrintTypeTaggedArgs(x, v, n); + } else { + /* Double comma means an escaped real comma, not a type string */ + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1); + } + } else { + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + } + } + + outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat); + x->x_outatc = 0; +#ifdef DEBUG + printf("\n"); +#endif + fflush(stdout); /* Added for Sami 5/21/98 */ +} + +static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) { + char *typeTags, *thisType; + char *p; + + int myargc = x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + + typeTags = v; + + if (!IsNiceString(typeTags, typeTags+n)) { + /* No null-termination, so maybe it wasn't a type tag + string after all */ + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + return; + } + + p = DataAfterAlignedString(typeTags, typeTags+n); + + + for (thisType = typeTags + 1; *thisType != 0; ++thisType) { + switch (*thisType) { + case 'i': case 'r': case 'm': case 'c': +#ifdef DEBUG + //post("integer: %d", ntohl(*((int *) p))); +#endif + /* Martin Peach fix for negative floats: + * was: SETFLOAT(mya+myargc,ntohl(*((int *) p))); + * now is: + */ + SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p))); + myargc++; + + p += 4; + break; + + case 'f': { + int i = ntohl(*((int *) p)); + float *floatp = ((float *) (&i)); +#ifdef DEBUG + post("float: %f", *floatp); +#endif + SETFLOAT(mya+myargc,*floatp); + myargc++; + + p += 4; + } + break; + + case 'h': case 't': +#ifdef DEBUG + printf("[A 64-bit int] "); +#endif + post("[A 64-bit int] not implemented"); + + p += 8; + break; + + case 'd': +#ifdef DEBUG + printf("[A 64-bit float] "); +#endif + post("[A 64-bit float] not implemented"); + + p += 8; + break; + + case 's': case 'S': + if (!IsNiceString(p, typeTags+n)) { + post("Type tag said this arg is a string but it's not!\n"); + return; + } else { +#ifdef DEBUG + post("string: \"%s\"", p); +#endif + SETSYMBOL(mya+myargc,gensym(p)); + myargc++; + //outlet_list(x->x_msgout, 0,sizeof(p), p); + //outlet_anything(x->x_msgout, 0, sizeof(p), p); + p = DataAfterAlignedString(p, typeTags+n); + // append to output vector .. + } + break; + + case 'T': +#ifdef DEBUG + printf("[True] "); +#endif + SETFLOAT(mya+myargc,1.); + myargc++; + break; + case 'F': +#ifdef DEBUG + printf("[False] "); +#endif + SETFLOAT(mya+myargc,0.); + myargc++; + break; + case 'N': +#ifdef DEBUG + printf("[Nil]"); +#endif + post("sendOSC: [Nil] not implemented"); + break; + case 'I': +#ifdef DEBUG + printf("[Infinitum]"); +#endif + post("sendOSC: [Infinitum] not implemented"); + break; + + default: + post("sendOSC: [Unrecognized type tag %c]", *thisType); + // return; + } + } + x->x_outatc = myargc; +} + +static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) { + int i, thisi; + float thisf; + int *ints; + char *chars; + char *string, *nextString; + + int myargc= x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + + + /* Go through the arguments 32 bits at a time */ + ints = v; + chars = v; + + for (i = 0; i= -1000 && thisi <= 1000000) { +#ifdef DEBUG + printf("%d ", thisi); +#endif + // append to output vector .. + SETFLOAT(mya+myargc,(t_float) (thisi)); + myargc++; + // outlet_float(x->x_msgout, thisi); + i++; + } else if (thisf >= -1000.f && thisf <= 1000000.f && + (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) { +#ifdef DEBUG + printf("%f ", thisf); +#endif + // append to output vector .. + SETFLOAT(mya+myargc,thisf); + myargc++; + //outlet_float(x->x_msgout, thisf); + i++; + } else if (IsNiceString(string, chars+n)) { + nextString = DataAfterAlignedString(string, chars+n); +#ifdef DEBUG + printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string); +#endif + // append to output vector .. + SETSYMBOL(mya+myargc,gensym(string)); + myargc++; + //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string)); + i += (nextString-string) / 4; + } else { + // unhandled .. ;) +#ifdef DEBUG + printf("0x%x xx", ints[i]); +#endif + i++; + } + x->x_outatc = myargc; + } +} + + +#define STRING_ALIGN_PAD 4 + +char *DataAfterAlignedString(char *string, char *boundary) +{ + /* The argument is a block of data beginning with a string. The + string has (presumably) been padded with extra null characters + so that the overall length is a multiple of STRING_ALIGN_PAD + bytes. Return a pointer to the next byte after the null + byte(s). The boundary argument points to the character after + the last valid character in the buffer---if the string hasn't + ended by there, something's wrong. + + If the data looks wrong, return 0, and set htm_error_string */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + } + + /* Now string[i] is the first null character */ + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + if (string[i] != '\0') { + htm_error_string = "DataAfterAlignedString: Incorrectly padded string."; + return 0; + } + } + + return string+i; +} + +Boolean IsNiceString(char *string, char *boundary) +{ + /* Arguments same as DataAfterAlignedString(). Is the given "string" + really a string? I.e., is it a sequence of isprint() characters + terminated with 1-4 null characters to align on a 4-byte boundary? */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: IsNiceString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (!isprint(string[i])) return FALSE; + if (string + i >= boundary) return FALSE; + } + + /* If we made it this far, it's a null-terminated sequence of printing characters + in the given boundary. Now we just make sure it's null padded... */ + + /* Now string[i] is the first null character */ + i++; + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string[i] != '\0') return FALSE; + } + + return TRUE; +} + + + + + + + + + +#include +void complain(char *s, ...) { + va_list ap; + va_start(ap, s); + fprintf(stderr, "*** ERROR: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +#endif /* __sgi or LINUX or WIN32 */ diff --git a/apps/plugins/pdbox/PDa/extra/equalizer.c b/apps/plugins/pdbox/PDa/extra/equalizer.c new file mode 100644 index 0000000000..1d21c4087c --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/equalizer.c @@ -0,0 +1,178 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- equ ----------------------------*/ +static t_class *equ_class; + +void equ_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b0 = 1 + alpha*e_A(x->x_gain); + t_float b1 = -2.*cos(omega); + t_float b2 = 1 - alpha*e_A(x->x_gain); + t_float a0 = 1 + alpha/e_A(x->x_gain); + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha/e_A(x->x_gain); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("equ: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void equ_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + equ_bang(x); +} + + +static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void equalizer_setup(void) +{ + equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(equ_class,equ_bang); + class_addfloat(equ_class,equ_float); +} + + + + + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- equ ----------------------------*/ +static t_class *equ_class; + +void equ_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b0 = 1 + alpha*e_A(x->x_gain); + t_float b1 = -2.*cos(omega); + t_float b2 = 1 - alpha*e_A(x->x_gain); + t_float a0 = 1 + alpha/e_A(x->x_gain); + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha/e_A(x->x_gain); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("equ: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void equ_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + equ_bang(x); +} + + +static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void equalizer_setup(void) +{ + equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(equ_class,equ_bang); + class_addfloat(equ_class,equ_float); +} + + + + + diff --git a/apps/plugins/pdbox/PDa/extra/fatom.h b/apps/plugins/pdbox/PDa/extra/fatom.h new file mode 100644 index 0000000000..abaf9b91c1 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/fatom.h @@ -0,0 +1,970 @@ +/* ------------------------ fatom ----------------------------- */ + +#define x_val a_pos.a_w.w_float +#define DEBUG(x) + +#include +#include + +typedef struct _fatom +{ + t_object x_obj; + t_atom a_pos; /* the value of the fatom */ + + t_symbol* x_send; + t_symbol* x_receive; + t_glist * x_glist; /* value of the current canvas, intialized in _new */ + int x_rect_width; /* width of the widget */ + int x_rect_height; /* height of the widget */ + t_symbol* x_sym; /* symbol for receiving callbacks from GUI */ + t_symbol* x_type; /* type of fatom (vslider, hslider, checkbutton) */ + + t_symbol* x_text; /* associated widget text */ + int x_max; /* maximum value of a_pos (x_val) */ + int x_min; /* minimum value of a_pos (x_val) */ + int x_width; /* width of widget (e.g x_rect_height + 15 for hslider, x_rect_width + 15 for slider) */ + t_symbol* x_color; + t_symbol* x_bgcolor; +} t_fatom; + +/* widget helper functions */ + + + + +static void draw_inlets(t_fatom *x, t_glist *glist, int firsttime, int nin, int nout) +{ + int n = nin; + int nplus, i; + nplus = (n == 1 ? 1 : n-1); + DEBUG(post("draw inlet");) + for (i = 0; i < n; i++) + { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height); + } + n = nout; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist), + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, text_ypix(&x->x_obj, glist), + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1); + + } + DEBUG(post("draw inlet end");) +} + + +static void draw_handle(t_fatom *x, t_glist *glist, int firsttime) { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2); + + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4, + x); + else + sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n", + glist_getcanvas(glist), x, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4); +} + +static void create_widget(t_fatom *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if (!strcmp(x->x_type->s_name,"vslider")) { + x->x_rect_width = x->x_width+15; + x->x_rect_height = x->x_max-x->x_min+26; + + sys_vgui("scale .x%x.c.s%x \ + -sliderlength 10 \ + -showvalue 0 \ + -length %d \ + -resolution 0.01 \ + -repeatinterval 20 \ + -from %d -to %d \ + -width %d \ + -bg %s \ + -activebackground %s \ + -troughcolor %s \ + -command fatom_cb%x\n",canvas,x, + x->x_max-x->x_min+14, + x->x_max, + x->x_min, + x->x_width, + x->x_color->s_name, + x->x_color->s_name, + x->x_bgcolor->s_name, + x); + } else if (!strcmp(x->x_type->s_name,"hslider")) { + x->x_rect_width = x->x_max-x->x_min + 24; + x->x_rect_height = x->x_width + 15; + sys_vgui("scale .x%x.c.s%x \ + -sliderlength 10 \ + -showvalue 0 \ + -length %d \ + -resolution 0.01 \ + -orient horizontal \ + -repeatinterval 20 \ + -from %d -to %d \ + -width %d \ + -bg %s \ + -activebackground %s \ + -troughcolor %s \ + -command fatom_cb%x\n",canvas,x, + x->x_max-x->x_min+14, + x->x_min, + x->x_max, + x->x_width, + x->x_color->s_name, + x->x_color->s_name, + x->x_bgcolor->s_name, + x); + } else if (!strcmp(x->x_type->s_name,"checkbutton")) { + x->x_rect_width = 32; + x->x_rect_height = 28; + sys_vgui("checkbutton .x%x.c.s%x \ + -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -text \"%s\" \ + -bg %s \ + -activebackground %s \ + \n",canvas,x,x,x,x, + x->x_text->s_name, + x->x_color->s_name, + x->x_bgcolor->s_name); + } else if (!strcmp(x->x_type->s_name,"hradio")) { + int i; + x->x_rect_width = 8*20; + x->x_rect_height = 25; + for (i=0;i<8;i++) { + sys_vgui("radiobutton .x%x.c.s%x%d \ + -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i); + } + /* TODO pack them */ + } else if (!strcmp(x->x_type->s_name,"vradio")) { + int i; + x->x_rect_width = 30; + x->x_rect_height = 20*8+5; + for (i=0;i<8;i++) { + sys_vgui("radiobutton .x%x.c.s%x%d \ + -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i); + } + /* TODO pack them */ + } else { + x->x_rect_width = 32; + x->x_rect_height = 140; + sys_vgui("scale .x%x.c.s%x \ + -sliderlength 10 \ + -showvalue 0 \ + -length 131 \ + -from 127 -to 0 \ + -command fatom_cb%x\n",canvas,x,x); + } + + /* set the start value */ + if (!strcmp(x->x_type->s_name,"checkbutton")) { + if (x->x_val) + sys_vgui(".x%x.c.s%x select\n",canvas,x,x->x_val); + else + sys_vgui(".x%x.c.s%x deselect\n",canvas,x,x->x_val); + } else + sys_vgui(".x%x.c.s%x set %f\n",canvas,x,x->x_val); + +} + + + + + +static void fatom_drawme(t_fatom *x, t_glist *glist, int firsttime) +{ + t_canvas *canvas=glist_getcanvas(glist);// x->x_glist;//glist_getcanvas(glist); + DEBUG(post("drawme %d",firsttime);) + if (firsttime) { + DEBUG(post("glist %x canvas %x",x->x_glist,canvas)); + create_widget(x,glist); + x->x_glist = canvas; + sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x -tags %xS\n", + canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2,x->x_glist,x,x); + + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2); + } + draw_inlets(x, glist, firsttime, 1,1); + // draw_handle(x, glist, firsttime); + +} + + +static void fatom_erase(t_fatom* x,t_glist* glist) +{ + int n; + + DEBUG(post("erase");) + sys_vgui("destroy .x%x.c.s%x\n",glist_getcanvas(glist),x); + + sys_vgui(".x%x.c delete %xS\n",glist_getcanvas(glist), x); + + /* inlets and outlets */ + + sys_vgui(".x%x.c delete %xi%d\n",glist_getcanvas(glist),x,0); + sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,0); + sys_vgui(".x%x.c delete %xhandle\n",glist_getcanvas(glist),x,0); +} + + + +/* ------------------------ fatom widgetbehaviour----------------------------- */ + + +static void fatom_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_fatom* s = (t_fatom*)z; + + width = s->x_rect_width; + height = s->x_rect_height; + *xp1 = text_xpix(&s->x_obj, owner); + *yp1 = text_ypix(&s->x_obj, owner); + *xp2 = text_xpix(&s->x_obj, owner) + width; + *yp2 = text_ypix(&s->x_obj, owner) + height; +} + +static void fatom_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_fatom *x = (t_fatom *)z; + DEBUG(post("displace");) + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if (glist_isvisible(glist)) + { + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height); + + fatom_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); + } + DEBUG(post("displace end");) +} + +static void fatom_select(t_gobj *z, t_glist *glist, int state) +{ + t_fatom *x = (t_fatom *)z; + if (state) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xSEL -outline blue\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height, + x); + } + else { + sys_vgui(".x%x.c delete %xSEL\n", + glist_getcanvas(glist), x); + } + + + +} + + +static void fatom_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void fatom_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void fatom_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_fatom* s = (t_fatom*)z; + t_rtext *y; + DEBUG(post("vis: %d",vis);) + if (vis) { +#ifdef PD_MINOR_VERSION + y = (t_rtext *) rtext_new(glist, (t_text *)z); +#else + y = (t_rtext *) rtext_new(glist, (t_text *)z,0,0); +#endif + fatom_drawme(s, glist, 1); + } + else { + y = glist_findrtext(glist, (t_text *)z); + fatom_erase(s,glist); + rtext_free(y); + } +} + +static void fatom_save(t_gobj *z, t_binbuf *b); + +t_widgetbehavior fatom_widgetbehavior; + + + + +static void fatom_size(t_fatom* x,t_floatarg w,t_floatarg h) { + x->x_rect_width = w; + x->x_rect_height = h; +} + +static void fatom_color(t_fatom* x,t_symbol* col) +{ + +} + + +static void fatom_f(t_fatom* x,t_floatarg f) +{ + x->x_val = f; + if (x->x_send == &s_) + outlet_float(x->x_obj.ob_outlet,f); + else + if (x->x_send->s_thing) pd_float(x->x_send->s_thing,f); +} + + +static void fatom_float(t_fatom* x,t_floatarg f) +{ + if (glist_isvisible(x->x_glist)) { + if (!strcmp(x->x_type->s_name,"checkbutton")) { + if (x->x_val) + sys_vgui(".x%x.c.s%x select\n",x->x_glist,x,f); + else + sys_vgui(".x%x.c.s%x deselect\n",x->x_glist,x,f); + } else + sys_vgui(".x%x.c.s%x set %f\n",x->x_glist,x,f); + } + fatom_f(x,f); +} + + +static void fatom_bang(t_fatom* x,t_floatarg f) +{ + outlet_float(x->x_obj.ob_outlet,x->x_val); +} + + +static void fatom_properties(t_gobj *z, t_glist *owner) +{ + post("N/I"); +} + + +static void fatom_save(t_gobj *z, t_binbuf *b) +{ + + t_fatom *x = (t_fatom *)z; + + binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix , + gensym("fatom"),x->x_type); + binbuf_addv(b, ";"); +} + + +static void *fatom_new(t_fatom* x,int argc,t_atom* argv) +{ + char buf[256]; + int n = 0; + x->x_glist = canvas_getcurrent(); + + x->x_text = gensym(""); + x->x_max = 127; + x->x_min = 0; + x->x_width = 15; + x->x_color = gensym("grey"); + x->x_bgcolor = gensym("grey"); + x->x_send = &s_; + + while (argc) { + if (argv->a_type == A_FLOAT) { + if (n==0) x->x_max = atom_getfloat(argv); + if (n==1) x->x_min = atom_getfloat(argv); + if (n==2) x->x_width = atom_getfloat(argv); + } + + if (argv->a_type == A_SYMBOL) { + post("%d: symbol value %s",n,atom_getsymbol(argv)->s_name); + if (n==3) x->x_send = atom_getsymbol(argv); + if (n==4) x->x_color = atom_getsymbol(argv); + if (n==5) x->x_bgcolor = atom_getsymbol(argv); + } + argv++; + argc--; + n++; + } + + /* bind to a symbol for slider callback (later make this based on the + filepath ??) */ + + sprintf(buf,"fatom%x",(t_int)x); + x->x_sym = gensym(buf); + pd_bind(&x->x_obj.ob_pd, x->x_sym); + + /* pipe startup code to tk */ + + sys_vgui("proc fatom_cb%x {v} {\n pd [concat fatom%x f $v \\;]\n }\n",x,x); + + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void fatom_setup_common(t_class* class) +{ + + fatom_widgetbehavior.w_getrectfn = fatom_getrect; + fatom_widgetbehavior.w_displacefn = fatom_displace; + fatom_widgetbehavior.w_selectfn = fatom_select; + fatom_widgetbehavior.w_activatefn = fatom_activate; + fatom_widgetbehavior.w_deletefn = fatom_delete; + fatom_widgetbehavior.w_visfn = fatom_vis; +#if PD_MINOR_VERSION < 37 + fatom_widgetbehavior.w_savefn = fatom_save; + fatom_widgetbehavior.w_propertiesfn = NULL; +#endif + fatom_widgetbehavior.w_clickfn = NULL; + + class_addfloat(class, (t_method)fatom_float); + class_addbang(class, (t_method)fatom_bang); + class_addmethod(class, (t_method)fatom_f, gensym("f"), + A_FLOAT, 0); + +/* + class_addmethod(class, (t_method)fatom_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(class, (t_method)fatom_color, gensym("color"), + A_SYMBOL, 0); +*/ +/* + class_addmethod(class, (t_method)fatom_open, gensym("open"), + A_SYMBOL, 0); +*/ + + class_setwidget(class,&fatom_widgetbehavior); +#if PD_MINOR_VERSION >= 37 + class_setsavefn(class,&fatom_save); +#endif +} +/* ------------------------ fatom ----------------------------- */ + +#define x_val a_pos.a_w.w_float +#define DEBUG(x) + +#include +#include + +typedef struct _fatom +{ + t_object x_obj; + t_atom a_pos; /* the value of the fatom */ + + t_symbol* x_send; + t_symbol* x_receive; + t_glist * x_glist; /* value of the current canvas, intialized in _new */ + int x_rect_width; /* width of the widget */ + int x_rect_height; /* height of the widget */ + t_symbol* x_sym; /* symbol for receiving callbacks from GUI */ + t_symbol* x_type; /* type of fatom (vslider, hslider, checkbutton) */ + + t_symbol* x_text; /* associated widget text */ + int x_max; /* maximum value of a_pos (x_val) */ + int x_min; /* minimum value of a_pos (x_val) */ + int x_width; /* width of widget (e.g x_rect_height + 15 for hslider, x_rect_width + 15 for slider) */ + t_symbol* x_color; + t_symbol* x_bgcolor; +} t_fatom; + +/* widget helper functions */ + + + + +static void draw_inlets(t_fatom *x, t_glist *glist, int firsttime, int nin, int nout) +{ + int n = nin; + int nplus, i; + nplus = (n == 1 ? 1 : n-1); + DEBUG(post("draw inlet");) + for (i = 0; i < n; i++) + { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height); + } + n = nout; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist), + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, text_ypix(&x->x_obj, glist), + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1); + + } + DEBUG(post("draw inlet end");) +} + + +static void draw_handle(t_fatom *x, t_glist *glist, int firsttime) { + int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2); + + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n", + glist_getcanvas(glist), + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4, + x); + else + sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n", + glist_getcanvas(glist), x, + onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12, + onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4); +} + +static void create_widget(t_fatom *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if (!strcmp(x->x_type->s_name,"vslider")) { + x->x_rect_width = x->x_width+15; + x->x_rect_height = x->x_max-x->x_min+26; + + sys_vgui("scale .x%x.c.s%x \ + -sliderlength 10 \ + -showvalue 0 \ + -length %d \ + -resolution 0.01 \ + -repeatinterval 20 \ + -from %d -to %d \ + -width %d \ + -bg %s \ + -activebackground %s \ + -troughcolor %s \ + -command fatom_cb%x\n",canvas,x, + x->x_max-x->x_min+14, + x->x_max, + x->x_min, + x->x_width, + x->x_color->s_name, + x->x_color->s_name, + x->x_bgcolor->s_name, + x); + } else if (!strcmp(x->x_type->s_name,"hslider")) { + x->x_rect_width = x->x_max-x->x_min + 24; + x->x_rect_height = x->x_width + 15; + sys_vgui("scale .x%x.c.s%x \ + -sliderlength 10 \ + -showvalue 0 \ + -length %d \ + -resolution 0.01 \ + -orient horizontal \ + -repeatinterval 20 \ + -from %d -to %d \ + -width %d \ + -bg %s \ + -activebackground %s \ + -troughcolor %s \ + -command fatom_cb%x\n",canvas,x, + x->x_max-x->x_min+14, + x->x_min, + x->x_max, + x->x_width, + x->x_color->s_name, + x->x_color->s_name, + x->x_bgcolor->s_name, + x); + } else if (!strcmp(x->x_type->s_name,"checkbutton")) { + x->x_rect_width = 32; + x->x_rect_height = 28; + sys_vgui("checkbutton .x%x.c.s%x \ + -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -text \"%s\" \ + -bg %s \ + -activebackground %s \ + \n",canvas,x,x,x,x, + x->x_text->s_name, + x->x_color->s_name, + x->x_bgcolor->s_name); + } else if (!strcmp(x->x_type->s_name,"hradio")) { + int i; + x->x_rect_width = 8*20; + x->x_rect_height = 25; + for (i=0;i<8;i++) { + sys_vgui("radiobutton .x%x.c.s%x%d \ + -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i); + } + /* TODO pack them */ + } else if (!strcmp(x->x_type->s_name,"vradio")) { + int i; + x->x_rect_width = 30; + x->x_rect_height = 20*8+5; + for (i=0;i<8;i++) { + sys_vgui("radiobutton .x%x.c.s%x%d \ + -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i); + } + /* TODO pack them */ + } else { + x->x_rect_width = 32; + x->x_rect_height = 140; + sys_vgui("scale .x%x.c.s%x \ + -sliderlength 10 \ + -showvalue 0 \ + -length 131 \ + -from 127 -to 0 \ + -command fatom_cb%x\n",canvas,x,x); + } + + /* set the start value */ + if (!strcmp(x->x_type->s_name,"checkbutton")) { + if (x->x_val) + sys_vgui(".x%x.c.s%x select\n",canvas,x,x->x_val); + else + sys_vgui(".x%x.c.s%x deselect\n",canvas,x,x->x_val); + } else + sys_vgui(".x%x.c.s%x set %f\n",canvas,x,x->x_val); + +} + + + + + +static void fatom_drawme(t_fatom *x, t_glist *glist, int firsttime) +{ + t_canvas *canvas=glist_getcanvas(glist);// x->x_glist;//glist_getcanvas(glist); + DEBUG(post("drawme %d",firsttime);) + if (firsttime) { + DEBUG(post("glist %x canvas %x",x->x_glist,canvas)); + create_widget(x,glist); + x->x_glist = canvas; + sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x -tags %xS\n", + canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2,x->x_glist,x,x); + + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d\n", + canvas, x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2); + } + draw_inlets(x, glist, firsttime, 1,1); + // draw_handle(x, glist, firsttime); + +} + + +static void fatom_erase(t_fatom* x,t_glist* glist) +{ + int n; + + DEBUG(post("erase");) + sys_vgui("destroy .x%x.c.s%x\n",glist_getcanvas(glist),x); + + sys_vgui(".x%x.c delete %xS\n",glist_getcanvas(glist), x); + + /* inlets and outlets */ + + sys_vgui(".x%x.c delete %xi%d\n",glist_getcanvas(glist),x,0); + sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,0); + sys_vgui(".x%x.c delete %xhandle\n",glist_getcanvas(glist),x,0); +} + + + +/* ------------------------ fatom widgetbehaviour----------------------------- */ + + +static void fatom_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_fatom* s = (t_fatom*)z; + + width = s->x_rect_width; + height = s->x_rect_height; + *xp1 = text_xpix(&s->x_obj, owner); + *yp1 = text_ypix(&s->x_obj, owner); + *xp2 = text_xpix(&s->x_obj, owner) + width; + *yp2 = text_ypix(&s->x_obj, owner) + height; +} + +static void fatom_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_fatom *x = (t_fatom *)z; + DEBUG(post("displace");) + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + if (glist_isvisible(glist)) + { + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height); + + fatom_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); + } + DEBUG(post("displace end");) +} + +static void fatom_select(t_gobj *z, t_glist *glist, int state) +{ + t_fatom *x = (t_fatom *)z; + if (state) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xSEL -outline blue\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height, + x); + } + else { + sys_vgui(".x%x.c delete %xSEL\n", + glist_getcanvas(glist), x); + } + + + +} + + +static void fatom_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void fatom_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void fatom_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_fatom* s = (t_fatom*)z; + t_rtext *y; + DEBUG(post("vis: %d",vis);) + if (vis) { +#ifdef PD_MINOR_VERSION + y = (t_rtext *) rtext_new(glist, (t_text *)z); +#else + y = (t_rtext *) rtext_new(glist, (t_text *)z,0,0); +#endif + fatom_drawme(s, glist, 1); + } + else { + y = glist_findrtext(glist, (t_text *)z); + fatom_erase(s,glist); + rtext_free(y); + } +} + +static void fatom_save(t_gobj *z, t_binbuf *b); + +t_widgetbehavior fatom_widgetbehavior; + + + + +static void fatom_size(t_fatom* x,t_floatarg w,t_floatarg h) { + x->x_rect_width = w; + x->x_rect_height = h; +} + +static void fatom_color(t_fatom* x,t_symbol* col) +{ + +} + + +static void fatom_f(t_fatom* x,t_floatarg f) +{ + x->x_val = f; + if (x->x_send == &s_) + outlet_float(x->x_obj.ob_outlet,f); + else + if (x->x_send->s_thing) pd_float(x->x_send->s_thing,f); +} + + +static void fatom_float(t_fatom* x,t_floatarg f) +{ + if (glist_isvisible(x->x_glist)) { + if (!strcmp(x->x_type->s_name,"checkbutton")) { + if (x->x_val) + sys_vgui(".x%x.c.s%x select\n",x->x_glist,x,f); + else + sys_vgui(".x%x.c.s%x deselect\n",x->x_glist,x,f); + } else + sys_vgui(".x%x.c.s%x set %f\n",x->x_glist,x,f); + } + fatom_f(x,f); +} + + +static void fatom_bang(t_fatom* x,t_floatarg f) +{ + outlet_float(x->x_obj.ob_outlet,x->x_val); +} + + +static void fatom_properties(t_gobj *z, t_glist *owner) +{ + post("N/I"); +} + + +static void fatom_save(t_gobj *z, t_binbuf *b) +{ + + t_fatom *x = (t_fatom *)z; + + binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix , + gensym("fatom"),x->x_type); + binbuf_addv(b, ";"); +} + + +static void *fatom_new(t_fatom* x,int argc,t_atom* argv) +{ + char buf[256]; + int n = 0; + x->x_glist = canvas_getcurrent(); + + x->x_text = gensym(""); + x->x_max = 127; + x->x_min = 0; + x->x_width = 15; + x->x_color = gensym("grey"); + x->x_bgcolor = gensym("grey"); + x->x_send = &s_; + + while (argc) { + if (argv->a_type == A_FLOAT) { + if (n==0) x->x_max = atom_getfloat(argv); + if (n==1) x->x_min = atom_getfloat(argv); + if (n==2) x->x_width = atom_getfloat(argv); + } + + if (argv->a_type == A_SYMBOL) { + post("%d: symbol value %s",n,atom_getsymbol(argv)->s_name); + if (n==3) x->x_send = atom_getsymbol(argv); + if (n==4) x->x_color = atom_getsymbol(argv); + if (n==5) x->x_bgcolor = atom_getsymbol(argv); + } + argv++; + argc--; + n++; + } + + /* bind to a symbol for slider callback (later make this based on the + filepath ??) */ + + sprintf(buf,"fatom%x",(t_int)x); + x->x_sym = gensym(buf); + pd_bind(&x->x_obj.ob_pd, x->x_sym); + + /* pipe startup code to tk */ + + sys_vgui("proc fatom_cb%x {v} {\n pd [concat fatom%x f $v \\;]\n }\n",x,x); + + outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void fatom_setup_common(t_class* class) +{ + + fatom_widgetbehavior.w_getrectfn = fatom_getrect; + fatom_widgetbehavior.w_displacefn = fatom_displace; + fatom_widgetbehavior.w_selectfn = fatom_select; + fatom_widgetbehavior.w_activatefn = fatom_activate; + fatom_widgetbehavior.w_deletefn = fatom_delete; + fatom_widgetbehavior.w_visfn = fatom_vis; +#if PD_MINOR_VERSION < 37 + fatom_widgetbehavior.w_savefn = fatom_save; + fatom_widgetbehavior.w_propertiesfn = NULL; +#endif + fatom_widgetbehavior.w_clickfn = NULL; + + class_addfloat(class, (t_method)fatom_float); + class_addbang(class, (t_method)fatom_bang); + class_addmethod(class, (t_method)fatom_f, gensym("f"), + A_FLOAT, 0); + +/* + class_addmethod(class, (t_method)fatom_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(class, (t_method)fatom_color, gensym("color"), + A_SYMBOL, 0); +*/ +/* + class_addmethod(class, (t_method)fatom_open, gensym("open"), + A_SYMBOL, 0); +*/ + + class_setwidget(class,&fatom_widgetbehavior); +#if PD_MINOR_VERSION >= 37 + class_setsavefn(class,&fatom_save); +#endif +} diff --git a/apps/plugins/pdbox/PDa/extra/filters.h b/apps/plugins/pdbox/PDa/extra/filters.h new file mode 100644 index 0000000000..72d997e425 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/filters.h @@ -0,0 +1,148 @@ +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + + +#ifndef __GGEE_FILTERS_H__ +#define __GGEE_FILTERS_H__ + + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + + +#include +#define LN2 0.69314718 +#define e_A(g) (pow(10,(g/40.))) +#define e_omega(f,r) (2.0*M_PI*f/r) +#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega))) +#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1))) + + + + +typedef struct _rbjfilter +{ + t_object x_obj; + t_float x_rate; + t_float x_freq; + t_float x_gain; + t_float x_bw; +} t_rbjfilter; + + +static int check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + + + + + +#endif +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + + +#ifndef __GGEE_FILTERS_H__ +#define __GGEE_FILTERS_H__ + + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + + +#include +#define LN2 0.69314718 +#define e_A(g) (pow(10,(g/40.))) +#define e_omega(f,r) (2.0*M_PI*f/r) +#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega))) +#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1))) + + + + +typedef struct _rbjfilter +{ + t_object x_obj; + t_float x_rate; + t_float x_freq; + t_float x_gain; + t_float x_bw; +} t_rbjfilter; + + +static int check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + + + + + +#endif diff --git a/apps/plugins/pdbox/PDa/extra/g_canvas.h b/apps/plugins/pdbox/PDa/extra/g_canvas.h new file mode 100644 index 0000000000..54ab985feb --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/g_canvas.h @@ -0,0 +1,1204 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file defines the structure for "glists" and related structures and +functions. "Glists" and "canvases" and "graphs" used to be different +structures until being unified in version 0.35. + +A glist occupies its own window if the "gl_havewindow" flag is set. Its +appearance on its "parent" or "owner" (if it has one) is as a graph if +"gl_isgraph" is set, and otherwise as a text box. + +A glist is "root" if it has no owner, i.e., a document window. In this +case "gl_havewindow" is always set. + +We maintain a list of root windows, so that we can traverse the whole +collection of everything in a Pd process. + +If a glist has a window it may still not be "mapped." Miniaturized +windows aren't mapped, for example, but a window is also not mapped +immediately upon creation. In either case gl_havewindow is true but +gl_mapped is false. + +Closing a non-root window makes it invisible; closing a root destroys it. + +A glist that's just a text object on its parent is always "toplevel." An +embedded glist can switch back and forth to appear as a toplevel by double- +clicking on it. Single-clicking a text box makes the toplevel become visible +and raises the window it's in. + +If a glist shows up as a graph on its parent, the graph is blanked while the +glist has its own window, even if miniaturized. + +*/ + +/* NOTE: this file describes Pd implementation details which may change +in future releases. The public (stable) API is in m_pd.h. */ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { +#endif + +/* --------------------- geometry ---------------------------- */ +#define IOWIDTH 7 /* width of an inlet/outlet in pixels */ +#define IOMIDDLE ((IOWIDTH-1)/2) +#define GLIST_DEFGRAPHWIDTH 200 +#define GLIST_DEFGRAPHHEIGHT 140 +/* ----------------------- data ------------------------------- */ + +typedef struct _updateheader +{ + struct _updateheader *upd_next; + unsigned int upd_array:1; /* true if array, false if glist */ + unsigned int upd_queued:1; /* true if we're queued */ +} t_updateheader; + + /* types to support glists grabbing mouse motion or keys from parent */ +typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy); +typedef void (*t_glistkeyfn)(void *z, t_floatarg key); + +EXTERN_STRUCT _rtext; +#define t_rtext struct _rtext + +EXTERN_STRUCT _gtemplate; +#define t_gtemplate struct _gtemplate + +EXTERN_STRUCT _guiconnect; +#define t_guiconnect struct _guiconnect + +EXTERN_STRUCT _tscalar; +#define t_tscalar struct _tscalar + +EXTERN_STRUCT _canvasenvironment; +#define t_canvasenvironment struct _canvasenvironment + +typedef struct _selection +{ + t_gobj *sel_what; + struct _selection *sel_next; +} t_selection; + + /* this structure is instantiated whenever a glist becomes visible. */ +typedef struct _editor +{ + t_updateheader e_upd; /* update header structure */ + t_selection *e_updlist; /* list of objects to update */ + t_rtext *e_rtext; /* text responder linked list */ + t_selection *e_selection; /* head of the selection list */ + t_rtext *e_textedfor; /* the rtext if any that we are editing */ + t_gobj *e_grab; /* object being "dragged" */ + t_glistmotionfn e_motionfn; /* ... motion callback */ + t_glistkeyfn e_keyfn; /* ... keypress callback */ + t_binbuf *e_connectbuf; /* connections to deleted objects */ + t_binbuf *e_deleted; /* last stuff we deleted */ + t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */ + struct _glist *e_glist; /* glist which owns this */ + int e_xwas; /* xpos on last mousedown or motion event */ + int e_ywas; /* ypos, similarly */ + int e_selectline_index1; /* indices for the selected line if any */ + int e_selectline_outno; /* (only valid if e_selectedline is set) */ + int e_selectline_index2; + int e_selectline_inno; + t_outconnect *e_selectline_tag; + unsigned int e_onmotion: 3; /* action to take on motion */ + 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_editor; + +#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */ +#define MA_MOVE 1 /* drag the selection around */ +#define MA_CONNECT 2 /* make a connection */ +#define MA_REGION 3 /* selection region */ +#define MA_PASSOUT 4 /* send on to e_grab */ +#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */ + +/* editor structure for "garrays". We don't bother to delete and regenerate +this structure when the "garray" becomes invisible or visible, although we +could do so if the structure gets big (like the "editor" above.) */ + +typedef struct _arrayvis +{ + t_updateheader av_upd; /* update header structure */ + t_garray *av_garray; /* owning structure */ +} t_arrayvis; + +/* the t_tick structure describes where to draw x and y "ticks" for a glist */ + +typedef struct _tick /* where to put ticks on x or y axes */ +{ + float k_point; /* one point to draw a big tick at */ + float k_inc; /* x or y increment per little tick */ + int k_lperb; /* little ticks per big; 0 if no ticks to draw */ +} t_tick; + +/* the t_glist structure, which describes a list of elements that live on an +area of a window. + +*/ + +struct _glist +{ + t_object gl_obj; /* header in case we're a glist */ + t_gobj *gl_list; /* the actual data */ + struct _gstub *gl_stub; /* safe pointer handler */ + int gl_valid; /* incremented when pointers might be stale */ + struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */ + int gl_pixwidth; /* width in pixels (on parent, if a graph) */ + int gl_pixheight; + float gl_x1; /* bounding rectangle in our own coordinates */ + float gl_y1; + float gl_x2; + float gl_y2; + int gl_screenx1; /* screen coordinates when toplevel */ + int gl_screeny1; + int gl_screenx2; + int gl_screeny2; + t_tick gl_xtick; /* ticks marking X values */ + int gl_nxlabels; /* number of X coordinate labels */ + t_symbol **gl_xlabel; /* ... an array to hold them */ + float gl_xlabely; /* ... and their Y coordinates */ + t_tick gl_ytick; /* same as above for Y ticks and labels */ + int gl_nylabels; + t_symbol **gl_ylabel; + float gl_ylabelx; + t_editor *gl_editor; /* editor structure when visible */ + t_symbol *gl_name; /* symbol bound here */ + int gl_font; /* nominal font size in points, e.g., 10 */ + struct _glist *gl_next; /* link in list of toplevels */ + t_canvasenvironment *gl_env; /* root canvases and abstractions only */ + unsigned int gl_havewindow:1; /* true if we own a window */ + unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */ + unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */ + unsigned int gl_loading:1; /* am now loading from file */ + unsigned int gl_willvis:1; /* make me visible after loading */ + unsigned int gl_edit:1; /* edit mode */ + unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */ + unsigned int gl_stretch:1; /* stretch contents on resize */ + unsigned int gl_isgraph:1; /* show as graph on parent */ +}; + +#define gl_gobj gl_obj.te_g +#define gl_pd gl_gobj.g_pd + +/* a data structure to describe a field in a pure datum */ + +#define DT_FLOAT 0 +#define DT_SYMBOL 1 +#define DT_LIST 2 +#define DT_ARRAY 3 + +typedef struct _dataslot +{ + int ds_type; + t_symbol *ds_name; + t_symbol *ds_arraytemplate; /* filled in for arrays only */ +} t_dataslot; + + +/* T.Grill - changed t_pd member to t_pdobj to avoid name clashed */ +typedef struct _template +{ + t_pd t_pdobj; /* header */ + struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */ + t_symbol *t_sym; /* name */ + int t_n; /* number of dataslots (fields) */ + t_dataslot *t_vec; /* array of dataslots */ +} t_template; + +struct _array +{ + int a_n; /* number of elements */ + int a_elemsize; /* size in bytes; LATER get this from template */ + char *a_vec; /* array of elements */ + t_symbol *a_templatesym; /* template for elements */ + int a_valid; /* protection against stale pointers into array */ + t_gpointer a_gp; /* pointer to scalar or array element we're in */ + t_gstub *a_stub; +}; + + /* structure for traversing all the connections in a glist */ +typedef struct _linetraverser +{ + t_canvas *tr_x; + t_object *tr_ob; + int tr_nout; + int tr_outno; + t_object *tr_ob2; + t_outlet *tr_outlet; + t_inlet *tr_inlet; + int tr_nin; + int tr_inno; + int tr_x11, tr_y11, tr_x12, tr_y12; + int tr_x21, tr_y21, tr_x22, tr_y22; + int tr_lx1, tr_ly1, tr_lx2, tr_ly2; + t_outconnect *tr_nextoc; + int tr_nextoutno; +} t_linetraverser; + +/* function types used to define graphical behavior for gobjs, a bit like X +widgets. We don't use Pd methods because Pd's typechecking can't specify the +types of pointer arguments. Also it's more convenient this way, since +every "patchable" object can just get the "text" behaviors. */ + + /* Call this to get a gobj's bounding rectangle in pixels */ +typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist, + int *x1, int *y1, int *x2, int *y2); + /* and this to displace a gobj: */ +typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy); + /* change color to show selection: */ +typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state); + /* change appearance to show activation/deactivation: */ +typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state); + /* warn a gobj it's about to be deleted */ +typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist); + /* making visible or invisible */ +typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag); + /* field a mouse click (when not in "edit" mode) */ +typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + /* ... and later, resizing; getting/setting font or color... */ + +struct _widgetbehavior +{ + t_getrectfn w_getrectfn; + t_displacefn w_displacefn; + t_selectfn w_selectfn; + t_activatefn w_activatefn; + t_deletefn w_deletefn; + t_visfn w_visfn; + t_clickfn w_clickfn; +}; + +/* -------- behaviors for scalars defined by objects in template --------- */ +/* these are set by "drawing commands" in g_template.c which add appearance to +scalars, which live in some other window. If the scalar is just included +in a canvas the "parent" is a misnomer. There is also a text scalar object +which really does draw the scalar on the parent window; see g_scalar.c. */ + +/* note how the click function wants the whole scalar, not the "data", so +doesn't work on array elements... LATER reconsider this */ + + /* bounding rectangle: */ +typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int *x1, int *y1, int *x2, int *y2); + /* displace it */ +typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int dx, int dy); + /* change color to show selection */ +typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int state); + /* change appearance to show activation/deactivation: */ +typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int state); + /* making visible or invisible */ +typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int flag); + /* field a mouse click */ +typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist, + t_scalar *sc, t_template *tmpl, float basex, float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + +struct _parentwidgetbehavior +{ + t_parentgetrectfn w_parentgetrectfn; + t_parentdisplacefn w_parentdisplacefn; + t_parentselectfn w_parentselectfn; + t_parentactivatefn w_parentactivatefn; + t_parentvisfn w_parentvisfn; + t_parentclickfn w_parentclickfn; +}; + + /* cursor definitions; used as return value for t_parentclickfn */ +#define CURSOR_RUNMODE_NOTHING 0 +#define CURSOR_RUNMODE_CLICKME 1 +#define CURSOR_RUNMODE_THICKEN 2 +#define CURSOR_RUNMODE_ADDPOINT 3 +#define CURSOR_EDITMODE_NOTHING 4 +#define CURSOR_EDITMODE_CONNECT 5 +#define CURSOR_EDITMODE_DISCONNECT 6 +EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum); + +extern t_canvas *canvas_editing; /* last canvas to start text edting */ +extern t_canvas *canvas_whichfind; /* last canvas we did a find in */ +extern t_canvas *canvas_list; /* list of all root canvases */ +extern t_class *vinlet_class, *voutlet_class; +extern int glist_valid; /* incremented when pointers might be stale */ + +/* ------------------- functions on any gobj ----------------------------- */ +EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1, + int *x2, int *y2); +EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy); +EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state); +EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state); +EXTERN void gobj_delete(t_gobj *x, t_glist *owner); +EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag); +EXTERN int gobj_click(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit); +EXTERN void gobj_save(t_gobj *x, t_binbuf *b); +EXTERN void gobj_properties(t_gobj *x, struct _glist *glist); +EXTERN void gobj_save(t_gobj *x, t_binbuf *b); + +/* -------------------- functions on glists --------------------- */ +EXTERN t_glist *glist_new( void); +EXTERN void glist_init(t_glist *x); +EXTERN void glist_add(t_glist *x, t_gobj *g); +EXTERN void glist_cleanup(t_glist *x); +EXTERN void glist_free(t_glist *x); + +EXTERN void glist_clear(t_glist *x); +EXTERN t_canvas *glist_getcanvas(t_glist *x); +EXTERN int glist_isselected(t_glist *x, t_gobj *y); +EXTERN void glist_select(t_glist *x, t_gobj *y); +EXTERN void glist_deselect(t_glist *x, t_gobj *y); +EXTERN void glist_noselect(t_glist *x); +EXTERN void glist_selectall(t_glist *x); +EXTERN void glist_delete(t_glist *x, t_gobj *y); +EXTERN void glist_retext(t_glist *x, t_text *y); +EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, + t_glistkeyfn keyfn, int xpos, int ypos); +EXTERN int glist_isvisible(t_glist *x); +EXTERN int glist_istoplevel(t_glist *x); +EXTERN t_glist *glist_findgraph(t_glist *x); +EXTERN int glist_getfont(t_glist *x); +EXTERN void glist_sort(t_glist *canvas); +EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format); +EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format); + +EXTERN float glist_pixelstox(t_glist *x, float xpix); +EXTERN float glist_pixelstoy(t_glist *x, float ypix); +EXTERN float glist_xtopixels(t_glist *x, float xval); +EXTERN float glist_ytopixels(t_glist *x, float yval); +EXTERN float glist_dpixtodx(t_glist *x, float dxpix); +EXTERN float glist_dpixtody(t_glist *x, float dypix); + +EXTERN void glist_redrawitem(t_glist *owner, t_gobj *gobj); +EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval); +EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv); +EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym, + float x1, float y1, float x2, float y2, + float px1, float py1, float px2, float py2); +EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name, + t_floatarg size, t_floatarg saveit, t_floatarg newgraph); +EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething); +EXTERN int glist_isgraph(t_glist *x); +EXTERN void glist_redraw(t_glist *x); +EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, + char *tag, int x1, int y1, int x2, int y2); +EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag); +EXTERN void canvas_create_editor(t_glist *x, int createit); +void canvas_deletelinesforio(t_canvas *x, t_text *text, + t_inlet *inp, t_outlet *outp); + + +/* -------------------- functions on texts ------------------------- */ +EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize); +EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag, + int width, int height, int firsttime); +EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag); +EXTERN int text_xcoord(t_text *x, t_glist *glist); +EXTERN int text_ycoord(t_text *x, t_glist *glist); +EXTERN int text_xpix(t_text *x, t_glist *glist); +EXTERN int text_ypix(t_text *x, t_glist *glist); +EXTERN int text_shouldvis(t_text *x, t_glist *glist); + +/* -------------------- functions on rtexts ------------------------- */ +#define RTEXT_DOWN 1 +#define RTEXT_DRAG 2 +#define RTEXT_DBL 3 +#define RTEXT_SHIFT 4 + +EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who); +EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who); +EXTERN void rtext_draw(t_rtext *x); +EXTERN void rtext_erase(t_rtext *x); +EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x); +EXTERN int rtext_height(t_rtext *x); +EXTERN void rtext_displace(t_rtext *x, int dx, int dy); +EXTERN void rtext_select(t_rtext *x, int state); +EXTERN void rtext_activate(t_rtext *x, int state); +EXTERN void rtext_free(t_rtext *x); +EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s); +EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag); +EXTERN void rtext_retext(t_rtext *x); +EXTERN int rtext_width(t_rtext *x); +EXTERN int rtext_height(t_rtext *x); +EXTERN char *rtext_gettag(t_rtext *x); +EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize); + +/* -------------------- functions on canvases ------------------------ */ +EXTERN t_class *canvas_class; + +EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv); +EXTERN t_symbol *canvas_makebindsym(t_symbol *s); +EXTERN void canvas_vistext(t_canvas *x, t_text *y); +EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text); +EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text); +EXTERN void canvas_stowconnections(t_canvas *x); +EXTERN void canvas_restoreconnections(t_canvas *x); +EXTERN void canvas_redraw(t_canvas *x); + +EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym); +EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip); +EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym); +EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op); +EXTERN void canvas_redrawallfortemplate(t_canvas *tmpl); +EXTERN void canvas_zapallfortemplate(t_canvas *tmpl); +EXTERN void canvas_setusedastemplate(t_canvas *x); +EXTERN t_canvas *canvas_getcurrent(void); +EXTERN void canvas_setcurrent(t_canvas *x); +EXTERN void canvas_unsetcurrent(t_canvas *x); +EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s); +EXTERN t_canvas *canvas_getrootfor(t_canvas *x); +EXTERN void canvas_dirty(t_canvas *x, t_int n); +EXTERN int canvas_getfont(t_canvas *x); +typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3); + +EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn, + t_int x1, t_int x2, t_int x3); + +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 int canvas_isabstraction(t_canvas *x); +EXTERN int canvas_istable(t_canvas *x); +EXTERN int canvas_showtext(t_canvas *x); +EXTERN void canvas_vis(t_canvas *x, t_floatarg f); +EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x); +EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir); +EXTERN void canvas_loadbang(t_canvas *x); +EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos, + int *x1p, int *y1p, int *x2p, int *y2p); +EXTERN int canvas_setdeleting(t_canvas *x, int flag); + +typedef void (*t_undofn)(t_canvas *canvas, void *buf, + int action); /* a function that does UNDO/REDO */ +#define UNDO_FREE 0 /* free current undo/redo buffer */ +#define UNDO_UNDO 1 /* undo */ +#define UNDO_REDO 2 /* redo */ +EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, + const char *name); +EXTERN void canvas_noundo(t_canvas *x); +EXTERN int canvas_getindex(t_canvas *x, t_gobj *y); + +/* T.Grill - made public for dynamic object creation */ +/* in g_editor.c */ +EXTERN void canvas_connect(t_canvas *x, + t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno); +EXTERN void canvas_disconnect(t_canvas *x, + float index1, float outno, float index2, float inno); +EXTERN int canvas_isconnected (t_canvas *x, + t_text *ob1, int n1, t_text *ob2, int n2); +EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy); + + +/* ---- functions on canvasses as objects --------------------- */ + +EXTERN void canvas_fattenforscalars(t_canvas *x, + int *x1, int *y1, int *x2, int *y2); +EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis); +EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift, + int alt, int dbl, int doit); +EXTERN t_glist *canvas_getglistonsuper(void); + +EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x); +EXTERN t_outconnect *linetraverser_next(t_linetraverser *t); +EXTERN void linetraverser_skipobject(t_linetraverser *t); + +/* --------------------- functions on tscalars --------------------- */ + +EXTERN void tscalar_getrect(t_tscalar *x, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2); +EXTERN void tscalar_vis(t_tscalar *x, t_glist *owner, int flag); +EXTERN int tscalar_click(t_tscalar *x, int xpix, int ypix, int shift, + int alt, int dbl, int doit); + +/* --------- functions on garrays (graphical arrays) -------------------- */ + +EXTERN t_template *garray_template(t_garray *x); + +/* -------------------- arrays --------------------- */ +EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl, + t_floatarg f, t_floatarg saveit); +EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent); +EXTERN void array_resize(t_array *x, t_template *tmpl, int n); +EXTERN void array_free(t_array *x); + +/* --------------------- gpointers and stubs ---------------- */ +EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a); +EXTERN void gstub_cutoff(t_gstub *gs); +EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x); + +/* --------------------- scalars ------------------------- */ +EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp); +EXTERN void word_restore(t_word *wp, t_template *tmpl, + int argc, t_atom *argv); +EXTERN t_scalar *scalar_new(t_glist *owner, + t_symbol *templatesym); +EXTERN void scalar_getbasexy(t_scalar *x, float *basex, float *basey); + +/* ------helper routines for "garrays" and "plots" -------------- */ +EXTERN int array_doclick(t_array *array, t_glist *glist, t_gobj *gobj, + t_symbol *elemtemplatesym, + float linewidth, float xloc, float xinc, float yloc, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + +EXTERN void array_getcoordinate(t_glist *glist, + char *elem, int xonset, int yonset, int wonset, int indx, + float basex, float basey, float xinc, + float *xp, float *yp, float *wp); + +EXTERN int array_getfields(t_symbol *elemtemplatesym, + t_canvas **elemtemplatecanvasp, + t_template **elemtemplatep, int *elemsizep, + int *xonsetp, int *yonsetp, int *wonsetp); + +/* --------------------- templates ------------------------- */ +EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv); +EXTERN void template_free(t_template *x); +EXTERN int template_match(t_template *x1, t_template *x2); +EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset, + int *p_type, t_symbol **p_arraytype); +EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp, + int loud); +EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp, + t_float f, int loud); +EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, t_symbol *s, int loud); + +EXTERN t_template *gtemplate_get(t_gtemplate *x); +EXTERN t_template *template_findbyname(t_symbol *s); +EXTERN t_canvas *template_findcanvas(t_template *tmpl); + +EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, + t_word *wp, t_float f, int loud); +EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, t_symbol *s, int loud); + +/* ----------------------- guiconnects, g_guiconnect.c --------- */ +EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym); +EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay); + +/* ------------- IEMGUI routines used in other g_ files ---------------- */ +EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s); +EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s); + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +} +#endif +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file defines the structure for "glists" and related structures and +functions. "Glists" and "canvases" and "graphs" used to be different +structures until being unified in version 0.35. + +A glist occupies its own window if the "gl_havewindow" flag is set. Its +appearance on its "parent" or "owner" (if it has one) is as a graph if +"gl_isgraph" is set, and otherwise as a text box. + +A glist is "root" if it has no owner, i.e., a document window. In this +case "gl_havewindow" is always set. + +We maintain a list of root windows, so that we can traverse the whole +collection of everything in a Pd process. + +If a glist has a window it may still not be "mapped." Miniaturized +windows aren't mapped, for example, but a window is also not mapped +immediately upon creation. In either case gl_havewindow is true but +gl_mapped is false. + +Closing a non-root window makes it invisible; closing a root destroys it. + +A glist that's just a text object on its parent is always "toplevel." An +embedded glist can switch back and forth to appear as a toplevel by double- +clicking on it. Single-clicking a text box makes the toplevel become visible +and raises the window it's in. + +If a glist shows up as a graph on its parent, the graph is blanked while the +glist has its own window, even if miniaturized. + +*/ + +/* NOTE: this file describes Pd implementation details which may change +in future releases. The public (stable) API is in m_pd.h. */ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { +#endif + +/* --------------------- geometry ---------------------------- */ +#define IOWIDTH 7 /* width of an inlet/outlet in pixels */ +#define IOMIDDLE ((IOWIDTH-1)/2) +#define GLIST_DEFGRAPHWIDTH 200 +#define GLIST_DEFGRAPHHEIGHT 140 +/* ----------------------- data ------------------------------- */ + +typedef struct _updateheader +{ + struct _updateheader *upd_next; + unsigned int upd_array:1; /* true if array, false if glist */ + unsigned int upd_queued:1; /* true if we're queued */ +} t_updateheader; + + /* types to support glists grabbing mouse motion or keys from parent */ +typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy); +typedef void (*t_glistkeyfn)(void *z, t_floatarg key); + +EXTERN_STRUCT _rtext; +#define t_rtext struct _rtext + +EXTERN_STRUCT _gtemplate; +#define t_gtemplate struct _gtemplate + +EXTERN_STRUCT _guiconnect; +#define t_guiconnect struct _guiconnect + +EXTERN_STRUCT _tscalar; +#define t_tscalar struct _tscalar + +EXTERN_STRUCT _canvasenvironment; +#define t_canvasenvironment struct _canvasenvironment + +typedef struct _selection +{ + t_gobj *sel_what; + struct _selection *sel_next; +} t_selection; + + /* this structure is instantiated whenever a glist becomes visible. */ +typedef struct _editor +{ + t_updateheader e_upd; /* update header structure */ + t_selection *e_updlist; /* list of objects to update */ + t_rtext *e_rtext; /* text responder linked list */ + t_selection *e_selection; /* head of the selection list */ + t_rtext *e_textedfor; /* the rtext if any that we are editing */ + t_gobj *e_grab; /* object being "dragged" */ + t_glistmotionfn e_motionfn; /* ... motion callback */ + t_glistkeyfn e_keyfn; /* ... keypress callback */ + t_binbuf *e_connectbuf; /* connections to deleted objects */ + t_binbuf *e_deleted; /* last stuff we deleted */ + t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */ + struct _glist *e_glist; /* glist which owns this */ + int e_xwas; /* xpos on last mousedown or motion event */ + int e_ywas; /* ypos, similarly */ + int e_selectline_index1; /* indices for the selected line if any */ + int e_selectline_outno; /* (only valid if e_selectedline is set) */ + int e_selectline_index2; + int e_selectline_inno; + t_outconnect *e_selectline_tag; + unsigned int e_onmotion: 3; /* action to take on motion */ + 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_editor; + +#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */ +#define MA_MOVE 1 /* drag the selection around */ +#define MA_CONNECT 2 /* make a connection */ +#define MA_REGION 3 /* selection region */ +#define MA_PASSOUT 4 /* send on to e_grab */ +#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */ + +/* editor structure for "garrays". We don't bother to delete and regenerate +this structure when the "garray" becomes invisible or visible, although we +could do so if the structure gets big (like the "editor" above.) */ + +typedef struct _arrayvis +{ + t_updateheader av_upd; /* update header structure */ + t_garray *av_garray; /* owning structure */ +} t_arrayvis; + +/* the t_tick structure describes where to draw x and y "ticks" for a glist */ + +typedef struct _tick /* where to put ticks on x or y axes */ +{ + float k_point; /* one point to draw a big tick at */ + float k_inc; /* x or y increment per little tick */ + int k_lperb; /* little ticks per big; 0 if no ticks to draw */ +} t_tick; + +/* the t_glist structure, which describes a list of elements that live on an +area of a window. + +*/ + +struct _glist +{ + t_object gl_obj; /* header in case we're a glist */ + t_gobj *gl_list; /* the actual data */ + struct _gstub *gl_stub; /* safe pointer handler */ + int gl_valid; /* incremented when pointers might be stale */ + struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */ + int gl_pixwidth; /* width in pixels (on parent, if a graph) */ + int gl_pixheight; + float gl_x1; /* bounding rectangle in our own coordinates */ + float gl_y1; + float gl_x2; + float gl_y2; + int gl_screenx1; /* screen coordinates when toplevel */ + int gl_screeny1; + int gl_screenx2; + int gl_screeny2; + t_tick gl_xtick; /* ticks marking X values */ + int gl_nxlabels; /* number of X coordinate labels */ + t_symbol **gl_xlabel; /* ... an array to hold them */ + float gl_xlabely; /* ... and their Y coordinates */ + t_tick gl_ytick; /* same as above for Y ticks and labels */ + int gl_nylabels; + t_symbol **gl_ylabel; + float gl_ylabelx; + t_editor *gl_editor; /* editor structure when visible */ + t_symbol *gl_name; /* symbol bound here */ + int gl_font; /* nominal font size in points, e.g., 10 */ + struct _glist *gl_next; /* link in list of toplevels */ + t_canvasenvironment *gl_env; /* root canvases and abstractions only */ + unsigned int gl_havewindow:1; /* true if we own a window */ + unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */ + unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */ + unsigned int gl_loading:1; /* am now loading from file */ + unsigned int gl_willvis:1; /* make me visible after loading */ + unsigned int gl_edit:1; /* edit mode */ + unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */ + unsigned int gl_stretch:1; /* stretch contents on resize */ + unsigned int gl_isgraph:1; /* show as graph on parent */ +}; + +#define gl_gobj gl_obj.te_g +#define gl_pd gl_gobj.g_pd + +/* a data structure to describe a field in a pure datum */ + +#define DT_FLOAT 0 +#define DT_SYMBOL 1 +#define DT_LIST 2 +#define DT_ARRAY 3 + +typedef struct _dataslot +{ + int ds_type; + t_symbol *ds_name; + t_symbol *ds_arraytemplate; /* filled in for arrays only */ +} t_dataslot; + + +/* T.Grill - changed t_pd member to t_pdobj to avoid name clashed */ +typedef struct _template +{ + t_pd t_pdobj; /* header */ + struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */ + t_symbol *t_sym; /* name */ + int t_n; /* number of dataslots (fields) */ + t_dataslot *t_vec; /* array of dataslots */ +} t_template; + +struct _array +{ + int a_n; /* number of elements */ + int a_elemsize; /* size in bytes; LATER get this from template */ + char *a_vec; /* array of elements */ + t_symbol *a_templatesym; /* template for elements */ + int a_valid; /* protection against stale pointers into array */ + t_gpointer a_gp; /* pointer to scalar or array element we're in */ + t_gstub *a_stub; +}; + + /* structure for traversing all the connections in a glist */ +typedef struct _linetraverser +{ + t_canvas *tr_x; + t_object *tr_ob; + int tr_nout; + int tr_outno; + t_object *tr_ob2; + t_outlet *tr_outlet; + t_inlet *tr_inlet; + int tr_nin; + int tr_inno; + int tr_x11, tr_y11, tr_x12, tr_y12; + int tr_x21, tr_y21, tr_x22, tr_y22; + int tr_lx1, tr_ly1, tr_lx2, tr_ly2; + t_outconnect *tr_nextoc; + int tr_nextoutno; +} t_linetraverser; + +/* function types used to define graphical behavior for gobjs, a bit like X +widgets. We don't use Pd methods because Pd's typechecking can't specify the +types of pointer arguments. Also it's more convenient this way, since +every "patchable" object can just get the "text" behaviors. */ + + /* Call this to get a gobj's bounding rectangle in pixels */ +typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist, + int *x1, int *y1, int *x2, int *y2); + /* and this to displace a gobj: */ +typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy); + /* change color to show selection: */ +typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state); + /* change appearance to show activation/deactivation: */ +typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state); + /* warn a gobj it's about to be deleted */ +typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist); + /* making visible or invisible */ +typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag); + /* field a mouse click (when not in "edit" mode) */ +typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + /* ... and later, resizing; getting/setting font or color... */ + +struct _widgetbehavior +{ + t_getrectfn w_getrectfn; + t_displacefn w_displacefn; + t_selectfn w_selectfn; + t_activatefn w_activatefn; + t_deletefn w_deletefn; + t_visfn w_visfn; + t_clickfn w_clickfn; +}; + +/* -------- behaviors for scalars defined by objects in template --------- */ +/* these are set by "drawing commands" in g_template.c which add appearance to +scalars, which live in some other window. If the scalar is just included +in a canvas the "parent" is a misnomer. There is also a text scalar object +which really does draw the scalar on the parent window; see g_scalar.c. */ + +/* note how the click function wants the whole scalar, not the "data", so +doesn't work on array elements... LATER reconsider this */ + + /* bounding rectangle: */ +typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int *x1, int *y1, int *x2, int *y2); + /* displace it */ +typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int dx, int dy); + /* change color to show selection */ +typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int state); + /* change appearance to show activation/deactivation: */ +typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int state); + /* making visible or invisible */ +typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist, + t_word *data, t_template *tmpl, float basex, float basey, + int flag); + /* field a mouse click */ +typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist, + t_scalar *sc, t_template *tmpl, float basex, float basey, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + +struct _parentwidgetbehavior +{ + t_parentgetrectfn w_parentgetrectfn; + t_parentdisplacefn w_parentdisplacefn; + t_parentselectfn w_parentselectfn; + t_parentactivatefn w_parentactivatefn; + t_parentvisfn w_parentvisfn; + t_parentclickfn w_parentclickfn; +}; + + /* cursor definitions; used as return value for t_parentclickfn */ +#define CURSOR_RUNMODE_NOTHING 0 +#define CURSOR_RUNMODE_CLICKME 1 +#define CURSOR_RUNMODE_THICKEN 2 +#define CURSOR_RUNMODE_ADDPOINT 3 +#define CURSOR_EDITMODE_NOTHING 4 +#define CURSOR_EDITMODE_CONNECT 5 +#define CURSOR_EDITMODE_DISCONNECT 6 +EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum); + +extern t_canvas *canvas_editing; /* last canvas to start text edting */ +extern t_canvas *canvas_whichfind; /* last canvas we did a find in */ +extern t_canvas *canvas_list; /* list of all root canvases */ +extern t_class *vinlet_class, *voutlet_class; +extern int glist_valid; /* incremented when pointers might be stale */ + +/* ------------------- functions on any gobj ----------------------------- */ +EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1, + int *x2, int *y2); +EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy); +EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state); +EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state); +EXTERN void gobj_delete(t_gobj *x, t_glist *owner); +EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag); +EXTERN int gobj_click(t_gobj *x, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit); +EXTERN void gobj_save(t_gobj *x, t_binbuf *b); +EXTERN void gobj_properties(t_gobj *x, struct _glist *glist); +EXTERN void gobj_save(t_gobj *x, t_binbuf *b); + +/* -------------------- functions on glists --------------------- */ +EXTERN t_glist *glist_new( void); +EXTERN void glist_init(t_glist *x); +EXTERN void glist_add(t_glist *x, t_gobj *g); +EXTERN void glist_cleanup(t_glist *x); +EXTERN void glist_free(t_glist *x); + +EXTERN void glist_clear(t_glist *x); +EXTERN t_canvas *glist_getcanvas(t_glist *x); +EXTERN int glist_isselected(t_glist *x, t_gobj *y); +EXTERN void glist_select(t_glist *x, t_gobj *y); +EXTERN void glist_deselect(t_glist *x, t_gobj *y); +EXTERN void glist_noselect(t_glist *x); +EXTERN void glist_selectall(t_glist *x); +EXTERN void glist_delete(t_glist *x, t_gobj *y); +EXTERN void glist_retext(t_glist *x, t_text *y); +EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn, + t_glistkeyfn keyfn, int xpos, int ypos); +EXTERN int glist_isvisible(t_glist *x); +EXTERN int glist_istoplevel(t_glist *x); +EXTERN t_glist *glist_findgraph(t_glist *x); +EXTERN int glist_getfont(t_glist *x); +EXTERN void glist_sort(t_glist *canvas); +EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format); +EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format); + +EXTERN float glist_pixelstox(t_glist *x, float xpix); +EXTERN float glist_pixelstoy(t_glist *x, float ypix); +EXTERN float glist_xtopixels(t_glist *x, float xval); +EXTERN float glist_ytopixels(t_glist *x, float yval); +EXTERN float glist_dpixtodx(t_glist *x, float dxpix); +EXTERN float glist_dpixtody(t_glist *x, float dypix); + +EXTERN void glist_redrawitem(t_glist *owner, t_gobj *gobj); +EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval); +EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv); +EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym, + float x1, float y1, float x2, float y2, + float px1, float py1, float px2, float py2); +EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name, + t_floatarg size, t_floatarg saveit, t_floatarg newgraph); +EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething); +EXTERN int glist_isgraph(t_glist *x); +EXTERN void glist_redraw(t_glist *x); +EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, + char *tag, int x1, int y1, int x2, int y2); +EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag); +EXTERN void canvas_create_editor(t_glist *x, int createit); +void canvas_deletelinesforio(t_canvas *x, t_text *text, + t_inlet *inp, t_outlet *outp); + + +/* -------------------- functions on texts ------------------------- */ +EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize); +EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag, + int width, int height, int firsttime); +EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag); +EXTERN int text_xcoord(t_text *x, t_glist *glist); +EXTERN int text_ycoord(t_text *x, t_glist *glist); +EXTERN int text_xpix(t_text *x, t_glist *glist); +EXTERN int text_ypix(t_text *x, t_glist *glist); +EXTERN int text_shouldvis(t_text *x, t_glist *glist); + +/* -------------------- functions on rtexts ------------------------- */ +#define RTEXT_DOWN 1 +#define RTEXT_DRAG 2 +#define RTEXT_DBL 3 +#define RTEXT_SHIFT 4 + +EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who); +EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who); +EXTERN void rtext_draw(t_rtext *x); +EXTERN void rtext_erase(t_rtext *x); +EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x); +EXTERN int rtext_height(t_rtext *x); +EXTERN void rtext_displace(t_rtext *x, int dx, int dy); +EXTERN void rtext_select(t_rtext *x, int state); +EXTERN void rtext_activate(t_rtext *x, int state); +EXTERN void rtext_free(t_rtext *x); +EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s); +EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag); +EXTERN void rtext_retext(t_rtext *x); +EXTERN int rtext_width(t_rtext *x); +EXTERN int rtext_height(t_rtext *x); +EXTERN char *rtext_gettag(t_rtext *x); +EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize); + +/* -------------------- functions on canvases ------------------------ */ +EXTERN t_class *canvas_class; + +EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv); +EXTERN t_symbol *canvas_makebindsym(t_symbol *s); +EXTERN void canvas_vistext(t_canvas *x, t_text *y); +EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text); +EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text); +EXTERN void canvas_stowconnections(t_canvas *x); +EXTERN void canvas_restoreconnections(t_canvas *x); +EXTERN void canvas_redraw(t_canvas *x); + +EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym); +EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip); +EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym); +EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op); +EXTERN void canvas_redrawallfortemplate(t_canvas *tmpl); +EXTERN void canvas_zapallfortemplate(t_canvas *tmpl); +EXTERN void canvas_setusedastemplate(t_canvas *x); +EXTERN t_canvas *canvas_getcurrent(void); +EXTERN void canvas_setcurrent(t_canvas *x); +EXTERN void canvas_unsetcurrent(t_canvas *x); +EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s); +EXTERN t_canvas *canvas_getrootfor(t_canvas *x); +EXTERN void canvas_dirty(t_canvas *x, t_int n); +EXTERN int canvas_getfont(t_canvas *x); +typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3); + +EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn, + t_int x1, t_int x2, t_int x3); + +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 int canvas_isabstraction(t_canvas *x); +EXTERN int canvas_istable(t_canvas *x); +EXTERN int canvas_showtext(t_canvas *x); +EXTERN void canvas_vis(t_canvas *x, t_floatarg f); +EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x); +EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir); +EXTERN void canvas_loadbang(t_canvas *x); +EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos, + int *x1p, int *y1p, int *x2p, int *y2p); +EXTERN int canvas_setdeleting(t_canvas *x, int flag); + +typedef void (*t_undofn)(t_canvas *canvas, void *buf, + int action); /* a function that does UNDO/REDO */ +#define UNDO_FREE 0 /* free current undo/redo buffer */ +#define UNDO_UNDO 1 /* undo */ +#define UNDO_REDO 2 /* redo */ +EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, + const char *name); +EXTERN void canvas_noundo(t_canvas *x); +EXTERN int canvas_getindex(t_canvas *x, t_gobj *y); + +/* T.Grill - made public for dynamic object creation */ +/* in g_editor.c */ +EXTERN void canvas_connect(t_canvas *x, + t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno); +EXTERN void canvas_disconnect(t_canvas *x, + float index1, float outno, float index2, float inno); +EXTERN int canvas_isconnected (t_canvas *x, + t_text *ob1, int n1, t_text *ob2, int n2); +EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy); + + +/* ---- functions on canvasses as objects --------------------- */ + +EXTERN void canvas_fattenforscalars(t_canvas *x, + int *x1, int *y1, int *x2, int *y2); +EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis); +EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift, + int alt, int dbl, int doit); +EXTERN t_glist *canvas_getglistonsuper(void); + +EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x); +EXTERN t_outconnect *linetraverser_next(t_linetraverser *t); +EXTERN void linetraverser_skipobject(t_linetraverser *t); + +/* --------------------- functions on tscalars --------------------- */ + +EXTERN void tscalar_getrect(t_tscalar *x, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2); +EXTERN void tscalar_vis(t_tscalar *x, t_glist *owner, int flag); +EXTERN int tscalar_click(t_tscalar *x, int xpix, int ypix, int shift, + int alt, int dbl, int doit); + +/* --------- functions on garrays (graphical arrays) -------------------- */ + +EXTERN t_template *garray_template(t_garray *x); + +/* -------------------- arrays --------------------- */ +EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl, + t_floatarg f, t_floatarg saveit); +EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent); +EXTERN void array_resize(t_array *x, t_template *tmpl, int n); +EXTERN void array_free(t_array *x); + +/* --------------------- gpointers and stubs ---------------- */ +EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a); +EXTERN void gstub_cutoff(t_gstub *gs); +EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x); + +/* --------------------- scalars ------------------------- */ +EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp); +EXTERN void word_restore(t_word *wp, t_template *tmpl, + int argc, t_atom *argv); +EXTERN t_scalar *scalar_new(t_glist *owner, + t_symbol *templatesym); +EXTERN void scalar_getbasexy(t_scalar *x, float *basex, float *basey); + +/* ------helper routines for "garrays" and "plots" -------------- */ +EXTERN int array_doclick(t_array *array, t_glist *glist, t_gobj *gobj, + t_symbol *elemtemplatesym, + float linewidth, float xloc, float xinc, float yloc, + int xpix, int ypix, int shift, int alt, int dbl, int doit); + +EXTERN void array_getcoordinate(t_glist *glist, + char *elem, int xonset, int yonset, int wonset, int indx, + float basex, float basey, float xinc, + float *xp, float *yp, float *wp); + +EXTERN int array_getfields(t_symbol *elemtemplatesym, + t_canvas **elemtemplatecanvasp, + t_template **elemtemplatep, int *elemsizep, + int *xonsetp, int *yonsetp, int *wonsetp); + +/* --------------------- templates ------------------------- */ +EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv); +EXTERN void template_free(t_template *x); +EXTERN int template_match(t_template *x1, t_template *x2); +EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset, + int *p_type, t_symbol **p_arraytype); +EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp, + int loud); +EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp, + t_float f, int loud); +EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, t_symbol *s, int loud); + +EXTERN t_template *gtemplate_get(t_gtemplate *x); +EXTERN t_template *template_findbyname(t_symbol *s); +EXTERN t_canvas *template_findcanvas(t_template *tmpl); + +EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, + t_word *wp, t_float f, int loud); +EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, int loud); +EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname, + t_word *wp, t_symbol *s, int loud); + +/* ----------------------- guiconnects, g_guiconnect.c --------- */ +EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym); +EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay); + +/* ------------- IEMGUI routines used in other g_ files ---------------- */ +EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s); +EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s); + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +} +#endif diff --git a/apps/plugins/pdbox/PDa/extra/gcanvas-help.pd b/apps/plugins/pdbox/PDa/extra/gcanvas-help.pd new file mode 100644 index 0000000000..e0e3fd6f4d --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/gcanvas-help.pd @@ -0,0 +1,16 @@ +#N canvas 0 0 240 300 8; +#X obj 21 61 gcanvas 80 80; +#X text 14 9 gcanvas .. mouse coordinate enabled canvas; +#X text 13 22 ==========================================; +#X floatatom 21 148 5 0 0 0 - - -; +#X floatatom 94 147 5 0 0 0 - - -; +#X connect 0 0 3 0; +#X connect 0 1 4 0; +#N canvas 0 0 240 300 8; +#X obj 21 61 gcanvas 80 80; +#X text 14 9 gcanvas .. mouse coordinate enabled canvas; +#X text 13 22 ==========================================; +#X floatatom 21 148 5 0 0 0 - - -; +#X floatatom 94 147 5 0 0 0 - - -; +#X connect 0 0 3 0; +#X connect 0 1 4 0; diff --git a/apps/plugins/pdbox/PDa/extra/gcanvas.c b/apps/plugins/pdbox/PDa/extra/gcanvas.c new file mode 100644 index 0000000000..aed5c96cec --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/gcanvas.c @@ -0,0 +1,758 @@ +/* (C) Guenter Geiger */ + + +#include "m_pd.h" +#include "g_canvas.h" + +/* ------------------------ gcanvas ----------------------------- */ + + +#define BACKGROUNDCOLOR "grey" + +#define DEFAULTSIZE 80 + +static t_class *gcanvas_class; + +typedef struct _gcanvas +{ + t_object x_obj; + t_glist * x_glist; + t_outlet* out2; + t_outlet* out3; + int x_width; + int x_height; + int x; + int y; + int x_xgrid; + int x_ygrid; +} t_gcanvas; + + +static void rectangle(void* cv,void* o,char c,int x, int y,int w,int h,char* color) { + sys_vgui(".x%x.c create rectangle \ + %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color); +} + +static void move_object(void* cv,void* o,char c,int x, int y,int w,int h) { + sys_vgui(".x%x.c coords %x%c %d %d %d %d\n", + cv,o,c,x,y,x+w,y+h); + +} + +static void color_object(void* cv,void* o,char c,char* color) { + sys_vgui(".x%x.c itemconfigure %x%c -fill %s\n", cv, + o, c,color); +} + +static void delete_object(void* cv,void* o,char c) { + sys_vgui(".x%x.c delete %x%c\n", + cv, o,c); +} + +static void line(void* cv,void* o,char c,int x,int y,int w,int h,char* color) { + sys_vgui(".x%x.c create line \ + %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color); +} + + +/* widget helper functions */ + +void gcanvas_drawme(t_gcanvas *x, t_glist *glist, int firsttime) +{ + int i; + if (firsttime) { + rectangle(glist_getcanvas(glist),x,'a', + x->x_obj.te_xpix, x->x_obj.te_ypix, + x->x_width, x->x_height,BACKGROUNDCOLOR); + for (i=1;ix_xgrid;i++) + line(glist_getcanvas(glist),x,'b'+ i, + x->x_obj.te_xpix + x->x_width*i/x->x_xgrid, + x->x_obj.te_ypix, + 0, x->x_height,"red"); + for (i=1;ix_ygrid;i++) + line(glist_getcanvas(glist),x,'B'+ i, + x->x_obj.te_xpix, + x->x_obj.te_ypix + x->x_height*i/x->x_ygrid, + x->x_width, 0,"blue"); + } + else { + move_object( + glist_getcanvas(glist),x,'a', + x->x_obj.te_xpix, x->x_obj.te_ypix, + x->x_width, x->x_height); + for (i=1;ix_xgrid;i++) + move_object(glist_getcanvas(glist),x,'b'+ i, + x->x_obj.te_xpix + x->x_width*i/x->x_xgrid, + x->x_obj.te_ypix, + 0, x->x_height); + for (i=1;ix_ygrid;i++) + move_object(glist_getcanvas(glist),x,'B'+ i, + x->x_obj.te_xpix, + x->x_obj.te_ypix + x->x_height*i/x->x_ygrid, + x->x_width, 0); + } + + { + /* outlets */ + int n = 3; + int nplus, i; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, x->x_obj.te_ypix + x->x_height - 1, + onset + IOWIDTH, x->x_obj.te_ypix + x->x_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, x->x_obj.te_ypix + x->x_height - 1, + onset + IOWIDTH, x->x_obj.te_ypix + x->x_height); + } + /* inlets */ + n = 0; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, x->x_obj.te_ypix, + onset + IOWIDTH, x->x_obj.te_ypix + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, x->x_obj.te_ypix, + onset + IOWIDTH, x->x_obj.te_ypix + 1); + + } + } + +} + + + + +void gcanvas_erase(t_gcanvas* x,t_glist* glist) +{ + int n,i; + delete_object(glist_getcanvas(glist),x,'a'); + for (i=1;ix_xgrid;i++) + delete_object(glist_getcanvas(glist),x,'b'+ i); + for (i=1;ix_ygrid;i++) + delete_object(glist_getcanvas(glist),x,'B'+ i); + + n = 2; + while (n--) { + sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,n); + } +} + + + +/* ------------------------ gcanvas widgetbehaviour----------------------------- */ + + +static void gcanvas_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_gcanvas* s = (t_gcanvas*)z; + + + width = s->x_width; + height = s->x_height; + *xp1 = s->x_obj.te_xpix; + *yp1 = s->x_obj.te_ypix; + *xp2 = s->x_obj.te_xpix + width; + *yp2 = s->x_obj.te_ypix + height; +} + +static void gcanvas_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_gcanvas *x = (t_gcanvas *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + gcanvas_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void gcanvas_select(t_gobj *z, t_glist *glist, int state) +{ + t_gcanvas *x = (t_gcanvas *)z; + color_object(glist,x,'a',state ? "blue" : BACKGROUNDCOLOR); +} + + +static void gcanvas_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void gcanvas_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void gcanvas_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_gcanvas* s = (t_gcanvas*)z; + if (vis) + gcanvas_drawme(s, glist, 1); + else + gcanvas_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void gcanvas_save(t_gobj *z, t_binbuf *b) +{ + t_gcanvas *x = (t_gcanvas *)z; + binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + gensym("gcanvas"),x->x_width,x->x_height, + x->x_xgrid, + x->x_ygrid); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior gcanvas_widgetbehavior; + +static void gcanvas_motion(t_gcanvas *x, t_floatarg dx, t_floatarg dy) +{ + x->x += dx; + x->y += dy; + outlet_float(x->out2,x->y); + outlet_float(x->x_obj.ob_outlet,x->x); +} + +void gcanvas_key(t_gcanvas *x, t_floatarg f) +{ + post("key"); +} + + +static void gcanvas_click(t_gcanvas *x, + t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, + t_floatarg doit,int up) +{ + glist_grab(x->x_glist, &x->x_obj.te_g, (t_glistmotionfn) gcanvas_motion, + (t_glistkeyfn) NULL, xpos, ypos); + + x->x = xpos - x->x_obj.te_xpix; + x->y = ypos - x->x_obj.te_ypix; + outlet_float(x->out2,x->y); + outlet_float(x->x_obj.ob_outlet,x->x); + outlet_float(x->out3,0); +} + +static int gcanvas_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if (doit) + gcanvas_click((t_gcanvas *)z, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, 0, (t_floatarg)alt,dbl); + + if (dbl) outlet_float(((t_gcanvas*)z)->out3,1); + return (1); +} + +void gcanvas_size(t_gcanvas* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; + gcanvas_drawme(x, x->x_glist, 0); +} + +static void gcanvas_setwidget(void) +{ + gcanvas_widgetbehavior.w_getrectfn = gcanvas_getrect; + gcanvas_widgetbehavior.w_displacefn = gcanvas_displace; + gcanvas_widgetbehavior.w_selectfn = gcanvas_select; + gcanvas_widgetbehavior.w_activatefn = gcanvas_activate; + gcanvas_widgetbehavior.w_deletefn = gcanvas_delete; + gcanvas_widgetbehavior.w_visfn = gcanvas_vis; + gcanvas_widgetbehavior.w_clickfn = gcanvas_newclick; + class_setsavefn(gcanvas_class,gcanvas_save); +} + + +static void *gcanvas_new(t_symbol* s,t_int ac,t_atom* at) +{ + t_gcanvas *x = (t_gcanvas *)pd_new(gcanvas_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + + /* Fetch the width */ + + x->x_width = DEFAULTSIZE; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_width = atom_getfloat(at++); + + if (x->x_width < 0 || x->x_width > 2000) { + error("gcanvas: unallowed width %f",x->x_width); + x->x_width = DEFAULTSIZE; + } + } + + /* Fetch the height */ + + x->x_height = DEFAULTSIZE; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_height = atom_getfloat(at++); + + if (x->x_height < 0 || x->x_height > 2000) { + error("gcanvas: unallowed height %f",x->x_height); + x->x_width = DEFAULTSIZE; + } + } + + /* Fetch the xgrid */ + + x->x_xgrid = 0; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_xgrid = atom_getfloat(at++); + + if (x->x_xgrid < 0 || x->x_xgrid > x->x_width/2) { + error("gcanvas: unallowed xgrid %f",x->x_xgrid); + x->x_xgrid = 0; + } + } + + /* Fetch the ygrid */ + + x->x_ygrid = 0; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_ygrid = atom_getfloat(at++); + + if (x->x_ygrid < 0 || x->x_ygrid > x->x_height/2) { + error("gcanvas: unallowed xgrid %f",x->x_ygrid); + x->x_ygrid = 0; + } + } + + outlet_new(&x->x_obj, &s_float); + x->out2 = outlet_new(&x->x_obj, &s_float); + x->out3 = outlet_new(&x->x_obj, &s_float); + return (x); +} + + + +void gcanvas_setup(void) +{ + gcanvas_class = class_new(gensym("gcanvas"), (t_newmethod)gcanvas_new, 0, + sizeof(t_gcanvas),0, A_GIMME,0); + + class_addmethod(gcanvas_class, (t_method)gcanvas_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(gcanvas_class, (t_method)gcanvas_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + gcanvas_setwidget(); + class_setwidget(gcanvas_class,&gcanvas_widgetbehavior); +} + + +/* (C) Guenter Geiger */ + + +#include "m_pd.h" +#include "g_canvas.h" + +/* ------------------------ gcanvas ----------------------------- */ + + +#define BACKGROUNDCOLOR "grey" + +#define DEFAULTSIZE 80 + +static t_class *gcanvas_class; + +typedef struct _gcanvas +{ + t_object x_obj; + t_glist * x_glist; + t_outlet* out2; + t_outlet* out3; + int x_width; + int x_height; + int x; + int y; + int x_xgrid; + int x_ygrid; +} t_gcanvas; + + +static void rectangle(void* cv,void* o,char c,int x, int y,int w,int h,char* color) { + sys_vgui(".x%x.c create rectangle \ + %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color); +} + +static void move_object(void* cv,void* o,char c,int x, int y,int w,int h) { + sys_vgui(".x%x.c coords %x%c %d %d %d %d\n", + cv,o,c,x,y,x+w,y+h); + +} + +static void color_object(void* cv,void* o,char c,char* color) { + sys_vgui(".x%x.c itemconfigure %x%c -fill %s\n", cv, + o, c,color); +} + +static void delete_object(void* cv,void* o,char c) { + sys_vgui(".x%x.c delete %x%c\n", + cv, o,c); +} + +static void line(void* cv,void* o,char c,int x,int y,int w,int h,char* color) { + sys_vgui(".x%x.c create line \ + %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color); +} + + +/* widget helper functions */ + +void gcanvas_drawme(t_gcanvas *x, t_glist *glist, int firsttime) +{ + int i; + if (firsttime) { + rectangle(glist_getcanvas(glist),x,'a', + x->x_obj.te_xpix, x->x_obj.te_ypix, + x->x_width, x->x_height,BACKGROUNDCOLOR); + for (i=1;ix_xgrid;i++) + line(glist_getcanvas(glist),x,'b'+ i, + x->x_obj.te_xpix + x->x_width*i/x->x_xgrid, + x->x_obj.te_ypix, + 0, x->x_height,"red"); + for (i=1;ix_ygrid;i++) + line(glist_getcanvas(glist),x,'B'+ i, + x->x_obj.te_xpix, + x->x_obj.te_ypix + x->x_height*i/x->x_ygrid, + x->x_width, 0,"blue"); + } + else { + move_object( + glist_getcanvas(glist),x,'a', + x->x_obj.te_xpix, x->x_obj.te_ypix, + x->x_width, x->x_height); + for (i=1;ix_xgrid;i++) + move_object(glist_getcanvas(glist),x,'b'+ i, + x->x_obj.te_xpix + x->x_width*i/x->x_xgrid, + x->x_obj.te_ypix, + 0, x->x_height); + for (i=1;ix_ygrid;i++) + move_object(glist_getcanvas(glist),x,'B'+ i, + x->x_obj.te_xpix, + x->x_obj.te_ypix + x->x_height*i/x->x_ygrid, + x->x_width, 0); + } + + { + /* outlets */ + int n = 3; + int nplus, i; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, x->x_obj.te_ypix + x->x_height - 1, + onset + IOWIDTH, x->x_obj.te_ypix + x->x_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, x->x_obj.te_ypix + x->x_height - 1, + onset + IOWIDTH, x->x_obj.te_ypix + x->x_height); + } + /* inlets */ + n = 0; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, x->x_obj.te_ypix, + onset + IOWIDTH, x->x_obj.te_ypix + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, x->x_obj.te_ypix, + onset + IOWIDTH, x->x_obj.te_ypix + 1); + + } + } + +} + + + + +void gcanvas_erase(t_gcanvas* x,t_glist* glist) +{ + int n,i; + delete_object(glist_getcanvas(glist),x,'a'); + for (i=1;ix_xgrid;i++) + delete_object(glist_getcanvas(glist),x,'b'+ i); + for (i=1;ix_ygrid;i++) + delete_object(glist_getcanvas(glist),x,'B'+ i); + + n = 2; + while (n--) { + sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,n); + } +} + + + +/* ------------------------ gcanvas widgetbehaviour----------------------------- */ + + +static void gcanvas_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_gcanvas* s = (t_gcanvas*)z; + + + width = s->x_width; + height = s->x_height; + *xp1 = s->x_obj.te_xpix; + *yp1 = s->x_obj.te_ypix; + *xp2 = s->x_obj.te_xpix + width; + *yp2 = s->x_obj.te_ypix + height; +} + +static void gcanvas_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_gcanvas *x = (t_gcanvas *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + gcanvas_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void gcanvas_select(t_gobj *z, t_glist *glist, int state) +{ + t_gcanvas *x = (t_gcanvas *)z; + color_object(glist,x,'a',state ? "blue" : BACKGROUNDCOLOR); +} + + +static void gcanvas_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void gcanvas_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void gcanvas_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_gcanvas* s = (t_gcanvas*)z; + if (vis) + gcanvas_drawme(s, glist, 1); + else + gcanvas_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void gcanvas_save(t_gobj *z, t_binbuf *b) +{ + t_gcanvas *x = (t_gcanvas *)z; + binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + gensym("gcanvas"),x->x_width,x->x_height, + x->x_xgrid, + x->x_ygrid); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior gcanvas_widgetbehavior; + +static void gcanvas_motion(t_gcanvas *x, t_floatarg dx, t_floatarg dy) +{ + x->x += dx; + x->y += dy; + outlet_float(x->out2,x->y); + outlet_float(x->x_obj.ob_outlet,x->x); +} + +void gcanvas_key(t_gcanvas *x, t_floatarg f) +{ + post("key"); +} + + +static void gcanvas_click(t_gcanvas *x, + t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, + t_floatarg doit,int up) +{ + glist_grab(x->x_glist, &x->x_obj.te_g, (t_glistmotionfn) gcanvas_motion, + (t_glistkeyfn) NULL, xpos, ypos); + + x->x = xpos - x->x_obj.te_xpix; + x->y = ypos - x->x_obj.te_ypix; + outlet_float(x->out2,x->y); + outlet_float(x->x_obj.ob_outlet,x->x); + outlet_float(x->out3,0); +} + +static int gcanvas_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + if (doit) + gcanvas_click((t_gcanvas *)z, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, 0, (t_floatarg)alt,dbl); + + if (dbl) outlet_float(((t_gcanvas*)z)->out3,1); + return (1); +} + +void gcanvas_size(t_gcanvas* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; + gcanvas_drawme(x, x->x_glist, 0); +} + +static void gcanvas_setwidget(void) +{ + gcanvas_widgetbehavior.w_getrectfn = gcanvas_getrect; + gcanvas_widgetbehavior.w_displacefn = gcanvas_displace; + gcanvas_widgetbehavior.w_selectfn = gcanvas_select; + gcanvas_widgetbehavior.w_activatefn = gcanvas_activate; + gcanvas_widgetbehavior.w_deletefn = gcanvas_delete; + gcanvas_widgetbehavior.w_visfn = gcanvas_vis; + gcanvas_widgetbehavior.w_clickfn = gcanvas_newclick; + class_setsavefn(gcanvas_class,gcanvas_save); +} + + +static void *gcanvas_new(t_symbol* s,t_int ac,t_atom* at) +{ + t_gcanvas *x = (t_gcanvas *)pd_new(gcanvas_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + + /* Fetch the width */ + + x->x_width = DEFAULTSIZE; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_width = atom_getfloat(at++); + + if (x->x_width < 0 || x->x_width > 2000) { + error("gcanvas: unallowed width %f",x->x_width); + x->x_width = DEFAULTSIZE; + } + } + + /* Fetch the height */ + + x->x_height = DEFAULTSIZE; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_height = atom_getfloat(at++); + + if (x->x_height < 0 || x->x_height > 2000) { + error("gcanvas: unallowed height %f",x->x_height); + x->x_width = DEFAULTSIZE; + } + } + + /* Fetch the xgrid */ + + x->x_xgrid = 0; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_xgrid = atom_getfloat(at++); + + if (x->x_xgrid < 0 || x->x_xgrid > x->x_width/2) { + error("gcanvas: unallowed xgrid %f",x->x_xgrid); + x->x_xgrid = 0; + } + } + + /* Fetch the ygrid */ + + x->x_ygrid = 0; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_ygrid = atom_getfloat(at++); + + if (x->x_ygrid < 0 || x->x_ygrid > x->x_height/2) { + error("gcanvas: unallowed xgrid %f",x->x_ygrid); + x->x_ygrid = 0; + } + } + + outlet_new(&x->x_obj, &s_float); + x->out2 = outlet_new(&x->x_obj, &s_float); + x->out3 = outlet_new(&x->x_obj, &s_float); + return (x); +} + + + +void gcanvas_setup(void) +{ + gcanvas_class = class_new(gensym("gcanvas"), (t_newmethod)gcanvas_new, 0, + sizeof(t_gcanvas),0, A_GIMME,0); + + class_addmethod(gcanvas_class, (t_method)gcanvas_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(gcanvas_class, (t_method)gcanvas_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + gcanvas_setwidget(); + class_setwidget(gcanvas_class,&gcanvas_widgetbehavior); +} + + diff --git a/apps/plugins/pdbox/PDa/extra/highpass.c b/apps/plugins/pdbox/PDa/extra/highpass.c new file mode 100644 index 0000000000..88ba4564e6 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/highpass.c @@ -0,0 +1,174 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + +/* ------------------- highpass ----------------------------*/ + +static t_class *highpass_class; + +void highpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = -(1 + cos(omega)); + t_float b0 = -b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highpass_bang(x); +} + + +static void *highpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void highpass_setup(void) +{ + highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highpass_class,highpass_bang); + class_addfloat(highpass_class,highpass_float); +} + + + + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + +/* ------------------- highpass ----------------------------*/ + +static t_class *highpass_class; + +void highpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = -(1 + cos(omega)); + t_float b0 = -b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highpass_bang(x); +} + + +static void *highpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void highpass_setup(void) +{ + highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highpass_class,highpass_bang); + class_addfloat(highpass_class,highpass_float); +} + + + + diff --git a/apps/plugins/pdbox/PDa/extra/highshelf.c b/apps/plugins/pdbox/PDa/extra/highshelf.c new file mode 100644 index 0000000000..0060d896c2 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/highshelf.c @@ -0,0 +1,180 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + +/* ------------------- highshelf ----------------------------*/ + +static t_class *highshelf_class; + +void highshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw* 0.01); + + t_float b0 = A*((A+1) + (A-1)*cs + beta*sn); + t_float b1 =-2.*A*((A-1) + (A+1)*cs); + t_float b2 = A*((A+1) + (A-1)*cs - beta*sn); + t_float a0 = ((A+1) - (A-1)*cs + beta*sn); + t_float a1 = 2.*((A-1) - (A+1)*cs); + t_float a2 = ((A+1) - (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highshelf_bang(x); +} + + +static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void highshelf_setup(void) +{ + highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highshelf_class,highshelf_bang); + class_addfloat(highshelf_class,highshelf_float); +} + + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + +/* ------------------- highshelf ----------------------------*/ + +static t_class *highshelf_class; + +void highshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw* 0.01); + + t_float b0 = A*((A+1) + (A-1)*cs + beta*sn); + t_float b1 =-2.*A*((A-1) + (A+1)*cs); + t_float b2 = A*((A+1) + (A-1)*cs - beta*sn); + t_float a0 = ((A+1) - (A-1)*cs + beta*sn); + t_float a1 = 2.*((A-1) - (A+1)*cs); + t_float a2 = ((A+1) - (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highshelf_bang(x); +} + + +static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void highshelf_setup(void) +{ + highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highshelf_class,highshelf_bang); + class_addfloat(highshelf_class,highshelf_float); +} + + diff --git a/apps/plugins/pdbox/PDa/extra/hlshelf.c b/apps/plugins/pdbox/PDa/extra/hlshelf.c new file mode 100644 index 0000000000..46190c9b7c --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/hlshelf.c @@ -0,0 +1,452 @@ +/* (C) Guenter Geiger */ + + +#include +#include + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ hlshelf ----------------------------- */ + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + +#define SRATE 44100.0 +#define MAX_GAIN 120.0f + +static t_class *hlshelf_class; + + +typedef struct _hlshelf +{ + t_object x_obj; + float s_rate; + float s_gain0; + float s_gain1; + float s_gain2; + float s_ltransfq; + float s_htransfq; + float s_lradians; + float s_hradians; +} t_hlshelf; + + +int hlshelf_check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + +void hlshelf_check(t_hlshelf *x) +{ + + if(x->s_gain0 - x->s_gain1 > MAX_GAIN) { + x->s_gain0 = x->s_gain1 + MAX_GAIN; + post("setting gain0 to %f",x->s_gain0); + } + + + if(x->s_gain1 > MAX_GAIN) { + x->s_gain1 = MAX_GAIN; + post("setting gain1 to %f",x->s_gain1); + } + + if(x->s_gain2 - x->s_gain1 > MAX_GAIN) { + x->s_gain2 = x->s_gain1 + MAX_GAIN; + post("setting gain2 to %f",x->s_gain2); + } + + /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */ + x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f; + + if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + +} + + +void hlshelf_bang(t_hlshelf *x) +{ + t_atom at[6]; + float c0, c1, c2, d0, d1, d2; /* output coefs */ + float a1, a2, b1, b2, g1, g2; /* temp coefs */ + double xf; + + hlshelf_check(x); + + /* low shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a1 = 1.0f; + b1 = -1.0f; + g1 = 0.0f; + } + else + { + double t = tan(x->s_lradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a1 = (r - 1) / (r + 1); + b1 = (kr - 1) / (kr + 1); + g1 = (kr + 1) / (r + 1); + } + + /* high shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a2 = -1.0f; + b2 = 1.0f; + g2 = 0.0f; + } + else + { + double t = tan(x->s_hradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a2 = (1 - r) / (1 + r); + b2 = (1 - kr) / (1 + kr); + g2 = (1 + kr) / (1 + r); + } + + /* form product */ + c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ; + c1 = a1 + a2; + c2 = a1 * a2; + d0 = 1.0f; + d1 = b1 + b2; + d2 = b1 * b2; + + if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) { + post("hlshelf: filter unstable -> resetting"); + c0=1.;c1=0.;c2=0.; + d0=1.;d1=0.;d2=0.; + } + + SETFLOAT(at,-c1/d0); + SETFLOAT(at+1,-c2/d0); + SETFLOAT(at+2,d0/d0); + SETFLOAT(at+3,d1/d0); + SETFLOAT(at+4,d2/d0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + +void hlshelf_float(t_hlshelf *x,t_floatarg f) +{ + x->s_gain0 = f; + hlshelf_bang(x); +} + + +static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at) +{ + t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class); + t_float k0 = atom_getfloat(at); + t_float k1 = atom_getfloat(at+1); + t_float k2 = atom_getfloat(at+2); + t_float f1 = atom_getfloat(at+3); + t_float f2 = atom_getfloat(at+4); + + + f1 = atom_getfloat(at); + f2 = atom_getfloat(at); + + if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */ + f1 = 150.0f; + f2 = 5000.0f; + } + + if (f1 < 0) f1 = 0.0f; + if (f2 > SRATE) f2 = .5f*SRATE; + + x->s_rate = SRATE; /* srate default */ + x->s_gain0 = k0; + x->s_gain1 = k1; + x->s_gain2 = k2; + + x->s_ltransfq = 0.0f; + x->s_htransfq = SRATE/2; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + + floatinlet_new(&x->x_obj, &x->s_gain1); + floatinlet_new(&x->x_obj, &x->s_gain2); + floatinlet_new(&x->x_obj, &x->s_ltransfq); + floatinlet_new(&x->x_obj, &x->s_htransfq); + outlet_new(&x->x_obj, &s_list); + + return (x); +} + +void hlshelf_setup(void) +{ + hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0, + sizeof(t_hlshelf), 0, A_GIMME, 0); + class_addbang(hlshelf_class,hlshelf_bang); + class_addfloat(hlshelf_class,hlshelf_float); +} + + +/* (C) Guenter Geiger */ + + +#include +#include + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ hlshelf ----------------------------- */ + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + +#define SRATE 44100.0 +#define MAX_GAIN 120.0f + +static t_class *hlshelf_class; + + +typedef struct _hlshelf +{ + t_object x_obj; + float s_rate; + float s_gain0; + float s_gain1; + float s_gain2; + float s_ltransfq; + float s_htransfq; + float s_lradians; + float s_hradians; +} t_hlshelf; + + +int hlshelf_check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + +void hlshelf_check(t_hlshelf *x) +{ + + if(x->s_gain0 - x->s_gain1 > MAX_GAIN) { + x->s_gain0 = x->s_gain1 + MAX_GAIN; + post("setting gain0 to %f",x->s_gain0); + } + + + if(x->s_gain1 > MAX_GAIN) { + x->s_gain1 = MAX_GAIN; + post("setting gain1 to %f",x->s_gain1); + } + + if(x->s_gain2 - x->s_gain1 > MAX_GAIN) { + x->s_gain2 = x->s_gain1 + MAX_GAIN; + post("setting gain2 to %f",x->s_gain2); + } + + /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */ + x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f; + + if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + +} + + +void hlshelf_bang(t_hlshelf *x) +{ + t_atom at[6]; + float c0, c1, c2, d0, d1, d2; /* output coefs */ + float a1, a2, b1, b2, g1, g2; /* temp coefs */ + double xf; + + hlshelf_check(x); + + /* low shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a1 = 1.0f; + b1 = -1.0f; + g1 = 0.0f; + } + else + { + double t = tan(x->s_lradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a1 = (r - 1) / (r + 1); + b1 = (kr - 1) / (kr + 1); + g1 = (kr + 1) / (r + 1); + } + + /* high shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a2 = -1.0f; + b2 = 1.0f; + g2 = 0.0f; + } + else + { + double t = tan(x->s_hradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a2 = (1 - r) / (1 + r); + b2 = (1 - kr) / (1 + kr); + g2 = (1 + kr) / (1 + r); + } + + /* form product */ + c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ; + c1 = a1 + a2; + c2 = a1 * a2; + d0 = 1.0f; + d1 = b1 + b2; + d2 = b1 * b2; + + if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) { + post("hlshelf: filter unstable -> resetting"); + c0=1.;c1=0.;c2=0.; + d0=1.;d1=0.;d2=0.; + } + + SETFLOAT(at,-c1/d0); + SETFLOAT(at+1,-c2/d0); + SETFLOAT(at+2,d0/d0); + SETFLOAT(at+3,d1/d0); + SETFLOAT(at+4,d2/d0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + +void hlshelf_float(t_hlshelf *x,t_floatarg f) +{ + x->s_gain0 = f; + hlshelf_bang(x); +} + + +static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at) +{ + t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class); + t_float k0 = atom_getfloat(at); + t_float k1 = atom_getfloat(at+1); + t_float k2 = atom_getfloat(at+2); + t_float f1 = atom_getfloat(at+3); + t_float f2 = atom_getfloat(at+4); + + + f1 = atom_getfloat(at); + f2 = atom_getfloat(at); + + if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */ + f1 = 150.0f; + f2 = 5000.0f; + } + + if (f1 < 0) f1 = 0.0f; + if (f2 > SRATE) f2 = .5f*SRATE; + + x->s_rate = SRATE; /* srate default */ + x->s_gain0 = k0; + x->s_gain1 = k1; + x->s_gain2 = k2; + + x->s_ltransfq = 0.0f; + x->s_htransfq = SRATE/2; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + + floatinlet_new(&x->x_obj, &x->s_gain1); + floatinlet_new(&x->x_obj, &x->s_gain2); + floatinlet_new(&x->x_obj, &x->s_ltransfq); + floatinlet_new(&x->x_obj, &x->s_htransfq); + outlet_new(&x->x_obj, &s_list); + + return (x); +} + +void hlshelf_setup(void) +{ + hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0, + sizeof(t_hlshelf), 0, A_GIMME, 0); + class_addbang(hlshelf_class,hlshelf_bang); + class_addfloat(hlshelf_class,hlshelf_float); +} + + diff --git a/apps/plugins/pdbox/PDa/extra/image.c b/apps/plugins/pdbox/PDa/extra/image.c new file mode 100644 index 0000000000..6de48ef8fb --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/image.c @@ -0,0 +1,434 @@ +#include "m_pd.h" +#include "g_canvas.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ image ----------------------------- */ + +static t_class *image_class; + +typedef struct _image +{ + t_object x_obj; + t_glist * x_glist; + int x_width; + int x_height; + t_symbol* x_fname; +} t_image; + +/* widget helper functions */ + +void image_drawme(t_image *x, t_glist *glist, int firsttime) +{ + if (firsttime) { + char fname[MAXPDSTRING]; + canvas_makefilename(glist_getcanvas(x->x_glist), x->x_fname->s_name, + fname, MAXPDSTRING); + + sys_vgui("image create photo img%x -file %s\n",x,fname); + sys_vgui(".x%x.c create image %d %d -image img%x -tags %xS\n", + glist_getcanvas(glist),text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x,x); + + /* TODO callback from gui + sys_vgui("image_size logo"); + */ + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); + } + +} + + +void image_erase(t_image* x,t_glist* glist) +{ + int n; + sys_vgui(".x%x.c delete %xS\n", + glist_getcanvas(glist), x); + +} + + + +/* ------------------------ image widgetbehaviour----------------------------- */ + + +static void image_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_image* x = (t_image*)z; + + + width = x->x_width; + height = x->x_height; + *xp1 = text_xpix(&x->x_obj, glist); + *yp1 = text_ypix(&x->x_obj, glist); + *xp2 = text_xpix(&x->x_obj, glist) + width; + *yp2 = text_ypix(&x->x_obj, glist) + height; +} + +static void image_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_image *x = (t_image *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height); + + image_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void image_select(t_gobj *z, t_glist *glist, int state) +{ + t_image *x = (t_image *)z; + if (state) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xSEL -outline blue\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x); + } + else { + sys_vgui(".x%x.c delete %xSEL\n", + glist_getcanvas(glist), x); + } + + + +} + + +static void image_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void image_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void image_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_image* s = (t_image*)z; + if (vis) + image_drawme(s, glist, 1); + else + image_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void image_save(t_gobj *z, t_binbuf *b) +{ + t_image *x = (t_image *)z; + binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix, + gensym("image"),x->x_fname); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior image_widgetbehavior; + +void image_size(t_image* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; +} + +void image_color(t_image* x,t_symbol* col) +{ +/* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang .. + so color black does the same as bang, but doesn't forward the bang +*/ +} + +static void image_setwidget(void) +{ + image_widgetbehavior.w_getrectfn = image_getrect; + image_widgetbehavior.w_displacefn = image_displace; + image_widgetbehavior.w_selectfn = image_select; + image_widgetbehavior.w_activatefn = image_activate; + image_widgetbehavior.w_deletefn = image_delete; + image_widgetbehavior.w_visfn = image_vis; +#if (PD_VERSION_MINOR > 31) + image_widgetbehavior.w_clickfn = NULL; + image_widgetbehavior.w_propertiesfn = NULL; +#endif +#if PD_MINOR_VERSION < 37 + image_widgetbehavior.w_savefn = image_save; +#endif +} + + +static void *image_new(t_symbol* fname) +{ + t_image *x = (t_image *)pd_new(image_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + x->x_width = 15; + x->x_height = 15; + + x->x_fname = fname; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +void image_setup(void) +{ + image_class = class_new(gensym("image"), (t_newmethod)image_new, 0, + sizeof(t_image),0, A_DEFSYM,0); + +/* + class_addmethod(image_class, (t_method)image_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(image_class, (t_method)image_color, gensym("color"), + A_SYMBOL, 0); +*/ +/* + class_addmethod(image_class, (t_method)image_open, gensym("open"), + A_SYMBOL, 0); +*/ + image_setwidget(); + class_setwidget(image_class,&image_widgetbehavior); +#if PD_MINOR_VERSION >= 37 + class_setsavefn(image_class,&image_save); +#endif +} + + +#include "m_pd.h" +#include "g_canvas.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ image ----------------------------- */ + +static t_class *image_class; + +typedef struct _image +{ + t_object x_obj; + t_glist * x_glist; + int x_width; + int x_height; + t_symbol* x_fname; +} t_image; + +/* widget helper functions */ + +void image_drawme(t_image *x, t_glist *glist, int firsttime) +{ + if (firsttime) { + char fname[MAXPDSTRING]; + canvas_makefilename(glist_getcanvas(x->x_glist), x->x_fname->s_name, + fname, MAXPDSTRING); + + sys_vgui("image create photo img%x -file %s\n",x,fname); + sys_vgui(".x%x.c create image %d %d -image img%x -tags %xS\n", + glist_getcanvas(glist),text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x,x); + + /* TODO callback from gui + sys_vgui("image_size logo"); + */ + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); + } + +} + + +void image_erase(t_image* x,t_glist* glist) +{ + int n; + sys_vgui(".x%x.c delete %xS\n", + glist_getcanvas(glist), x); + +} + + + +/* ------------------------ image widgetbehaviour----------------------------- */ + + +static void image_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_image* x = (t_image*)z; + + + width = x->x_width; + height = x->x_height; + *xp1 = text_xpix(&x->x_obj, glist); + *yp1 = text_ypix(&x->x_obj, glist); + *xp2 = text_xpix(&x->x_obj, glist) + width; + *yp2 = text_ypix(&x->x_obj, glist) + height; +} + +static void image_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_image *x = (t_image *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height); + + image_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void image_select(t_gobj *z, t_glist *glist, int state) +{ + t_image *x = (t_image *)z; + if (state) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xSEL -outline blue\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x); + } + else { + sys_vgui(".x%x.c delete %xSEL\n", + glist_getcanvas(glist), x); + } + + + +} + + +static void image_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void image_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void image_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_image* s = (t_image*)z; + if (vis) + image_drawme(s, glist, 1); + else + image_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void image_save(t_gobj *z, t_binbuf *b) +{ + t_image *x = (t_image *)z; + binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix, + gensym("image"),x->x_fname); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior image_widgetbehavior; + +void image_size(t_image* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; +} + +void image_color(t_image* x,t_symbol* col) +{ +/* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang .. + so color black does the same as bang, but doesn't forward the bang +*/ +} + +static void image_setwidget(void) +{ + image_widgetbehavior.w_getrectfn = image_getrect; + image_widgetbehavior.w_displacefn = image_displace; + image_widgetbehavior.w_selectfn = image_select; + image_widgetbehavior.w_activatefn = image_activate; + image_widgetbehavior.w_deletefn = image_delete; + image_widgetbehavior.w_visfn = image_vis; +#if (PD_VERSION_MINOR > 31) + image_widgetbehavior.w_clickfn = NULL; + image_widgetbehavior.w_propertiesfn = NULL; +#endif +#if PD_MINOR_VERSION < 37 + image_widgetbehavior.w_savefn = image_save; +#endif +} + + +static void *image_new(t_symbol* fname) +{ + t_image *x = (t_image *)pd_new(image_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + x->x_width = 15; + x->x_height = 15; + + x->x_fname = fname; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +void image_setup(void) +{ + image_class = class_new(gensym("image"), (t_newmethod)image_new, 0, + sizeof(t_image),0, A_DEFSYM,0); + +/* + class_addmethod(image_class, (t_method)image_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(image_class, (t_method)image_color, gensym("color"), + A_SYMBOL, 0); +*/ +/* + class_addmethod(image_class, (t_method)image_open, gensym("open"), + A_SYMBOL, 0); +*/ + image_setwidget(); + class_setwidget(image_class,&image_widgetbehavior); +#if PD_MINOR_VERSION >= 37 + class_setsavefn(image_class,&image_save); +#endif +} + + diff --git a/apps/plugins/pdbox/PDa/extra/lowpass.c b/apps/plugins/pdbox/PDa/extra/lowpass.c new file mode 100644 index 0000000000..c242aff0a8 --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/lowpass.c @@ -0,0 +1,178 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- lowpass ----------------------------*/ + +static t_class *lowpass_class; + +void lowpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b1 = 1 - cos(omega); + t_float b0 = b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowpass_bang(x); +} + + +static void *lowpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void lowpass_setup(void) +{ + lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowpass_class,lowpass_bang); + class_addfloat(lowpass_class,lowpass_float); +} + + + + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- lowpass ----------------------------*/ + +static t_class *lowpass_class; + +void lowpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b1 = 1 - cos(omega); + t_float b0 = b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowpass_bang(x); +} + + +static void *lowpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void lowpass_setup(void) +{ + lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowpass_class,lowpass_bang); + class_addfloat(lowpass_class,lowpass_float); +} + + + + diff --git a/apps/plugins/pdbox/PDa/extra/lowshelf.c b/apps/plugins/pdbox/PDa/extra/lowshelf.c new file mode 100644 index 0000000000..52c30d839d --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/lowshelf.c @@ -0,0 +1,182 @@ +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- lowshelf ----------------------------*/ + +static t_class *lowshelf_class; + +void lowshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw*0.01); + + t_float b0 = A*((A+1) - (A-1)*cs + beta*sn); + t_float b1 = 2.*A*((A-1) - (A+1)*cs); + t_float b2 = A*((A+1) - (A-1)*cs - beta*sn); + t_float a0 = ((A+1) + (A-1)*cs + beta*sn); + t_float a1 = -2.*((A-1) + (A+1)*cs); + t_float a2 = ((A+1) + (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowshelf_bang(x); +} + + +static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void lowshelf_setup(void) +{ + lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowshelf_class,lowshelf_bang); + class_addfloat(lowshelf_class,lowshelf_float); +} + + +/* (C) Guenter Geiger */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include +#include "filters.h" + + + +/* ------------------- lowshelf ----------------------------*/ + +static t_class *lowshelf_class; + +void lowshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw*0.01); + + t_float b0 = A*((A+1) - (A-1)*cs + beta*sn); + t_float b1 = 2.*A*((A-1) - (A+1)*cs); + t_float b2 = A*((A+1) - (A-1)*cs - beta*sn); + t_float a0 = ((A+1) + (A-1)*cs + beta*sn); + t_float a1 = -2.*((A-1) + (A+1)*cs); + t_float a2 = ((A+1) + (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowshelf_bang(x); +} + + +static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void lowshelf_setup(void) +{ + lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowshelf_class,lowshelf_bang); + class_addfloat(lowshelf_class,lowshelf_float); +} + + diff --git a/apps/plugins/pdbox/PDa/extra/m_pd.h b/apps/plugins/pdbox/PDa/extra/m_pd.h new file mode 100644 index 0000000000..403c5b382b --- /dev/null +++ b/apps/plugins/pdbox/PDa/extra/m_pd.h @@ -0,0 +1,1300 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __m_pd_h_ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { +#endif + +#define PD_VERSION 0.37 /* oops, don't use this... */ */ +#define PD_MAJOR_VERSION 0 /* ... use these two instead. */ +#define PD_MINOR_VERSION 37 + +/* old name for "MSW" flag -- we have to take it for the sake of many old +"nmakefiles" for externs, which will define NT and not MSW */ +#if defined(NT) && !defined(MSW) +#define MSW +#endif + +#ifdef MSW +// #pragma warning( disable : 4091 ) +#pragma warning( disable : 4305 ) /* uncast const double to float */ +#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */ +#pragma warning( disable : 4101 ) /* unused automatic variables */ +#endif /* MSW */ + + /* the external storage class is "extern" in UNIX; in MSW it's ugly. */ +#ifdef MSW +#ifdef PD_INTERNAL +#define EXTERN __declspec(dllexport) extern +#else +#define EXTERN __declspec(dllimport) extern +#endif /* PD_INTERNAL */ +#else +#define EXTERN extern +#endif /* MSW */ + + /* and depending on the compiler, hidden data structures are + declared differently: */ +#if defined( __GNUC__) || defined( __BORLANDC__ ) || defined( __MWERKS__ ) +#define EXTERN_STRUCT struct +#else +#define EXTERN_STRUCT extern struct +#endif + + +#if !defined(_SIZE_T) && !defined(_SIZE_T_) +#include /* just for size_t -- how lame! */ +#endif + +#define MAXPDSTRING 1000 /* use this for anything you want */ +#define MAXPDARG 5 /* max number of args we can typecheck today */ + + /* signed and unsigned integer types the size of a pointer: */ +#ifdef __alpha__ +typedef long t_int; +#else +typedef int t_int; +#endif + +typedef float t_float; /* a floating-point number at most the same size */ +typedef float t_floatarg; /* floating-point type for function calls */ + +typedef struct _symbol +{ + char *s_name; + struct _class **s_thing; + struct _symbol *s_next; +} t_symbol; + +EXTERN_STRUCT _array; +#define t_array struct _array /* g_canvas.h */ + +/* pointers to glist and array elements go through a "stub" which sticks +around after the glist or array is freed. The stub itself is deleted when +both the glist/array is gone and the refcount is zero, ensuring that no +gpointers are pointing here. */ + +#define GP_NONE 0 /* the stub points nowhere (has been cut off) */ +#define GP_GLIST 1 /* the stub points to a glist element */ +#define GP_ARRAY 2 /* ... or array */ + +typedef struct _gstub +{ + union + { + struct _glist *gs_glist; /* glist we're in */ + struct _array *gs_array; /* array we're in */ + } gs_un; + int gs_which; /* GP_GLIST/GP_ARRAY */ + int gs_refcount; /* number of gpointers pointing here */ +} t_gstub; + +typedef struct _gpointer /* pointer to a gobj in a glist */ +{ + union + { + struct _scalar *gp_scalar; /* scalar we're in (if glist) */ + union word *gp_w; /* raw data (if array) */ + } gp_un; + int gp_valid; /* number which must match gpointee */ + t_gstub *gp_stub; /* stub which points to glist/array */ +} t_gpointer; + +typedef union word +{ + t_float w_float; + t_symbol *w_symbol; + t_gpointer *w_gpointer; + t_array *w_array; + struct _glist *w_list; + int w_index; +} t_word; + +typedef enum +{ + A_NULL, + A_FLOAT, + A_SYMBOL, + A_POINTER, + A_SEMI, + A_COMMA, + A_DEFFLOAT, + A_DEFSYM, + A_DOLLAR, + A_DOLLSYM, + A_GIMME, + A_CANT +} t_atomtype; + +#define A_DEFSYMBOL A_DEFSYM /* better name for this */ + +typedef struct _atom +{ + t_atomtype a_type; + union word a_w; +} t_atom; + +EXTERN_STRUCT _class; +#define t_class struct _class + +EXTERN_STRUCT _outlet; +#define t_outlet struct _outlet + +EXTERN_STRUCT _inlet; +#define t_inlet struct _inlet + +EXTERN_STRUCT _binbuf; +#define t_binbuf struct _binbuf + +EXTERN_STRUCT _clock; +#define t_clock struct _clock + +EXTERN_STRUCT _outconnect; +#define t_outconnect struct _outconnect + +EXTERN_STRUCT _glist; +#define t_glist struct _glist +#define t_canvas struct _glist /* LATER lose this */ + +typedef t_class *t_pd; /* pure datum: nothing but a class pointer */ + +typedef struct _gobj /* a graphical object */ +{ + t_pd g_pd; /* pure datum header (class) */ + struct _gobj *g_next; /* next in list */ +} t_gobj; + +typedef struct _scalar /* a graphical object holding data */ +{ + t_gobj sc_gobj; /* header for graphical object */ + t_symbol *sc_template; /* template name (LATER replace with pointer) */ + t_word sc_vec[1]; /* indeterminate-length array of words */ +} t_scalar; + +typedef struct _text /* patchable object - graphical, with text */ +{ + t_gobj te_g; /* header for graphical object */ + t_binbuf *te_binbuf; /* holder for the text */ + t_outlet *te_outlet; /* linked list of outlets */ + t_inlet *te_inlet; /* linked list of inlets */ + short te_xpix; /* x&y location (within the toplevel) */ + short te_ypix; + short te_width; /* requested width in chars, 0 if auto */ + unsigned int te_type:2; /* from defs below */ +} t_text; + +#define T_TEXT 0 /* just a textual comment */ +#define T_OBJECT 1 /* a MAX style patchable object */ +#define T_MESSAGE 2 /* a MAX stype message */ +#define T_ATOM 3 /* a cell to display a number or symbol */ + +#define te_pd te_g.g_pd + + /* t_object is synonym for t_text (LATER unify them) */ + +typedef struct _text t_object; + +#define ob_outlet te_outlet +#define ob_inlet te_inlet +#define ob_binbuf te_binbuf +#define ob_pd te_g.g_pd +#define ob_g te_g + +typedef void (*t_method)(void); +typedef void *(*t_newmethod)( void); +typedef void (*t_gotfn)(void *x, ...); + +/* ---------------- pre-defined objects and symbols --------------*/ +EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */ +EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */ +EXTERN t_symbol s_pointer; +EXTERN t_symbol s_float; +EXTERN t_symbol s_symbol; +EXTERN t_symbol s_bang; +EXTERN t_symbol s_list; +EXTERN t_symbol s_anything; +EXTERN t_symbol s_signal; +EXTERN t_symbol s__N; +EXTERN t_symbol s__X; +EXTERN t_symbol s_x; +EXTERN t_symbol s_y; +EXTERN t_symbol s_; + +/* --------- prototypes from the central message system ----------- */ +EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv); +EXTERN t_symbol *gensym(char *s); +EXTERN t_gotfn getfn(t_pd *x, t_symbol *s); +EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s); +EXTERN void nullfn(void); +EXTERN void pd_vmess(t_pd *x, t_symbol *s, char *fmt, ...); +#define mess0(x, s) ((*getfn((x), (s)))((x))) +#define mess1(x, s, a) ((*getfn((x), (s)))((x), (a))) +#define mess2(x, s, a,b) ((*getfn((x), (s)))((x), (a),(b))) +#define mess3(x, s, a,b,c) ((*getfn((x), (s)))((x), (a),(b),(c))) +#define mess4(x, s, a,b,c,d) ((*getfn((x), (s)))((x), (a),(b),(c),(d))) +#define mess5(x, s, a,b,c,d,e) ((*getfn((x), (s)))((x), (a),(b),(c),(d),(e))) +EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv); +EXTERN t_pd *pd_newest(void); + +/* --------------- memory management -------------------- */ +EXTERN void *getbytes(size_t nbytes); +EXTERN void *getzbytes(size_t nbytes); +EXTERN void *copybytes(void *src, size_t nbytes); +EXTERN void freebytes(void *x, size_t nbytes); +EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize); + +/* -------------------- atoms ----------------------------- */ + +#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0) +#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0) +#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \ + (atom)->a_w.w_gpointer = (gp)) +#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f)) +#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \ + (atom)->a_w.w_symbol = (s)) +#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \ + (atom)->a_w.w_index = (n)) +#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \ + (atom)->a_w.w_symbol= (s)) + +EXTERN t_float atom_getfloat(t_atom *a); +EXTERN t_int atom_getint(t_atom *a); +EXTERN t_symbol *atom_getsymbol(t_atom *a); +EXTERN t_symbol *atom_gensym(t_atom *a); +EXTERN t_float atom_getfloatarg(int which, int argc, t_atom *argv); +EXTERN t_int atom_getintarg(int which, int argc, t_atom *argv); +EXTERN t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv); + +EXTERN void atom_string(t_atom *a, char *buf, unsigned int bufsize); + +/* ------------------ binbufs --------------- */ + +EXTERN t_binbuf *binbuf_new(void); +EXTERN void binbuf_free(t_binbuf *x); +EXTERN t_binbuf *binbuf_duplicate(t_binbuf *y); + +EXTERN void binbuf_text(t_binbuf *x, char *text, size_t size); +EXTERN void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp); +EXTERN void binbuf_clear(t_binbuf *x); +EXTERN void binbuf_add(t_binbuf *x, int argc, t_atom *argv); +EXTERN void binbuf_addv(t_binbuf *x, char *fmt, ...); +EXTERN void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y); +EXTERN void binbuf_addsemi(t_binbuf *x); +EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv); +EXTERN void binbuf_print(t_binbuf *x); +EXTERN int binbuf_getnatom(t_binbuf *x); +EXTERN t_atom *binbuf_getvec(t_binbuf *x); +EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv); +EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname, + int crflag); +EXTERN int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname, + int crflag); +EXTERN int binbuf_write(t_binbuf *x, char *filename, char *dir, + int crflag); +EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir); +EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, + int tonew); + +/* ------------------ clocks --------------- */ + +typedef long long t_time; +EXTERN t_clock *clock_new(void *owner, t_method fn); +EXTERN void clock_set(t_clock *x, t_time systime); +EXTERN void clock_delay(t_clock *x, t_time delaytime); +EXTERN void clock_unset(t_clock *x); +EXTERN t_time clock_getlogicaltime(void); +EXTERN t_time clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */ +EXTERN t_time clock_gettimesince(t_time prevsystime); +EXTERN t_time clock_getsystimeafter(t_time delaytime); +EXTERN void clock_free(t_clock *x); + +/* ----------------- pure data ---------------- */ +EXTERN t_pd *pd_new(t_class *cls); +EXTERN void pd_free(t_pd *x); +EXTERN void pd_bind(t_pd *x, t_symbol *s); +EXTERN void pd_unbind(t_pd *x, t_symbol *s); +EXTERN t_pd *pd_findbyclass(t_symbol *s, t_class *c); +EXTERN void pd_pushsym(t_pd *x); +EXTERN void pd_popsym(t_pd *x); +EXTERN t_symbol *pd_getfilename(void); +EXTERN t_symbol *pd_getdirname(void); +EXTERN void pd_bang(t_pd *x); +EXTERN void pd_pointer(t_pd *x, t_gpointer *gp); +EXTERN void pd_float(t_pd *x, t_float f); +EXTERN void pd_symbol(t_pd *x, t_symbol *s); +EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv); +#define pd_class(x) (*(x)) + +/* ----------------- pointers ---------------- */ +EXTERN void gpointer_init(t_gpointer *gp); +EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto); +EXTERN void gpointer_unset(t_gpointer *gp); +EXTERN int gpointer_check(const t_gpointer *gp, int headok); + +/* ----------------- patchable "objects" -------------- */ +EXTERN_STRUCT _inlet; +#define t_inlet struct _inlet +EXTERN_STRUCT _outlet; +#define t_outlet struct _outlet + +EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, + t_symbol *s2); +EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp); +EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp); +EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp); +EXTERN void inlet_free(t_inlet *x); + +EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s); +EXTERN void outlet_bang(t_outlet *x); +EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp); +EXTERN void outlet_float(t_outlet *x, t_float f); +EXTERN void outlet_symbol(t_outlet *x, t_symbol *s); +EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv); +EXTERN t_symbol *outlet_getsymbol(t_outlet *x); +EXTERN void outlet_free(t_outlet *x); +EXTERN t_object *pd_checkobject(t_pd *x); + + +/* -------------------- canvases -------------- */ + +EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir); + +EXTERN void canvas_setargs(int argc, t_atom *argv); +EXTERN void canvas_getargs(int *argcp, t_atom **argvp); +EXTERN t_symbol *canvas_getcurrentdir(void); +EXTERN t_glist *canvas_getcurrent(void); +EXTERN void canvas_makefilename(t_glist *c, char *file, + char *result,int resultsize); +EXTERN t_symbol *canvas_getdir(t_glist *x); +EXTERN int sys_fontwidth(int fontsize); +EXTERN int sys_fontheight(int fontsize); +EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b); + +/* ---------------- widget behaviors ---------------------- */ + +EXTERN_STRUCT _widgetbehavior; +#define t_widgetbehavior struct _widgetbehavior + +EXTERN_STRUCT _parentwidgetbehavior; +#define t_parentwidgetbehavior struct _parentwidgetbehavior +EXTERN t_parentwidgetbehavior *pd_getparentwidget(t_pd *x); + +/* -------------------- classes -------------- */ + +#define CLASS_DEFAULT 0 /* flags for new classes below */ +#define CLASS_PD 1 +#define CLASS_GOBJ 2 +#define CLASS_PATCHABLE 3 +#define CLASS_NOINLET 8 + +#define CLASS_TYPEMASK 3 + + +EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod, + t_method freemethod, size_t size, int flags, t_atomtype arg1, ...); +EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s, + t_atomtype type1, ...); +EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel, + t_atomtype arg1, ...); +EXTERN void class_addbang(t_class *c, t_method fn); +EXTERN void class_addpointer(t_class *c, t_method fn); +EXTERN void class_doaddfloat(t_class *c, t_method fn); +EXTERN void class_addsymbol(t_class *c, t_method fn); +EXTERN void class_addlist(t_class *c, t_method fn); +EXTERN void class_addanything(t_class *c, t_method fn); +EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s); +EXTERN void class_setwidget(t_class *c, t_widgetbehavior *w); +EXTERN void class_setparentwidget(t_class *c, t_parentwidgetbehavior *w); +EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c); +EXTERN char *class_getname(t_class *c); +EXTERN char *class_gethelpname(t_class *c); +EXTERN void class_setdrawcommand(t_class *c); +EXTERN int class_isdrawcommand(t_class *c); +EXTERN void class_domainsignalin(t_class *c, int onset); +#define CLASS_MAINSIGNALIN(c, type, field) \ + class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0) + + /* prototype for functions to save Pd's to a binbuf */ +typedef void (*t_savefn)(t_gobj *x, t_binbuf *b); +EXTERN void class_setsavefn(t_class *c, t_savefn f); +EXTERN t_savefn class_getsavefn(t_class *c); + /* prototype for functions to open properties dialogs */ +typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist); +EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f); +EXTERN t_propertiesfn class_getpropertiesfn(t_class *c); + +#ifndef PD_CLASS_DEF +#define class_addbang(x, y) class_addbang((x), (t_method)(y)) +#define class_addpointer(x, y) class_addpointer((x), (t_method)(y)) +#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y)) +#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y)) +#define class_addlist(x, y) class_addlist((x), (t_method)(y)) +#define class_addanything(x, y) class_addanything((x), (t_method)(y)) +#endif + +/* ------------ printing --------------------------------- */ +EXTERN void post(char *fmt, ...); +EXTERN void startpost(char *fmt, ...); +EXTERN void poststring(char *s); +EXTERN void postfloat(float f); +EXTERN void postatom(int argc, t_atom *argv); +EXTERN void endpost(void); +EXTERN void error(char *fmt, ...); +EXTERN void bug(char *fmt, ...); +EXTERN void pd_error(void *object, char *fmt, ...); +EXTERN void sys_logerror(char *object, char *s); +EXTERN void sys_unixerror(char *object); +EXTERN void sys_ouch(void); + +#ifdef __linux__ +EXTERN char* sys_get_path( void); +#endif +EXTERN void sys_addpath(const char* p); + + +/* ------------ system interface routines ------------------- */ +EXTERN int sys_isreadablefile(const char *name); +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 sched_geteventno(void); +EXTERN double sys_getrealtime(void); + + +/* ------------ threading ------------------- */ +/* T.Grill - see m_sched.c */ + +EXTERN void sys_lock(void); +EXTERN void sys_unlock(void); +EXTERN int sys_trylock(void); + + +/* --------------- signals ----------------------------------- */ + +#define MAXLOGSIG 32 +#define MAXSIGSIZE (1 << MAXLOGSIG) +#ifndef FIXEDPOINT +typedef float t_sample; +#else +#include "m_fixed.h" +#endif + + +typedef struct _signal +{ + int s_n; /* number of points in the array */ + t_sample *s_vec; /* the array */ + float s_sr; /* sample rate */ + int s_refcount; /* number of times used */ + int s_isborrowed; /* whether we're going to borrow our array */ + struct _signal *s_borrowedfrom; /* signal to borrow it from */ + struct _signal *s_nextfree; /* next in freelist */ + struct _signal *s_nextused; /* next in used list */ +} t_signal; + + +typedef t_int *(*t_perfroutine)(t_int *args); + +EXTERN t_int *plus_perform(t_int *args); +EXTERN t_int *zero_perform(t_int *args); +EXTERN t_int *copy_perform(t_int *args); + +EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n); +EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n); +EXTERN void dsp_add_scalarcopy(t_sample *in, t_sample *out, int n); +EXTERN void dsp_add_zero(t_sample *out, int n); + +EXTERN int sys_getblksize(void); +EXTERN float sys_getsr(void); +EXTERN int sys_get_inchannels(void); +EXTERN int sys_get_outchannels(void); + +EXTERN void dsp_add(t_perfroutine f, int n, ...); +EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec); +EXTERN void pd_fft(float *buf, int npoints, int inverse); +EXTERN int ilog2(int n); + +EXTERN void mayer_fht(t_sample *fz, int n); +EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag); +EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag); +EXTERN void mayer_realfft(int n, t_sample *real); +EXTERN void mayer_realifft(int n, t_sample *real); + +EXTERN t_sample *cos_table; + +#define LOGCOSTABSIZE 9 +#define COSTABSIZE (1<