Browse Source

Add camomile as plugin

camomile
falkTX 6 years ago
parent
commit
713be25fe0
100 changed files with 64174 additions and 0 deletions
  1. +3
    -0
      ports/Makefile
  2. +190
    -0
      ports/camomile/LV2/premake.lua
  3. +96
    -0
      ports/camomile/VST/premake.lua
  4. +4928
    -0
      ports/camomile/source/BinaryData.cpp
  5. +57
    -0
      ports/camomile/source/BinaryData.h
  6. +31
    -0
      ports/camomile/source/JuceHeader.h
  7. +45
    -0
      ports/camomile/source/JucePluginCharacteristics.h
  8. +76
    -0
      ports/camomile/source/LibPd/libpd_wrapper/s_libpdmidi.c
  9. +126
    -0
      ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.c
  10. +49
    -0
      ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.h
  11. +51
    -0
      ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.c
  12. +48
    -0
      ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.h
  13. +413
    -0
      ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.c
  14. +45
    -0
      ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.h
  15. +83
    -0
      ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.c
  16. +19
    -0
      ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.h
  17. +26
    -0
      ports/camomile/source/LibPd/libpd_wrapper/z_hooks.c
  18. +35
    -0
      ports/camomile/source/LibPd/libpd_wrapper/z_hooks.h
  19. +639
    -0
      ports/camomile/source/LibPd/libpd_wrapper/z_libpd.c
  20. +163
    -0
      ports/camomile/source/LibPd/libpd_wrapper/z_libpd.h
  21. +12
    -0
      ports/camomile/source/LibPd/pure-data/src/.dir-locals.el
  22. +261
    -0
      ports/camomile/source/LibPd/pure-data/src/CHANGELOG.txt
  23. +409
    -0
      ports/camomile/source/LibPd/pure-data/src/Makefile.am
  24. +843
    -0
      ports/camomile/source/LibPd/pure-data/src/d_arithmetic.c
  25. +1049
    -0
      ports/camomile/source/LibPd/pure-data/src/d_array.c
  26. +850
    -0
      ports/camomile/source/LibPd/pure-data/src/d_ctl.c
  27. +202
    -0
      ports/camomile/source/LibPd/pure-data/src/d_dac.c
  28. +346
    -0
      ports/camomile/source/LibPd/pure-data/src/d_delay.c
  29. +355
    -0
      ports/camomile/source/LibPd/pure-data/src/d_fft.c
  30. +3486
    -0
      ports/camomile/source/LibPd/pure-data/src/d_fft_fftsg.c
  31. +185
    -0
      ports/camomile/source/LibPd/pure-data/src/d_fft_fftw.c
  32. +1082
    -0
      ports/camomile/source/LibPd/pure-data/src/d_filter.c
  33. +361
    -0
      ports/camomile/source/LibPd/pure-data/src/d_global.c
  34. +806
    -0
      ports/camomile/source/LibPd/pure-data/src/d_math.c
  35. +136
    -0
      ports/camomile/source/LibPd/pure-data/src/d_misc.c
  36. +521
    -0
      ports/camomile/source/LibPd/pure-data/src/d_osc.c
  37. +216
    -0
      ports/camomile/source/LibPd/pure-data/src/d_resample.c
  38. +2734
    -0
      ports/camomile/source/LibPd/pure-data/src/d_soundfile.c
  39. +1240
    -0
      ports/camomile/source/LibPd/pure-data/src/d_ugen.c
  40. +786
    -0
      ports/camomile/source/LibPd/pure-data/src/g_all_guis.c
  41. +324
    -0
      ports/camomile/source/LibPd/pure-data/src/g_all_guis.h
  42. +1252
    -0
      ports/camomile/source/LibPd/pure-data/src/g_array.c
  43. +578
    -0
      ports/camomile/source/LibPd/pure-data/src/g_bang.c
  44. +1845
    -0
      ports/camomile/source/LibPd/pure-data/src/g_canvas.c
  45. +663
    -0
      ports/camomile/source/LibPd/pure-data/src/g_canvas.h
  46. +464
    -0
      ports/camomile/source/LibPd/pure-data/src/g_clone.c
  47. +2990
    -0
      ports/camomile/source/LibPd/pure-data/src/g_editor.c
  48. +1111
    -0
      ports/camomile/source/LibPd/pure-data/src/g_graph.c
  49. +97
    -0
      ports/camomile/source/LibPd/pure-data/src/g_guiconnect.c
  50. +775
    -0
      ports/camomile/source/LibPd/pure-data/src/g_hdial.c
  51. +691
    -0
      ports/camomile/source/LibPd/pure-data/src/g_hslider.c
  52. +599
    -0
      ports/camomile/source/LibPd/pure-data/src/g_io.c
  53. +406
    -0
      ports/camomile/source/LibPd/pure-data/src/g_mycanvas.c
  54. +926
    -0
      ports/camomile/source/LibPd/pure-data/src/g_numbox.c
  55. +811
    -0
      ports/camomile/source/LibPd/pure-data/src/g_readwrite.c
  56. +664
    -0
      ports/camomile/source/LibPd/pure-data/src/g_rtext.c
  57. +452
    -0
      ports/camomile/source/LibPd/pure-data/src/g_scalar.c
  58. +2772
    -0
      ports/camomile/source/LibPd/pure-data/src/g_template.c
  59. +1489
    -0
      ports/camomile/source/LibPd/pure-data/src/g_text.c
  60. +520
    -0
      ports/camomile/source/LibPd/pure-data/src/g_toggle.c
  61. +1278
    -0
      ports/camomile/source/LibPd/pure-data/src/g_traversal.c
  62. +767
    -0
      ports/camomile/source/LibPd/pure-data/src/g_vdial.c
  63. +690
    -0
      ports/camomile/source/LibPd/pure-data/src/g_vslider.c
  64. +773
    -0
      ports/camomile/source/LibPd/pure-data/src/g_vumeter.c
  65. +128
    -0
      ports/camomile/source/LibPd/pure-data/src/m_atom.c
  66. +1546
    -0
      ports/camomile/source/LibPd/pure-data/src/m_binbuf.c
  67. +1080
    -0
      ports/camomile/source/LibPd/pure-data/src/m_class.c
  68. +110
    -0
      ports/camomile/source/LibPd/pure-data/src/m_conf.c
  69. +216
    -0
      ports/camomile/source/LibPd/pure-data/src/m_glob.c
  70. +98
    -0
      ports/camomile/source/LibPd/pure-data/src/m_imp.h
  71. +89
    -0
      ports/camomile/source/LibPd/pure-data/src/m_memory.c
  72. +756
    -0
      ports/camomile/source/LibPd/pure-data/src/m_obj.c
  73. +321
    -0
      ports/camomile/source/LibPd/pure-data/src/m_pd.c
  74. +894
    -0
      ports/camomile/source/LibPd/pure-data/src/m_pd.h
  75. +620
    -0
      ports/camomile/source/LibPd/pure-data/src/m_sched.c
  76. +271
    -0
      ports/camomile/source/LibPd/pure-data/src/makefile.gnu
  77. +242
    -0
      ports/camomile/source/LibPd/pure-data/src/makefile.mac
  78. +318
    -0
      ports/camomile/source/LibPd/pure-data/src/makefile.mingw
  79. +220
    -0
      ports/camomile/source/LibPd/pure-data/src/makefile.msvc
  80. +142
    -0
      ports/camomile/source/LibPd/pure-data/src/notes.txt
  81. BIN
      ports/camomile/source/LibPd/pure-data/src/pd.ico
  82. +25
    -0
      ports/camomile/source/LibPd/pure-data/src/pd.rc
  83. +1134
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio.c
  84. +973
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.c
  85. +40
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.h
  86. +1365
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_alsamm.c
  87. +43
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_audiounit.c
  88. +37
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_dummy.c
  89. +132
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_esd.c
  90. +572
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_jack.c
  91. +794
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_mmio.c
  92. +795
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_oss.c
  93. +642
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_pa.c
  94. +255
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_paring.c
  95. +75
    -0
      ports/camomile/source/LibPd/pure-data/src/s_audio_paring.h
  96. +36
    -0
      ports/camomile/source/LibPd/pure-data/src/s_entry.c
  97. +697
    -0
      ports/camomile/source/LibPd/pure-data/src/s_file.c
  98. +1607
    -0
      ports/camomile/source/LibPd/pure-data/src/s_inter.c
  99. +492
    -0
      ports/camomile/source/LibPd/pure-data/src/s_loader.c
  100. +1469
    -0
      ports/camomile/source/LibPd/pure-data/src/s_main.c

+ 3
- 0
ports/Makefile View File

@@ -22,6 +22,7 @@ lv2: libs
ifeq ($(LINUX_EMBED),true) ifeq ($(LINUX_EMBED),true)
$(MAKE) -C arctican-function/LV2 $(MAKE) -C arctican-function/LV2
$(MAKE) -C arctican-pilgrim/LV2 $(MAKE) -C arctican-pilgrim/LV2
$(MAKE) -C camomile/LV2
$(MAKE) -C drowaudio-distortion/LV2 $(MAKE) -C drowaudio-distortion/LV2
$(MAKE) -C drowaudio-distortionshaper/LV2 $(MAKE) -C drowaudio-distortionshaper/LV2
$(MAKE) -C drowaudio-flanger/LV2 $(MAKE) -C drowaudio-flanger/LV2
@@ -121,6 +122,7 @@ clean:
# LV2 # LV2
$(MAKE) clean -C arctican-function/LV2 $(MAKE) clean -C arctican-function/LV2
$(MAKE) clean -C arctican-pilgrim/LV2 $(MAKE) clean -C arctican-pilgrim/LV2
$(MAKE) clean -C camomile/LV2
$(MAKE) clean -C dexed/LV2 $(MAKE) clean -C dexed/LV2
$(MAKE) clean -C drowaudio-distortion/LV2 $(MAKE) clean -C drowaudio-distortion/LV2
$(MAKE) clean -C drowaudio-distortionshaper/LV2 $(MAKE) clean -C drowaudio-distortionshaper/LV2
@@ -156,6 +158,7 @@ clean:
# VST # VST
$(MAKE) clean -C arctican-function/VST $(MAKE) clean -C arctican-function/VST
$(MAKE) clean -C arctican-pilgrim/VST $(MAKE) clean -C arctican-pilgrim/VST
$(MAKE) clean -C camomile/VST
$(MAKE) clean -C dexed/VST $(MAKE) clean -C dexed/VST
$(MAKE) clean -C drowaudio-distortion/VST $(MAKE) clean -C drowaudio-distortion/VST
$(MAKE) clean -C drowaudio-distortionshaper/VST $(MAKE) clean -C drowaudio-distortionshaper/VST


+ 190
- 0
ports/camomile/LV2/premake.lua View File

@@ -0,0 +1,190 @@
dofile("../../../scripts/make-project.lua")
package = make_juce_lv2_project("Camomile")
package.defines = { package.defines, "PD=1", "USEAPI_DUMMY=1", "PD_INTERNAL=1", "PDINSTANCE=1", "PDTHREADS=1", "HAVE_LIBDL=1", "HAVE_UNISTD_H=1" }
package.includepaths = {
package.includepaths,
"../source/LibPd/pure-data/src",
"../source/LibPd/libpd_wrapper"
}
if (os.getenv("LINUX_EMBED")) then
package.files = {
matchfiles (
"../source/BinaryData.cpp",
"../source/PluginEnvironment.cpp",
"../source/PluginFileWatcher.cpp",
"../source/PluginParameter.cpp",
"../source/PluginParser.cpp",
"../source/PluginProcessor.cpp",
"../source/PluginProcessorBuses.cpp",
"../source/PluginProcessorReceive.cpp",
"../source/Pd/*.c",
"../source/Pd/*.cpp",
"../source/LibPd/pure-data/src/d_arithmetic.c",
"../source/LibPd/pure-data/src/d_array.c",
"../source/LibPd/pure-data/src/d_ctl.c",
"../source/LibPd/pure-data/src/d_dac.c",
"../source/LibPd/pure-data/src/d_delay.c",
"../source/LibPd/pure-data/src/d_fft.c",
"../source/LibPd/pure-data/src/d_fft_fftsg.c",
"../source/LibPd/pure-data/src/d_filter.c",
"../source/LibPd/pure-data/src/d_global.c",
"../source/LibPd/pure-data/src/d_math.c",
"../source/LibPd/pure-data/src/d_misc.c",
"../source/LibPd/pure-data/src/d_osc.c",
"../source/LibPd/pure-data/src/d_resample.c",
"../source/LibPd/pure-data/src/d_soundfile.c",
"../source/LibPd/pure-data/src/d_ugen.c",
"../source/LibPd/pure-data/src/g_all_guis.c",
"../source/LibPd/pure-data/src/g_array.c",
"../source/LibPd/pure-data/src/g_bang.c",
"../source/LibPd/pure-data/src/g_canvas.c",
"../source/LibPd/pure-data/src/g_clone.c",
"../source/LibPd/pure-data/src/g_editor.c",
"../source/LibPd/pure-data/src/g_graph.c",
"../source/LibPd/pure-data/src/g_guiconnect.c",
"../source/LibPd/pure-data/src/g_hdial.c",
"../source/LibPd/pure-data/src/g_hslider.c",
"../source/LibPd/pure-data/src/g_io.c",
"../source/LibPd/pure-data/src/g_mycanvas.c",
"../source/LibPd/pure-data/src/g_numbox.c",
"../source/LibPd/pure-data/src/g_readwrite.c",
"../source/LibPd/pure-data/src/g_rtext.c",
"../source/LibPd/pure-data/src/g_scalar.c",
"../source/LibPd/pure-data/src/g_template.c",
"../source/LibPd/pure-data/src/g_text.c",
"../source/LibPd/pure-data/src/g_toggle.c",
"../source/LibPd/pure-data/src/g_traversal.c",
"../source/LibPd/pure-data/src/g_vdial.c",
"../source/LibPd/pure-data/src/g_vslider.c",
"../source/LibPd/pure-data/src/g_vumeter.c",
"../source/LibPd/pure-data/src/m_atom.c",
"../source/LibPd/pure-data/src/m_binbuf.c",
"../source/LibPd/pure-data/src/m_class.c",
"../source/LibPd/pure-data/src/m_conf.c",
"../source/LibPd/pure-data/src/m_glob.c",
"../source/LibPd/pure-data/src/m_memory.c",
"../source/LibPd/pure-data/src/m_obj.c",
"../source/LibPd/pure-data/src/m_pd.c",
"../source/LibPd/pure-data/src/m_sched.c",
"../source/LibPd/pure-data/src/s_audio.c",
"../source/LibPd/pure-data/src/s_audio_dummy.c",
"../source/LibPd/pure-data/src/s_inter.c",
"../source/LibPd/pure-data/src/s_loader.c",
"../source/LibPd/pure-data/src/s_main.c",
"../source/LibPd/pure-data/src/s_path.c",
"../source/LibPd/pure-data/src/s_print.c",
"../source/LibPd/pure-data/src/s_utf8.c",
"../source/LibPd/pure-data/src/x_acoustics.c",
"../source/LibPd/pure-data/src/x_arithmetic.c",
"../source/LibPd/pure-data/src/x_array.c",
"../source/LibPd/pure-data/src/x_connective.c",
"../source/LibPd/pure-data/src/x_gui.c",
"../source/LibPd/pure-data/src/x_interface.c",
"../source/LibPd/pure-data/src/x_list.c",
"../source/LibPd/pure-data/src/x_midi.c",
"../source/LibPd/pure-data/src/x_misc.c",
"../source/LibPd/pure-data/src/x_net.c",
"../source/LibPd/pure-data/src/x_scalar.c",
"../source/LibPd/pure-data/src/x_text.c",
"../source/LibPd/pure-data/src/x_time.c",
"../source/LibPd/pure-data/src/x_vexp.c",
"../source/LibPd/pure-data/src/x_vexp_fun.c",
"../source/LibPd/pure-data/src/x_vexp_if.c",
"../source/LibPd/libpd_wrapper/s_libpdmidi.c",
"../source/LibPd/libpd_wrapper/x_libpdreceive.c",
"../source/LibPd/libpd_wrapper/z_hooks.c",
"../source/LibPd/libpd_wrapper/z_libpd.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}
else
package.files = {
matchfiles (
"../source/*.cpp",
"../source/Pd/*.c",
"../source/Pd/*.cpp",
"../source/LibPd/pure-data/src/d_arithmetic.c",
"../source/LibPd/pure-data/src/d_array.c",
"../source/LibPd/pure-data/src/d_ctl.c",
"../source/LibPd/pure-data/src/d_dac.c",
"../source/LibPd/pure-data/src/d_delay.c",
"../source/LibPd/pure-data/src/d_fft.c",
"../source/LibPd/pure-data/src/d_fft_fftsg.c",
"../source/LibPd/pure-data/src/d_filter.c",
"../source/LibPd/pure-data/src/d_global.c",
"../source/LibPd/pure-data/src/d_math.c",
"../source/LibPd/pure-data/src/d_misc.c",
"../source/LibPd/pure-data/src/d_osc.c",
"../source/LibPd/pure-data/src/d_resample.c",
"../source/LibPd/pure-data/src/d_soundfile.c",
"../source/LibPd/pure-data/src/d_ugen.c",
"../source/LibPd/pure-data/src/g_all_guis.c",
"../source/LibPd/pure-data/src/g_array.c",
"../source/LibPd/pure-data/src/g_bang.c",
"../source/LibPd/pure-data/src/g_canvas.c",
"../source/LibPd/pure-data/src/g_clone.c",
"../source/LibPd/pure-data/src/g_editor.c",
"../source/LibPd/pure-data/src/g_graph.c",
"../source/LibPd/pure-data/src/g_guiconnect.c",
"../source/LibPd/pure-data/src/g_hdial.c",
"../source/LibPd/pure-data/src/g_hslider.c",
"../source/LibPd/pure-data/src/g_io.c",
"../source/LibPd/pure-data/src/g_mycanvas.c",
"../source/LibPd/pure-data/src/g_numbox.c",
"../source/LibPd/pure-data/src/g_readwrite.c",
"../source/LibPd/pure-data/src/g_rtext.c",
"../source/LibPd/pure-data/src/g_scalar.c",
"../source/LibPd/pure-data/src/g_template.c",
"../source/LibPd/pure-data/src/g_text.c",
"../source/LibPd/pure-data/src/g_toggle.c",
"../source/LibPd/pure-data/src/g_traversal.c",
"../source/LibPd/pure-data/src/g_vdial.c",
"../source/LibPd/pure-data/src/g_vslider.c",
"../source/LibPd/pure-data/src/g_vumeter.c",
"../source/LibPd/pure-data/src/m_atom.c",
"../source/LibPd/pure-data/src/m_binbuf.c",
"../source/LibPd/pure-data/src/m_class.c",
"../source/LibPd/pure-data/src/m_conf.c",
"../source/LibPd/pure-data/src/m_glob.c",
"../source/LibPd/pure-data/src/m_memory.c",
"../source/LibPd/pure-data/src/m_obj.c",
"../source/LibPd/pure-data/src/m_pd.c",
"../source/LibPd/pure-data/src/m_sched.c",
"../source/LibPd/pure-data/src/s_audio.c",
"../source/LibPd/pure-data/src/s_audio_dummy.c",
"../source/LibPd/pure-data/src/s_inter.c",
"../source/LibPd/pure-data/src/s_loader.c",
"../source/LibPd/pure-data/src/s_main.c",
"../source/LibPd/pure-data/src/s_path.c",
"../source/LibPd/pure-data/src/s_print.c",
"../source/LibPd/pure-data/src/s_utf8.c",
"../source/LibPd/pure-data/src/x_acoustics.c",
"../source/LibPd/pure-data/src/x_arithmetic.c",
"../source/LibPd/pure-data/src/x_array.c",
"../source/LibPd/pure-data/src/x_connective.c",
"../source/LibPd/pure-data/src/x_gui.c",
"../source/LibPd/pure-data/src/x_interface.c",
"../source/LibPd/pure-data/src/x_list.c",
"../source/LibPd/pure-data/src/x_midi.c",
"../source/LibPd/pure-data/src/x_misc.c",
"../source/LibPd/pure-data/src/x_net.c",
"../source/LibPd/pure-data/src/x_scalar.c",
"../source/LibPd/pure-data/src/x_text.c",
"../source/LibPd/pure-data/src/x_time.c",
"../source/LibPd/pure-data/src/x_vexp.c",
"../source/LibPd/pure-data/src/x_vexp_fun.c",
"../source/LibPd/pure-data/src/x_vexp_if.c",
"../source/LibPd/libpd_wrapper/s_libpdmidi.c",
"../source/LibPd/libpd_wrapper/x_libpdreceive.c",
"../source/LibPd/libpd_wrapper/z_hooks.c",
"../source/LibPd/libpd_wrapper/z_libpd.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}
end

+ 96
- 0
ports/camomile/VST/premake.lua View File

@@ -0,0 +1,96 @@
dofile("../../../scripts/make-project.lua")
package = make_juce_vst_project("Camomile")
package.defines = { package.defines, "PD=1", "USEAPI_DUMMY=1", "PD_INTERNAL=1", "PDINSTANCE=1", "PDTHREADS=1", "HAVE_LIBDL=1", "HAVE_UNISTD_H=1" }
package.includepaths = {
package.includepaths,
"../source/LibPd/pure-data/src",
"../source/LibPd/libpd_wrapper"
}
package.files = {
matchfiles (
"../source/*.cpp",
"../source/Pd/*.c",
"../source/Pd/*.cpp",
"../source/LibPd/pure-data/src/d_arithmetic.c",
"../source/LibPd/pure-data/src/d_array.c",
"../source/LibPd/pure-data/src/d_ctl.c",
"../source/LibPd/pure-data/src/d_dac.c",
"../source/LibPd/pure-data/src/d_delay.c",
"../source/LibPd/pure-data/src/d_fft.c",
"../source/LibPd/pure-data/src/d_fft_fftsg.c",
"../source/LibPd/pure-data/src/d_filter.c",
"../source/LibPd/pure-data/src/d_global.c",
"../source/LibPd/pure-data/src/d_math.c",
"../source/LibPd/pure-data/src/d_misc.c",
"../source/LibPd/pure-data/src/d_osc.c",
"../source/LibPd/pure-data/src/d_resample.c",
"../source/LibPd/pure-data/src/d_soundfile.c",
"../source/LibPd/pure-data/src/d_ugen.c",
"../source/LibPd/pure-data/src/g_all_guis.c",
"../source/LibPd/pure-data/src/g_array.c",
"../source/LibPd/pure-data/src/g_bang.c",
"../source/LibPd/pure-data/src/g_canvas.c",
"../source/LibPd/pure-data/src/g_clone.c",
"../source/LibPd/pure-data/src/g_editor.c",
"../source/LibPd/pure-data/src/g_graph.c",
"../source/LibPd/pure-data/src/g_guiconnect.c",
"../source/LibPd/pure-data/src/g_hdial.c",
"../source/LibPd/pure-data/src/g_hslider.c",
"../source/LibPd/pure-data/src/g_io.c",
"../source/LibPd/pure-data/src/g_mycanvas.c",
"../source/LibPd/pure-data/src/g_numbox.c",
"../source/LibPd/pure-data/src/g_readwrite.c",
"../source/LibPd/pure-data/src/g_rtext.c",
"../source/LibPd/pure-data/src/g_scalar.c",
"../source/LibPd/pure-data/src/g_template.c",
"../source/LibPd/pure-data/src/g_text.c",
"../source/LibPd/pure-data/src/g_toggle.c",
"../source/LibPd/pure-data/src/g_traversal.c",
"../source/LibPd/pure-data/src/g_vdial.c",
"../source/LibPd/pure-data/src/g_vslider.c",
"../source/LibPd/pure-data/src/g_vumeter.c",
"../source/LibPd/pure-data/src/m_atom.c",
"../source/LibPd/pure-data/src/m_binbuf.c",
"../source/LibPd/pure-data/src/m_class.c",
"../source/LibPd/pure-data/src/m_conf.c",
"../source/LibPd/pure-data/src/m_glob.c",
"../source/LibPd/pure-data/src/m_memory.c",
"../source/LibPd/pure-data/src/m_obj.c",
"../source/LibPd/pure-data/src/m_pd.c",
"../source/LibPd/pure-data/src/m_sched.c",
"../source/LibPd/pure-data/src/s_audio.c",
"../source/LibPd/pure-data/src/s_audio_dummy.c",
"../source/LibPd/pure-data/src/s_inter.c",
"../source/LibPd/pure-data/src/s_loader.c",
"../source/LibPd/pure-data/src/s_main.c",
"../source/LibPd/pure-data/src/s_path.c",
"../source/LibPd/pure-data/src/s_print.c",
"../source/LibPd/pure-data/src/s_utf8.c",
"../source/LibPd/pure-data/src/x_acoustics.c",
"../source/LibPd/pure-data/src/x_arithmetic.c",
"../source/LibPd/pure-data/src/x_array.c",
"../source/LibPd/pure-data/src/x_connective.c",
"../source/LibPd/pure-data/src/x_gui.c",
"../source/LibPd/pure-data/src/x_interface.c",
"../source/LibPd/pure-data/src/x_list.c",
"../source/LibPd/pure-data/src/x_midi.c",
"../source/LibPd/pure-data/src/x_misc.c",
"../source/LibPd/pure-data/src/x_net.c",
"../source/LibPd/pure-data/src/x_scalar.c",
"../source/LibPd/pure-data/src/x_text.c",
"../source/LibPd/pure-data/src/x_time.c",
"../source/LibPd/pure-data/src/x_vexp.c",
"../source/LibPd/pure-data/src/x_vexp_fun.c",
"../source/LibPd/pure-data/src/x_vexp_if.c",
"../source/LibPd/libpd_wrapper/s_libpdmidi.c",
"../source/LibPd/libpd_wrapper/x_libpdreceive.c",
"../source/LibPd/libpd_wrapper/z_hooks.c",
"../source/LibPd/libpd_wrapper/z_libpd.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}

+ 4928
- 0
ports/camomile/source/BinaryData.cpp
File diff suppressed because it is too large
View File


+ 57
- 0
ports/camomile/source/BinaryData.h View File

@@ -0,0 +1,57 @@
/* =========================================================================================
This is an auto-generated file: Any edits you make may be overwritten!
*/
#pragma once
namespace BinaryData
{
extern const char* CreditsAU;
const int CreditsAUSize = 479;
extern const char* CreditsLV2;
const int CreditsLV2Size = 624;
extern const char* CreditsVST;
const int CreditsVSTSize = 537;
extern const char* DejaVuSansMono_ttf;
const int DejaVuSansMono_ttfSize = 340712;
extern const char* copy_png;
const int copy_pngSize = 4098;
extern const char* flower_center_png;
const int flower_center_pngSize = 3299;
extern const char* flower_petals_png;
const int flower_petals_pngSize = 22287;
extern const char* garbage_png;
const int garbage_pngSize = 5113;
extern const char* reload_png;
const int reload_pngSize = 8380;
extern const char* settings_png;
const int settings_pngSize = 12539;
// Number of elements in the namedResourceList and originalFileNames arrays.
const int namedResourceListSize = 10;
// Points to the start of a list of resource names.
extern const char* namedResourceList[];
// Points to the start of a list of resource filenames.
extern const char* originalFilenames[];
// If you provide the name of one of the binary resource variables above, this function will
// return the corresponding data and its size (or a null pointer if the name isn't found).
const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes);
// If you provide the name of one of the binary resource variables above, this function will
// return the corresponding original, non-mangled filename (or a null pointer if the name isn't found).
const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);
}

+ 31
- 0
ports/camomile/source/JuceHeader.h View File

@@ -0,0 +1,31 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
This is the header file that your files should include in order to get all the
JUCE library headers. You should avoid including the JUCE headers directly in
your own source files, because that wouldn't pick up the correct configuration
options for your app.
*/
#pragma once
#include "JucePluginMain.h"
#include "BinaryData.h"
#if ! DONT_SET_USING_JUCE_NAMESPACE
// If your code uses a lot of JUCE classes, then this will obviously save you
// a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE.
using namespace juce;
#endif
#if ! JUCE_DONT_DECLARE_PROJECTINFO
namespace ProjectInfo
{
const char* const projectName = "CamomileLV2";
const char* const versionString = "1.0.6";
const int versionNumber = 0x10006;
}
#endif

+ 45
- 0
ports/camomile/source/JucePluginCharacteristics.h View File

@@ -0,0 +1,45 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
If you want to change any of these values, use the Introjucer to do so,
rather than editing this file directly!
Any commented-out settings will assume their default values.
*/
#ifndef __JUCE_APPCONFIG_E0XYLT__
#define __JUCE_APPCONFIG_E0XYLT__
//==============================================================================
// Audio plugin settings..
#include "PluginConfig.h"
#define JucePlugin_ManufacturerCode 0x50494755
#define JucePlugin_IsSynth 0
#define JucePlugin_IsMidiEffect 0
#define JucePlugin_WantsMidiInput 1
#define JucePlugin_ProducesMidiOutput 1
#define JucePlugin_SilenceInProducesSilenceOut 1
#define JucePlugin_EditorRequiresKeyboardFocus 1
#define JucePlugin_VersionCode 0x10006
#define JucePlugin_VersionString "1.0.6"
#define JucePlugin_VSTUniqueID JucePlugin_PluginCode
#define JucePlugin_VSTCategory kPlugCategEffect
#define JucePlugin_AUMainType kAudioUnitType_Effect
#define JucePlugin_AUSubType JucePlugin_PluginCode
#define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode
#define JucePlugin_RTASCategory ePlugInCategory_None
#define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode
#define JucePlugin_RTASProductId JucePlugin_PluginCode
// #define JucePlugin_LV2Category "DynamicsPlugin"
#define JucePlugin_WantsLV2Latency 1
#define JucePlugin_WantsLV2Presets 1
#define JucePlugin_WantsLV2State 1
#define JucePlugin_WantsLV2TimePos 1
#endif // __JUCE_APPCONFIG_E0XYLT__

+ 76
- 0
ports/camomile/source/LibPd/libpd_wrapper/s_libpdmidi.c View File

@@ -0,0 +1,76 @@
/* Copyright (c) 1997-2010 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

#include "m_pd.h"
#include "s_stuff.h"
#include "z_libpd.h"
#include "z_hooks.h"

#define CLAMP(x, low, high) ((x > high) ? high : ((x < low) ? low : x))
#define CLAMP4BIT(x) CLAMP(x, 0, 0x0f)
#define CLAMP7BIT(x) CLAMP(x, 0, 0x7f)
#define CLAMP8BIT(x) CLAMP(x, 0, 0xff)
#define CLAMP12BIT(x) CLAMP(x, 0, 0x0fff)
#define CLAMP14BIT(x) CLAMP(x, 0, 0x3fff)

#define CHANNEL ((CLAMP12BIT(port) << 4) | CLAMP4BIT(channel))

void outmidi_noteon(int port, int channel, int pitch, int velo) {
if (libpd_noteonhook)
libpd_noteonhook(CHANNEL, CLAMP7BIT(pitch), CLAMP7BIT(velo));
}

void outmidi_controlchange(int port, int channel, int ctl, int value) {
if (libpd_controlchangehook)
libpd_controlchangehook(CHANNEL, CLAMP7BIT(ctl), CLAMP7BIT(value));
}

void outmidi_programchange(int port, int channel, int value) {
if (libpd_programchangehook)
libpd_programchangehook(CHANNEL, CLAMP7BIT(value));
}

void outmidi_pitchbend(int port, int channel, int value) {
if (libpd_pitchbendhook)
libpd_pitchbendhook(CHANNEL, CLAMP14BIT(value) - 8192); // remove offset
}

void outmidi_aftertouch(int port, int channel, int value) {
if (libpd_aftertouchhook)
libpd_aftertouchhook(CHANNEL, CLAMP7BIT(value));
}

void outmidi_polyaftertouch(int port, int channel, int pitch, int value) {
if (libpd_polyaftertouchhook)
libpd_polyaftertouchhook(CHANNEL, CLAMP7BIT(pitch), CLAMP7BIT(value));
}

void outmidi_byte(int port, int value) {
if (libpd_midibytehook)
libpd_midibytehook(CLAMP12BIT(port), CLAMP8BIT(value));
}

/* tell Pd gui that our list of MIDI APIs is empty */
#include <string.h>
void sys_get_midi_apis(char *buf) {strcpy(buf, "{}");}

// The rest is not relevant to libpd.
void sys_listmididevs(void) {}
void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
int *pnmidioutdev, int *pmidioutdev) {*pnmidiindev = *pnmidioutdev = 0;}
void sys_open_midi(int nmidiindev, int *midiindev,
int nmidioutdev, int *midioutdev, int enable) {}
void sys_close_midi() {}
void sys_reopen_midi(void) {}
void sys_initmidiqueue(void) {}
void sys_pollmidiqueue(void) {}
void sys_setmiditimediff(double inbuftime, double outbuftime) {}
void glob_midi_setapi(void *dummy, t_floatarg f) {}
void glob_midi_properties(t_pd *dummy, t_floatarg flongform) {}
void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) {}
int sys_mididevnametonumber(int output, const char *name) { return 0; }
void sys_mididevnumbertoname(int output, int devno, char *name, int namesize) {}
void sys_set_midi_api(int api) {}
int sys_midiapi;


+ 126
- 0
ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.c View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#include "ringbuffer.h"

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#if __STDC_VERSION__ >= 201112L // use stdatomic if C11 is available
#include <stdatomic.h>
#define SYNC_FETCH(ptr) atomic_fetch_or((_Atomic int *)ptr, 0)
#define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \
atomic_compare_exchange_strong((_Atomic int *)ptr, &oldval, newval)
#else // use platform specfics
#ifdef __APPLE__ // apple atomics
#include <libkern/OSAtomic.h>
#define SYNC_FETCH(ptr) OSAtomicOr32Barrier(0, (volatile uint32_t *)ptr)
#define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \
OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr)
#elif defined(_WIN32) || defined(_WIN64) // win api atomics
#define SYNC_FETCH(ptr) InterlockedOr(ptr, 0)
#define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \
InterlockedCompareExchange(ptr, oldval, newval)
#else // gcc atomics
#define SYNC_FETCH(ptr) __sync_fetch_and_or(ptr, 0)
#define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \
__sync_val_compare_and_swap(ptr, oldval, newval)
#endif
#endif

ring_buffer *rb_create(int size) {
if (size & 0xff) return NULL; // size must be a multiple of 256
ring_buffer *buffer = malloc(sizeof(ring_buffer));
if (!buffer) return NULL;
buffer->buf_ptr = calloc(size, sizeof(char));
if (!buffer->buf_ptr) {
free(buffer);
return NULL;
}
buffer->size = size;
buffer->write_idx = 0;
buffer->read_idx = 0;
return buffer;
}

void rb_free(ring_buffer *buffer) {
free(buffer->buf_ptr);
free(buffer);
}

int rb_available_to_write(ring_buffer *buffer) {
if (buffer) {
// Note: The largest possible result is buffer->size - 1 because
// we adopt the convention that read_idx == write_idx means that the
// buffer is empty.
int read_idx = SYNC_FETCH(&(buffer->read_idx));
int write_idx = SYNC_FETCH(&(buffer->write_idx));
return (buffer->size + read_idx - write_idx - 1) % buffer->size;
} else {
return 0;
}
}

int rb_available_to_read(ring_buffer *buffer) {
if (buffer) {
int read_idx = SYNC_FETCH(&(buffer->read_idx));
int write_idx = SYNC_FETCH(&(buffer->write_idx));
return (buffer->size + write_idx - read_idx) % buffer->size;
} else {
return 0;
}
}

int rb_write_to_buffer(ring_buffer *buffer, int n, ...) {
if (!buffer) return -1;
int write_idx = buffer->write_idx; // No need for sync in writer thread.
int available = rb_available_to_write(buffer);
va_list args;
va_start(args, n);
int i;
for (i = 0; i < n; ++i) {
const char* src = va_arg(args, const char*);
int len = va_arg(args, int);
available -= len;
if (len < 0 || available < 0) return -1;
if (write_idx + len <= buffer->size) {
memcpy(buffer->buf_ptr + write_idx, src, len);
} else {
int d = buffer->size - write_idx;
memcpy(buffer->buf_ptr + write_idx, src, d);
memcpy(buffer->buf_ptr, src + d, len - d);
}
write_idx = (write_idx + len) % buffer->size;
}
va_end(args);
SYNC_COMPARE_AND_SWAP(&(buffer->write_idx), buffer->write_idx,
write_idx); // Includes memory barrier.
return 0;
}

int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len) {
if (len == 0) return 0;
if (!buffer || len < 0 || len > rb_available_to_read(buffer)) return -1;
// Note that rb_available_to_read also serves as a memory barrier, and so any
// writes to buffer->buf_ptr that precede the update of buffer->write_idx are
// visible to us now.
int read_idx = buffer->read_idx; // No need for sync in reader thread.
if (read_idx + len <= buffer->size) {
memcpy(dest, buffer->buf_ptr + read_idx, len);
} else {
int d = buffer->size - read_idx;
memcpy(dest, buffer->buf_ptr + read_idx, d);
memcpy(dest + d, buffer->buf_ptr, len - d);
}
SYNC_COMPARE_AND_SWAP(&(buffer->read_idx), buffer->read_idx,
(read_idx + len) % buffer->size); // Includes memory barrier.
return 0;
}

+ 49
- 0
ports/camomile/source/LibPd/libpd_wrapper/util/ringbuffer.h View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#ifndef __OPENSL_RING_BUFFER_H__
#define __OPENSL_RING_BUFFER_H__

// Simple lock-free ring buffer implementation for one writer thread and one
// consumer thread.
typedef struct ring_buffer {
int size;
char *buf_ptr;
int write_idx;
int read_idx;
} ring_buffer;

// Creates a ring buffer (returns NULL on failure).
ring_buffer *rb_create(int size);

// Deletes a ring buffer.
void rb_free(ring_buffer *buffer);

// Returns the number of bytes that can currently be written; safe to be called
// from any thread.
int rb_available_to_write(ring_buffer *buffer);

// Returns the number of bytes that can currently be read; safe to be called
// from any thread.
int rb_available_to_read(ring_buffer *buffer);

// Writes bytes from n sources to the ring buffer (if the ring buffer has
// enough space). The varargs are pairs of type (const char*, int) giving a
// pointer to a buffer and the number of bytes to be copied. Only to be called
// from a single writer thread.
// Returns 0 on success.
int rb_write_to_buffer(ring_buffer *buffer, int n, ...);

// Reads the given number of bytes fromthe ring buffer to dest if the ring
// buffer has enough data. Only to be called from a single reader thread.
// Returns 0 on success.
int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len);

#endif

+ 51
- 0
ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.c View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com) &
* Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#include "z_print_util.h"

#include <stdlib.h>
#include <string.h>

t_libpd_printhook libpd_concatenated_printhook = NULL;

#define PRINT_LINE_SIZE 2048

void libpd_set_concatenated_printhook(const t_libpd_printhook hook) {
libpd_concatenated_printhook = hook;
}

void libpd_print_concatenator(const char *s) {
if (!libpd_concatenated_printhook) return;

static char concatenated_print_line[PRINT_LINE_SIZE];
static int len_line = 0;
concatenated_print_line[len_line] = '\0';

int len = (int) strlen(s);
while (len_line + len >= PRINT_LINE_SIZE) {
int d = PRINT_LINE_SIZE - 1 - len_line;
strncat(concatenated_print_line, s, d);
libpd_concatenated_printhook(concatenated_print_line);
s += d;
len -= d;
len_line = 0;
concatenated_print_line[0] = '\0';
}

strncat(concatenated_print_line, s, len);
len_line += len;

if (len_line > 0 && concatenated_print_line[len_line - 1] == '\n') {
concatenated_print_line[len_line - 1] = '\0';
libpd_concatenated_printhook(concatenated_print_line);
len_line = 0;
}
}

+ 48
- 0
ports/camomile/source/LibPd/libpd_wrapper/util/z_print_util.h View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com) &
* Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#ifndef __Z_PRINT_UTIL_H__
#define __Z_PRINT_UTIL_H__

#include "z_libpd.h"

#ifdef __cplusplus
extern "C"
{
#endif

// Concatenate print messages into single lines before returning them
// to a print hook: ie "hello 123" is sent in 1 part -> "hello 123"
//
// For comparison, the default behavior returns individual words and spaces:
// ie "hello 123" is sent in 3 parts -> "hello", " ", "123"

// Assign the pointer to your print handler.
EXTERN void libpd_set_concatenated_printhook(const t_libpd_printhook hook);

// Assign this function pointer to libpd_printhook or libpd_queued_printhook,
// depending on whether you're using queued messages, to intercept and
// concatenate print messages:
//
// libpd_set_printhook(libpd_print_concatenator);
// libpd_set_concatenated_printhook(your_print_handler);
//
// Note: The char pointer argument is only good for the duration of the print
// callback; if you intend to use the argument after the callback has
// returned, you need to make a defensive copy.
//
void libpd_print_concatenator(const char *s);

#ifdef __cplusplus
}
#endif

#endif

+ 413
- 0
ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.c View File

@@ -0,0 +1,413 @@
/*
* Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#include "z_queued.h"

#include <stdlib.h>
#include <string.h>

#include "ringbuffer.h"

t_libpd_printhook libpd_queued_printhook = NULL;
t_libpd_banghook libpd_queued_banghook = NULL;
t_libpd_floathook libpd_queued_floathook = NULL;
t_libpd_symbolhook libpd_queued_symbolhook = NULL;
t_libpd_listhook libpd_queued_listhook = NULL;
t_libpd_messagehook libpd_queued_messagehook = NULL;

t_libpd_noteonhook libpd_queued_noteonhook = NULL;
t_libpd_controlchangehook libpd_queued_controlchangehook = NULL;
t_libpd_programchangehook libpd_queued_programchangehook = NULL;
t_libpd_pitchbendhook libpd_queued_pitchbendhook = NULL;
t_libpd_aftertouchhook libpd_queued_aftertouchhook = NULL;
t_libpd_polyaftertouchhook libpd_queued_polyaftertouchhook = NULL;
t_libpd_midibytehook libpd_queued_midibytehook = NULL;

typedef struct _pd_params {
enum {
LIBPD_PRINT, LIBPD_BANG, LIBPD_FLOAT,
LIBPD_SYMBOL, LIBPD_LIST, LIBPD_MESSAGE,
} type;
const char *src;
float x;
const char *sym;
int argc;
} pd_params;

typedef struct _midi_params {
enum {
LIBPD_NOTEON, LIBPD_CONTROLCHANGE, LIBPD_PROGRAMCHANGE, LIBPD_PITCHBEND,
LIBPD_AFTERTOUCH, LIBPD_POLYAFTERTOUCH, LIBPD_MIDIBYTE
} type;
int midi1;
int midi2;
int midi3;
} midi_params;

#define BUFFER_SIZE 16384
#define S_PD_PARAMS sizeof(pd_params)
#define S_MIDI_PARAMS sizeof(midi_params)
#define S_ATOM sizeof(t_atom)

static ring_buffer *pd_receive_buffer = NULL;
static ring_buffer *midi_receive_buffer = NULL;

static void receive_print(pd_params *p, char **buffer) {
if (libpd_queued_printhook) {
libpd_queued_printhook(*buffer);
}
*buffer += p->argc;
}

static void receive_bang(pd_params *p, char **buffer) {
if (libpd_queued_banghook) {
libpd_queued_banghook(p->src);
}
}

static void receive_float(pd_params *p, char **buffer) {
if (libpd_queued_floathook) {
libpd_queued_floathook(p->src, p->x);
}
}

static void receive_symbol(pd_params *p, char **buffer) {
if (libpd_queued_symbolhook) {
libpd_queued_symbolhook(p->src, p->sym);
}
}

static void receive_list(pd_params *p, char **buffer) {
if (libpd_queued_listhook) {
libpd_queued_listhook(p->src, p->argc, (t_atom *) *buffer);
}
*buffer += p->argc * S_ATOM;
}

static void receive_message(pd_params *p, char **buffer) {
if (libpd_queued_messagehook) {
libpd_queued_messagehook(p->src, p->sym, p->argc, (t_atom *) *buffer);
}
*buffer += p->argc * S_ATOM;
}

#define LIBPD_WORD_ALIGN 8

static void internal_printhook(const char *s) {
static char padding[LIBPD_WORD_ALIGN];
int len = (int) strlen(s) + 1; // remember terminating null char
int rest = len % LIBPD_WORD_ALIGN;
if (rest) rest = LIBPD_WORD_ALIGN - rest;
int total = len + rest;
if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS + total) {
pd_params p = {LIBPD_PRINT, NULL, 0.0f, NULL, total};
rb_write_to_buffer(pd_receive_buffer, 3,
(const char *)&p, S_PD_PARAMS, s, len, padding, rest);
}
}

static void internal_banghook(const char *src) {
if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS) {
pd_params p = {LIBPD_BANG, src, 0.0f, NULL, 0};
rb_write_to_buffer(pd_receive_buffer, 1, (const char *)&p, S_PD_PARAMS);
}
}

static void internal_floathook(const char *src, float x) {
if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS) {
pd_params p = {LIBPD_FLOAT, src, x, NULL, 0};
rb_write_to_buffer(pd_receive_buffer, 1, (const char *)&p, S_PD_PARAMS);
}
}

static void internal_symbolhook(const char *src, const char *sym) {
if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS) {
pd_params p = {LIBPD_SYMBOL, src, 0.0f, sym, 0};
rb_write_to_buffer(pd_receive_buffer, 1, (const char *)&p, S_PD_PARAMS);
}
}

static void internal_listhook(const char *src, int argc, t_atom *argv) {
int n = argc * S_ATOM;
if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS + n) {
pd_params p = {LIBPD_LIST, src, 0.0f, NULL, argc};
rb_write_to_buffer(pd_receive_buffer, 2,
(const char *)&p, S_PD_PARAMS, (const char *)argv, n);
}
}

static void internal_messagehook(const char *src, const char* sym,
int argc, t_atom *argv) {
int n = argc * S_ATOM;
if (rb_available_to_write(pd_receive_buffer) >= S_PD_PARAMS + n) {
pd_params p = {LIBPD_MESSAGE, src, 0.0f, sym, argc};
rb_write_to_buffer(pd_receive_buffer, 2,
(const char *)&p, S_PD_PARAMS, (const char *)argv, n);
}
}

static void receive_noteon(midi_params *p, char **buffer) {
if (libpd_queued_noteonhook) {
libpd_queued_noteonhook(p->midi1, p->midi2, p->midi3);
}
}

static void receive_controlchange(midi_params *p, char **buffer) {
if (libpd_queued_controlchangehook) {
libpd_queued_controlchangehook(p->midi1, p->midi2, p->midi3);
}
}

static void receive_programchange(midi_params *p, char **buffer) {
if (libpd_queued_programchangehook) {
libpd_queued_programchangehook(p->midi1, p->midi2);
}
}

static void receive_pitchbend(midi_params *p, char **buffer) {
if (libpd_queued_pitchbendhook) {
libpd_queued_pitchbendhook(p->midi1, p->midi2);
}
}

static void receive_aftertouch(midi_params *p, char **buffer) {
if (libpd_queued_aftertouchhook) {
libpd_queued_aftertouchhook(p->midi1, p->midi2);
}
}

static void receive_polyaftertouch(midi_params *p, char **buffer) {
if (libpd_queued_polyaftertouchhook) {
libpd_queued_polyaftertouchhook(p->midi1, p->midi2, p->midi3);
}
}

static void receive_midibyte(midi_params *p, char **buffer) {
if (libpd_queued_midibytehook) {
libpd_queued_midibytehook(p->midi1, p->midi2);
}
}

static void internal_noteonhook(int channel, int pitch, int velocity) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_NOTEON, channel, pitch, velocity};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

static void internal_controlchangehook(int channel, int controller, int value) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_CONTROLCHANGE, channel, controller, value};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

static void internal_programchangehook(int channel, int value) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_PROGRAMCHANGE, channel, value, 0};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

static void internal_pitchbendhook(int channel, int value) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_PITCHBEND, channel, value, 0};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

static void internal_aftertouchhook(int channel, int value) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_AFTERTOUCH, channel, value, 0};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

static void internal_polyaftertouchhook(int channel, int pitch, int value) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_POLYAFTERTOUCH, channel, pitch, value};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

static void internal_midibytehook(int port, int byte) {
if (rb_available_to_write(midi_receive_buffer) >= S_MIDI_PARAMS) {
midi_params p = {LIBPD_MIDIBYTE, port, byte, 0};
rb_write_to_buffer(midi_receive_buffer, 1, (const char *)&p, S_MIDI_PARAMS);
}
}

void libpd_set_queued_printhook(const t_libpd_printhook hook) {
libpd_queued_printhook = hook;
}

void libpd_set_queued_banghook(const t_libpd_banghook hook) {
libpd_queued_banghook = hook;
}

void libpd_set_queued_floathook(const t_libpd_floathook hook) {
libpd_queued_floathook = hook;
}

void libpd_set_queued_symbolhook(const t_libpd_symbolhook hook) {
libpd_queued_symbolhook = hook;
}

void libpd_set_queued_listhook(const t_libpd_listhook hook) {
libpd_queued_listhook = hook;
}

void libpd_set_queued_messagehook(const t_libpd_messagehook hook) {
libpd_queued_messagehook = hook;
}

void libpd_set_queued_noteonhook(const t_libpd_noteonhook hook) {
libpd_queued_noteonhook = hook;
}

void libpd_set_queued_controlchangehook(const t_libpd_controlchangehook hook) {
libpd_queued_controlchangehook = hook;
}

void libpd_set_queued_programchangehook(const t_libpd_programchangehook hook) {
libpd_queued_programchangehook = hook;
}

void libpd_set_queued_pitchbendhook(const t_libpd_pitchbendhook hook) {
libpd_queued_pitchbendhook = hook;
}

void libpd_set_queued_aftertouchhook(const t_libpd_aftertouchhook hook) {
libpd_queued_aftertouchhook = hook;
}

void libpd_set_queued_polyaftertouchhook(const t_libpd_polyaftertouchhook hook) {
libpd_queued_polyaftertouchhook = hook;
}

void libpd_set_queued_midibytehook(const t_libpd_midibytehook hook) {
libpd_queued_midibytehook = hook;
}

int libpd_queued_init() {
pd_receive_buffer = rb_create(BUFFER_SIZE);
if (!pd_receive_buffer) return -1;
midi_receive_buffer = rb_create(BUFFER_SIZE);
if (!midi_receive_buffer) return -1;

libpd_set_printhook(internal_printhook);
libpd_set_banghook(internal_banghook);
libpd_set_floathook(internal_floathook);
libpd_set_symbolhook(internal_symbolhook);
libpd_set_listhook(internal_listhook);
libpd_set_messagehook(internal_messagehook);

libpd_set_noteonhook(internal_noteonhook);
libpd_set_controlchangehook(internal_controlchangehook);
libpd_set_programchangehook(internal_programchangehook);
libpd_set_pitchbendhook(internal_pitchbendhook);
libpd_set_aftertouchhook(internal_aftertouchhook);
libpd_set_polyaftertouchhook(internal_polyaftertouchhook);
libpd_set_midibytehook(internal_midibytehook);

libpd_init();
return 0;
}

void libpd_queued_release() {
rb_free(pd_receive_buffer);
rb_free(midi_receive_buffer);
}

void libpd_queued_receive_pd_messages() {
size_t available = rb_available_to_read(pd_receive_buffer);
if (!available) return;
static char temp_buffer[BUFFER_SIZE];
rb_read_from_buffer(pd_receive_buffer, temp_buffer, (int) available);
char *end = temp_buffer + available;
char *buffer = temp_buffer;
while (buffer < end) {
pd_params *p = (pd_params *)buffer;
buffer += S_PD_PARAMS;
switch (p->type) {
case LIBPD_PRINT: {
receive_print(p, &buffer);
break;
}
case LIBPD_BANG: {
receive_bang(p, &buffer);
break;
}
case LIBPD_FLOAT: {
receive_float(p, &buffer);
break;
}
case LIBPD_SYMBOL: {
receive_symbol(p, &buffer);
break;
}
case LIBPD_LIST: {
receive_list(p, &buffer);
break;
}
case LIBPD_MESSAGE: {
receive_message(p, &buffer);
break;
}
default:
break;
}
}
}

void libpd_queued_receive_midi_messages() {
size_t available = rb_available_to_read(midi_receive_buffer);
if (!available) return;
static char temp_buffer[BUFFER_SIZE];
rb_read_from_buffer(midi_receive_buffer, temp_buffer, (int) available);
char *end = temp_buffer + available;
char *buffer = temp_buffer;
while (buffer < end) {
midi_params *p = (midi_params *)buffer;
buffer += S_MIDI_PARAMS;
switch (p->type) {
case LIBPD_NOTEON: {
receive_noteon(p, &buffer);
break;
}
case LIBPD_CONTROLCHANGE: {
receive_controlchange(p, &buffer);
break;
}
case LIBPD_PROGRAMCHANGE: {
receive_programchange(p, &buffer);
break;
}
case LIBPD_PITCHBEND: {
receive_pitchbend(p, &buffer);
break;
}
case LIBPD_AFTERTOUCH: {
receive_aftertouch(p, &buffer);
break;
}
case LIBPD_POLYAFTERTOUCH: {
receive_polyaftertouch(p, &buffer);
break;
}
case LIBPD_MIDIBYTE: {
receive_midibyte(p, &buffer);
break;
}
default:
break;
}
}
}

+ 45
- 0
ports/camomile/source/LibPd/libpd_wrapper/util/z_queued.h View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#ifndef __Z_QUEUED_H__
#define __Z_QUEUED_H__

#include "z_libpd.h"

#ifdef __cplusplus
extern "C"
{
#endif

EXTERN void libpd_set_queued_printhook(const t_libpd_printhook hook);
EXTERN void libpd_set_queued_banghook(const t_libpd_banghook hook);
EXTERN void libpd_set_queued_floathook(const t_libpd_floathook hook);
EXTERN void libpd_set_queued_symbolhook(const t_libpd_symbolhook hook);
EXTERN void libpd_set_queued_listhook(const t_libpd_listhook hook);
EXTERN void libpd_set_queued_messagehook(const t_libpd_messagehook hook);

EXTERN void libpd_set_queued_noteonhook(const t_libpd_noteonhook hook);
EXTERN void libpd_set_queued_controlchangehook(const t_libpd_controlchangehook hook);
EXTERN void libpd_set_queued_programchangehook(const t_libpd_programchangehook hook);
EXTERN void libpd_set_queued_pitchbendhook(const t_libpd_pitchbendhook hook);
EXTERN void libpd_set_queued_aftertouchhook(const t_libpd_aftertouchhook hook);
EXTERN void libpd_set_queued_polyaftertouchhook(const t_libpd_polyaftertouchhook hook);
EXTERN void libpd_set_queued_midibytehook(const t_libpd_midibytehook hook);

int libpd_queued_init();
void libpd_queued_release();
void libpd_queued_receive_pd_messages();
void libpd_queued_receive_midi_messages();

#ifdef __cplusplus
}
#endif

#endif

+ 83
- 0
ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.c View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#include <stdio.h>
#include "m_pd.h"
#include "x_libpdreceive.h"
#include "z_libpd.h"
#include "z_hooks.h"

static t_class *libpdrec_class;

typedef struct _libpdrec {
t_object x_obj;
t_symbol *x_sym;
} t_libpdrec;

static void libpdrecbang(t_libpdrec *x) {
if (libpd_banghook) (*libpd_banghook)(x->x_sym->s_name);
}

static void libpdrecfloat(t_libpdrec *x, t_float f) {
if (libpd_floathook) (*libpd_floathook)(x->x_sym->s_name, f);
}

static void libpdrecsymbol(t_libpdrec *x, t_symbol *s) {
if (libpd_symbolhook) (*libpd_symbolhook)(x->x_sym->s_name, s->s_name);
}

static void libpdrecpointer(t_libpdrec *x, t_gpointer *gp) {
// just ignore pointers for now...
}

static void libpdreclist(t_libpdrec *x, t_symbol *s, int argc, t_atom *argv) {
if (libpd_listhook) (*libpd_listhook)(x->x_sym->s_name, argc, argv);
}

static void libpdrecanything(t_libpdrec *x, t_symbol *s,
int argc, t_atom *argv) {
if (libpd_messagehook)
(*libpd_messagehook)(x->x_sym->s_name, s->s_name, argc, argv);
}

static void libpdreceive_free(t_libpdrec *x) {
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
}

static void *libpdreceive_donew(t_symbol *s) {
t_libpdrec *x;
x = (t_libpdrec *)pd_new(libpdrec_class);
x->x_sym = s;
pd_bind(&x->x_obj.ob_pd, s);
return x;
}

// This is exposed in the libpd API so must set the lock.
void *libpdreceive_new(t_symbol *s) {
t_libpdrec *x;
sys_lock();
x = (t_libpdrec *)libpdreceive_donew(s);
sys_unlock();
return x;
}

void libpdreceive_setup(void) {
sys_lock();
libpdrec_class = class_new(gensym("libpd_receive"),
(t_newmethod)libpdreceive_donew, (t_method)libpdreceive_free,
sizeof(t_libpdrec), CLASS_DEFAULT, A_DEFSYM, 0);
class_addbang(libpdrec_class, libpdrecbang);
class_addfloat(libpdrec_class, libpdrecfloat);
class_addsymbol(libpdrec_class, libpdrecsymbol);
class_addpointer(libpdrec_class, libpdrecpointer);
class_addlist(libpdrec_class, libpdreclist);
class_addanything(libpdrec_class, libpdrecanything);
sys_unlock();
}

+ 19
- 0
ports/camomile/source/LibPd/libpd_wrapper/x_libpdreceive.h View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#ifndef __X_LIBPDREC_H__
#define __X_LIBPDREC_H__

#include "m_pd.h"

void libpdreceive_setup(void);
void *libpdreceive_new(t_symbol *);

#endif

+ 26
- 0
ports/camomile/source/LibPd/libpd_wrapper/z_hooks.c View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/
#include "z_hooks.h"

t_libpd_printhook libpd_printhook = NULL;
t_libpd_banghook libpd_banghook = NULL;
t_libpd_floathook libpd_floathook = NULL;
t_libpd_symbolhook libpd_symbolhook = NULL;
t_libpd_listhook libpd_listhook = NULL;
t_libpd_messagehook libpd_messagehook = NULL;

t_libpd_noteonhook libpd_noteonhook = NULL;
t_libpd_controlchangehook libpd_controlchangehook = NULL;
t_libpd_programchangehook libpd_programchangehook = NULL;
t_libpd_pitchbendhook libpd_pitchbendhook = NULL;
t_libpd_aftertouchhook libpd_aftertouchhook = NULL;
t_libpd_polyaftertouchhook libpd_polyaftertouchhook = NULL;
t_libpd_midibytehook libpd_midibytehook = NULL;

+ 35
- 0
ports/camomile/source/LibPd/libpd_wrapper/z_hooks.h View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2013 Dan Wilcox (danomatika@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#ifndef __Z_HOOKS_H__
#define __Z_HOOKS_H__

#include "z_libpd.h"

// the internal hooks
// in a separate file so they can be used throughout the libpd_wrapper sources,
// do *not* include this file in a user-facing header

extern t_libpd_printhook libpd_printhook;
extern t_libpd_banghook libpd_banghook;
extern t_libpd_floathook libpd_floathook;
extern t_libpd_symbolhook libpd_symbolhook;
extern t_libpd_listhook libpd_listhook;
extern t_libpd_messagehook libpd_messagehook;

extern t_libpd_noteonhook libpd_noteonhook;
extern t_libpd_controlchangehook libpd_controlchangehook;
extern t_libpd_programchangehook libpd_programchangehook;
extern t_libpd_pitchbendhook libpd_pitchbendhook;
extern t_libpd_aftertouchhook libpd_aftertouchhook;
extern t_libpd_polyaftertouchhook libpd_polyaftertouchhook;
extern t_libpd_midibytehook libpd_midibytehook;

#endif

+ 639
- 0
ports/camomile/source/LibPd/libpd_wrapper/z_libpd.c View File

@@ -0,0 +1,639 @@
/*
* Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#ifndef LIBPD_NO_NUMERIC
# include <locale.h>
#endif
#include "z_libpd.h"
#include "x_libpdreceive.h"
#include "z_hooks.h"
#include "s_stuff.h"
#include "m_imp.h"
#include "g_all_guis.h"

#if PD_MINOR_VERSION < 46
# define HAVE_SCHED_TICK_ARG
#endif

#ifdef HAVE_SCHED_TICK_ARG
# define SCHED_TICK(x) sched_tick(x)
#else
# define SCHED_TICK(x) sched_tick()
#endif

// forward declares
void pd_init(void);
int sys_startgui(const char *libdir);
void sys_stopgui(void);
int sys_pollgui(void);

// (optional) built in pd externals setup functions
#ifdef LIBPD_EXTRA
void bob_tilde_setup();
void bonk_tilde_setup();
void choice_setup();
void fiddle_tilde_setup();
void loop_tilde_setup();
void lrshift_tilde_setup();
void pique_setup();
void sigmund_tilde_setup();
void stdout_setup();
#endif

static PERTHREAD t_atom *argv = NULL;
static PERTHREAD t_atom *curr = NULL;
static PERTHREAD int argm = 0;
static PERTHREAD int argc = 0;

static void *get_object(const char *s) {
t_pd *x = gensym(s)->s_thing;
return x;
}

// this is called instead of sys_main() to start things
int libpd_init(void) {
static int initialized = 0;
if (initialized) return -1; // only allow init once (for now)
initialized = 1;
signal(SIGFPE, SIG_IGN);
libpd_start_message(32); // allocate array for message assembly
sys_printhook = (t_printhook) libpd_printhook;
// are all these settings necessary?
sys_externalschedlib = 0;
sys_printtostderr = 0;
sys_usestdpath = 0; // don't use pd_extrapath, only sys_searchpath
sys_debuglevel = 0;
sys_noloadbang = 0;
sys_hipriority = 0;
sys_nmidiin = 0;
sys_nmidiout = 0;
#ifdef HAVE_SCHED_TICK_ARG
sys_time = 0;
#endif
pd_init();
STUFF->st_soundin = NULL;
STUFF->st_soundout = NULL;
STUFF->st_schedblocksize = DEFDACBLKSIZE;
sys_init_fdpoll();
libpdreceive_setup();
sys_set_audio_api(API_DUMMY);
STUFF->st_searchpath = NULL;
sys_libdir = gensym("");
#ifdef LIBPD_EXTRA
bob_tilde_setup();
bonk_tilde_setup();
choice_setup();
fiddle_tilde_setup();
loop_tilde_setup();
lrshift_tilde_setup();
pique_setup();
sigmund_tilde_setup();
stdout_setup();
#endif
#ifndef LIBPD_NO_NUMERIC
setlocale(LC_NUMERIC, "C");
#endif
return 0;
}

void libpd_clear_search_path(void) {
sys_lock();
namelist_free(STUFF->st_searchpath);
STUFF->st_searchpath = NULL;
sys_unlock();
}

void libpd_add_to_search_path(const char *s) {
sys_lock();
STUFF->st_searchpath = namelist_append(STUFF->st_searchpath, s, 0);
sys_unlock();
}

void *libpd_openfile(const char *basename, const char *dirname) {
void * retval;
sys_lock();
pd_globallock();
retval = (void *)glob_evalfile(NULL, gensym(basename), gensym(dirname));
pd_globalunlock();
sys_unlock();
return retval;
}

void libpd_closefile(void *x) {
sys_lock();
pd_free((t_pd *)x);
sys_unlock();
}

int libpd_getdollarzero(void *x) {
sys_lock();
pd_pushsym((t_pd *)x);
int dzero = canvas_getdollarzero();
pd_popsym((t_pd *)x);
sys_unlock();
return dzero;
}

int libpd_init_audio(int inChans, int outChans, int sampleRate) {
int indev[MAXAUDIOINDEV], inch[MAXAUDIOINDEV],
outdev[MAXAUDIOOUTDEV], outch[MAXAUDIOOUTDEV];
indev[0] = outdev[0] = DEFAULTAUDIODEV;
inch[0] = inChans;
outch[0] = outChans;
sys_lock();
sys_set_audio_settings(1, indev, 1, inch,
1, outdev, 1, outch, sampleRate, -1, 1, DEFDACBLKSIZE);
sched_set_using_audio(SCHED_AUDIO_CALLBACK);
sys_reopen_audio();
sys_unlock();
return 0;
}

int libpd_process_raw(const float *inBuffer, float *outBuffer) {
size_t n_in = STUFF->st_inchannels * DEFDACBLKSIZE;
size_t n_out = STUFF->st_outchannels * DEFDACBLKSIZE;
t_sample *p;
size_t i;
sys_lock();
sys_microsleep(0);
for (p = STUFF->st_soundin, i = 0; i < n_in; i++) {
*p++ = *inBuffer++;
}
memset(STUFF->st_soundout, 0, n_out * sizeof(t_sample));
SCHED_TICK(pd_this->pd_systime + STUFF->st_time_per_dsp_tick);
for (p = STUFF->st_soundout, i = 0; i < n_out; i++) {
*outBuffer++ = *p++;
}
sys_unlock();
return 0;
}

static const t_sample sample_to_short = SHRT_MAX,
short_to_sample = 1.0 / (t_sample) SHRT_MAX;

#define PROCESS(_x, _y) \
int i, j, k; \
t_sample *p0, *p1; \
sys_lock(); \
sys_microsleep(0); \
for (i = 0; i < ticks; i++) { \
for (j = 0, p0 = STUFF->st_soundin; j < DEFDACBLKSIZE; j++, p0++) { \
for (k = 0, p1 = p0; k < STUFF->st_inchannels; k++, p1 += DEFDACBLKSIZE) \
{ \
*p1 = *inBuffer++ _x; \
} \
} \
memset(STUFF->st_soundout, 0, \
STUFF->st_outchannels*DEFDACBLKSIZE*sizeof(t_sample)); \
SCHED_TICK(pd_this->pd_systime + STUFF->st_time_per_dsp_tick); \
for (j = 0, p0 = STUFF->st_soundout; j < DEFDACBLKSIZE; j++, p0++) { \
for (k = 0, p1 = p0; k < STUFF->st_outchannels; k++, p1 += DEFDACBLKSIZE) \
{ \
*outBuffer++ = *p1 _y; \
} \
} \
} \
sys_unlock(); \
return 0;

int libpd_process_short(const int ticks, const short *inBuffer, short *outBuffer) {
PROCESS(* short_to_sample, * sample_to_short)
}

int libpd_process_float(const int ticks, const float *inBuffer, float *outBuffer) {
PROCESS(,)
}

int libpd_process_double(const int ticks, const double *inBuffer, double *outBuffer) {
PROCESS(,)
}
#define GETARRAY \
t_garray *garray = (t_garray *) pd_findbyclass(gensym(name), garray_class); \
if (!garray) {sys_unlock(); return -1;} \

int libpd_arraysize(const char *name) {
int retval;
sys_lock();
GETARRAY
retval = garray_npoints(garray);
sys_unlock();
return retval;
}

#define MEMCPY(_x, _y) \
GETARRAY \
if (n < 0 || offset < 0 || offset + n > garray_npoints(garray)) return -2; \
t_word *vec = ((t_word *) garray_vec(garray)) + offset; \
int i; \
for (i = 0; i < n; i++) _x = _y;

int libpd_read_array(float *dest, const char *name, int offset, int n) {
sys_lock();
MEMCPY(*dest++, (vec++)->w_float)
sys_unlock();
return 0;
}

int libpd_write_array(const char *name, int offset, const float *src, int n) {
sys_lock();
MEMCPY((vec++)->w_float, *src++)
sys_unlock();
return 0;
}

void libpd_set_float(t_atom *v, float x) {
SETFLOAT(v, x);
}

void libpd_set_symbol(t_atom *v, const char *sym) {
SETSYMBOL(v, gensym(sym));
}

int libpd_list(const char *recv, int n, t_atom *v) {
t_pd *dest;
sys_lock();
dest = get_object(recv);
if (dest == NULL)
{
sys_unlock();
return -1;
}
pd_list(dest, &s_list, n, v);
sys_unlock();
return 0;
}

int libpd_message(const char *recv, const char *msg, int n, t_atom *v) {
t_pd *dest;
sys_lock();
dest = get_object(recv);
if (dest == NULL)
{
sys_unlock();
return -1;
}
pd_typedmess(dest, gensym(msg), n, v);
sys_unlock();
return 0;
}

int libpd_start_message(int max_length) {
if (max_length > argm) {
t_atom *v = realloc(argv, max_length * sizeof(t_atom));
if (v) {
argv = v;
argm = max_length;
} else {
return -1;
}
}
argc = 0;
curr = argv;
return 0;
}

#define ADD_ARG(f) f(curr, x); curr++; argc++;

void libpd_add_float(float x) {
ADD_ARG(SETFLOAT);
}

void libpd_add_symbol(const char *s) {
t_symbol *x;
sys_lock();
x = gensym(s);
sys_unlock();
ADD_ARG(SETSYMBOL);
}

int libpd_finish_list(const char *recv) {
return libpd_list(recv, argc, argv);
}

int libpd_finish_message(const char *recv, const char *msg) {
return libpd_message(recv, msg, argc, argv);
}

void *libpd_bind(const char *sym) {
t_symbol *x;
sys_lock();
x = gensym(sym);
sys_unlock();
return libpdreceive_new(x);
}

void libpd_unbind(void *p) {
sys_lock();
pd_free((t_pd *)p);
sys_unlock();
}

int libpd_is_float(t_atom *a) {
return (a)->a_type == A_FLOAT;
}

int libpd_is_symbol(t_atom *a) {
return (a)->a_type == A_SYMBOL;
}

float libpd_get_float(t_atom *a) {
return (a)->a_w.w_float;
}

char *libpd_get_symbol(t_atom *a) {
return (a)->a_w.w_symbol->s_name;
}

t_atom *libpd_next_atom(t_atom *a) {
return a + 1;
}

void libpd_set_printhook(const t_libpd_printhook hook) {
libpd_printhook = hook;
}

void libpd_set_banghook(const t_libpd_banghook hook) {
libpd_banghook = hook;
}

void libpd_set_floathook(const t_libpd_floathook hook) {
libpd_floathook = hook;
}

void libpd_set_symbolhook(const t_libpd_symbolhook hook) {
libpd_symbolhook = hook;
}

void libpd_set_listhook(const t_libpd_listhook hook) {
libpd_listhook = hook;
}

void libpd_set_messagehook(const t_libpd_messagehook hook) {
libpd_messagehook = hook;
}

int libpd_symbol(const char *recv, const char *sym) {
void *obj;
sys_lock();
obj = get_object(recv);
if (obj == NULL)
{
sys_unlock();
return -1;
}
pd_symbol(obj, gensym(sym));
sys_unlock();
return 0;
}

int libpd_float(const char *recv, float x) {
void *obj;
sys_lock();
obj = get_object(recv);
if (obj == NULL)
{
sys_unlock();
return -1;
}
pd_float(obj, x);
sys_unlock();
return 0;
}

int libpd_bang(const char *recv) {
void *obj;
sys_lock();
obj = get_object(recv);
if (obj == NULL)
{
sys_unlock();
return -1;
}
pd_bang(obj);
sys_unlock();
return 0;
}

int libpd_blocksize(void) {
return DEFDACBLKSIZE;
}

int libpd_exists(const char *sym) {
int retval;
sys_lock();
retval = (get_object(sym) != NULL);
sys_unlock();
return retval;
}

#define CHECK_CHANNEL if (channel < 0) return -1;
#define CHECK_PORT if (port < 0 || port > 0x0fff) return -1;
#define CHECK_RANGE_7BIT(v) if (v < 0 || v > 0x7f) return -1;
#define CHECK_RANGE_8BIT(v) if (v < 0 || v > 0xff) return -1;
#define PORT (channel >> 4)
#define CHANNEL (channel & 0x0f)

int libpd_noteon(int channel, int pitch, int velocity) {
CHECK_CHANNEL
CHECK_RANGE_7BIT(pitch)
CHECK_RANGE_7BIT(velocity)
sys_lock();
inmidi_noteon(PORT, CHANNEL, pitch, velocity);
sys_unlock();
return 0;
}

int libpd_controlchange(int channel, int controller, int value) {
CHECK_CHANNEL
CHECK_RANGE_7BIT(controller)
CHECK_RANGE_7BIT(value)
sys_lock();
inmidi_controlchange(PORT, CHANNEL, controller, value);
sys_unlock();
return 0;
}

int libpd_programchange(int channel, int value) {
CHECK_CHANNEL
CHECK_RANGE_7BIT(value)
sys_lock();
inmidi_programchange(PORT, CHANNEL, value);
sys_unlock();
return 0;
}

int libpd_pitchbend(int channel, int value) {
CHECK_CHANNEL
if (value < -8192 || value > 8191) return -1;
sys_lock();
inmidi_pitchbend(PORT, CHANNEL, value + 8192);
sys_unlock();
// Note: For consistency with Pd, we center the output of [pitchin]
// at 8192.
return 0;
}

int libpd_aftertouch(int channel, int value) {
CHECK_CHANNEL
CHECK_RANGE_7BIT(value)
sys_lock();
inmidi_aftertouch(PORT, CHANNEL, value);
sys_unlock();
return 0;
}

int libpd_polyaftertouch(int channel, int pitch, int value) {
CHECK_CHANNEL
CHECK_RANGE_7BIT(pitch)
CHECK_RANGE_7BIT(value)
sys_lock();
inmidi_polyaftertouch(PORT, CHANNEL, pitch, value);
sys_unlock();
return 0;
}

int libpd_midibyte(int port, int byte) {
CHECK_PORT
CHECK_RANGE_8BIT(byte)
sys_lock();
inmidi_byte(port, byte);
sys_unlock();
return 0;
}

int libpd_sysex(int port, int byte) {
CHECK_PORT
CHECK_RANGE_8BIT(byte)
sys_lock();
inmidi_sysex(port, byte);
sys_unlock();
return 0;
}

int libpd_sysrealtime(int port, int byte) {
CHECK_PORT
CHECK_RANGE_8BIT(byte)
sys_lock();
inmidi_realtimein(port, byte);
sys_unlock();
return 0;
}

void libpd_set_noteonhook(const t_libpd_noteonhook hook) {
libpd_noteonhook = hook;
}

void libpd_set_controlchangehook(const t_libpd_controlchangehook hook) {
libpd_controlchangehook = hook;
}

void libpd_set_programchangehook(const t_libpd_programchangehook hook) {
libpd_programchangehook = hook;
}

void libpd_set_pitchbendhook(const t_libpd_pitchbendhook hook) {
libpd_pitchbendhook = hook;
}

void libpd_set_aftertouchhook(const t_libpd_aftertouchhook hook) {
libpd_aftertouchhook = hook;
}

void libpd_set_polyaftertouchhook(const t_libpd_polyaftertouchhook hook) {
libpd_polyaftertouchhook = hook;
}

void libpd_set_midibytehook(const t_libpd_midibytehook hook) {
libpd_midibytehook = hook;
}

int libpd_start_gui(char *path) {
int retval;
sys_lock();
retval = sys_startgui(path);
sys_unlock();
return retval;
}

void libpd_stop_gui(void) {
sys_lock();
sys_stopgui();
sys_unlock();
}

void libpd_poll_gui(void) {
sys_lock();
sys_pollgui();
sys_unlock();
}

t_pdinstance *libpd_new_instance(void) {
#ifdef PDINSTANCE
return pdinstance_new();
#else
return 0;
#endif
}

void libpd_set_instance(t_pdinstance *x) {
#ifdef PDINSTANCE
pd_setinstance(x);
#endif
}

void libpd_free_instance(t_pdinstance *x) {
#ifdef PDINSTANCE
pdinstance_free(x);
#endif
}

t_pdinstance *libpd_this_instance(void) {
return pd_this;
}

t_pdinstance *libpd_get_instance(int index) {
#ifdef PDINSTANCE
if(index < 0 || index >= pd_ninstances) {return 0;}
return pd_instances[index];
#else
return pd_this;
#endif
}

int libpd_num_instances(void) {
#ifdef PDINSTANCE
return pd_ninstances;
#else
return 1;
#endif
}

void libpd_set_verbose(int verbose) {
if (verbose < 0) verbose = 0;
sys_verbose = verbose;
}

int libpd_get_verbose(void) {
return sys_verbose;
}

// dummy routines needed because we don't use s_file.c
void glob_loadpreferences(t_pd *dummy, t_symbol *s) {}
void glob_savepreferences(t_pd *dummy, t_symbol *s) {}
void glob_forgetpreferences(t_pd *dummy) {}
void sys_loadpreferences(const char *filename, int startingup) {}
int sys_oktoloadfiles(int done) {return 1;}
void sys_savepreferences(const char *filename) {} // used in s_path.c

+ 163
- 0
ports/camomile/source/LibPd/libpd_wrapper/z_libpd.h View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
* See https://github.com/libpd/libpd/wiki for documentation
*
*/

#ifndef __Z_LIBPD_H__
#define __Z_LIBPD_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include "m_pd.h"

EXTERN int libpd_init(void);
EXTERN void libpd_clear_search_path(void);
EXTERN void libpd_add_to_search_path(const char *sym);
EXTERN void *libpd_openfile(const char *basename, const char *dirname);
EXTERN void libpd_closefile(void *p);
EXTERN int libpd_getdollarzero(void *p);

EXTERN int libpd_blocksize(void);
EXTERN int libpd_init_audio(int inChans, int outChans, int sampleRate);
EXTERN int libpd_process_raw(const float *inBuffer, float *outBuffer);
EXTERN int libpd_process_short(const int ticks,
const short *inBuffer, short *outBuffer);
EXTERN int libpd_process_float(const int ticks,
const float *inBuffer, float *outBuffer);
EXTERN int libpd_process_double(const int ticks,
const double *inBuffer, double *outBuffer);

EXTERN int libpd_arraysize(const char *name);
// The parameters of the next two functions are inspired by memcpy.
EXTERN int libpd_read_array(float *dest, const char *src, int offset, int n);
EXTERN int libpd_write_array(const char *dest, int offset, const float *src, int n);

EXTERN int libpd_bang(const char *recv);
EXTERN int libpd_float(const char *recv, float x);
EXTERN int libpd_symbol(const char *recv, const char *sym);

EXTERN void libpd_set_float(t_atom *v, float x);
EXTERN void libpd_set_symbol(t_atom *v, const char *sym);
EXTERN int libpd_list(const char *recv, int argc, t_atom *argv);
EXTERN int libpd_message(const char *recv, const char *msg, int argc, t_atom *argv);

EXTERN int libpd_start_message(int max_length);
EXTERN void libpd_add_float(float x);
EXTERN void libpd_add_symbol(const char *sym);
EXTERN int libpd_finish_list(const char *recv);
EXTERN int libpd_finish_message(const char *recv, const char *msg);

EXTERN int libpd_exists(const char *sym);
EXTERN void *libpd_bind(const char *sym);
EXTERN void libpd_unbind(void *p);

EXTERN int libpd_is_float(t_atom *a);
EXTERN int libpd_is_symbol(t_atom *a);
EXTERN float libpd_get_float(t_atom *a);
EXTERN char *libpd_get_symbol(t_atom *a);
EXTERN t_atom *libpd_next_atom(t_atom *a);

typedef void (*t_libpd_printhook)(const char *recv);
typedef void (*t_libpd_banghook)(const char *recv);
typedef void (*t_libpd_floathook)(const char *recv, float x);
typedef void (*t_libpd_symbolhook)(const char *recv, const char *sym);
typedef void (*t_libpd_listhook)(const char *recv, int argc, t_atom *argv);
typedef void (*t_libpd_messagehook)(const char *recv, const char *msg,
int argc, t_atom *argv);

EXTERN void libpd_set_printhook(const t_libpd_printhook hook);
EXTERN void libpd_set_banghook(const t_libpd_banghook hook);
EXTERN void libpd_set_floathook(const t_libpd_floathook hook);
EXTERN void libpd_set_symbolhook(const t_libpd_symbolhook hook);
EXTERN void libpd_set_listhook(const t_libpd_listhook hook);
EXTERN void libpd_set_messagehook(const t_libpd_messagehook hook);

EXTERN int libpd_noteon(int channel, int pitch, int velocity);
EXTERN int libpd_controlchange(int channel, int controller, int value);
EXTERN int libpd_programchange(int channel, int value);
EXTERN int libpd_pitchbend(int channel, int value);
EXTERN int libpd_aftertouch(int channel, int value);
EXTERN int libpd_polyaftertouch(int channel, int pitch, int value);
EXTERN int libpd_midibyte(int port, int byte);
EXTERN int libpd_sysex(int port, int byte);
EXTERN int libpd_sysrealtime(int port, int byte);

typedef void (*t_libpd_noteonhook)(int channel, int pitch, int velocity);
typedef void (*t_libpd_controlchangehook)(int channel,
int controller, int value);
typedef void (*t_libpd_programchangehook)(int channel, int value);
typedef void (*t_libpd_pitchbendhook)(int channel, int value);
typedef void (*t_libpd_aftertouchhook)(int channel, int value);
typedef void (*t_libpd_polyaftertouchhook)(int channel, int pitch, int value);
typedef void (*t_libpd_midibytehook)(int port, int byte);

EXTERN void libpd_set_noteonhook(const t_libpd_noteonhook hook);
EXTERN void libpd_set_controlchangehook(const t_libpd_controlchangehook hook);
EXTERN void libpd_set_programchangehook(const t_libpd_programchangehook hook);
EXTERN void libpd_set_pitchbendhook(const t_libpd_pitchbendhook hook);
EXTERN void libpd_set_aftertouchhook(const t_libpd_aftertouchhook hook);
EXTERN void libpd_set_polyaftertouchhook(const t_libpd_polyaftertouchhook hook);
EXTERN void libpd_set_midibytehook(const t_libpd_midibytehook hook);

/// \section GUI

/// open the current patches within a Pd vanilla GUI
/// requires the path to Pd's main folder that contains bin/, tcl/, etc
/// returns 0 on success
EXTERN int libpd_start_gui(char *path);

/// stop the Pd vanilla GUI
EXTERN void libpd_stop_gui(void);

/// update and handle any GUI messages
EXTERN void libpd_poll_gui(void);

/// \section Multiple Instances

/// create a new pd instance
/// returns 0 when libpd is not compiled with PDINSTANCE
EXTERN t_pdinstance *libpd_new_instance(void);

/// set the current pd instance,
/// subsequent libpd calls will affect this instance only
/// does nothing when libpd is not compiled with PDINSTANCE
EXTERN void libpd_set_instance(t_pdinstance *x);

/// free a pd instance
/// does nothing when libpd is not compiled with PDINSTANCE
EXTERN void libpd_free_instance(t_pdinstance *x);

/// get the current pd instance
EXTERN t_pdinstance *libpd_this_instance(void);

/// get a pd instance by index
/// returns 0 if index is out of bounds
/// returns "this" instance when libpd is not compiled with PDINSTANCE
EXTERN t_pdinstance *libpd_get_instance(int index);

/// get the number of pd instances
/// returns 1 when libpd is not compiled with PDINSTANCE
EXTERN int libpd_num_instances(void);

/// \section Log Level

/// set verbose print state: 0 or 1
EXTERN void libpd_set_verbose(int verbose);

/// get the verbose print state: 0 or 1
EXTERN int libpd_get_verbose(void);

#ifdef __cplusplus
}
#endif

#endif

+ 12
- 0
ports/camomile/source/LibPd/pure-data/src/.dir-locals.el View File

@@ -0,0 +1,12 @@
; see also https://github.com/erdc-cm/petsc-dev/blob/master/.dir-locals.el
(
(nil . ((indent-tabs-mode . nil)
(tab-width . 4)
(fill-column . 80)))
;; Warn about spaces used for indentation:
(c-mode . ((c-file-style . "bsd")
(c-basic-offset . 4)
(c-comment-only-line-offset . 4)
))
(haskell-mode . ((eval . (highlight-regexp "^ *"))))
(java-mode . ((c-file-style . "bsd"))))

+ 261
- 0
ports/camomile/source/LibPd/pure-data/src/CHANGELOG.txt View File

@@ -0,0 +1,261 @@
This file describes implementation and API changes; stuff more visible to the
user appears in the "release notes" instead. See the bottom of this file
for original notes on source style and organization.

0.42.0

changed definition of t_float, t_sample, t_floatarg so that they can be
set via #defines (PD_FLOATTYPE, etc).

0.41.0

add support for callback-based audio I/O
headers & code changed to use t_float or t_sample instead of float (patches
by zmoelnig).


0.40.0

0.39.0

canvas_dspstate and signalinlet_new() exported to m_pd.h

new function verbose() added to m_pd.h

0.38.0

finally figured out how to do "-enable-", etc., flags in the configure
script correctly.

The scheduler now has a hook (set_so you can add polling routines) :
sys_idlehook().

I'm now uploading directly to CVS repository ("main" and "stable_0_38"
branches.) There are still problems keeping CVS's and my versions of
portaudio the same (CVS bashes the "ident" lines).

t_int to int in binbuf_addv prototype

64-bit fix to externs makefiles

Pd now uses portaudio out-of-the-box; customized files are moved to
"src" directory.

All "tags" are printf'd as %lx to make 64-bit safe.

GUI queueing mechanism added: sys_queuegui() etc.

massive rewrite of array code to unify arrays and scalars.

fixed empty lists automatically to call "bang" method if one is supplied.

rewrote the "namelist" stuff to facilitate preference saving (s_stuff.h,
s_path.c, s_file.c, s_main.c)

0.37.2

expr() "exp" temporary variables renamed to avoid compilation problems

0.37.1

makefile.in: MANINSTDIR = $(DESTDIR)/$(MANDIR) changed to
$(DESTDIR)/$(INSTALL_PREFIX)/$(MANDIR) (thx. Mathieu Bouchard)

applied 2 jack patches from Luke Yelavich

add -fno-strict-aliasing to config script (linux&mac) to improve underflow,
etc., protection

add underflow protection to vcf~ object; rewrote underflow protection to be
faster in throw~/catch~ and send~/receive~

fixed bug in -inchannels/-outchannels arg parsing

fixed u_main.tk to make "apple" key work to accelerate menus on MACOS

fooled with MIDI to try to get sysex and other system messages to work.
Needs lots of testing now...

finally fixed OSS to open audio with NODELAY... also cleared dup-on-exec flag.

bug fix in scalar_properties

major editions to the IEM GUIs to fix bugs in how "$" variables are handled.
The code still isn't pretty but hopefully at least works now.

tried to get alsa noninterleaved access to work (needed for RME). Failed
to get my RME card to load under ALSA and gave up for now.

fixed scalar drawing to fail gracefully when the template canvas disappears

bug fix in vd~ for very small delays (d_delay.c)

set up sys_oldtclversion flag to correct for changed text selection
(u_main.tk, s_main.c, g_rtext.c)

tried again to add "readn" support to s_audio_alsa.c: coded, but failing so far.

fixed broken octave divider example

removed "-Werror" from default makefile; fixed configure script to respect
"CFLAGS" environment variable instead. Suggest developers should use
"setenv CFLAGS -Werror".

added "-alsaadd" flag so people can specify alsa devnames to add to list.
fixed some problems with Pd crashing when ALSA failed to open.

took out the 2-pixel padding for MSW in g_canvas.g (HORIZBORDER/VERTBORDER)

went back to s_midi_mmio (portaudio version got assertion errors and anyway
I could never get sysex working in it as I had wanted.)

Took bug fixes from s_midi_pm.c, s_audio_jack.c, s_inter.c from "devel" branch;
also added "static" flag to configure.in (but the devel configure.in as a whole
doesn't seem to work for OSX, for me at least.)
Might have fixed a bug where labels disappear in buttons, etc, when saved
and reloaded.

brought s_audio_alsa.c up to alsa 1.0.0 compatibility

fixed "-alsaadd" (never worked before)

fooled with macintosh audio. Fixed some (not all) of the audio I/O APIs
to deal with open failures better (reducing sys_{in,out}channels accordingly)

In the Alsa API, the synchronization test was too stringent and was loosened
to 3*DACBLKSIZE/2.

'make install' fixed to deal with 'extra' correctly.

one more improvement in jack support (guenter)

make an "nrt" flag so mac can disable pthread_setschedparam call if yu want.

------------------- original source notes -------------

0. structure definition roadmap. First, the containment tree of things
that can be sent messages ("pure data"). (note that t_object and t_text,
and t_graph and t_canvas, should be unified...)

------------ BFFORE 0.35: ---------
m_pd.h t_pd anything with a class
t_gobj "graphic object"
t_text text object
g_canvas.h
t_glist list of graphic objects
g_canvas.c t_canvas Pd "document"

------------ AFTER 0.35: ---------
m_pd.h t_pd anything with a class
t_gobj "graphic object"
t_text patchable object, AKA t_object
g_canvas.h t_glist list of graphic objects, AKA t_canvas

... and other structures:
g_canvas.h t_selection -- linked list of gobjs
t_editor -- editor state, allocated for visible glists
m_imp.h t_methodentry -- method handler
t_widgetbehavior -- class-dependent editing behavior for gobjs
t_parentwidgetbehavior -- objects' behavior on parent window
t_class -- method definitions, instance size, flags, etc.


1. C coding style. The source should pass most "warnings" of C compilers
(-Wall on linux, for instance; see the makefile.) Some informalities
are intentional, for instance the loose use of function prototypes (see
below) and uncast conversions from longer to shorter numerical formats.
The code doesn't respect "const" yet.

1.1. Prefixes in structure elements. The names of structure elements always
have a K&R-style prefix, as in ((t_atom)x)->a_type, where the "a_" prefix
indicates "atom." This is intended to enhance readability (although the
convention arose from a limitation of early C compilers.) Common prefixes are
"w_" (word), "a_" (atom), "s_" (symbol), "ob_" (object), "te_" (text object),
"g_" (graphical object), and "gl_" (glist, a list of graphical objects). Also,
global symbols sometimes get prefixes, as in "s_float" (the symbol whose string
is "float). Typedefs are prefixed by "t_". Most _private_ structures, i.e.,
structures whose definitions appear in a ".c" file, are prefixed by "x_".

1.2. Function arguments. Many functions take as their first
argument a pointer named "x", which is a pointer to a structure suggested
by the function prefix; e.g., canvas_dirty(x, n) where "x" points to a canvas
(t_canvas *x).

1.3. Function Prototypes. Functions which are used in at least two different
files (besides where they originate) are prototyped in the appropriate include
file. Functions which are provided in one file and used in one other are
prototyped right where they are used. This is just to keep the size of the
".h" files down for readability's sake.

1.4. Whacko private terminology. Some terms are lifted from other historically
relevant programs, notably "ugen" (which is just a tilde object; see d_ugen.c.)

1.5. Spacing. Tabs are 8 spaces; indentation is 4 spaces. Indenting
curly brackets are by themselves on their own lines, as in:

if (x)
{
x = 0;
}

Lines should fit within 80 spaces.

2. Max patch-level compatibility. "Import" and "Export" functions are
provided which aspire to strict compatibility with 0.26 patches (ISPW version),
but which don't get anywhere close to that yet. Where possible, features
appearing on the Mac will comeday also be provided; for instance, the connect
message on the Mac offers segmented patch cords; these will devolve into
straight lines in Pd. Many, many UI objects in Opcode Max will not appear in
Pd, at least at first.

3. Compatibility with Max 0.26 "externs", i.e., source-level compatibility. Pd
objects follow the style of 0.26 objects as closely as possible, making
exceptions in cases where the 0.26 model is clearly deficient. These are:

3.1. Anything involving the MacIntosh "Handle" data type is changed to use
char * or void * instead.

3.2. Pd passes true single-precision floating-point arguments to methods;
Max uses double.
Typedefs are provided:
t_floatarg, t_intarg for arguments passed by the message system
t_float, t_int for the "word" union (in atoms, for example.)

3.3. Badly-named entities got name changes:

w_long --> w_int (in the "union word" structure)

3.4. Many library functions are renamed and have different arguments;
I hope to provide an include file to alias them when compiling Max externs.

4. Function name prefixes.
Many function names have prefixes which indicate what "package" they belong
to. The exceptions are:
typedmess, vmess, getfn, gensym (m_class.c)
getbytes, freebytes, resizebytes (m_memory.c)
post, error, bug (s_print.c)
which are all frequently called and which don't fit into simple categories.
Important packages are:
(pd-gui:) pdgui -- everything
(pd:) pd -- functions common to all "pd" objects
obj -- fuctions common to all "patchable" objects ala Max
sys -- "system" level functions
binbuf -- functions manipulating binbufs
class -- functions manipulating classes
(other) -- functions common to the named Pd class

5. Source file prefixes.
PD:
s system interface
m message system
g graphics stuff
d DSP objects
x control objects
z other

PD-GUI:
t TK front end




+ 409
- 0
ports/camomile/source/LibPd/pure-data/src/Makefile.am View File

@@ -0,0 +1,409 @@
#########################################
##### Defaults & Paths #####

AUTOMAKE_OPTIONS = foreign
CLEANFILES=

bin_SCRIPTS =
noinst_SCRIPTS =

pd_CFLAGS = -DPD -DINSTALL_PREFIX=\"$(prefix)\" -DPD_INTERNAL
pd_LDFLAGS =
pd_LDADD =

# there are pd_* and pd_*_core variables as we need different flags on Windows
# for the DLL and the EXE, other OSes simply set pd_* = $(pd_*_core) later
# also, the "_core" suffix is used as this keeps automake from thinking these
# are library or binary variables since we only need them as placeholders
pd_LDFLAGS_core =
pd_LDADD_core =

pdsend_CFLAGS =
pdreceive_CFLAGS =
pd_watchdog_CFLAGS =
LIBS = @LIBS@

SUFFIXES = .@EXTENSION@ .@SHARED_LIB@

#########################################
##### Files, Binaries, & Libs #####

# pd core & utils
bin_PROGRAMS = pd pdsend pdreceive

pdsend_SOURCES = u_pdsend.c
pdreceive_SOURCES = u_pdreceive.c
pd_watchdog_SOURCES = s_watchdog.c

# on Windows, pd.exe contains only s_entry.c and links against pd.dll
# (where all the logic resides), that's why we have to split the sources
# (only to later merge them again for non-Windows systems)
pd_SOURCES = s_entry.c
pd_SOURCES_core = \
d_arithmetic.c \
d_array.c \
d_ctl.c \
d_dac.c \
d_delay.c \
d_fft.c \
d_filter.c \
d_global.c \
d_math.c \
d_misc.c \
d_osc.c \
d_resample.c \
d_soundfile.c \
d_ugen.c \
g_all_guis.c \
g_array.c \
g_bang.c \
g_canvas.c \
g_clone.c \
g_editor.c \
g_graph.c \
g_guiconnect.c \
g_hdial.c \
g_hslider.c \
g_io.c \
g_mycanvas.c \
g_numbox.c \
g_readwrite.c \
g_rtext.c \
g_scalar.c \
g_template.c \
g_text.c \
g_toggle.c \
g_traversal.c \
g_vdial.c \
g_vslider.c \
g_vumeter.c \
m_atom.c \
m_binbuf.c \
m_class.c \
m_conf.c \
m_glob.c \
m_memory.c \
m_obj.c \
m_pd.c \
m_sched.c \
s_audio.c \
s_file.c \
s_inter.c \
s_loader.c \
s_main.c \
s_midi.c \
s_path.c \
s_print.c \
s_utf8.c \
x_acoustics.c \
x_arithmetic.c \
x_array.c \
x_connective.c \
x_gui.c \
x_interface.c \
x_list.c \
x_midi.c \
x_misc.c \
x_net.c \
x_scalar.c \
x_text.c \
x_time.c \
x_vexp.c \
x_vexp_fun.c \
x_vexp_if.c

# pd-watchdog and "local" pd symlink location for tcl scripts
libpdbindir = $(pkglibdir)/bin

# these install to ${includedir}/pd
pkginclude_HEADERS = m_pd.h m_imp.h g_canvas.h s_stuff.h g_all_guis.h x_vexp.h
# compatibility: m_pd.h also goes into ${includedir}/
include_HEADERS = m_pd.h
noinst_HEADERS = g_all_guis.h s_audio_alsa.h s_audio_paring.h s_utf8.h x_vexp.h

# we want these in the dist tarball
EXTRA_DIST = CHANGELOG.txt notes.txt pd.ico pd.rc \
makefile.gnu makefile.mac makefile.mingw makefile.msvc \
s_audio_audiounit.c s_audio_esd.c

# add WISH define if it's set
WISH=@WISH@
WISHDEFINE=$(if $(WISH),-DWISH='"$(WISH)"')
pd_CFLAGS += $(WISHDEFINE)

#########################################
##### Configurations Per Library #####

##### Advanced Linux Sound Architecture #####
if ALSA
pd_CFLAGS += -DUSEAPI_ALSA
pd_LDADD_core += @ALSA_LIBS@
pd_SOURCES_core += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c
endif

##### OSX CoreAudio #####
# needed by PortAudio on OSX
if COREAUDIO
LIBS += -framework CoreAudio -framework CoreMIDI \
-framework AudioUnit -framework AudioToolbox
endif

##### Jack Audio Connection Kit #####
# TODO support Jack xrun
if JACK
pd_CFLAGS += -DUSEAPI_JACK -DJACK_XRUN
pd_SOURCES_core += s_audio_jack.c

if JACK_FRAMEWORK
# link to Jackmp.framework on macOS
pd_LDFLAGS_core += -weak_framework Jackmp
else
# link to Jack discovered by configure
pd_LDADD_core += @JACK_LIBS@
endif

endif

##### GNU/Linux Open Sound System #####
if OSS
pd_CFLAGS += -DUSEAPI_OSS
pd_SOURCES_core += s_audio_oss.c s_midi_oss.c
endif

##### Windows MultiMedia (File) I/O #####
if MMIO
pd_CFLAGS += -DUSEAPI_MMIO
pd_SOURCES_core += s_audio_mmio.c
endif

##### PortAudio #####
if PORTAUDIO
pd_CFLAGS += -DUSEAPI_PORTAUDIO
pd_SOURCES_core += s_audio_pa.c s_audio_paring.c

if LOCAL_PORTAUDIO
# link the included portaudio which is built as a static lib
AM_CPPFLAGS += -I$(top_srcdir)/portaudio/portaudio/include
pd_LDADD_core += $(top_builddir)/portaudio/libportaudio.a
else
# link the system's portaudio
pd_LDADD_core += -lportaudio
endif

# need Carbon framework for PA on Mac
if MACOSX
LIBS += -framework Carbon
endif

endif

##### ASIO #####
# ASIO needs to go after PORTAUDIO in order for it to link properly
if ASIO
# always Windows
pd_LDADD_core += $(top_builddir)/asio/libasio.a
endif

##### PortMidi #####
if PORTMIDI
pd_SOURCES_core += s_midi_pm.c

if LOCAL_PORTMIDI
# link the included portmidi which is built as a static lib
AM_CPPFLAGS += \
-I$(top_srcdir)/portmidi/portmidi/pm_common \
-I$(top_srcdir)/portmidi/portmidi/porttime
pd_LDADD_core += $(top_builddir)/portmidi/libportmidi.a
else
# link the system's portmidi
pd_LDADD_core += -lportmidi
endif

# need Carbon framework for PM on Mac
if MACOSX
LIBS += -framework CoreFoundation -framework Carbon
endif

endif

##### NO API? #####
# if no audio or midi api was detected/specified, fall back to dummy apis
# ie. GNU/HURD, IPHONEOS, ... have no MIDI (not even OSS)
if AUDIO_DUMMY
pd_CFLAGS += -DUSEAPI_DUMMY
pd_SOURCES_core += s_audio_dummy.c
endif
if MIDI_DUMMY
pd_CFLAGS += -DUSEAPI_MIDIDUMMY
pd_SOURCES_core += s_midi_dummy.c
endif

##### FFTW fft library #####
if FFTW
pd_SOURCES_core += d_fft_fftw.c
else
pd_SOURCES_core += d_fft_fftsg.c
endif

#########################################
##### Configurations Per Platform #####

##### GNU/Hurd #####
if HURD

# install watchdog to $(libdir)/pd/bin as it's not a user facing program
libpdbin_PROGRAMS = pd-watchdog

# this flag has to have a single leading "-" for libtool, even though ld uses
# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld...
pd_LDFLAGS_core += -export-dynamic

# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it
pd_LDFLAGS_core += $(LIBM)

# force linking to pthread, which should really be done with some autotools way
pd_LDFLAGS_core += -lpthread

# force linking to dl, which should really be done with some autotools way
pd_LDFLAGS_core += -ldl

endif

##### GNU/Linux #####
if LINUX

# install watchdog to $(libdir)/pd/bin as it's not a user facing program
libpdbin_PROGRAMS = pd-watchdog

# this flag has to have a single leading "-" for libtool, even though ld uses
# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld...
pd_LDFLAGS_core += -export-dynamic

# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it
pd_LDFLAGS_core += $(LIBM)

endif

##### Apple Mac OSX #####
if MACOSX

# install watchdog to $(libdir)/pd/bin as it's not a user facing program
libpdbin_PROGRAMS = pd-watchdog

# kludge, should use auto macro __APPLE__
# but who knows what externals rely on this
pd_CFLAGS += -DMACOSX

# for dynamic loading & threading
LIBS += -ldl -lm -lpthread

endif

##### Windows #####
if WINDOWS

# win32 sockets, multimedia, and all that
LIBS += -lwsock32 -lwinmm -lole32 -static-libgcc -static-libstdc++

bin_SCRIPTS += pd.dll pd.lib pd.def pd.com
CLEANFILES += pd.dll pd.lib pd.def pd.com
noinst_SCRIPTS += libpd.a
CLEANFILES += libpd.a
CLEANFILES += pd.res

# hide the console
pd_LDFLAGS += -mwindows
# link with ressources and pd.dll import library
pd_LDADD += pd.res pd.lib

pd_OBJECTS_core = $(pd_SOURCES_core:.c=.o)

# the variables are taken from the automake Makefile
$(pd_OBJECTS_core) : %.o : %.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(pd_CFLAGS) $(CFLAGS) -c -o $@ $<

pd.res: pd.rc
$(WINDRES) $< -O coff -o $@

# import library for pd.dll. also works with MSVC!
pd.lib: pd.dll

# another import library (when linking with -lpd), the same as pd.lib.
libpd.a: pd.lib
cp $< $@

pd.def: pd.dll

pd.dll: $(pd_OBJECTS_core)
$(CXX) -shared $(pd_LDFLAGS_core) -o pd.dll \
$(pd_OBJECTS_core) $(pd_LDADD_core) $(LIBS) \
-Wl,--export-all-symbols -Wl,--out-implib=pd.lib -Wl,--output-def=pd.def

# same as pd.exe but without -mwindows and resources
# NOTE: this is a bit ugly. I couldn't figure out how to get automake to build
# two programs with the same basename but different suffix.
pd.com: pd-s_entry.o pd.lib
$(CXX) $(LDFLAGS) -o pd.com pd-s_entry.o $(LIBS) pd.lib

else
# for other OS, join pd_* with pd_*_core
pd_SOURCES += $(pd_SOURCES_core)
pd_LDADD += $(pd_LDADD_core)
pd_LDFLAGS += $(pd_LDFLAGS_core)
endif

##### Windows MinGW #####
if MINGW
# To use SetDllDirectory() in s_loader.c, we need a minimum of Windows
# XP SP1. WINVER isnt' fine-grained enough for that, so we use the
# next minor version of Windows, 5.2. That gives us -DWINVER=0x0502
pd_CFLAGS += -DWINVER=0x0502 -D_WIN32_WINNT=0x0502
endif

#########################################
##### Targets #####

.PHONY: convenience-links

all-local: convenience-links

# create a bin folder & symlinks to the binaries in order to
# replicate the src/makefile.* build result
convenience-links: $(libpdbin_PROGRAMS) $(bin_PROGRAMS)
$(MKDIR_P) $(top_builddir)/bin
rm -rf $(top_builddir)/bin/pd*
$(LN_S) $(top_builddir)/src/pd$(EXEEXT) $(top_builddir)/bin/pd$(EXEEXT)
$(LN_S) $(top_builddir)/src/pdsend$(EXEEXT) $(top_builddir)/bin/pdsend$(EXEEXT)
$(LN_S) $(top_builddir)/src/pdreceive$(EXEEXT) $(top_builddir)/bin/pdreceive$(EXEEXT)
$(LN_S) $(top_srcdir)/tcl/pd-gui.in $(top_builddir)/bin/pd-gui
test -e $(top_builddir)/src/pd-watchdog$(EXEEXT) && $(LN_S) $(top_builddir)/src/pd-watchdog$(EXEEXT) $(top_builddir)/bin/pd-watchdog$(EXEEXT) || true

clean-local:
rm -rf $(top_builddir)/bin

# link to $(libdir)/pd/bin so the tcl scripts can
# launch the core if the gui is started first
#
# We have to make the dir just in case as it may not exist yet &
# we remove any existing symlink if doing a repeated install.
install-exec-hook:
$(MKDIR_P) $(DESTDIR)$(libpdbindir)
rm -f $(DESTDIR)$(libpdbindir)/pd
$(LN_S) $(DESTDIR)$(bindir)/pd $(DESTDIR)$(libpdbindir)/pd

# remove the $(libdir)/pd/bin link
# &
# remove the leftover $(includedir)/pd dir, fail silently on any non-empty dirs
#
# The "|| true" ensures that if the dir is *not* empty, then rmdir does not throw
# an error and stop make.
uninstall-hook:
rm -f $(DESTDIR)$(libpdbindir)/pd
if test -d $(DESTDIR)$(pkgincludedir) ; then \
rmdir $(DESTDIR)$(pkgincludedir) 2>/dev/null || true ; \
fi

# generate Emacs tags
etags: TAGS
etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl

+ 843
- 0
ports/camomile/source/LibPd/pure-data/src/d_arithmetic.c View File

@@ -0,0 +1,843 @@
/* 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. */

/* arithmetic binops (+, -, *, /).
If no creation argument is given, there are two signal inlets for vector/vector
operation; otherwise it's vector/scalar and the second inlet takes a float
to reset the value.
*/

#include "m_pd.h"

/* ----------------------------- plus ----------------------------- */
static t_class *plus_class, *scalarplus_class;

typedef struct _plus
{
t_object x_obj;
t_float x_f;
} t_plus;

typedef struct _scalarplus
{
t_object x_obj;
t_float x_f;
t_float x_g; /* inlet value */
} t_scalarplus;

static void *plus_new(t_symbol *s, int argc, t_atom *argv)
{
if (argc > 1) post("+~: extra arguments ignored");
if (argc)
{
t_scalarplus *x = (t_scalarplus *)pd_new(scalarplus_class);
floatinlet_new(&x->x_obj, &x->x_g);
x->x_g = atom_getfloatarg(0, argc, argv);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
else
{
t_plus *x = (t_plus *)pd_new(plus_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
}

t_int *plus_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--) *out++ = *in1++ + *in2++;
return (w+5);
}

t_int *plus_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
{
t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];

t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];

out[0] = f0 + g0; out[1] = f1 + g1; out[2] = f2 + g2; out[3] = f3 + g3;
out[4] = f4 + g4; out[5] = f5 + g5; out[6] = f6 + g6; out[7] = f7 + g7;
}
return (w+5);
}

t_int *scalarplus_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float f = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--) *out++ = *in++ + f;
return (w+5);
}

t_int *scalarplus_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float g = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in += 8, out += 8)
{
t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];

out[0] = f0 + g; out[1] = f1 + g; out[2] = f2 + g; out[3] = f3 + g;
out[4] = f4 + g; out[5] = f5 + g; out[6] = f6 + g; out[7] = f7 + g;
}
return (w+5);
}

void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n)
{
if (n&7)
dsp_add(plus_perform, 4, in1, in2, out, n);
else
dsp_add(plus_perf8, 4, in1, in2, out, n);
}

static void plus_dsp(t_plus *x, t_signal **sp)
{
dsp_add_plus(sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void scalarplus_dsp(t_scalarplus *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(scalarplus_perform, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
else
dsp_add(scalarplus_perf8, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
}

static void plus_setup(void)
{
plus_class = class_new(gensym("+~"), (t_newmethod)plus_new, 0,
sizeof(t_plus), 0, A_GIMME, 0);
class_addmethod(plus_class, (t_method)plus_dsp, gensym("dsp"), A_CANT, 0);
CLASS_MAINSIGNALIN(plus_class, t_plus, x_f);
class_sethelpsymbol(plus_class, gensym("sigbinops"));
scalarplus_class = class_new(gensym("+~"), 0, 0,
sizeof(t_scalarplus), 0, 0);
CLASS_MAINSIGNALIN(scalarplus_class, t_scalarplus, x_f);
class_addmethod(scalarplus_class, (t_method)scalarplus_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(scalarplus_class, gensym("sigbinops"));
}

/* ----------------------------- minus ----------------------------- */
static t_class *minus_class, *scalarminus_class;

typedef struct _minus
{
t_object x_obj;
t_float x_f;
} t_minus;

typedef struct _scalarminus
{
t_object x_obj;
t_float x_f;
t_float x_g;
} t_scalarminus;

static void *minus_new(t_symbol *s, int argc, t_atom *argv)
{
if (argc > 1) post("-~: extra arguments ignored");
if (argc)
{
t_scalarminus *x = (t_scalarminus *)pd_new(scalarminus_class);
floatinlet_new(&x->x_obj, &x->x_g);
x->x_g = atom_getfloatarg(0, argc, argv);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
else
{
t_minus *x = (t_minus *)pd_new(minus_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
}

t_int *minus_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--) *out++ = *in1++ - *in2++;
return (w+5);
}

t_int *minus_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
{
t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];

t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];

out[0] = f0 - g0; out[1] = f1 - g1; out[2] = f2 - g2; out[3] = f3 - g3;
out[4] = f4 - g4; out[5] = f5 - g5; out[6] = f6 - g6; out[7] = f7 - g7;
}
return (w+5);
}

t_int *scalarminus_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float f = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--) *out++ = *in++ - f;
return (w+5);
}

t_int *scalarminus_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float g = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in += 8, out += 8)
{
t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];

out[0] = f0 - g; out[1] = f1 - g; out[2] = f2 - g; out[3] = f3 - g;
out[4] = f4 - g; out[5] = f5 - g; out[6] = f6 - g; out[7] = f7 - g;
}
return (w+5);
}

static void minus_dsp(t_minus *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(minus_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
else
dsp_add(minus_perf8, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void scalarminus_dsp(t_scalarminus *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(scalarminus_perform, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
else
dsp_add(scalarminus_perf8, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
}

static void minus_setup(void)
{
minus_class = class_new(gensym("-~"), (t_newmethod)minus_new, 0,
sizeof(t_minus), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(minus_class, t_minus, x_f);
class_addmethod(minus_class, (t_method)minus_dsp, gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(minus_class, gensym("sigbinops"));
scalarminus_class = class_new(gensym("-~"), 0, 0,
sizeof(t_scalarminus), 0, 0);
CLASS_MAINSIGNALIN(scalarminus_class, t_scalarminus, x_f);
class_addmethod(scalarminus_class, (t_method)scalarminus_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(scalarminus_class, gensym("sigbinops"));
}

/* ----------------------------- times ----------------------------- */

static t_class *times_class, *scalartimes_class;

typedef struct _times
{
t_object x_obj;
t_float x_f;
} t_times;

typedef struct _scalartimes
{
t_object x_obj;
t_float x_f;
t_float x_g;
} t_scalartimes;

static void *times_new(t_symbol *s, int argc, t_atom *argv)
{
if (argc > 1) post("*~: extra arguments ignored");
if (argc)
{
t_scalartimes *x = (t_scalartimes *)pd_new(scalartimes_class);
floatinlet_new(&x->x_obj, &x->x_g);
x->x_g = atom_getfloatarg(0, argc, argv);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
else
{
t_times *x = (t_times *)pd_new(times_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
}

t_int *times_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--) *out++ = *in1++ * *in2++;
return (w+5);
}

t_int *times_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
{
t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];

t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];

out[0] = f0 * g0; out[1] = f1 * g1; out[2] = f2 * g2; out[3] = f3 * g3;
out[4] = f4 * g4; out[5] = f5 * g5; out[6] = f6 * g6; out[7] = f7 * g7;
}
return (w+5);
}

t_int *scalartimes_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float f = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--) *out++ = *in++ * f;
return (w+5);
}

t_int *scalartimes_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float g = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in += 8, out += 8)
{
t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];

out[0] = f0 * g; out[1] = f1 * g; out[2] = f2 * g; out[3] = f3 * g;
out[4] = f4 * g; out[5] = f5 * g; out[6] = f6 * g; out[7] = f7 * g;
}
return (w+5);
}

static void times_dsp(t_times *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(times_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
else
dsp_add(times_perf8, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void scalartimes_dsp(t_scalartimes *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(scalartimes_perform, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
else
dsp_add(scalartimes_perf8, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
}

static void times_setup(void)
{
times_class = class_new(gensym("*~"), (t_newmethod)times_new, 0,
sizeof(t_times), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(times_class, t_times, x_f);
class_addmethod(times_class, (t_method)times_dsp, gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(times_class, gensym("sigbinops"));
scalartimes_class = class_new(gensym("*~"), 0, 0,
sizeof(t_scalartimes), 0, 0);
CLASS_MAINSIGNALIN(scalartimes_class, t_scalartimes, x_f);
class_addmethod(scalartimes_class, (t_method)scalartimes_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(scalartimes_class, gensym("sigbinops"));
}

/* ----------------------------- over ----------------------------- */
static t_class *over_class, *scalarover_class;

typedef struct _over
{
t_object x_obj;
t_float x_f;
} t_over;

typedef struct _scalarover
{
t_object x_obj;
t_float x_f;
t_float x_g;
} t_scalarover;

static void *over_new(t_symbol *s, int argc, t_atom *argv)
{
if (argc > 1) post("/~: extra arguments ignored");
if (argc)
{
t_scalarover *x = (t_scalarover *)pd_new(scalarover_class);
floatinlet_new(&x->x_obj, &x->x_g);
x->x_g = atom_getfloatarg(0, argc, argv);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
else
{
t_over *x = (t_over *)pd_new(over_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
}

t_int *over_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
t_sample f = *in1++, g = *in2++;
*out++ = (g ? f / g : 0);
}
return (w+5);
}

t_int *over_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
{
t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];

t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];

out[0] = (g0? f0 / g0 : 0);
out[1] = (g1? f1 / g1 : 0);
out[2] = (g2? f2 / g2 : 0);
out[3] = (g3? f3 / g3 : 0);
out[4] = (g4? f4 / g4 : 0);
out[5] = (g5? f5 / g5 : 0);
out[6] = (g6? f6 / g6 : 0);
out[7] = (g7? f7 / g7 : 0);
}
return (w+5);
}

t_int *scalarover_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float f = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
if(f) f = 1./f;
while (n--) *out++ = *in++ * f;
return (w+5);
}

t_int *scalarover_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float g = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
if (g) g = 1.f / g;
for (; n; n -= 8, in += 8, out += 8)
{
t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];

out[0] = f0 * g; out[1] = f1 * g; out[2] = f2 * g; out[3] = f3 * g;
out[4] = f4 * g; out[5] = f5 * g; out[6] = f6 * g; out[7] = f7 * g;
}
return (w+5);
}

static void over_dsp(t_over *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(over_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
else
dsp_add(over_perf8, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void scalarover_dsp(t_scalarover *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(scalarover_perform, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
else
dsp_add(scalarover_perf8, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
}

static void over_setup(void)
{
over_class = class_new(gensym("/~"), (t_newmethod)over_new, 0,
sizeof(t_over), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(over_class, t_over, x_f);
class_addmethod(over_class, (t_method)over_dsp, gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(over_class, gensym("sigbinops"));
scalarover_class = class_new(gensym("/~"), 0, 0,
sizeof(t_scalarover), 0, 0);
CLASS_MAINSIGNALIN(scalarover_class, t_scalarover, x_f);
class_addmethod(scalarover_class, (t_method)scalarover_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(scalarover_class, gensym("sigbinops"));
}

/* ----------------------------- max ----------------------------- */
static t_class *max_class, *scalarmax_class;

typedef struct _max
{
t_object x_obj;
t_float x_f;
} t_max;

typedef struct _scalarmax
{
t_object x_obj;
t_float x_f;
t_float x_g;
} t_scalarmax;

static void *max_new(t_symbol *s, int argc, t_atom *argv)
{
if (argc > 1) post("max~: extra arguments ignored");
if (argc)
{
t_scalarmax *x = (t_scalarmax *)pd_new(scalarmax_class);
floatinlet_new(&x->x_obj, &x->x_g);
x->x_g = atom_getfloatarg(0, argc, argv);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
else
{
t_max *x = (t_max *)pd_new(max_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
}

t_int *max_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
t_sample f = *in1++, g = *in2++;
*out++ = (f > g ? f : g);
}
return (w+5);
}

t_int *max_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
{
t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];

t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];

out[0] = (f0 > g0 ? f0 : g0); out[1] = (f1 > g1 ? f1 : g1);
out[2] = (f2 > g2 ? f2 : g2); out[3] = (f3 > g3 ? f3 : g3);
out[4] = (f4 > g4 ? f4 : g4); out[5] = (f5 > g5 ? f5 : g5);
out[6] = (f6 > g6 ? f6 : g6); out[7] = (f7 > g7 ? f7 : g7);
}
return (w+5);
}

t_int *scalarmax_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float f = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
t_sample g = *in++;
*out++ = (f > g ? f : g);
}
return (w+5);
}

t_int *scalarmax_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float g = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in += 8, out += 8)
{
t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];

out[0] = (f0 > g ? f0 : g); out[1] = (f1 > g ? f1 : g);
out[2] = (f2 > g ? f2 : g); out[3] = (f3 > g ? f3 : g);
out[4] = (f4 > g ? f4 : g); out[5] = (f5 > g ? f5 : g);
out[6] = (f6 > g ? f6 : g); out[7] = (f7 > g ? f7 : g);
}
return (w+5);
}

static void max_dsp(t_max *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(max_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
else
dsp_add(max_perf8, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void scalarmax_dsp(t_scalarmax *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(scalarmax_perform, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
else
dsp_add(scalarmax_perf8, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
}

static void max_setup(void)
{
max_class = class_new(gensym("max~"), (t_newmethod)max_new, 0,
sizeof(t_max), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(max_class, t_max, x_f);
class_addmethod(max_class, (t_method)max_dsp, gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(max_class, gensym("sigbinops"));
scalarmax_class = class_new(gensym("max~"), 0, 0,
sizeof(t_scalarmax), 0, 0);
CLASS_MAINSIGNALIN(scalarmax_class, t_scalarmax, x_f);
class_addmethod(scalarmax_class, (t_method)scalarmax_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(scalarmax_class, gensym("sigbinops"));
}

/* ----------------------------- min ----------------------------- */
static t_class *min_class, *scalarmin_class;

typedef struct _min
{
t_object x_obj;
t_float x_f;
} t_min;

typedef struct _scalarmin
{
t_object x_obj;
t_float x_g;
t_float x_f;
} t_scalarmin;

static void *min_new(t_symbol *s, int argc, t_atom *argv)
{
if (argc > 1) post("min~: extra arguments ignored");
if (argc)
{
t_scalarmin *x = (t_scalarmin *)pd_new(scalarmin_class);
floatinlet_new(&x->x_obj, &x->x_g);
x->x_g = atom_getfloatarg(0, argc, argv);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
else
{
t_min *x = (t_min *)pd_new(min_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}
}

t_int *min_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
t_sample f = *in1++, g = *in2++;
*out++ = (f < g ? f : g);
}
return (w+5);
}

t_int *min_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
{
t_sample f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
t_sample f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];

t_sample g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
t_sample g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];

out[0] = (f0 < g0 ? f0 : g0); out[1] = (f1 < g1 ? f1 : g1);
out[2] = (f2 < g2 ? f2 : g2); out[3] = (f3 < g3 ? f3 : g3);
out[4] = (f4 < g4 ? f4 : g4); out[5] = (f5 < g5 ? f5 : g5);
out[6] = (f6 < g6 ? f6 : g6); out[7] = (f7 < g7 ? f7 : g7);
}
return (w+5);
}

t_int *scalarmin_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float f = *(t_float *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
t_sample g = *in++;
*out++ = (f < g ? f : g);
}
return (w+5);
}

t_int *scalarmin_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_float g = *(t_float *)(w[2]);
t_float *out = (t_float *)(w[3]);
int n = (int)(w[4]);
for (; n; n -= 8, in += 8, out += 8)
{
t_sample f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
t_sample f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];

out[0] = (f0 < g ? f0 : g); out[1] = (f1 < g ? f1 : g);
out[2] = (f2 < g ? f2 : g); out[3] = (f3 < g ? f3 : g);
out[4] = (f4 < g ? f4 : g); out[5] = (f5 < g ? f5 : g);
out[6] = (f6 < g ? f6 : g); out[7] = (f7 < g ? f7 : g);
}
return (w+5);
}

static void min_dsp(t_min *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(min_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
else
dsp_add(min_perf8, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void scalarmin_dsp(t_scalarmin *x, t_signal **sp)
{
if (sp[0]->s_n&7)
dsp_add(scalarmin_perform, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
else
dsp_add(scalarmin_perf8, 4, sp[0]->s_vec, &x->x_g,
sp[1]->s_vec, sp[0]->s_n);
}

static void min_setup(void)
{
min_class = class_new(gensym("min~"), (t_newmethod)min_new, 0,
sizeof(t_min), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(min_class, t_min, x_f);
class_addmethod(min_class, (t_method)min_dsp, gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(min_class, gensym("sigbinops"));
scalarmin_class = class_new(gensym("min~"), 0, 0,
sizeof(t_scalarmin), 0, 0);
CLASS_MAINSIGNALIN(scalarmin_class, t_scalarmin, x_f);
class_addmethod(scalarmin_class, (t_method)scalarmin_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(scalarmin_class, gensym("sigbinops"));
}

/* ----------------------- global setup routine ---------------- */
void d_arithmetic_setup(void)
{
plus_setup();
minus_setup();
times_setup();
over_setup();
max_setup();
min_setup();
}


+ 1049
- 0
ports/camomile/source/LibPd/pure-data/src/d_array.c
File diff suppressed because it is too large
View File


+ 850
- 0
ports/camomile/source/LibPd/pure-data/src/d_ctl.c View File

@@ -0,0 +1,850 @@
/* 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. */

/* sig~ and line~ control-to-signal converters;
snapshot~ signal-to-control converter.
*/

#include "m_pd.h"
#include "math.h"

/* -------------------------- sig~ ------------------------------ */
static t_class *sig_tilde_class;

typedef struct _sig
{
t_object x_obj;
t_float x_f;
} t_sig;

static t_int *sig_tilde_perform(t_int *w)
{
t_float f = *(t_float *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--)
*out++ = f;
return (w+4);
}

static t_int *sig_tilde_perf8(t_int *w)
{
t_float f = *(t_float *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);

for (; n; n -= 8, out += 8)
{
out[0] = f;
out[1] = f;
out[2] = f;
out[3] = f;
out[4] = f;
out[5] = f;
out[6] = f;
out[7] = f;
}
return (w+4);
}

void dsp_add_scalarcopy(t_float *in, t_sample *out, int n)
{
if (n&7)
dsp_add(sig_tilde_perform, 3, in, out, n);
else
dsp_add(sig_tilde_perf8, 3, in, out, n);
}

static void sig_tilde_float(t_sig *x, t_float f)
{
x->x_f = f;
}

static void sig_tilde_dsp(t_sig *x, t_signal **sp)
{
dsp_add(sig_tilde_perform, 3, &x->x_f, sp[0]->s_vec, sp[0]->s_n);
}

static void *sig_tilde_new(t_floatarg f)
{
t_sig *x = (t_sig *)pd_new(sig_tilde_class);
x->x_f = f;
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}

static void sig_tilde_setup(void)
{
sig_tilde_class = class_new(gensym("sig~"), (t_newmethod)sig_tilde_new, 0,
sizeof(t_sig), 0, A_DEFFLOAT, 0);
class_addfloat(sig_tilde_class, (t_method)sig_tilde_float);
class_addmethod(sig_tilde_class, (t_method)sig_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* -------------------------- line~ ------------------------------ */
static t_class *line_tilde_class;

typedef struct _line
{
t_object x_obj;
t_sample x_target; /* target value of ramp */
t_sample x_value; /* current value of ramp at block-borders */
t_sample x_biginc;
t_sample x_inc;
t_float x_1overn;
t_float x_dspticktomsec;
t_float x_inletvalue;
t_float x_inletwas;
int x_ticksleft;
int x_retarget;
} t_line;

static t_int *line_tilde_perform(t_int *w)
{
t_line *x = (t_line *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
t_sample f = x->x_value;

if (PD_BIGORSMALL(f))
x->x_value = f = 0;
if (x->x_retarget)
{
int nticks = x->x_inletwas * x->x_dspticktomsec;
if (!nticks) nticks = 1;
x->x_ticksleft = nticks;
x->x_biginc = (x->x_target - x->x_value)/(t_float)nticks;
x->x_inc = x->x_1overn * x->x_biginc;
x->x_retarget = 0;
}
if (x->x_ticksleft)
{
t_sample f = x->x_value;
while (n--) *out++ = f, f += x->x_inc;
x->x_value += x->x_biginc;
x->x_ticksleft--;
}
else
{
t_sample g = x->x_value = x->x_target;
while (n--)
*out++ = g;
}
return (w+4);
}

/* TB: vectorized version */
static t_int *line_tilde_perf8(t_int *w)
{
t_line *x = (t_line *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
t_sample f = x->x_value;

if (PD_BIGORSMALL(f))
x->x_value = f = 0;
if (x->x_retarget)
{
int nticks = x->x_inletwas * x->x_dspticktomsec;
if (!nticks) nticks = 1;
x->x_ticksleft = nticks;
x->x_biginc = (x->x_target - x->x_value)/(t_sample)nticks;
x->x_inc = x->x_1overn * x->x_biginc;
x->x_retarget = 0;
}
if (x->x_ticksleft)
{
t_sample f = x->x_value;
while (n--) *out++ = f, f += x->x_inc;
x->x_value += x->x_biginc;
x->x_ticksleft--;
}
else
{
t_sample f = x->x_value = x->x_target;
for (; n; n -= 8, out += 8)
{
out[0] = f; out[1] = f; out[2] = f; out[3] = f;
out[4] = f; out[5] = f; out[6] = f; out[7] = f;
}
}
return (w+4);
}

static void line_tilde_float(t_line *x, t_float f)
{
if (x->x_inletvalue <= 0)
{
x->x_target = x->x_value = f;
x->x_ticksleft = x->x_retarget = 0;
}
else
{
x->x_target = f;
x->x_retarget = 1;
x->x_inletwas = x->x_inletvalue;
x->x_inletvalue = 0;
}
}

static void line_tilde_stop(t_line *x)
{
x->x_target = x->x_value;
x->x_ticksleft = x->x_retarget = 0;
}

static void line_tilde_dsp(t_line *x, t_signal **sp)
{
if(sp[0]->s_n&7)
dsp_add(line_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
else
dsp_add(line_tilde_perf8, 3, x, sp[0]->s_vec, sp[0]->s_n);
x->x_1overn = 1./sp[0]->s_n;
x->x_dspticktomsec = sp[0]->s_sr / (1000 * sp[0]->s_n);
}

static void *line_tilde_new(void)
{
t_line *x = (t_line *)pd_new(line_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
floatinlet_new(&x->x_obj, &x->x_inletvalue);
x->x_ticksleft = x->x_retarget = 0;
x->x_value = x->x_target = x->x_inletvalue = x->x_inletwas = 0;
return (x);
}

static void line_tilde_setup(void)
{
line_tilde_class = class_new(gensym("line~"), line_tilde_new, 0,
sizeof(t_line), 0, 0);
class_addfloat(line_tilde_class, (t_method)line_tilde_float);
class_addmethod(line_tilde_class, (t_method)line_tilde_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(line_tilde_class, (t_method)line_tilde_stop,
gensym("stop"), 0);
}

/* -------------------------- vline~ ------------------------------ */
static t_class *vline_tilde_class;
#include "s_stuff.h" /* for DEFDACBLKSIZE; this should be in m_pd.h */
typedef struct _vseg
{
double s_targettime;
double s_starttime;
t_sample s_target;
struct _vseg *s_next;
} t_vseg;

typedef struct _vline
{
t_object x_obj;
double x_value;
double x_inc;
double x_referencetime;
double x_lastlogicaltime;
double x_nextblocktime;
double x_samppermsec;
double x_msecpersamp;
double x_targettime;
t_sample x_target;
t_float x_inlet1;
t_float x_inlet2;
t_vseg *x_list;
} t_vline;

static t_int *vline_tilde_perform(t_int *w)
{
t_vline *x = (t_vline *)(w[1]);
t_float *out = (t_float *)(w[2]);
int n = (int)(w[3]), i;
double f = x->x_value;
double inc = x->x_inc;
double msecpersamp = x->x_msecpersamp;
double samppermsec = x->x_samppermsec;
double timenow, logicaltimenow = clock_gettimesince(x->x_referencetime);
t_vseg *s = x->x_list;
if (logicaltimenow != x->x_lastlogicaltime)
{
int sampstotime = (n > DEFDACBLKSIZE ? n : DEFDACBLKSIZE);
x->x_lastlogicaltime = logicaltimenow;
x->x_nextblocktime = logicaltimenow - sampstotime * msecpersamp;
}
timenow = x->x_nextblocktime;
x->x_nextblocktime = timenow + n * msecpersamp;
for (i = 0; i < n; i++)
{
double timenext = timenow + msecpersamp;
checknext:
if (s)
{
/* has starttime elapsed? If so update value and increment */
if (s->s_starttime < timenext)
{
if (x->x_targettime <= timenext)
f = x->x_target, inc = 0;
/* if zero-length segment bash output value */
if (s->s_targettime <= s->s_starttime)
{
f = s->s_target;
inc = 0;
}
else
{
double incpermsec = (s->s_target - f)/
(s->s_targettime - s->s_starttime);
f = f + incpermsec * (timenext - s->s_starttime);
inc = incpermsec * msecpersamp;
}
x->x_inc = inc;
x->x_target = s->s_target;
x->x_targettime = s->s_targettime;
x->x_list = s->s_next;
t_freebytes(s, sizeof(*s));
s = x->x_list;
goto checknext;
}
}
if (x->x_targettime <= timenext)
f = x->x_target, inc = x->x_inc = 0, x->x_targettime = 1e20;
*out++ = f;
f = f + inc;
timenow = timenext;
}
x->x_value = f;
return (w+4);
}

static void vline_tilde_stop(t_vline *x)
{
t_vseg *s1, *s2;
for (s1 = x->x_list; s1; s1 = s2)
s2 = s1->s_next, t_freebytes(s1, sizeof(*s1));
x->x_list = 0;
x->x_inc = 0;
x->x_inlet1 = x->x_inlet2 = 0;
x->x_target = x->x_value;
x->x_targettime = 1e20;
}

static void vline_tilde_float(t_vline *x, t_float f)
{
double timenow = clock_gettimesince(x->x_referencetime);
t_float inlet1 = (x->x_inlet1 < 0 ? 0 : x->x_inlet1);
t_float inlet2 = x->x_inlet2;
double starttime = timenow + inlet2;
t_vseg *s1, *s2, *deletefrom = 0, *snew;
if (PD_BIGORSMALL(f))
f = 0;

/* negative delay input means stop and jump immediately to new value */
if (inlet2 < 0)
{
x->x_value = f;
vline_tilde_stop(x);
return;
}
snew = (t_vseg *)t_getbytes(sizeof(*snew));
/* check if we supplant the first item in the list. We supplant
an item by having an earlier starttime, or an equal starttime unless
the equal one was instantaneous and the new one isn't (in which case
we'll do a jump-and-slide starting at that time.) */
if (!x->x_list || x->x_list->s_starttime > starttime ||
(x->x_list->s_starttime == starttime &&
(x->x_list->s_targettime > x->x_list->s_starttime || inlet1 <= 0)))
{
deletefrom = x->x_list;
x->x_list = snew;
}
else
{
for (s1 = x->x_list; (s2 = s1->s_next); s1 = s2)
{
if (s2->s_starttime > starttime ||
(s2->s_starttime == starttime &&
(s2->s_targettime > s2->s_starttime || inlet1 <= 0)))
{
deletefrom = s2;
s1->s_next = snew;
goto didit;
}
}
s1->s_next = snew;
deletefrom = 0;
didit: ;
}
while (deletefrom)
{
s1 = deletefrom->s_next;
t_freebytes(deletefrom, sizeof(*deletefrom));
deletefrom = s1;
}
snew->s_next = 0;
snew->s_target = f;
snew->s_starttime = starttime;
snew->s_targettime = starttime + inlet1;
x->x_inlet1 = x->x_inlet2 = 0;
}

static void vline_tilde_dsp(t_vline *x, t_signal **sp)
{
dsp_add(vline_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
x->x_samppermsec = ((double)(sp[0]->s_sr)) / 1000;
x->x_msecpersamp = ((double)1000) / sp[0]->s_sr;
}

static void *vline_tilde_new(void)
{
t_vline *x = (t_vline *)pd_new(vline_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
floatinlet_new(&x->x_obj, &x->x_inlet1);
floatinlet_new(&x->x_obj, &x->x_inlet2);
x->x_inlet1 = x->x_inlet2 = 0;
x->x_value = x->x_inc = 0;
x->x_referencetime = x->x_lastlogicaltime = x->x_nextblocktime =
clock_getlogicaltime();
x->x_list = 0;
x->x_samppermsec = 0;
x->x_targettime = 1e20;
return (x);
}

static void vline_tilde_setup(void)
{
vline_tilde_class = class_new(gensym("vline~"), vline_tilde_new,
(t_method)vline_tilde_stop, sizeof(t_vline), 0, 0);
class_addfloat(vline_tilde_class, (t_method)vline_tilde_float);
class_addmethod(vline_tilde_class, (t_method)vline_tilde_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(vline_tilde_class, (t_method)vline_tilde_stop,
gensym("stop"), 0);
}

/* -------------------------- snapshot~ ------------------------------ */
static t_class *snapshot_tilde_class;

typedef struct _snapshot
{
t_object x_obj;
t_sample x_value;
t_float x_f;
} t_snapshot;

static void *snapshot_tilde_new(void)
{
t_snapshot *x = (t_snapshot *)pd_new(snapshot_tilde_class);
x->x_value = 0;
outlet_new(&x->x_obj, &s_float);
x->x_f = 0;
return (x);
}

static t_int *snapshot_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
*out = *in;
return (w+3);
}

static void snapshot_tilde_dsp(t_snapshot *x, t_signal **sp)
{
dsp_add(snapshot_tilde_perform, 2, sp[0]->s_vec + (sp[0]->s_n-1),
&x->x_value);
}

static void snapshot_tilde_bang(t_snapshot *x)
{
outlet_float(x->x_obj.ob_outlet, x->x_value);
}

static void snapshot_tilde_set(t_snapshot *x, t_floatarg f)
{
x->x_value = f;
}

static void snapshot_tilde_setup(void)
{
snapshot_tilde_class = class_new(gensym("snapshot~"), snapshot_tilde_new, 0,
sizeof(t_snapshot), 0, 0);
CLASS_MAINSIGNALIN(snapshot_tilde_class, t_snapshot, x_f);
class_addmethod(snapshot_tilde_class, (t_method)snapshot_tilde_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(snapshot_tilde_class, (t_method)snapshot_tilde_set,
gensym("set"), A_DEFFLOAT, 0);
class_addbang(snapshot_tilde_class, snapshot_tilde_bang);
}

/* -------------------------- vsnapshot~ ------------------------------ */
static t_class *vsnapshot_tilde_class;

typedef struct _vsnapshot
{
t_object x_obj;
int x_n;
int x_gotone;
t_sample *x_vec;
t_float x_f;
t_float x_sampspermsec;
double x_time;
} t_vsnapshot;

static void *vsnapshot_tilde_new(void)
{
t_vsnapshot *x = (t_vsnapshot *)pd_new(vsnapshot_tilde_class);
outlet_new(&x->x_obj, &s_float);
x->x_f = 0;
x->x_n = 0;
x->x_vec = 0;
x->x_gotone = 0;
return (x);
}

static t_int *vsnapshot_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_vsnapshot *x = (t_vsnapshot *)(w[2]);
t_sample *out = x->x_vec;
int n = x->x_n, i;
for (i = 0; i < n; i++)
out[i] = in[i];
x->x_time = clock_getlogicaltime();
x->x_gotone = 1;
return (w+3);
}

static void vsnapshot_tilde_dsp(t_vsnapshot *x, t_signal **sp)
{
int n = sp[0]->s_n;
if (n != x->x_n)
{
if (x->x_vec)
t_freebytes(x->x_vec, x->x_n * sizeof(t_sample));
x->x_vec = (t_sample *)getbytes(n * sizeof(t_sample));
x->x_gotone = 0;
x->x_n = n;
}
x->x_sampspermsec = sp[0]->s_sr / 1000;
dsp_add(vsnapshot_tilde_perform, 2, sp[0]->s_vec, x);
}

static void vsnapshot_tilde_bang(t_vsnapshot *x)
{
t_sample val;
if (x->x_gotone)
{
int indx = clock_gettimesince(x->x_time) * x->x_sampspermsec;
if (indx < 0)
indx = 0;
else if (indx >= x->x_n)
indx = x->x_n - 1;
val = x->x_vec[indx];
}
else val = 0;
outlet_float(x->x_obj.ob_outlet, val);
}

static void vsnapshot_tilde_ff(t_vsnapshot *x)
{
if (x->x_vec)
t_freebytes(x->x_vec, x->x_n * sizeof(t_sample));
}

static void vsnapshot_tilde_setup(void)
{
vsnapshot_tilde_class = class_new(gensym("vsnapshot~"),
vsnapshot_tilde_new, (t_method)vsnapshot_tilde_ff,
sizeof(t_vsnapshot), 0, 0);
CLASS_MAINSIGNALIN(vsnapshot_tilde_class, t_vsnapshot, x_f);
class_addmethod(vsnapshot_tilde_class, (t_method)vsnapshot_tilde_dsp,
gensym("dsp"), A_CANT, 0);
class_addbang(vsnapshot_tilde_class, vsnapshot_tilde_bang);
}


/* ---------------- env~ - simple envelope follower. ----------------- */

#define MAXOVERLAP 32
#define INITVSTAKEN 64

typedef struct sigenv
{
t_object x_obj; /* header */
void *x_outlet; /* a "float" outlet */
void *x_clock; /* a "clock" object */
t_sample *x_buf; /* a Hanning window */
int x_phase; /* number of points since last output */
int x_period; /* requested period of output */
int x_realperiod; /* period rounded up to vecsize multiple */
int x_npoints; /* analysis window size in samples */
t_float x_result; /* result to output */
t_sample x_sumbuf[MAXOVERLAP]; /* summing buffer */
t_float x_f;
int x_allocforvs; /* extra buffer for DSP vector size */
} t_sigenv;

t_class *env_tilde_class;
static void env_tilde_tick(t_sigenv *x);

static void *env_tilde_new(t_floatarg fnpoints, t_floatarg fperiod)
{
int npoints = fnpoints;
int period = fperiod;
t_sigenv *x;
t_sample *buf;
int i;

if (npoints < 1) npoints = 1024;
if (period < 1) period = npoints/2;
if (period < npoints / MAXOVERLAP + 1)
period = npoints / MAXOVERLAP + 1;
if (!(buf = getbytes(sizeof(t_sample) * (npoints + INITVSTAKEN))))
{
error("env: couldn't allocate buffer");
return (0);
}
x = (t_sigenv *)pd_new(env_tilde_class);
x->x_buf = buf;
x->x_npoints = npoints;
x->x_phase = 0;
x->x_period = period;
for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
for (i = 0; i < npoints; i++)
buf[i] = (1. - cos((2 * 3.14159 * i) / npoints))/npoints;
for (; i < npoints+INITVSTAKEN; i++) buf[i] = 0;
x->x_clock = clock_new(x, (t_method)env_tilde_tick);
x->x_outlet = outlet_new(&x->x_obj, gensym("float"));
x->x_f = 0;
x->x_allocforvs = INITVSTAKEN;
return (x);
}

static t_int *env_tilde_perform(t_int *w)
{
t_sigenv *x = (t_sigenv *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
int n = (int)(w[3]);
int count;
t_sample *sump;
in += n;
for (count = x->x_phase, sump = x->x_sumbuf;
count < x->x_npoints; count += x->x_realperiod, sump++)
{
t_sample *hp = x->x_buf + count;
t_sample *fp = in;
t_sample sum = *sump;
int i;

for (i = 0; i < n; i++)
{
fp--;
sum += *hp++ * (*fp * *fp);
}
*sump = sum;
}
sump[0] = 0;
x->x_phase -= n;
if (x->x_phase < 0)
{
x->x_result = x->x_sumbuf[0];
for (count = x->x_realperiod, sump = x->x_sumbuf;
count < x->x_npoints; count += x->x_realperiod, sump++)
sump[0] = sump[1];
sump[0] = 0;
x->x_phase = x->x_realperiod - n;
clock_delay(x->x_clock, 0L);
}
return (w+4);
}

static void env_tilde_dsp(t_sigenv *x, t_signal **sp)
{
if (x->x_period % sp[0]->s_n) x->x_realperiod =
x->x_period + sp[0]->s_n - (x->x_period % sp[0]->s_n);
else x->x_realperiod = x->x_period;
if (sp[0]->s_n > x->x_allocforvs)
{
void *xx = resizebytes(x->x_buf,
(x->x_npoints + x->x_allocforvs) * sizeof(t_sample),
(x->x_npoints + sp[0]->s_n) * sizeof(t_sample));
if (!xx)
{
error("env~: out of memory");
return;
}
x->x_buf = (t_sample *)xx;
x->x_allocforvs = sp[0]->s_n;
}
dsp_add(env_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
}

static void env_tilde_tick(t_sigenv *x) /* callback function for the clock */
{
outlet_float(x->x_outlet, powtodb(x->x_result));
}

static void env_tilde_ff(t_sigenv *x) /* cleanup on free */
{
clock_free(x->x_clock);
freebytes(x->x_buf, (x->x_npoints + x->x_allocforvs) * sizeof(*x->x_buf));
}


void env_tilde_setup(void )
{
env_tilde_class = class_new(gensym("env~"), (t_newmethod)env_tilde_new,
(t_method)env_tilde_ff, sizeof(t_sigenv), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(env_tilde_class, t_sigenv, x_f);
class_addmethod(env_tilde_class, (t_method)env_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* --------------------- threshold~ ----------------------------- */

static t_class *threshold_tilde_class;

typedef struct _threshold_tilde
{
t_object x_obj;
t_outlet *x_outlet1; /* bang out for high thresh */
t_outlet *x_outlet2; /* bang out for low thresh */
t_clock *x_clock; /* wakeup for message output */
t_float x_f; /* scalar inlet */
int x_state; /* 1 = high, 0 = low */
t_float x_hithresh; /* value of high threshold */
t_float x_lothresh; /* value of low threshold */
t_float x_deadwait; /* msec remaining in dead period */
t_float x_msecpertick; /* msec per DSP tick */
t_float x_hideadtime; /* hi dead time in msec */
t_float x_lodeadtime; /* lo dead time in msec */
} t_threshold_tilde;

static void threshold_tilde_tick(t_threshold_tilde *x);
static void threshold_tilde_set(t_threshold_tilde *x,
t_floatarg hithresh, t_floatarg hideadtime,
t_floatarg lothresh, t_floatarg lodeadtime);

static t_threshold_tilde *threshold_tilde_new(t_floatarg hithresh,
t_floatarg hideadtime, t_floatarg lothresh, t_floatarg lodeadtime)
{
t_threshold_tilde *x = (t_threshold_tilde *)
pd_new(threshold_tilde_class);
x->x_state = 0; /* low state */
x->x_deadwait = 0; /* no dead time */
x->x_clock = clock_new(x, (t_method)threshold_tilde_tick);
x->x_outlet1 = outlet_new(&x->x_obj, &s_bang);
x->x_outlet2 = outlet_new(&x->x_obj, &s_bang);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
x->x_msecpertick = 0.;
x->x_f = 0;
threshold_tilde_set(x, hithresh, hideadtime, lothresh, lodeadtime);
return (x);
}

/* "set" message to specify thresholds and dead times */
static void threshold_tilde_set(t_threshold_tilde *x,
t_floatarg hithresh, t_floatarg hideadtime,
t_floatarg lothresh, t_floatarg lodeadtime)
{
if (lothresh > hithresh)
lothresh = hithresh;
x->x_hithresh = hithresh;
x->x_hideadtime = hideadtime;
x->x_lothresh = lothresh;
x->x_lodeadtime = lodeadtime;
}

/* number in inlet sets state -- note incompatible with JMAX which used
"int" message for this, impossible here because of auto signal conversion */
static void threshold_tilde_ft1(t_threshold_tilde *x, t_floatarg f)
{
x->x_state = (f != 0);
x->x_deadwait = 0;
}

static void threshold_tilde_tick(t_threshold_tilde *x)
{
if (x->x_state)
outlet_bang(x->x_outlet1);
else outlet_bang(x->x_outlet2);
}

static t_int *threshold_tilde_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_threshold_tilde *x = (t_threshold_tilde *)(w[2]);
int n = (int)w[3];
if (x->x_deadwait > 0)
x->x_deadwait -= x->x_msecpertick;
else if (x->x_state)
{
/* we're high; look for low sample */
for (; n--; in1++)
{
if (*in1 < x->x_lothresh)
{
clock_delay(x->x_clock, 0L);
x->x_state = 0;
x->x_deadwait = x->x_lodeadtime;
goto done;
}
}
}
else
{
/* we're low; look for high sample */
for (; n--; in1++)
{
if (*in1 >= x->x_hithresh)
{
clock_delay(x->x_clock, 0L);
x->x_state = 1;
x->x_deadwait = x->x_hideadtime;
goto done;
}
}
}
done:
return (w+4);
}

void threshold_tilde_dsp(t_threshold_tilde *x, t_signal **sp)
{
x->x_msecpertick = 1000. * sp[0]->s_n / sp[0]->s_sr;
dsp_add(threshold_tilde_perform, 3, sp[0]->s_vec, x, sp[0]->s_n);
}

static void threshold_tilde_ff(t_threshold_tilde *x)
{
clock_free(x->x_clock);
}

static void threshold_tilde_setup( void)
{
threshold_tilde_class = class_new(gensym("threshold~"),
(t_newmethod)threshold_tilde_new, (t_method)threshold_tilde_ff,
sizeof(t_threshold_tilde), 0,
A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(threshold_tilde_class, t_threshold_tilde, x_f);
class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_set,
gensym("set"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_ft1,
gensym("ft1"), A_FLOAT, 0);
class_addmethod(threshold_tilde_class, (t_method)threshold_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------ global setup routine ------------------------- */

void d_ctl_setup(void)
{
sig_tilde_setup();
line_tilde_setup();
vline_tilde_setup();
snapshot_tilde_setup();
vsnapshot_tilde_setup();
env_tilde_setup();
threshold_tilde_setup();
}


+ 202
- 0
ports/camomile/source/LibPd/pure-data/src/d_dac.c View File

@@ -0,0 +1,202 @@
/* 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. */

/* The dac~ and adc~ routines.
*/

#include "m_pd.h"
#include "s_stuff.h"

/* ----------------------------- dac~ --------------------------- */
static t_class *dac_class;

typedef struct _dac
{
t_object x_obj;
t_int x_n;
t_int *x_vec;
t_float x_f;
} t_dac;

static void *dac_new(t_symbol *s, int argc, t_atom *argv)
{
t_dac *x = (t_dac *)pd_new(dac_class);
t_atom defarg[2], *ap;
int i;
if (!argc)
{
argv = defarg;
argc = 2;
SETFLOAT(&defarg[0], 1);
SETFLOAT(&defarg[1], 2);
}
x->x_n = argc;
x->x_vec = (t_int *)getbytes(argc * sizeof(*x->x_vec));
for (i = 0; i < argc; i++)
x->x_vec[i] = atom_getfloatarg(i, argc, argv);
for (i = 1; i < argc; i++)
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_f = 0;
return (x);
}

static void dac_dsp(t_dac *x, t_signal **sp)
{
t_int i, *ip;
t_signal **sp2;
for (i = x->x_n, ip = x->x_vec, sp2 = sp; i--; ip++, sp2++)
{
int ch = (int)(*ip - 1);
if ((*sp2)->s_n != DEFDACBLKSIZE)
error("dac~: bad vector size");
else if (ch >= 0 && ch < sys_get_outchannels())
dsp_add(plus_perform, 4, STUFF->st_soundout + DEFDACBLKSIZE*ch,
(*sp2)->s_vec, STUFF->st_soundout + DEFDACBLKSIZE*ch, DEFDACBLKSIZE);
}
}

static void dac_set(t_dac *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
for (i = 0; i < argc && i < x->x_n; i++)
x->x_vec[i] = atom_getfloatarg(i, argc, argv);
canvas_update_dsp();
}

static void dac_free(t_dac *x)
{
freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
}

static void dac_setup(void)
{
dac_class = class_new(gensym("dac~"), (t_newmethod)dac_new,
(t_method)dac_free, sizeof(t_dac), 0, A_GIMME, 0);
CLASS_MAINSIGNALIN(dac_class, t_dac, x_f);
class_addmethod(dac_class, (t_method)dac_dsp, gensym("dsp"), A_CANT, 0);
class_addmethod(dac_class, (t_method)dac_set, gensym("set"), A_GIMME, 0);
class_sethelpsymbol(dac_class, gensym("adc~_dac~"));
}

/* ----------------------------- adc~ --------------------------- */
static t_class *adc_class;

typedef struct _adc
{
t_object x_obj;
t_int x_n;
t_int *x_vec;
} t_adc;

static void *adc_new(t_symbol *s, int argc, t_atom *argv)
{
t_adc *x = (t_adc *)pd_new(adc_class);
t_atom defarg[2], *ap;
int i;
if (!argc)
{
argv = defarg;
argc = 2;
SETFLOAT(&defarg[0], 1);
SETFLOAT(&defarg[1], 2);
}
x->x_n = argc;
x->x_vec = (t_int *)getbytes(argc * sizeof(*x->x_vec));
for (i = 0; i < argc; i++)
x->x_vec[i] = atom_getfloatarg(i, argc, argv);
for (i = 0; i < argc; i++)
outlet_new(&x->x_obj, &s_signal);
return (x);
}

t_int *copy_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--) *out++ = *in1++;
return (w+4);
}

static t_int *copy_perf8(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);

for (; n; n -= 8, in1 += 8, out += 8)
{
t_sample f0 = in1[0];
t_sample f1 = in1[1];
t_sample f2 = in1[2];
t_sample f3 = in1[3];
t_sample f4 = in1[4];
t_sample f5 = in1[5];
t_sample f6 = in1[6];
t_sample f7 = in1[7];

out[0] = f0;
out[1] = f1;
out[2] = f2;
out[3] = f3;
out[4] = f4;
out[5] = f5;
out[6] = f6;
out[7] = f7;
}
return (w+4);
}

void dsp_add_copy(t_sample *in, t_sample *out, int n)
{
if (n&7)
dsp_add(copy_perform, 3, in, out, n);
else
dsp_add(copy_perf8, 3, in, out, n);
}

static void adc_dsp(t_adc *x, t_signal **sp)
{
t_int i, *ip;
t_signal **sp2;
for (i = x->x_n, ip = x->x_vec, sp2 = sp; i--; ip++, sp2++)
{
int ch = (int)(*ip - 1);
if ((*sp2)->s_n != DEFDACBLKSIZE)
error("adc~: bad vector size");
else if (ch >= 0 && ch < sys_get_inchannels())
dsp_add_copy(STUFF->st_soundin + DEFDACBLKSIZE*ch,
(*sp2)->s_vec, DEFDACBLKSIZE);
else dsp_add_zero((*sp2)->s_vec, DEFDACBLKSIZE);
}
}

static void adc_set(t_adc *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
for (i = 0; i < argc && i < x->x_n; i++)
x->x_vec[i] = atom_getfloatarg(i, argc, argv);
canvas_update_dsp();
}

static void adc_free(t_adc *x)
{
freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
}

static void adc_setup(void)
{
adc_class = class_new(gensym("adc~"), (t_newmethod)adc_new,
(t_method)adc_free, sizeof(t_adc), 0, A_GIMME, 0);
class_addmethod(adc_class, (t_method)adc_dsp, gensym("dsp"), A_CANT, 0);
class_addmethod(adc_class, (t_method)adc_set, gensym("set"), A_GIMME, 0);
class_sethelpsymbol(adc_class, gensym("adc~_dac~"));
}

void d_dac_setup(void)
{
dac_setup();
adc_setup();
}


+ 346
- 0
ports/camomile/source/LibPd/pure-data/src/d_delay.c View File

@@ -0,0 +1,346 @@
/* 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. */

/* send~, delread~, throw~, catch~ */

#include "m_pd.h"
#include <string.h>
extern int ugen_getsortno(void);

#define DEFDELVS 64 /* LATER get this from canvas at DSP time */
static const int delread_zero = 0; /* four bytes of zero for delread~, vd~*/

/* ----------------------------- delwrite~ ----------------------------- */
static t_class *sigdelwrite_class;

typedef struct delwritectl
{
int c_n;
t_sample *c_vec;
int c_phase;
} t_delwritectl;

typedef struct _sigdelwrite
{
t_object x_obj;
t_symbol *x_sym;
t_float x_deltime; /* delay in msec (added by Mathieu Bouchard) */
t_delwritectl x_cspace;
int x_sortno; /* DSP sort number at which this was last put on chain */
int x_rsortno; /* DSP sort # for first delread or write in chain */
int x_vecsize; /* vector size for delread~ to use */
t_float x_f;
} t_sigdelwrite;

#define XTRASAMPS 4
#define SAMPBLK 4

static void sigdelwrite_updatesr(t_sigdelwrite *x, t_float sr) /* added by Mathieu Bouchard */
{
int nsamps = x->x_deltime * sr * (t_float)(0.001f);
if (nsamps < 1) nsamps = 1;
nsamps += ((- nsamps) & (SAMPBLK - 1));
nsamps += DEFDELVS;
if (x->x_cspace.c_n != nsamps)
{
x->x_cspace.c_vec = (t_sample *)resizebytes(x->x_cspace.c_vec,
(x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample),
(nsamps + XTRASAMPS) * sizeof(t_sample));
x->x_cspace.c_n = nsamps;
x->x_cspace.c_phase = XTRASAMPS;
}
}

static void sigdelwrite_clear (t_sigdelwrite *x) /* added by Orm Finnendahl */
{
if (x->x_cspace.c_n > 0)
memset(x->x_cspace.c_vec, 0, sizeof(t_sample)*(x->x_cspace.c_n + XTRASAMPS));
}


/* routine to check that all delwrites/delreads/vds have same vecsize */
static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
{
if (x->x_rsortno != ugen_getsortno())
{
x->x_vecsize = vecsize;
x->x_rsortno = ugen_getsortno();
}
/*
LATER this should really check sample rate and blocking, once that is
supported. Probably we don't actually care about vecsize.
For now just suppress this check. */
#if 0
else if (vecsize != x->x_vecsize)
pd_error(x, "delread/delwrite/vd vector size mismatch");
#endif
}

static void *sigdelwrite_new(t_symbol *s, t_floatarg msec)
{
t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class);
if (!*s->s_name) s = gensym("delwrite~");
pd_bind(&x->x_obj.ob_pd, s);
x->x_sym = s;
x->x_deltime = msec;
x->x_cspace.c_n = 0;
x->x_cspace.c_vec = getbytes(XTRASAMPS * sizeof(t_sample));
x->x_sortno = 0;
x->x_vecsize = 0;
x->x_f = 0;
return (x);
}

static t_int *sigdelwrite_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_delwritectl *c = (t_delwritectl *)(w[2]);
int n = (int)(w[3]);
int phase = c->c_phase, nsamps = c->c_n;
t_sample *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS);
phase += n;

while (n--)
{
t_sample f = *in++;
if (PD_BIGORSMALL(f))
f = 0;
*bp++ = f;
if (bp == ep)
{
vp[0] = ep[-4];
vp[1] = ep[-3];
vp[2] = ep[-2];
vp[3] = ep[-1];
bp = vp + XTRASAMPS;
phase -= nsamps;
}
}
c->c_phase = phase;
return (w+4);
}

static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp)
{
dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n);
x->x_sortno = ugen_getsortno();
sigdelwrite_checkvecsize(x, sp[0]->s_n);
sigdelwrite_updatesr(x, sp[0]->s_sr);
}

static void sigdelwrite_free(t_sigdelwrite *x)
{
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
freebytes(x->x_cspace.c_vec,
(x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample));
}

static void sigdelwrite_setup(void)
{
sigdelwrite_class = class_new(gensym("delwrite~"),
(t_newmethod)sigdelwrite_new, (t_method)sigdelwrite_free,
sizeof(t_sigdelwrite), 0, A_DEFSYM, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, x_f);
class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(sigdelwrite_class, (t_method)sigdelwrite_clear,
gensym("clear"), 0);
}

/* ----------------------------- delread~ ----------------------------- */
static t_class *sigdelread_class;

typedef struct _sigdelread
{
t_object x_obj;
t_symbol *x_sym;
t_float x_deltime; /* delay in msec */
int x_delsamps; /* delay in samples */
t_float x_sr; /* samples per msec */
t_float x_n; /* vector size */
int x_zerodel; /* 0 or vecsize depending on read/write order */
} t_sigdelread;

static void sigdelread_float(t_sigdelread *x, t_float f);

static void *sigdelread_new(t_symbol *s, t_floatarg f)
{
t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class);
x->x_sym = s;
x->x_sr = 1;
x->x_n = 1;
x->x_zerodel = 0;
sigdelread_float(x, f);
outlet_new(&x->x_obj, &s_signal);
return (x);
}

static void sigdelread_float(t_sigdelread *x, t_float f)
{
int samps;
t_sigdelwrite *delwriter =
(t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
x->x_deltime = f;
if (delwriter)
{
int delsize = delwriter->x_cspace.c_n;
x->x_delsamps = (int)(0.5 + x->x_sr * x->x_deltime)
+ x->x_n - x->x_zerodel;
if (x->x_delsamps < x->x_n) x->x_delsamps = x->x_n;
else if (x->x_delsamps > delwriter->x_cspace.c_n)
x->x_delsamps = delwriter->x_cspace.c_n;
}
}

static t_int *sigdelread_perform(t_int *w)
{
t_sample *out = (t_sample *)(w[1]);
t_delwritectl *c = (t_delwritectl *)(w[2]);
int delsamps = *(int *)(w[3]);
int n = (int)(w[4]);
int phase = c->c_phase - delsamps, nsamps = c->c_n;
t_sample *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS);
if (phase < 0) phase += nsamps;
bp = vp + phase;

while (n--)
{
*out++ = *bp++;
if (bp == ep) bp -= nsamps;
}
return (w+5);
}

static void sigdelread_dsp(t_sigdelread *x, t_signal **sp)
{
t_sigdelwrite *delwriter =
(t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
x->x_sr = sp[0]->s_sr * 0.001;
x->x_n = sp[0]->s_n;
if (delwriter)
{
sigdelwrite_updatesr(delwriter, sp[0]->s_sr);
sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
0 : delwriter->x_vecsize);
sigdelread_float(x, x->x_deltime);
dsp_add(sigdelread_perform, 4,
sp[0]->s_vec, &delwriter->x_cspace, &x->x_delsamps, sp[0]->s_n);
}
else if (*x->x_sym->s_name)
error("delread~: %s: no such delwrite~",x->x_sym->s_name);
}

static void sigdelread_setup(void)
{
sigdelread_class = class_new(gensym("delread~"),
(t_newmethod)sigdelread_new, 0,
sizeof(t_sigdelread), 0, A_DEFSYM, A_DEFFLOAT, 0);
class_addmethod(sigdelread_class, (t_method)sigdelread_dsp,
gensym("dsp"), A_CANT, 0);
class_addfloat(sigdelread_class, (t_method)sigdelread_float);
}


/* ----------------------------- vd~ ----------------------------- */
static t_class *sigvd_class;

typedef struct _sigvd
{
t_object x_obj;
t_symbol *x_sym;
t_float x_sr; /* samples per msec */
int x_zerodel; /* 0 or vecsize depending on read/write order */
t_float x_f;
} t_sigvd;

static void *sigvd_new(t_symbol *s)
{
t_sigvd *x = (t_sigvd *)pd_new(sigvd_class);
x->x_sym = s;
x->x_sr = 1;
x->x_zerodel = 0;
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}

static t_int *sigvd_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
t_delwritectl *ctl = (t_delwritectl *)(w[3]);
t_sigvd *x = (t_sigvd *)(w[4]);
int n = (int)(w[5]);

int nsamps = ctl->c_n;
t_sample limit = nsamps - n;
t_sample fn = n-1;
t_sample *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase;
t_sample zerodel = x->x_zerodel;
while (n--)
{
t_sample delsamps = x->x_sr * *in++ - zerodel, frac;
int idelsamps;
t_sample a, b, c, d, cminusb;
if (!(delsamps >= 1.00001f)) /* too small or NAN */
delsamps = 1.00001f;
if (delsamps > limit) /* too big */
delsamps = limit;
delsamps += fn;
fn = fn - 1.0f;
idelsamps = delsamps;
frac = delsamps - (t_sample)idelsamps;
bp = wp - idelsamps;
if (bp < vp + 4) bp += nsamps;
d = bp[-3];
c = bp[-2];
b = bp[-1];
a = bp[0];
cminusb = c-b;
*out++ = b + frac * (
cminusb - 0.1666667f * (1.-frac) * (
(d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)
)
);
}
return (w+6);
}

static void sigvd_dsp(t_sigvd *x, t_signal **sp)
{
t_sigdelwrite *delwriter =
(t_sigdelwrite *)pd_findbyclass(x->x_sym, sigdelwrite_class);
x->x_sr = sp[0]->s_sr * 0.001;
if (delwriter)
{
sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
0 : delwriter->x_vecsize);
dsp_add(sigvd_perform, 5,
sp[0]->s_vec, sp[1]->s_vec,
&delwriter->x_cspace, x, sp[0]->s_n);
}
else if (*x->x_sym->s_name)
error("vd~: %s: no such delwrite~",x->x_sym->s_name);
}

static void sigvd_setup(void)
{
sigvd_class = class_new(gensym("delread4~"), (t_newmethod)sigvd_new, 0,
sizeof(t_sigvd), 0, A_DEFSYM, 0);
class_addcreator((t_newmethod)sigvd_new, gensym("vd~"), A_DEFSYM, 0);
class_addmethod(sigvd_class, (t_method)sigvd_dsp, gensym("dsp"), A_CANT, 0);
CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, x_f);
}

/* ----------------------- global setup routine ---------------- */

void d_delay_setup(void)
{
sigdelwrite_setup();
sigdelread_setup();
sigvd_setup();
}


+ 355
- 0
ports/camomile/source/LibPd/pure-data/src/d_fft.c View File

@@ -0,0 +1,355 @@
/* Copyright (c) 1997- Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

#include "m_pd.h"

/* This file interfaces to one of the Mayer, Ooura, or fftw FFT packages
to implement the "fft~", etc, Pd objects. If using Mayer, also compile
d_fft_mayer.c; if ooura, use d_fft_fftsg.c instead; if fftw, use d_fft_fftw.c
and also link in the fftw library. You can only have one of these three
linked in. The configure script can be used to select which one.
*/

/* ---------------- utility functions for DSP chains ---------------------- */

/* swap two arrays */
static t_int *sigfft_swap(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
int n = (int)w[3];
for (;n--; in1++, in2++)
{
t_sample f = *in1;
*in1 = *in2;
*in2 = f;
}
return (w+4);
}

/* take array1 (supply a pointer to beginning) and copy it,
into decreasing addresses, into array 2 (supply a pointer one past the
end), and negate the sign. */

static t_int *sigrfft_flip(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)w[3];
while (n--)
*(--out) = - *in++;
return (w+4);
}

/* ------------------------ fft~ and ifft~ -------------------------------- */
static t_class *sigfft_class, *sigifft_class;

typedef struct fft
{
t_object x_obj;
t_float x_f;
} t_sigfft;

static void *sigfft_new(void)
{
t_sigfft *x = (t_sigfft *)pd_new(sigfft_class);
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_f = 0;
return (x);
}

static void *sigifft_new(void)
{
t_sigfft *x = (t_sigfft *)pd_new(sigifft_class);
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_f = 0;
return (x);
}

static t_int *sigfft_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
int n = (int)w[3];
mayer_fft(n, in1, in2);
return (w+4);
}

static t_int *sigifft_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
int n = (int)w[3];
mayer_ifft(n, in1, in2);
return (w+4);
}

static void sigfft_dspx(t_sigfft *x, t_signal **sp, t_int *(*f)(t_int *w))
{
int n = sp[0]->s_n;
t_sample *in1 = sp[0]->s_vec;
t_sample *in2 = sp[1]->s_vec;
t_sample *out1 = sp[2]->s_vec;
t_sample *out2 = sp[3]->s_vec;
if (out1 == in2 && out2 == in1)
dsp_add(sigfft_swap, 3, out1, out2, n);
else if (out1 == in2)
{
dsp_add(copy_perform, 3, in2, out2, n);
dsp_add(copy_perform, 3, in1, out1, n);
}
else
{
if (out1 != in1) dsp_add(copy_perform, 3, in1, out1, n);
if (out2 != in2) dsp_add(copy_perform, 3, in2, out2, n);
}
dsp_add(f, 3, sp[2]->s_vec, sp[3]->s_vec, n);
}

static void sigfft_dsp(t_sigfft *x, t_signal **sp)
{
sigfft_dspx(x, sp, sigfft_perform);
}

static void sigifft_dsp(t_sigfft *x, t_signal **sp)
{
sigfft_dspx(x, sp, sigifft_perform);
}

static void sigfft_setup(void)
{
sigfft_class = class_new(gensym("fft~"), sigfft_new, 0,
sizeof(t_sigfft), 0, 0);
CLASS_MAINSIGNALIN(sigfft_class, t_sigfft, x_f);
class_addmethod(sigfft_class, (t_method)sigfft_dsp,
gensym("dsp"), A_CANT, 0);

sigifft_class = class_new(gensym("ifft~"), sigifft_new, 0,
sizeof(t_sigfft), 0, 0);
CLASS_MAINSIGNALIN(sigifft_class, t_sigfft, x_f);
class_addmethod(sigifft_class, (t_method)sigifft_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(sigifft_class, gensym("fft~"));
}

/* ----------------------- rfft~ -------------------------------- */

static t_class *sigrfft_class;

typedef struct rfft
{
t_object x_obj;
t_float x_f;
} t_sigrfft;

static void *sigrfft_new(void)
{
t_sigrfft *x = (t_sigrfft *)pd_new(sigrfft_class);
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *sigrfft_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
int n = (int)w[2];
mayer_realfft(n, in);
return (w+3);
}

static void sigrfft_dsp(t_sigrfft *x, t_signal **sp)
{
int n = sp[0]->s_n, n2 = (n>>1);
t_sample *in1 = sp[0]->s_vec;
t_sample *out1 = sp[1]->s_vec;
t_sample *out2 = sp[2]->s_vec;
if (n < 4)
{
error("fft: minimum 4 points");
return;
}
if (in1 != out1)
dsp_add(copy_perform, 3, in1, out1, n);
dsp_add(sigrfft_perform, 2, out1, n);
dsp_add(sigrfft_flip, 3, out1 + (n2+1), out2 + n2, n2-1);
dsp_add_zero(out1 + (n2+1), ((n2-1)&(~7)));
dsp_add_zero(out1 + (n2+1) + ((n2-1)&(~7)), ((n2-1)&7));
dsp_add_zero(out2 + n2, n2);
dsp_add_zero(out2, 1);
}

static void sigrfft_setup(void)
{
sigrfft_class = class_new(gensym("rfft~"), sigrfft_new, 0,
sizeof(t_sigrfft), 0, 0);
CLASS_MAINSIGNALIN(sigrfft_class, t_sigrfft, x_f);
class_addmethod(sigrfft_class, (t_method)sigrfft_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(sigrfft_class, gensym("fft~"));
}

/* ----------------------- rifft~ -------------------------------- */

static t_class *sigrifft_class;

typedef struct rifft
{
t_object x_obj;
t_float x_f;
} t_sigrifft;

static void *sigrifft_new(void)
{
t_sigrifft *x = (t_sigrifft *)pd_new(sigrifft_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *sigrifft_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
int n = (int)w[2];
mayer_realifft(n, in);
return (w+3);
}

static void sigrifft_dsp(t_sigrifft *x, t_signal **sp)
{
int n = sp[0]->s_n, n2 = (n>>1);
t_sample *in1 = sp[0]->s_vec;
t_sample *in2 = sp[1]->s_vec;
t_sample *out1 = sp[2]->s_vec;
if (n < 4)
{
error("fft: minimum 4 points");
return;
}
if (in2 == out1)
{
dsp_add(sigrfft_flip, 3, out1+1, out1 + n, n2-1);
dsp_add(copy_perform, 3, in1, out1, n2+1);
}
else
{
if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n2+1);
dsp_add(sigrfft_flip, 3, in2+1, out1 + n, n2-1);
}
dsp_add(sigrifft_perform, 2, out1, n);
}

static void sigrifft_setup(void)
{
sigrifft_class = class_new(gensym("rifft~"), sigrifft_new, 0,
sizeof(t_sigrifft), 0, 0);
CLASS_MAINSIGNALIN(sigrifft_class, t_sigrifft, x_f);
class_addmethod(sigrifft_class, (t_method)sigrifft_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(sigrifft_class, gensym("fft~"));
}

/* ----------------------- framp~ -------------------------------- */

static t_class *sigframp_class;

typedef struct framp
{
t_object x_obj;
t_float x_f;
} t_sigframp;

static void *sigframp_new(void)
{
t_sigframp *x = (t_sigframp *)pd_new(sigframp_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *sigframp_perform(t_int *w)
{
t_sample *inreal = (t_sample *)(w[1]);
t_sample *inimag = (t_sample *)(w[2]);
t_sample *outfreq = (t_sample *)(w[3]);
t_sample *outamp = (t_sample *)(w[4]);
t_sample lastreal = 0, currentreal = inreal[0], nextreal = inreal[1];
t_sample lastimag = 0, currentimag = inimag[0], nextimag = inimag[1];
int n = (int)w[5];
int m = n + 1;
t_sample fbin = 1, oneovern2 = 1.f/((t_sample)n * (t_sample)n);

inreal += 2;
inimag += 2;
*outamp++ = *outfreq++ = 0;
n -= 2;
while (n--)
{
t_sample re, im, pow, freq;
lastreal = currentreal;
currentreal = nextreal;
nextreal = *inreal++;
lastimag = currentimag;
currentimag = nextimag;
nextimag = *inimag++;
re = currentreal - 0.5f * (lastreal + nextreal);
im = currentimag - 0.5f * (lastimag + nextimag);
pow = re * re + im * im;
if (pow > 1e-19)
{
t_sample detune = ((lastreal - nextreal) * re +
(lastimag - nextimag) * im) / (2.0f * pow);
if (detune > 2 || detune < -2) freq = pow = 0;
else freq = fbin + detune;
}
else freq = pow = 0;
*outfreq++ = freq;
*outamp++ = oneovern2 * pow;
fbin += 1.0f;
}
while (m--) *outamp++ = *outfreq++ = 0;
return (w+6);
}

t_int *sigsqrt_perform(t_int *w);

static void sigframp_dsp(t_sigframp *x, t_signal **sp)
{
int n = sp[0]->s_n, n2 = (n>>1);
if (n < 4)
{
error("framp: minimum 4 points");
return;
}
dsp_add(sigframp_perform, 5, sp[0]->s_vec, sp[1]->s_vec,
sp[2]->s_vec, sp[3]->s_vec, n2);
dsp_add(sigsqrt_perform, 3, sp[3]->s_vec, sp[3]->s_vec, n2);
}

static void sigframp_setup(void)
{
sigframp_class = class_new(gensym("framp~"), sigframp_new, 0,
sizeof(t_sigframp), 0, 0);
CLASS_MAINSIGNALIN(sigframp_class, t_sigframp, x_f);
class_addmethod(sigframp_class, (t_method)sigframp_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------ global setup routine ------------------------- */

void d_fft_setup(void)
{
sigfft_setup();
sigrfft_setup();
sigrifft_setup();
sigframp_setup();
}

+ 3486
- 0
ports/camomile/source/LibPd/pure-data/src/d_fft_fftsg.c
File diff suppressed because it is too large
View File


+ 185
- 0
ports/camomile/source/LibPd/pure-data/src/d_fft_fftw.c View File

@@ -0,0 +1,185 @@
/* Copyright (c) 1997- Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* --------- Pd interface to FFTW library; imitate Mayer API ---------- */

/* changes and additions for FFTW3 by Thomas Grill */

#include "m_pd.h"
#include <fftw3.h>

int ilog2(int n);

#define MINFFT 0
#define MAXFFT 30

/* from the FFTW website:
#include <fftw3.h>
...
{
fftw_complex *in, *out;
fftw_plan p;
...
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
...
fftw_execute(p);
...
fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);
}

FFTW_FORWARD or FFTW_BACKWARD, and indicates the direction of the transform you
are interested in. Alternatively, you can use the sign of the exponent in the
transform, -1 or +1, which corresponds to FFTW_FORWARD or FFTW_BACKWARD
respectively. The flags argument is either FFTW_MEASURE

*/

/* complex stuff */

typedef struct {
fftwf_plan plan;
fftwf_complex *in,*out;
} cfftw_info;

static cfftw_info cfftw_fwd[MAXFFT+1 - MINFFT],cfftw_bwd[MAXFFT+1 - MINFFT];

static cfftw_info *cfftw_getplan(int n,int fwd)
{
cfftw_info *info;
int logn = ilog2(n);
if (logn < MINFFT || logn > MAXFFT)
return (0);
info = (fwd?cfftw_fwd:cfftw_bwd)+(logn-MINFFT);
if (!info->plan)
{
pd_globallock();
if (!info->plan) /* recheck in case it got set while we waited */
{
info->in =
(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
info->out =
(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
info->plan = fftwf_plan_dft_1d(n, info->in, info->out,
fwd?FFTW_FORWARD:FFTW_BACKWARD, FFTW_MEASURE);
}
pd_globalunlock();
}
return info;
}


/* real stuff */

typedef struct {
fftwf_plan plan;
float *in,*out;
} rfftw_info;

static rfftw_info rfftw_fwd[MAXFFT+1 - MINFFT],rfftw_bwd[MAXFFT+1 - MINFFT];

static rfftw_info *rfftw_getplan(int n,int fwd)
{
rfftw_info *info;
int logn = ilog2(n);
if (logn < MINFFT || logn > MAXFFT)
return (0);
info = (fwd?rfftw_fwd:rfftw_bwd)+(logn-MINFFT);
if (!info->plan)
{
info->in = (float*) fftwf_malloc(sizeof(float) * n);
info->out = (float*) fftwf_malloc(sizeof(float) * n);
info->plan = fftwf_plan_r2r_1d(n, info->in, info->out, fwd?FFTW_R2HC:FFTW_HC2R, FFTW_MEASURE);
}
return info;
}



EXTERN void mayer_fht(float *fz, int n)
{
post("FHT: not yet implemented");
}

static void mayer_do_cfft(int n, float *fz1, float *fz2, int fwd)
{
int i;
float *fz;
cfftw_info *p = cfftw_getplan(n, fwd);
if (!p)
return;

for (i = 0, fz = (float *)p->in; i < n; i++)
fz[i*2] = fz1[i], fz[i*2+1] = fz2[i];

fftwf_execute(p->plan);

for (i = 0, fz = (float *)p->out; i < n; i++)
fz1[i] = fz[i*2], fz2[i] = fz[i*2+1];
}

EXTERN void mayer_fft(int n, float *fz1, float *fz2)
{
mayer_do_cfft(n, fz1, fz2, 1);
}

EXTERN void mayer_ifft(int n, float *fz1, float *fz2)
{
mayer_do_cfft(n, fz1, fz2, 0);
}

/*
in the following the sign flips are done to
be compatible with the mayer_fft implementation,
but it's probably the mayer_fft that should be corrected...
*/

EXTERN void mayer_realfft(int n, float *fz)
{
int i;
rfftw_info *p = rfftw_getplan(n, 1);
if (!p)
return;

for (i = 0; i < n; i++)
p->in[i] = fz[i];
fftwf_execute(p->plan);
for (i = 0; i < n/2+1; i++)
fz[i] = p->out[i];
for (; i < n; i++)
fz[i] = -p->out[i];
}

EXTERN void mayer_realifft(int n, float *fz)
{
int i;
rfftw_info *p = rfftw_getplan(n, 0);
if (!p)
return;

for (i = 0; i < n/2+1; i++)
p->in[i] = fz[i];
for (; i < n; i++)
p->in[i] = -fz[i];
fftwf_execute(p->plan);
for (i = 0; i < n; i++)
fz[i] = p->out[i];
}

/* ancient ISPW-like version, used in fiddle~ and perhaps other externs
here and there. */
void pd_fft(t_float *buf, int npoints, int inverse)
{
cfftw_info *p = cfftw_getplan(npoints, !inverse);
int i;
float *fz;
for (i = 0, fz = (float *)(p->in); i < 2 * npoints; i++)
*fz++ = buf[i];
fftwf_execute(p->plan);
for (i = 0, fz = (float *)(p->out); i < 2 * npoints; i++)
buf[i] = *fz++;
}


+ 1082
- 0
ports/camomile/source/LibPd/pure-data/src/d_filter.c
File diff suppressed because it is too large
View File


+ 361
- 0
ports/camomile/source/LibPd/pure-data/src/d_global.c View File

@@ -0,0 +1,361 @@
/* 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. */

/* send~, receive~, throw~, catch~ */

#include "m_pd.h"
#include <string.h>

#define DEFSENDVS 64 /* LATER get send to get this from canvas */

/* ----------------------------- send~ ----------------------------- */
static t_class *sigsend_class;

typedef struct _sigsend
{
t_object x_obj;
t_symbol *x_sym;
int x_n;
t_sample *x_vec;
t_float x_f;
} t_sigsend;

static void *sigsend_new(t_symbol *s)
{
t_sigsend *x = (t_sigsend *)pd_new(sigsend_class);
pd_bind(&x->x_obj.ob_pd, s);
x->x_sym = s;
x->x_n = DEFSENDVS;
x->x_vec = (t_sample *)getbytes(DEFSENDVS * sizeof(t_sample));
memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(t_sample));
x->x_f = 0;
return (x);
}

static t_int *sigsend_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--)
{
*out = (PD_BIGORSMALL(*in) ? 0 : *in);
out++;
in++;
}
return (w+4);
}

static void sigsend_dsp(t_sigsend *x, t_signal **sp)
{
if (x->x_n == sp[0]->s_n)
dsp_add(sigsend_perform, 3, sp[0]->s_vec, x->x_vec, sp[0]->s_n);
else error("sigsend %s: unexpected vector size", x->x_sym->s_name);
}

static void sigsend_free(t_sigsend *x)
{
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
freebytes(x->x_vec, x->x_n * sizeof(t_sample));
}

static void sigsend_setup(void)
{
sigsend_class = class_new(gensym("send~"), (t_newmethod)sigsend_new,
(t_method)sigsend_free, sizeof(t_sigsend), 0, A_DEFSYM, 0);
class_addcreator((t_newmethod)sigsend_new, gensym("s~"), A_DEFSYM, 0);
CLASS_MAINSIGNALIN(sigsend_class, t_sigsend, x_f);
class_addmethod(sigsend_class, (t_method)sigsend_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ----------------------------- receive~ ----------------------------- */
static t_class *sigreceive_class;

typedef struct _sigreceive
{
t_object x_obj;
t_symbol *x_sym;
t_sample *x_wherefrom;
int x_n;
} t_sigreceive;

static void *sigreceive_new(t_symbol *s)
{
t_sigreceive *x = (t_sigreceive *)pd_new(sigreceive_class);
x->x_n = DEFSENDVS; /* LATER find our vector size correctly */
x->x_sym = s;
x->x_wherefrom = 0;
outlet_new(&x->x_obj, &s_signal);
return (x);
}

static t_int *sigreceive_perform(t_int *w)
{
t_sigreceive *x = (t_sigreceive *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
t_sample *in = x->x_wherefrom;
if (in)
{
while (n--)
*out++ = *in++;
}
else
{
while (n--)
*out++ = 0;
}
return (w+4);
}

/* tb: vectorized receive function */
static t_int *sigreceive_perf8(t_int *w)
{
t_sigreceive *x = (t_sigreceive *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
t_sample *in = x->x_wherefrom;
if (in)
{
for (; n; n -= 8, in += 8, out += 8)
{
out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3];
out[4] = in[4]; out[5] = in[5]; out[6] = in[6]; out[7] = in[7];
}
}
else
{
for (; n; n -= 8, in += 8, out += 8)
{
out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0;
out[4] = 0; out[5] = 0; out[6] = 0; out[7] = 0;
}
}
return (w+4);
}

static void sigreceive_set(t_sigreceive *x, t_symbol *s)
{
t_sigsend *sender = (t_sigsend *)pd_findbyclass((x->x_sym = s),
sigsend_class);
if (sender)
{
if (sender->x_n == x->x_n)
x->x_wherefrom = sender->x_vec;
else
{
pd_error(x, "receive~ %s: vector size mismatch", x->x_sym->s_name);
x->x_wherefrom = 0;
}
}
else
{
pd_error(x, "receive~ %s: no matching send", x->x_sym->s_name);
x->x_wherefrom = 0;
}
}

static void sigreceive_dsp(t_sigreceive *x, t_signal **sp)
{
if (sp[0]->s_n != x->x_n)
{
pd_error(x, "receive~ %s: vector size mismatch", x->x_sym->s_name);
}
else
{
sigreceive_set(x, x->x_sym);
if (sp[0]->s_n&7)
dsp_add(sigreceive_perform, 3,
x, sp[0]->s_vec, sp[0]->s_n);
else dsp_add(sigreceive_perf8, 3,
x, sp[0]->s_vec, sp[0]->s_n);
}
}

static void sigreceive_setup(void)
{
sigreceive_class = class_new(gensym("receive~"),
(t_newmethod)sigreceive_new, 0,
sizeof(t_sigreceive), 0, A_DEFSYM, 0);
class_addcreator((t_newmethod)sigreceive_new, gensym("r~"), A_DEFSYM, 0);
class_addmethod(sigreceive_class, (t_method)sigreceive_set, gensym("set"),
A_SYMBOL, 0);
class_addmethod(sigreceive_class, (t_method)sigreceive_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(sigreceive_class, gensym("send~"));
}

/* ----------------------------- catch~ ----------------------------- */
static t_class *sigcatch_class;

typedef struct _sigcatch
{
t_object x_obj;
t_symbol *x_sym;
int x_n;
t_sample *x_vec;
} t_sigcatch;

static void *sigcatch_new(t_symbol *s)
{
t_sigcatch *x = (t_sigcatch *)pd_new(sigcatch_class);
pd_bind(&x->x_obj.ob_pd, s);
x->x_sym = s;
x->x_n = DEFSENDVS;
x->x_vec = (t_sample *)getbytes(DEFSENDVS * sizeof(t_sample));
memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(t_sample));
outlet_new(&x->x_obj, &s_signal);
return (x);
}

static t_int *sigcatch_perform(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--) *out++ = *in, *in++ = 0;
return (w+4);
}

/* tb: vectorized catch function */
static t_int *sigcatch_perf8(t_int *w)
{
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
for (; n; n -= 8, in += 8, out += 8)
{
out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3];
out[4] = in[4]; out[5] = in[5]; out[6] = in[6]; out[7] = in[7];

in[0] = 0; in[1] = 0; in[2] = 0; in[3] = 0;
in[4] = 0; in[5] = 0; in[6] = 0; in[7] = 0;
}
return (w+4);
}

static void sigcatch_dsp(t_sigcatch *x, t_signal **sp)
{
if (x->x_n == sp[0]->s_n)
{
if(sp[0]->s_n&7)
dsp_add(sigcatch_perform, 3, x->x_vec, sp[0]->s_vec, sp[0]->s_n);
else
dsp_add(sigcatch_perf8, 3, x->x_vec, sp[0]->s_vec, sp[0]->s_n);
}
else error("sigcatch %s: unexpected vector size", x->x_sym->s_name);
}

static void sigcatch_free(t_sigcatch *x)
{
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
freebytes(x->x_vec, x->x_n * sizeof(t_sample));
}

static void sigcatch_setup(void)
{
sigcatch_class = class_new(gensym("catch~"), (t_newmethod)sigcatch_new,
(t_method)sigcatch_free, sizeof(t_sigcatch), CLASS_NOINLET, A_DEFSYM, 0);
class_addmethod(sigcatch_class, (t_method)sigcatch_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(sigcatch_class, gensym("throw~"));
}

/* ----------------------------- throw~ ----------------------------- */
static t_class *sigthrow_class;

typedef struct _sigthrow
{
t_object x_obj;
t_symbol *x_sym;
t_sample *x_whereto;
int x_n;
t_float x_f;
} t_sigthrow;

static void *sigthrow_new(t_symbol *s)
{
t_sigthrow *x = (t_sigthrow *)pd_new(sigthrow_class);
x->x_sym = s;
x->x_whereto = 0;
x->x_n = DEFSENDVS;
x->x_f = 0;
return (x);
}

static t_int *sigthrow_perform(t_int *w)
{
t_sigthrow *x = (t_sigthrow *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
int n = (int)(w[3]);
t_sample *out = x->x_whereto;
if (out)
{
while (n--)
{
*out += (PD_BIGORSMALL(*in) ? 0 : *in);
out++;
in++;
}
}
return (w+4);
}

static void sigthrow_set(t_sigthrow *x, t_symbol *s)
{
t_sigcatch *catcher = (t_sigcatch *)pd_findbyclass((x->x_sym = s),
sigcatch_class);
if (catcher)
{
if (catcher->x_n == x->x_n)
x->x_whereto = catcher->x_vec;
else
{
pd_error(x, "throw~ %s: vector size mismatch", x->x_sym->s_name);
x->x_whereto = 0;
}
}
else
{
pd_error(x, "throw~ %s: no matching catch", x->x_sym->s_name);
x->x_whereto = 0;
}
}

static void sigthrow_dsp(t_sigthrow *x, t_signal **sp)
{
if (sp[0]->s_n != x->x_n)
{
pd_error(x, "throw~ %s: vector size mismatch", x->x_sym->s_name);
}
else
{
sigthrow_set(x, x->x_sym);
dsp_add(sigthrow_perform, 3,
x, sp[0]->s_vec, sp[0]->s_n);
}
}

static void sigthrow_setup(void)
{
sigthrow_class = class_new(gensym("throw~"), (t_newmethod)sigthrow_new, 0,
sizeof(t_sigthrow), 0, A_DEFSYM, 0);
class_addmethod(sigthrow_class, (t_method)sigthrow_set, gensym("set"),
A_SYMBOL, 0);
CLASS_MAINSIGNALIN(sigthrow_class, t_sigthrow, x_f);
class_addmethod(sigthrow_class, (t_method)sigthrow_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ----------------------- global setup routine ---------------- */

void d_global_setup(void)
{
sigsend_setup();
sigreceive_setup();
sigcatch_setup();
sigthrow_setup();
}


+ 806
- 0
ports/camomile/source/LibPd/pure-data/src/d_math.c View File

@@ -0,0 +1,806 @@
/* 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," in this distribution. */

/* mathematical functions and other transfer functions, including tilde
versions of stuff from x_acoustics.c.
*/

#include "m_pd.h"
#include <math.h>
#define LOGTEN 2.302585092994

/* ------------------------- clip~ -------------------------- */
static t_class *clip_class;

typedef struct _clip
{
t_object x_obj;
t_float x_f;
t_float x_lo;
t_float x_hi;
} t_clip;

static void *clip_new(t_floatarg lo, t_floatarg hi)
{
t_clip *x = (t_clip *)pd_new(clip_class);
x->x_lo = lo;
x->x_hi = hi;
outlet_new(&x->x_obj, gensym("signal"));
floatinlet_new(&x->x_obj, &x->x_lo);
floatinlet_new(&x->x_obj, &x->x_hi);
x->x_f = 0;
return (x);
}

static t_int *clip_perform(t_int *w)
{
t_clip *x = (t_clip *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
t_sample f = *in++;
if (f < x->x_lo) f = x->x_lo;
if (f > x->x_hi) f = x->x_hi;
*out++ = f;
}
return (w+5);
}

static void clip_dsp(t_clip *x, t_signal **sp)
{
dsp_add(clip_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void clip_setup(void)
{
clip_class = class_new(gensym("clip~"), (t_newmethod)clip_new, 0,
sizeof(t_clip), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(clip_class, t_clip, x_f);
class_addmethod(clip_class, (t_method)clip_dsp, gensym("dsp"), A_CANT, 0);
}

/* sigrsqrt - reciprocal square root good to 8 mantissa bits */

#define DUMTAB1SIZE 256
#define DUMTAB2SIZE 1024

/* These are only written at setup time when there's a global lock in place. */
static float rsqrt_exptab[DUMTAB1SIZE], rsqrt_mantissatab[DUMTAB2SIZE];

static void init_rsqrt(void)
{
int i;
for (i = 0; i < DUMTAB1SIZE; i++)
{
union {
float f;
long l;
} u;
int32_t l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23;
u.l = l;
rsqrt_exptab[i] = 1./sqrt(u.f);
}
for (i = 0; i < DUMTAB2SIZE; i++)
{
float f = 1 + (1./DUMTAB2SIZE) * i;
rsqrt_mantissatab[i] = 1./sqrt(f);
}
}

/* these are used in externs like "bonk" */

t_float q8_rsqrt(t_float f0)
{
union {
float f;
long l;
} u;
u.f=f0;
if (u.f < 0) return (0);
else return (rsqrt_exptab[(u.l >> 23) & 0xff] *
rsqrt_mantissatab[(u.l >> 13) & 0x3ff]);
}

t_float q8_sqrt(t_float f0)
{
union {
float f;
long l;
} u;
u.f=f0;
if (u.f < 0) return (0);
else return (u.f * rsqrt_exptab[(u.l >> 23) & 0xff] *
rsqrt_mantissatab[(u.l >> 13) & 0x3ff]);
}

t_float qsqrt(t_float f) {return (q8_sqrt(f)); }
t_float qrsqrt(t_float f) {return (q8_rsqrt(f)); }

typedef struct sigrsqrt
{
t_object x_obj;
t_float x_f;
} t_sigrsqrt;

static t_class *sigrsqrt_class;

static void *sigrsqrt_new(void)
{
t_sigrsqrt *x = (t_sigrsqrt *)pd_new(sigrsqrt_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *sigrsqrt_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = *(t_int *)(w+3);
while (n--)
{
t_sample f = *in++;
union {
float f;
long l;
} u;
u.f = f;
if (f < 0) *out++ = 0;
else
{
t_sample g = rsqrt_exptab[(u.l >> 23) & 0xff] *
rsqrt_mantissatab[(u.l >> 13) & 0x3ff];
*out++ = 1.5 * g - 0.5 * g * g * g * f;
}
}
return (w + 4);
}

static void sigrsqrt_dsp(t_sigrsqrt *x, t_signal **sp)
{
dsp_add(sigrsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void sigrsqrt_setup(void)
{
init_rsqrt();
sigrsqrt_class = class_new(gensym("rsqrt~"), (t_newmethod)sigrsqrt_new, 0,
sizeof(t_sigrsqrt), 0, 0);
/* an old name for it: */
class_addcreator(sigrsqrt_new, gensym("q8_rsqrt~"), 0);
CLASS_MAINSIGNALIN(sigrsqrt_class, t_sigrsqrt, x_f);
class_addmethod(sigrsqrt_class, (t_method)sigrsqrt_dsp,
gensym("dsp"), A_CANT, 0);
}


/* sigsqrt - square root good to 8 mantissa bits */

typedef struct sigsqrt
{
t_object x_obj;
t_float x_f;
} t_sigsqrt;

static t_class *sigsqrt_class;

static void *sigsqrt_new(void)
{
t_sigsqrt *x = (t_sigsqrt *)pd_new(sigsqrt_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

t_int *sigsqrt_perform(t_int *w) /* not static; also used in d_fft.c */
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = *(t_int *)(w+3);
while (n--)
{
t_sample f = *in++;
union {
float f;
long l;
} u;
u.f = f;
if (f < 0) *out++ = 0;
else
{
t_sample g = rsqrt_exptab[(u.l >> 23) & 0xff] *
rsqrt_mantissatab[(u.l >> 13) & 0x3ff];
*out++ = f * (1.5 * g - 0.5 * g * g * g * f);
}
}
return (w + 4);
}

static void sigsqrt_dsp(t_sigsqrt *x, t_signal **sp)
{
dsp_add(sigsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void sigsqrt_setup(void)
{
sigsqrt_class = class_new(gensym("sqrt~"), (t_newmethod)sigsqrt_new, 0,
sizeof(t_sigsqrt), 0, 0);
class_addcreator(sigsqrt_new, gensym("q8_sqrt~"), 0); /* old name */
CLASS_MAINSIGNALIN(sigsqrt_class, t_sigsqrt, x_f);
class_addmethod(sigsqrt_class, (t_method)sigsqrt_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ wrap~ -------------------------- */

typedef struct wrap
{
t_object x_obj;
t_float x_f;
} t_sigwrap;

t_class *sigwrap_class;

static void *sigwrap_new(void)
{
t_sigwrap *x = (t_sigwrap *)pd_new(sigwrap_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *sigwrap_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
while (n--)
{
t_sample f = *in++;
int k = f;
if (k <= f) *out++ = f-k;
else *out++ = f - (k-1);
}
return (w + 4);
}

/* old buggy version that sometimes output 1 instead of 0 */
static t_int *sigwrap_old_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
while (n--)
{
t_sample f = *in++;
int k = f;
if (f > 0) *out++ = f-k;
else *out++ = f - (k-1);
}
return (w + 4);
}

static void sigwrap_dsp(t_sigwrap *x, t_signal **sp)
{
dsp_add((pd_compatibilitylevel < 48 ?
sigwrap_old_perform : sigwrap_perform),
3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void sigwrap_setup(void)
{
sigwrap_class = class_new(gensym("wrap~"), (t_newmethod)sigwrap_new, 0,
sizeof(t_sigwrap), 0, 0);
CLASS_MAINSIGNALIN(sigwrap_class, t_sigwrap, x_f);
class_addmethod(sigwrap_class, (t_method)sigwrap_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ mtof_tilde~ -------------------------- */

typedef struct mtof_tilde
{
t_object x_obj;
t_float x_f;
} t_mtof_tilde;

t_class *mtof_tilde_class;

static void *mtof_tilde_new(void)
{
t_mtof_tilde *x = (t_mtof_tilde *)pd_new(mtof_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *mtof_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
for (; n--; in++, out++)
{
t_sample f = *in;
if (f <= -1500) *out = 0;
else
{
if (f > 1499) f = 1499;
*out = 8.17579891564 * exp(.0577622650 * f);
}
}
return (w + 4);
}

static void mtof_tilde_dsp(t_mtof_tilde *x, t_signal **sp)
{
dsp_add(mtof_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void mtof_tilde_setup(void)
{
mtof_tilde_class = class_new(gensym("mtof~"), (t_newmethod)mtof_tilde_new, 0,
sizeof(t_mtof_tilde), 0, 0);
CLASS_MAINSIGNALIN(mtof_tilde_class, t_mtof_tilde, x_f);
class_addmethod(mtof_tilde_class, (t_method)mtof_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ ftom_tilde~ -------------------------- */

typedef struct ftom_tilde
{
t_object x_obj;
t_float x_f;
} t_ftom_tilde;

t_class *ftom_tilde_class;

static void *ftom_tilde_new(void)
{
t_ftom_tilde *x = (t_ftom_tilde *)pd_new(ftom_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *ftom_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
for (; n--; in++, out++)
{
t_sample f = *in;
*out = (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500);
}
return (w + 4);
}

static void ftom_tilde_dsp(t_ftom_tilde *x, t_signal **sp)
{
dsp_add(ftom_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void ftom_tilde_setup(void)
{
ftom_tilde_class = class_new(gensym("ftom~"), (t_newmethod)ftom_tilde_new, 0,
sizeof(t_ftom_tilde), 0, 0);
CLASS_MAINSIGNALIN(ftom_tilde_class, t_ftom_tilde, x_f);
class_addmethod(ftom_tilde_class, (t_method)ftom_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ dbtorms~ -------------------------- */

typedef struct dbtorms_tilde
{
t_object x_obj;
t_float x_f;
} t_dbtorms_tilde;

t_class *dbtorms_tilde_class;

static void *dbtorms_tilde_new(void)
{
t_dbtorms_tilde *x = (t_dbtorms_tilde *)pd_new(dbtorms_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *dbtorms_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
for (; n--; in++, out++)
{
t_sample f = *in;
if (f <= 0) *out = 0;
else
{
if (f > 485)
f = 485;
*out = exp((LOGTEN * 0.05) * (f-100.));
}
}
return (w + 4);
}

static void dbtorms_tilde_dsp(t_dbtorms_tilde *x, t_signal **sp)
{
dsp_add(dbtorms_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void dbtorms_tilde_setup(void)
{
dbtorms_tilde_class = class_new(gensym("dbtorms~"), (t_newmethod)dbtorms_tilde_new, 0,
sizeof(t_dbtorms_tilde), 0, 0);
CLASS_MAINSIGNALIN(dbtorms_tilde_class, t_dbtorms_tilde, x_f);
class_addmethod(dbtorms_tilde_class, (t_method)dbtorms_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ rmstodb~ -------------------------- */

typedef struct rmstodb_tilde
{
t_object x_obj;
t_float x_f;
} t_rmstodb_tilde;

t_class *rmstodb_tilde_class;

static void *rmstodb_tilde_new(void)
{
t_rmstodb_tilde *x = (t_rmstodb_tilde *)pd_new(rmstodb_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *rmstodb_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
for (; n--; in++, out++)
{
t_sample f = *in;
if (f <= 0) *out = 0;
else
{
t_sample g = 100 + 20./LOGTEN * log(f);
*out = (g < 0 ? 0 : g);
}
}
return (w + 4);
}

static void rmstodb_tilde_dsp(t_rmstodb_tilde *x, t_signal **sp)
{
dsp_add(rmstodb_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void rmstodb_tilde_setup(void)
{
rmstodb_tilde_class = class_new(gensym("rmstodb~"),
(t_newmethod)rmstodb_tilde_new, 0, sizeof(t_rmstodb_tilde), 0, 0);
CLASS_MAINSIGNALIN(rmstodb_tilde_class, t_rmstodb_tilde, x_f);
class_addmethod(rmstodb_tilde_class, (t_method)rmstodb_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ dbtopow~ -------------------------- */

typedef struct dbtopow_tilde
{
t_object x_obj;
t_float x_f;
} t_dbtopow_tilde;

t_class *dbtopow_tilde_class;

static void *dbtopow_tilde_new(void)
{
t_dbtopow_tilde *x = (t_dbtopow_tilde *)pd_new(dbtopow_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *dbtopow_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
for (; n--; in++, out++)
{
t_sample f = *in;
if (f <= 0) *out = 0;
else
{
if (f > 870)
f = 870;
*out = exp((LOGTEN * 0.1) * (f-100.));
}
}
return (w + 4);
}

static void dbtopow_tilde_dsp(t_dbtopow_tilde *x, t_signal **sp)
{
dsp_add(dbtopow_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void dbtopow_tilde_setup(void)
{
dbtopow_tilde_class = class_new(gensym("dbtopow~"), (t_newmethod)dbtopow_tilde_new, 0,
sizeof(t_dbtopow_tilde), 0, 0);
CLASS_MAINSIGNALIN(dbtopow_tilde_class, t_dbtopow_tilde, x_f);
class_addmethod(dbtopow_tilde_class, (t_method)dbtopow_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------------ powtodb~ -------------------------- */

typedef struct powtodb_tilde
{
t_object x_obj;
t_float x_f;
} t_powtodb_tilde;

t_class *powtodb_tilde_class;

static void *powtodb_tilde_new(void)
{
t_powtodb_tilde *x = (t_powtodb_tilde *)pd_new(powtodb_tilde_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *powtodb_tilde_perform(t_int *w)
{
t_sample *in = (t_sample *)w[1], *out = (t_sample *)w[2];
t_int n = (t_int)w[3];
for (; n--; in++, out++)
{
t_sample f = *in;
if (f <= 0) *out = 0;
else
{
t_sample g = 100 + 10./LOGTEN * log(f);
*out = (g < 0 ? 0 : g);
}
}
return (w + 4);
}

static void powtodb_tilde_dsp(t_powtodb_tilde *x, t_signal **sp)
{
dsp_add(powtodb_tilde_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

void powtodb_tilde_setup(void)
{
powtodb_tilde_class = class_new(gensym("powtodb~"), (t_newmethod)powtodb_tilde_new, 0,
sizeof(t_powtodb_tilde), 0, 0);
CLASS_MAINSIGNALIN(powtodb_tilde_class, t_powtodb_tilde, x_f);
class_addmethod(powtodb_tilde_class, (t_method)powtodb_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ----------------------------- pow ----------------------------- */
static t_class *pow_tilde_class;

typedef struct _pow_tilde
{
t_object x_obj;
t_float x_f;
} t_pow_tilde;

static void *pow_tilde_new(t_floatarg f)
{
t_pow_tilde *x = (t_pow_tilde *)pd_new(pow_tilde_class);
signalinlet_new(&x->x_obj, f);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;

return (x);
}

t_int *pow_tilde_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
float f = *in1++;
if (f > 0)
*out = pow(f, *in2);
else *out = 0;
out++;
in2++;
}
return (w+5);
}

static void pow_tilde_dsp(t_pow_tilde *x, t_signal **sp)
{
dsp_add(pow_tilde_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void pow_tilde_setup(void)
{
pow_tilde_class = class_new(gensym("pow~"), (t_newmethod)pow_tilde_new, 0,
sizeof(t_pow_tilde), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(pow_tilde_class, t_pow_tilde, x_f);
class_addmethod(pow_tilde_class, (t_method)pow_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ----------------------------- exp ----------------------------- */
static t_class *exp_tilde_class;

typedef struct _exp_tilde
{
t_object x_obj;
t_float x_f;
} t_exp_tilde;

static void *exp_tilde_new( void)
{
t_exp_tilde *x = (t_exp_tilde *)pd_new(exp_tilde_class);
outlet_new(&x->x_obj, &s_signal);
return (x);
}

t_int *exp_tilde_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--)
*out++ = exp(*in1++);
return (w+4);
}

static void exp_tilde_dsp(t_exp_tilde *x, t_signal **sp)
{
dsp_add(exp_tilde_perform, 3,
sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void exp_tilde_setup(void)
{
exp_tilde_class = class_new(gensym("exp~"), (t_newmethod)exp_tilde_new, 0,
sizeof(t_exp_tilde), 0, 0);
CLASS_MAINSIGNALIN(exp_tilde_class, t_exp_tilde, x_f);
class_addmethod(exp_tilde_class, (t_method)exp_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ----------------------------- log ----------------------------- */
static t_class *log_tilde_class;

typedef struct _log_tilde
{
t_object x_obj;
t_float x_f;
} t_log_tilde;

static void *log_tilde_new(t_floatarg f)
{
t_log_tilde *x = (t_log_tilde *)pd_new(log_tilde_class);
pd_float(
(t_pd *)inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal), f);
outlet_new(&x->x_obj, &s_signal);
x->x_f = 0;
return (x);
}

t_int *log_tilde_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
while (n--)
{
float f = *in1++, g = *in2++;
if (f <= 0)
*out = -1000; /* rather than blow up, output a number << 0 */
else if (g <= 0)
*out = log(f);
else *out = log(f)/log(g);
out++;
}
return (w+5);
}

static void log_tilde_dsp(t_log_tilde *x, t_signal **sp)
{
dsp_add(log_tilde_perform, 4,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
}

static void log_tilde_setup(void)
{
log_tilde_class = class_new(gensym("log~"), (t_newmethod)log_tilde_new, 0,
sizeof(t_log_tilde), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(log_tilde_class, t_log_tilde, x_f);
class_addmethod(log_tilde_class, (t_method)log_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ----------------------------- abs ----------------------------- */
static t_class *abs_tilde_class;

typedef struct _abs_tilde
{
t_object x_obj;
t_float x_f;
} t_abs_tilde;

static void *abs_tilde_new( void)
{
t_abs_tilde *x = (t_abs_tilde *)pd_new(abs_tilde_class);
outlet_new(&x->x_obj, &s_signal);
return (x);
}

t_int *abs_tilde_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
int n = (int)(w[3]);
while (n--)
{
float f = *in1++;
*out++ = (f >= 0 ? f : -f);
}
return (w+4);
}

static void abs_tilde_dsp(t_abs_tilde *x, t_signal **sp)
{
dsp_add(abs_tilde_perform, 3,
sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void abs_tilde_setup(void)
{
abs_tilde_class = class_new(gensym("abs~"), (t_newmethod)abs_tilde_new, 0,
sizeof(t_abs_tilde), 0, 0);
CLASS_MAINSIGNALIN(abs_tilde_class, t_abs_tilde, x_f);
class_addmethod(abs_tilde_class, (t_method)abs_tilde_dsp,
gensym("dsp"), A_CANT, 0);
}

/* ------------------------ global setup routine ------------------------- */

void d_math_setup(void)
{
t_symbol *s = gensym("acoustics~.pd");
clip_setup();
sigrsqrt_setup();
sigsqrt_setup();
sigwrap_setup();
mtof_tilde_setup();
ftom_tilde_setup();
dbtorms_tilde_setup();
rmstodb_tilde_setup();
dbtopow_tilde_setup();
powtodb_tilde_setup();
pow_tilde_setup();
exp_tilde_setup();
log_tilde_setup();
abs_tilde_setup();

class_sethelpsymbol(mtof_tilde_class, s);
class_sethelpsymbol(ftom_tilde_class, s);
class_sethelpsymbol(dbtorms_tilde_class, s);
class_sethelpsymbol(rmstodb_tilde_class, s);
class_sethelpsymbol(dbtopow_tilde_class, s);
class_sethelpsymbol(powtodb_tilde_class, s);
}


+ 136
- 0
ports/camomile/source/LibPd/pure-data/src/d_misc.c View File

@@ -0,0 +1,136 @@
/* 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. */

/* miscellaneous: print~; more to come.
*/

#include "m_pd.h"
#include <stdio.h>
#include <string.h>

/* ------------------------- print~ -------------------------- */
static t_class *print_class;

typedef struct _print
{
t_object x_obj;
t_float x_f;
t_symbol *x_sym;
int x_count;
} t_print;

static t_int *print_perform(t_int *w)
{
t_print *x = (t_print *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
int n = (int)(w[3]);
if (x->x_count)
{
int i=0;
startpost("%s:", x->x_sym->s_name);
for(i=0; i<n; i++) {
if(i%8==0)endpost();
startpost("%.4g ", in[i]);
}
endpost();
x->x_count--;
}
return (w+4);
}

static void print_dsp(t_print *x, t_signal **sp)
{
dsp_add(print_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
}

static void print_float(t_print *x, t_float f)
{
if (f < 0) f = 0;
x->x_count = f;
}

static void print_bang(t_print *x)
{
x->x_count = 1;
}

static void *print_new(t_symbol *s)
{
t_print *x = (t_print *)pd_new(print_class);
x->x_sym = (s->s_name[0]? s : gensym("print~"));
x->x_count = 0;
x->x_f = 0;
return (x);
}

static void print_setup(void)
{
print_class = class_new(gensym("print~"), (t_newmethod)print_new, 0,
sizeof(t_print), 0, A_DEFSYM, 0);
CLASS_MAINSIGNALIN(print_class, t_print, x_f);
class_addmethod(print_class, (t_method)print_dsp, gensym("dsp"), A_CANT, 0);
class_addbang(print_class, print_bang);
class_addfloat(print_class, print_float);
}

/* ------------------------ bang~ -------------------------- */

static t_class *bang_tilde_class;

typedef struct _bang
{
t_object x_obj;
t_clock *x_clock;
} t_bang;

static t_int *bang_tilde_perform(t_int *w)
{
t_bang *x = (t_bang *)(w[1]);
clock_delay(x->x_clock, 0);
return (w+2);
}

static void bang_tilde_dsp(t_bang *x, t_signal **sp)
{
dsp_add(bang_tilde_perform, 1, x);
}

static void bang_tilde_tick(t_bang *x)
{
outlet_bang(x->x_obj.ob_outlet);
}

static void bang_tilde_free(t_bang *x)
{
clock_free(x->x_clock);
}

static void *bang_tilde_new(t_symbol *s)
{
t_bang *x = (t_bang *)pd_new(bang_tilde_class);
x->x_clock = clock_new(x, (t_method)bang_tilde_tick);
outlet_new(&x->x_obj, &s_bang);
return (x);
}

static void bang_tilde_setup(void)
{
bang_tilde_class = class_new(gensym("bang~"), (t_newmethod)bang_tilde_new,
(t_method)bang_tilde_free, sizeof(t_bang), 0, 0);
class_addmethod(bang_tilde_class, (t_method)bang_tilde_dsp,
gensym("dsp"), 0);
}


/* ------------------------ global setup routine ------------------------- */

void d_misc_setup(void)
{
print_setup();
bang_tilde_setup();
}





+ 521
- 0
ports/camomile/source/LibPd/pure-data/src/d_osc.c View File

@@ -0,0 +1,521 @@
/* 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. */

/* sinusoidal oscillator and table lookup; see also tabosc4~ in d_array.c.
*/

#include "m_pd.h"
#include "math.h"

#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */


#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) \
|| defined(__OpenBSD__)
#include <machine/endian.h>
#endif

#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || \
defined(ANDROID)
#include <endian.h>
#endif

#ifdef __MINGW32__
#include <sys/param.h>
#endif

#ifdef _MSC_VER
/* _MSVC lacks BYTE_ORDER and LITTLE_ENDIAN */
#define LITTLE_ENDIAN 0x0001
#define BYTE_ORDER LITTLE_ENDIAN
#endif

#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN)
#error No byte order defined
#endif

#if BYTE_ORDER == LITTLE_ENDIAN
# define HIOFFSET 1
# define LOWOFFSET 0
#else
# define HIOFFSET 0 /* word offset to find MSB */
# define LOWOFFSET 1 /* word offset to find LSB */
#endif

union tabfudge
{
double tf_d;
int32_t tf_i[2];
};

/* -------------------------- phasor~ ------------------------------ */
static t_class *phasor_class;

#if 1 /* in the style of R. Hoeldrich (ICMC 1995 Banff) */

typedef struct _phasor
{
t_object x_obj;
double x_phase;
float x_conv;
float x_f; /* scalar frequency */
} t_phasor;

static void *phasor_new(t_floatarg f)
{
t_phasor *x = (t_phasor *)pd_new(phasor_class);
x->x_f = f;
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
x->x_phase = 0;
x->x_conv = 0;
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}

static t_int *phasor_perform(t_int *w)
{
t_phasor *x = (t_phasor *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *out = (t_float *)(w[3]);
int n = (int)(w[4]);
double dphase = x->x_phase + (double)UNITBIT32;
union tabfudge tf;
int normhipart;
float conv = x->x_conv;

tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];
tf.tf_d = dphase;

while (n--)
{
tf.tf_i[HIOFFSET] = normhipart;
dphase += *in++ * conv;
*out++ = tf.tf_d - UNITBIT32;
tf.tf_d = dphase;
}
tf.tf_i[HIOFFSET] = normhipart;
x->x_phase = tf.tf_d - UNITBIT32;
return (w+5);
}

static void phasor_dsp(t_phasor *x, t_signal **sp)
{
x->x_conv = 1./sp[0]->s_sr;
dsp_add(phasor_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void phasor_ft1(t_phasor *x, t_float f)
{
x->x_phase = f;
}

static void phasor_setup(void)
{
phasor_class = class_new(gensym("phasor~"), (t_newmethod)phasor_new, 0,
sizeof(t_phasor), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(phasor_class, t_phasor, x_f);
class_addmethod(phasor_class, (t_method)phasor_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(phasor_class, (t_method)phasor_ft1,
gensym("ft1"), A_FLOAT, 0);
}

#endif /* Hoeldrich version */

/* ------------------------ cos~ ----------------------------- */

float *cos_table;

static t_class *cos_class;

typedef struct _cos
{
t_object x_obj;
float x_f;
} t_cos;

static void *cos_new(void)
{
t_cos *x = (t_cos *)pd_new(cos_class);
outlet_new(&x->x_obj, gensym("signal"));
x->x_f = 0;
return (x);
}

static t_int *cos_perform(t_int *w)
{
t_float *in = (t_float *)(w[1]);
t_float *out = (t_float *)(w[2]);
int n = (int)(w[3]);
float *tab = cos_table, *addr, f1, f2, frac;
double dphase;
int normhipart;
union tabfudge tf;

tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];

#if 0 /* this is the readable version of the code. */
while (n--)
{
dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32;
tf.tf_d = dphase;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
}
#endif
#if 1 /* this is the same, unwrapped by hand. */
dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32;
tf.tf_d = dphase;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
while (--n)
{
dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32;
frac = tf.tf_d - UNITBIT32;
tf.tf_d = dphase;
f1 = addr[0];
f2 = addr[1];
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
*out++ = f1 + frac * (f2 - f1);
tf.tf_i[HIOFFSET] = normhipart;
}
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
#endif
return (w+4);
}

static void cos_dsp(t_cos *x, t_signal **sp)
{
dsp_add(cos_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void cos_maketable(void)
{
int i;
float *fp, phase, phsinc = (2. * 3.14159) / COSTABSIZE;
union tabfudge tf;

if (cos_table) return;
cos_table = (float *)getbytes(sizeof(float) * (COSTABSIZE+1));
for (i = COSTABSIZE + 1, fp = cos_table, phase = 0; i--;
fp++, phase += phsinc)
*fp = cos(phase);

/* here we check at startup whether the byte alignment
is as we declared it. If not, the code has to be
recompiled the other way. */
tf.tf_d = UNITBIT32 + 0.5;
if ((unsigned)tf.tf_i[LOWOFFSET] != 0x80000000)
bug("cos~: unexpected machine alignment");
}

static void cos_setup(void)
{
cos_class = class_new(gensym("cos~"), (t_newmethod)cos_new, 0,
sizeof(t_cos), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(cos_class, t_cos, x_f);
class_addmethod(cos_class, (t_method)cos_dsp, gensym("dsp"), A_CANT, 0);
cos_maketable();
}

/* ------------------------ osc~ ----------------------------- */

static t_class *osc_class, *scalarosc_class;

typedef struct _osc
{
t_object x_obj;
double x_phase;
float x_conv;
float x_f; /* frequency if scalar */
} t_osc;

static void *osc_new(t_floatarg f)
{
t_osc *x = (t_osc *)pd_new(osc_class);
x->x_f = f;
outlet_new(&x->x_obj, gensym("signal"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
x->x_phase = 0;
x->x_conv = 0;
return (x);
}

static t_int *osc_perform(t_int *w)
{
t_osc *x = (t_osc *)(w[1]);
t_float *in = (t_float *)(w[2]);
t_float *out = (t_float *)(w[3]);
int n = (int)(w[4]);
float *tab = cos_table, *addr, f1, f2, frac;
double dphase = x->x_phase + UNITBIT32;
int normhipart;
union tabfudge tf;
float conv = x->x_conv;

tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];
#if 0
while (n--)
{
tf.tf_d = dphase;
dphase += *in++ * conv;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
}
#endif
#if 1
tf.tf_d = dphase;
dphase += *in++ * conv;
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
while (--n)
{
tf.tf_d = dphase;
f1 = addr[0];
dphase += *in++ * conv;
f2 = addr[1];
addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1));
tf.tf_i[HIOFFSET] = normhipart;
*out++ = f1 + frac * (f2 - f1);
frac = tf.tf_d - UNITBIT32;
}
f1 = addr[0];
f2 = addr[1];
*out++ = f1 + frac * (f2 - f1);
#endif

tf.tf_d = UNITBIT32 * COSTABSIZE;
normhipart = tf.tf_i[HIOFFSET];
tf.tf_d = dphase + (UNITBIT32 * COSTABSIZE - UNITBIT32);
tf.tf_i[HIOFFSET] = normhipart;
x->x_phase = tf.tf_d - UNITBIT32 * COSTABSIZE;
return (w+5);
}

static void osc_dsp(t_osc *x, t_signal **sp)
{
x->x_conv = COSTABSIZE/sp[0]->s_sr;
dsp_add(osc_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void osc_ft1(t_osc *x, t_float f)
{
x->x_phase = COSTABSIZE * f;
}

static void osc_setup(void)
{
osc_class = class_new(gensym("osc~"), (t_newmethod)osc_new, 0,
sizeof(t_osc), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(osc_class, t_osc, x_f);
class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), A_CANT, 0);
class_addmethod(osc_class, (t_method)osc_ft1, gensym("ft1"), A_FLOAT, 0);

cos_maketable();
}

/* ---- vcf~ - resonant filter with audio-rate center frequency input ----- */

typedef struct vcfctl
{
float c_re;
float c_im;
float c_q;
float c_isr;
} t_vcfctl;

typedef struct sigvcf
{
t_object x_obj;
t_vcfctl x_cspace;
t_vcfctl *x_ctl;
float x_f;
} t_sigvcf;

t_class *sigvcf_class;

static void *sigvcf_new(t_floatarg q)
{
t_sigvcf *x = (t_sigvcf *)pd_new(sigvcf_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_ctl = &x->x_cspace;
x->x_cspace.c_re = 0;
x->x_cspace.c_im = 0;
x->x_cspace.c_q = q;
x->x_cspace.c_isr = 0;
x->x_f = 0;
return (x);
}

static void sigvcf_ft1(t_sigvcf *x, t_floatarg f)
{
x->x_ctl->c_q = (f > 0 ? f : 0.f);
}

static t_int *sigvcf_perform(t_int *w)
{
float *in1 = (float *)(w[1]);
float *in2 = (float *)(w[2]);
float *out1 = (float *)(w[3]);
float *out2 = (float *)(w[4]);
t_vcfctl *c = (t_vcfctl *)(w[5]);
int n = (int)w[6];
int i;
float re = c->c_re, re2;
float im = c->c_im;
float q = c->c_q;
float qinv = (q > 0? 1.0f/q : 0);
float ampcorrect = 2.0f - 2.0f / (q + 2.0f);
float isr = c->c_isr;
float coefr, coefi;
float *tab = cos_table, *addr, f1, f2, frac;
double dphase;
int normhipart, tabindex;
union tabfudge tf;

tf.tf_d = UNITBIT32;
normhipart = tf.tf_i[HIOFFSET];

for (i = 0; i < n; i++)
{
float cf, cfindx, r, oneminusr;
cf = *in2++ * isr;
if (cf < 0) cf = 0;
cfindx = cf * (float)(COSTABSIZE/6.28318f);
r = (qinv > 0 ? 1 - cf * qinv : 0);
if (r < 0) r = 0;
oneminusr = 1.0f - r;
dphase = ((double)(cfindx)) + UNITBIT32;
tf.tf_d = dphase;
tabindex = tf.tf_i[HIOFFSET] & (COSTABSIZE-1);
addr = tab + tabindex;
tf.tf_i[HIOFFSET] = normhipart;
frac = tf.tf_d - UNITBIT32;
f1 = addr[0];
f2 = addr[1];
coefr = r * (f1 + frac * (f2 - f1));

addr = tab + ((tabindex - (COSTABSIZE/4)) & (COSTABSIZE-1));
f1 = addr[0];
f2 = addr[1];
coefi = r * (f1 + frac * (f2 - f1));

f1 = *in1++;
re2 = re;
*out1++ = re = ampcorrect * oneminusr * f1
+ coefr * re2 - coefi * im;
*out2++ = im = coefi * re2 + coefr * im;
}
if (PD_BIGORSMALL(re))
re = 0;
if (PD_BIGORSMALL(im))
im = 0;
c->c_re = re;
c->c_im = im;
return (w+7);
}

static void sigvcf_dsp(t_sigvcf *x, t_signal **sp)
{
x->x_ctl->c_isr = 6.28318f/sp[0]->s_sr;
dsp_add(sigvcf_perform, 6,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,
x->x_ctl, sp[0]->s_n);
}

void sigvcf_setup(void)
{
sigvcf_class = class_new(gensym("vcf~"), (t_newmethod)sigvcf_new, 0,
sizeof(t_sigvcf), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sigvcf_class, t_sigvcf, x_f);
class_addmethod(sigvcf_class, (t_method)sigvcf_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(sigvcf_class, (t_method)sigvcf_ft1,
gensym("ft1"), A_FLOAT, 0);
}

/* -------------------------- noise~ ------------------------------ */
static t_class *noise_class;

typedef struct _noise
{
t_object x_obj;
int x_val;
} t_noise;

static void *noise_new(void)
{
t_noise *x = (t_noise *)pd_new(noise_class);
/* seed each instance differently. Once in a blue moon two threads
could grab the same seed value. We can live with that. */
static int init = 307;
x->x_val = (init *= 1319);
outlet_new(&x->x_obj, gensym("signal"));
return (x);
}

static t_int *noise_perform(t_int *w)
{
t_sample *out = (t_sample *)(w[1]);
int *vp = (int *)(w[2]);
int n = (int)(w[3]);
int val = *vp;
while (n--)
{
*out++ = ((float)((val & 0x7fffffff) - 0x40000000)) *
(float)(1.0 / 0x40000000);
val = val * 435898247 + 382842987;
}
*vp = val;
return (w+4);
}

static void noise_dsp(t_noise *x, t_signal **sp)
{
dsp_add(noise_perform, 3, sp[0]->s_vec, &x->x_val, sp[0]->s_n);
}

static void noise_float(t_noise *x, t_float f)
{
/* set the seed */
x->x_val = (int)f;
}

static void noise_setup(void)
{
noise_class = class_new(gensym("noise~"), (t_newmethod)noise_new, 0,
sizeof(t_noise), 0, A_DEFFLOAT, 0);
class_addmethod(noise_class, (t_method)noise_dsp,
gensym("dsp"), A_CANT, 0);
class_addmethod(noise_class, (t_method)noise_float,
gensym("seed"), A_FLOAT, 0);
}

/* ----------------------- global setup routine ---------------- */
void d_osc_setup(void)
{
phasor_setup();
cos_setup();
osc_setup();
sigvcf_setup();
noise_setup();
}

+ 216
- 0
ports/camomile/source/LibPd/pure-data/src/d_resample.c View File

@@ -0,0 +1,216 @@
/* 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. */


#include "m_pd.h"

/* --------------------- up/down-sampling --------------------- */
t_int *downsampling_perform_0(t_int *w)
{
t_sample *in = (t_sample *)(w[1]); /* original signal */
t_sample *out = (t_sample *)(w[2]); /* downsampled signal */
int down = (int)(w[3]); /* downsampling factor */
int parent = (int)(w[4]); /* original vectorsize */

int n=parent/down;

while(n--){
*out++=*in;
in+=down;
}

return (w+5);
}

t_int *upsampling_perform_0(t_int *w)
{
t_sample *in = (t_sample *)(w[1]); /* original signal */
t_sample *out = (t_sample *)(w[2]); /* upsampled signal */
int up = (int)(w[3]); /* upsampling factor */
int parent = (int)(w[4]); /* original vectorsize */

int n=parent*up;
t_sample *dummy = out;

while(n--)*out++=0;

n = parent;
out = dummy;
while(n--){
*out=*in++;
out+=up;
}

return (w+5);
}

t_int *upsampling_perform_hold(t_int *w)
{
t_sample *in = (t_sample *)(w[1]); /* original signal */
t_sample *out = (t_sample *)(w[2]); /* upsampled signal */
int up = (int)(w[3]); /* upsampling factor */
int parent = (int)(w[4]); /* original vectorsize */
int i=up;

int n=parent;
t_sample *dum_out = out;
t_sample *dum_in = in;

while (i--) {
n = parent;
out = dum_out+i;
in = dum_in;
while(n--){
*out=*in++;
out+=up;
}
}
return (w+5);
}

t_int *upsampling_perform_linear(t_int *w)
{
t_resample *x= (t_resample *)(w[1]);
t_sample *in = (t_sample *)(w[2]); /* original signal */
t_sample *out = (t_sample *)(w[3]); /* upsampled signal */
int up = (int)(w[4]); /* upsampling factor */
int parent = (int)(w[5]); /* original vectorsize */
int length = parent*up;
int n;
t_sample *fp;
t_sample a=*x->buffer, b=*in;


for (n=0; n<length; n++) {
t_sample findex = (t_sample)(n+1)/up;
int index = findex;
t_sample frac=findex - index;
if (frac==0.)frac=1.;
*out++ = frac * b + (1.-frac) * a;
fp = in+index;
b=*fp;
a=(index)?*(fp-1):a;
}

*x->buffer = a;
return (w+6);
}

/* ----------------------- public -------------------------------- */

/* utils */

void resample_init(t_resample *x)
{
x->method=0;

x->downsample=x->upsample=1;

x->s_n = x->coefsize = x->bufsize = 0;
x->s_vec = x->coeffs = x->buffer = 0;
}

void resample_free(t_resample *x)
{
if (x->s_n) t_freebytes(x->s_vec, x->s_n*sizeof(*x->s_vec));
if (x->coefsize) t_freebytes(x->coeffs, x->coefsize*sizeof(*x->coeffs));
if (x->bufsize) t_freebytes(x->buffer, x->bufsize*sizeof(*x->buffer));

x->s_n = x->coefsize = x->bufsize = 0;
x->s_vec = x->coeffs = x->buffer = 0;
}


/* dsp-adding */

void resample_dsp(t_resample *x,
t_sample* in, int insize,
t_sample* out, int outsize,
int method)
{
if (insize == outsize){
bug("nothing to be done");
return;
}

if (insize > outsize) { /* downsampling */
if (insize % outsize) {
error("bad downsampling factor");
return;
}
switch (method) {
default:
dsp_add(downsampling_perform_0, 4, in, out, insize/outsize, insize);
}


} else { /* upsampling */
if (outsize % insize) {
error("bad upsampling factor");
return;
}
switch (method) {
case 1:
dsp_add(upsampling_perform_hold, 4, in, out, outsize/insize, insize);
break;
case 2:
if (x->bufsize != 1) {
t_freebytes(x->buffer, x->bufsize*sizeof(*x->buffer));
x->bufsize = 1;
x->buffer = t_getbytes(x->bufsize*sizeof(*x->buffer));
}
dsp_add(upsampling_perform_linear, 5, x, in, out, outsize/insize, insize);
break;
default:
dsp_add(upsampling_perform_0, 4, in, out, outsize/insize, insize);
}
}
}

void resamplefrom_dsp(t_resample *x,
t_sample *in,
int insize, int outsize, int method)
{
if (insize==outsize) {
t_freebytes(x->s_vec, x->s_n * sizeof(*x->s_vec));
x->s_n = 0;
x->s_vec = in;
return;
}

if (x->s_n != outsize) {
t_sample *buf=x->s_vec;
t_freebytes(buf, x->s_n * sizeof(*buf));
buf = (t_sample *)t_getbytes(outsize * sizeof(*buf));
x->s_vec = buf;
x->s_n = outsize;
}

resample_dsp(x, in, insize, x->s_vec, x->s_n, method);
return;
}

void resampleto_dsp(t_resample *x,
t_sample *out,
int insize, int outsize, int method)
{
if (insize==outsize) {
if (x->s_n)t_freebytes(x->s_vec, x->s_n * sizeof(*x->s_vec));
x->s_n = 0;
x->s_vec = out;
return;
}

if (x->s_n != insize) {
t_sample *buf=x->s_vec;
t_freebytes(buf, x->s_n * sizeof(*buf));
buf = (t_sample *)t_getbytes(insize * sizeof(*buf));
x->s_vec = buf;
x->s_n = insize;
}

resample_dsp(x, x->s_vec, x->s_n, out, outsize, method);

return;
}

+ 2734
- 0
ports/camomile/source/LibPd/pure-data/src/d_soundfile.c
File diff suppressed because it is too large
View File


+ 1240
- 0
ports/camomile/source/LibPd/pure-data/src/d_ugen.c
File diff suppressed because it is too large
View File


+ 786
- 0
ports/camomile/source/LibPd/pure-data/src/g_all_guis.c View File

@@ -0,0 +1,786 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

/* #define GGEE_HSLIDER_COMPATIBLE */

/*------------------ global variables -------------------------*/

int iemgui_color_hex[]=
{
16579836, 10526880, 4210752, 16572640, 16572608,
16579784, 14220504, 14220540, 14476540, 16308476,
14737632, 8158332, 2105376, 16525352, 16559172,
15263784, 1370132, 2684148, 3952892, 16003312,
12369084, 6316128, 0, 9177096, 5779456,
7874580, 2641940, 17488, 5256, 5767248
};

int iemgui_vu_db2i[]=
{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9,10,10,10,10,10,
11,11,11,11,11,12,12,12,12,12,
13,13,13,13,14,14,14,14,15,15,
15,15,16,16,16,16,17,17,17,18,
18,18,19,19,19,20,20,20,21,21,
22,22,23,23,24,24,25,26,27,28,
29,30,31,32,33,33,34,34,35,35,
36,36,37,37,37,38,38,38,39,39,
39,39,39,39,40,40
};

int iemgui_vu_col[]=
{
0,17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
15,15,15,15,15,15,15,15,15,15,14,14,13,13,13,13,13,13,13,13,13,13,13,19,19,19
};

char *iemgui_vu_scale_str[]=
{
"",
"<-99",
"",
"",
"",
"-50",
"",
"",
"",
"-30",
"",
"",
"",
"-20",
"",
"",
"",
"-12",
"",
"",
"",
"-6",
"",
"",
"",
"-2",
"",
"",
"",
"-0dB",
"",
"",
"",
"+2",
"",
"",
"",
"+6",
"",
"",
"",
">+12",
"",
"",
"",
"",
"",
};


/*------------------ global functions -------------------------*/


int iemgui_clip_size(int size)
{
if(size < IEM_GUI_MINSIZE)
size = IEM_GUI_MINSIZE;
return(size);
}

int iemgui_clip_font(int size)
{
if(size < IEM_FONT_MINSIZE)
size = IEM_FONT_MINSIZE;
return(size);
}

int iemgui_modulo_color(int col)
{
while(col >= IEM_GUI_MAX_COLOR)
col -= IEM_GUI_MAX_COLOR;
while(col < 0)
col += IEM_GUI_MAX_COLOR;
return(col);
}

t_symbol *iemgui_dollar2raute(t_symbol *s)
{
char buf[MAXPDSTRING+1], *s1, *s2;
if (strlen(s->s_name) >= MAXPDSTRING)
return (s);
for (s1 = s->s_name, s2 = buf; ; s1++, s2++)
{
if (*s1 == '$')
*s2 = '#';
else if (!(*s2 = *s1))
break;
}
return(gensym(buf));
}

t_symbol *iemgui_raute2dollar(t_symbol *s)
{
char buf[MAXPDSTRING+1], *s1, *s2;
if (strlen(s->s_name) >= MAXPDSTRING)
return (s);
for (s1 = s->s_name, s2 = buf; ; s1++, s2++)
{
if (*s1 == '#')
*s2 = '$';
else if (!(*s2 = *s1))
break;
}
return(gensym(buf));
}

void iemgui_verify_snd_ne_rcv(t_iemgui *iemgui)
{
iemgui->x_fsf.x_put_in2out = 1;
if(iemgui->x_fsf.x_snd_able && iemgui->x_fsf.x_rcv_able)
{
if(!strcmp(iemgui->x_snd->s_name, iemgui->x_rcv->s_name))
iemgui->x_fsf.x_put_in2out = 0;
}
}

t_symbol *iemgui_new_dogetname(t_iemgui *iemgui, int indx, t_atom *argv)
{
if (IS_A_SYMBOL(argv, indx))
return (atom_getsymbolarg(indx, 100000, argv));
else if (IS_A_FLOAT(argv, indx))
{
char str[80];
sprintf(str, "%d", (int)atom_getfloatarg(indx, 100000, argv));
return (gensym(str));
}
else return (gensym("empty"));
}

void iemgui_new_getnames(t_iemgui *iemgui, int indx, t_atom *argv)
{
if (argv)
{
iemgui->x_snd = iemgui_new_dogetname(iemgui, indx, argv);
iemgui->x_rcv = iemgui_new_dogetname(iemgui, indx+1, argv);
iemgui->x_lab = iemgui_new_dogetname(iemgui, indx+2, argv);
}
else iemgui->x_snd = iemgui->x_rcv = iemgui->x_lab = gensym("empty");
iemgui->x_snd_unexpanded = iemgui->x_rcv_unexpanded =
iemgui->x_lab_unexpanded = 0;
iemgui->x_binbufindex = indx;
iemgui->x_labelbindex = indx + 3;
}

/* convert symbols in "$" form to the expanded symbols */
void iemgui_all_dollararg2sym(t_iemgui *iemgui, t_symbol **srlsym)
{
/* save unexpanded ones for later */
iemgui->x_snd_unexpanded = srlsym[0];
iemgui->x_rcv_unexpanded = srlsym[1];
iemgui->x_lab_unexpanded = srlsym[2];
srlsym[0] = canvas_realizedollar(iemgui->x_glist, srlsym[0]);
srlsym[1] = canvas_realizedollar(iemgui->x_glist, srlsym[1]);
srlsym[2] = canvas_realizedollar(iemgui->x_glist, srlsym[2]);
}

/* initialize a single symbol in unexpanded form. We reach into the
binbuf to grab them; if there's nothing there, set it to the
fallback; if still nothing, set to "empty". */
static void iemgui_init_sym2dollararg(t_iemgui *iemgui, t_symbol **symp,
int indx, t_symbol *fallback)
{
if (!*symp)
{
t_binbuf *b = iemgui->x_obj.ob_binbuf;
if (binbuf_getnatom(b) > indx)
{
char buf[80];
atom_string(binbuf_getvec(b) + indx, buf, 80);
*symp = gensym(buf);
}
else if (fallback)
*symp = fallback;
else *symp = gensym("empty");
}
}

/* get the unexpanded versions of the symbols; initialize them if
necessary. */
void iemgui_all_sym2dollararg(t_iemgui *iemgui, t_symbol **srlsym)
{
iemgui_init_sym2dollararg(iemgui, &iemgui->x_snd_unexpanded,
iemgui->x_binbufindex+1, iemgui->x_snd);
iemgui_init_sym2dollararg(iemgui, &iemgui->x_rcv_unexpanded,
iemgui->x_binbufindex+2, iemgui->x_rcv);
iemgui_init_sym2dollararg(iemgui, &iemgui->x_lab_unexpanded,
iemgui->x_labelbindex, iemgui->x_lab);
srlsym[0] = iemgui->x_snd_unexpanded;
srlsym[1] = iemgui->x_rcv_unexpanded;
srlsym[2] = iemgui->x_lab_unexpanded;
}

static t_symbol* color2symbol(int col) {
const int compat = (pd_compatibilitylevel < 48)?1:
/* FIXXME: for Pd>=0.48, the default compatibility mode should be OFF */
1;

char colname[MAXPDSTRING];
colname[0] = colname[MAXPDSTRING-1] = 0;

if (compat)
{
/* compatibility with Pd<=0.47: saves colors as numbers with limited resolution */
int col2 = -1 - (((0xfc0000 & col) >> 6)|((0xfc00 & col) >> 4)|((0xfc & col) >> 2));
snprintf(colname, MAXPDSTRING-1, "%d", col2);
} else {
snprintf(colname, MAXPDSTRING-1, "#%06x", col);
}
return gensym(colname);
}

void iemgui_all_col2save(t_iemgui *iemgui, t_symbol**bflcol)
{
bflcol[0] = color2symbol(iemgui->x_bcol);
bflcol[1] = color2symbol(iemgui->x_fcol);
bflcol[2] = color2symbol(iemgui->x_lcol);
}

static int iemgui_getcolorarg(int index, int argc, t_atom*argv)
{
if(index < 0 || index >= argc)
return 0;
if(IS_A_FLOAT(argv,index))
return atom_getfloatarg(index, argc, argv);
if(IS_A_SYMBOL(argv,index))
{
t_symbol*s=atom_getsymbolarg(index, argc, argv);
if ('#' == s->s_name[0])
return (int)strtol(s->s_name+1, 0, 16);
}
return 0;
}

static int colfromatomload(t_atom*colatom)
{
int color;
/* old-fashioned color argument, either a number or symbol
evaluating to an integer */
if (colatom->a_type == A_FLOAT)
color = atom_getfloat(colatom);
else if (colatom->a_type == A_SYMBOL &&
(isdigit(colatom->a_w.w_symbol->s_name[0]) ||
colatom->a_w.w_symbol->s_name[0] == '-'))
color = atoi(colatom->a_w.w_symbol->s_name);

/* symbolic color */
else return (iemgui_getcolorarg(0, 1, colatom));
if (color < 0)
{
color = -1 - color;
color = ((color & 0x3f000) << 6)|((color & 0xfc0) << 4)|
((color & 0x3f) << 2);
}
else
{
color = iemgui_modulo_color(color);
color = iemgui_color_hex[color];
}
return (color);
}

void iemgui_all_loadcolors(t_iemgui *iemgui, t_atom*bcol, t_atom*fcol, t_atom*lcol)
{
if(bcol)iemgui->x_bcol = colfromatomload(bcol);
if(fcol)iemgui->x_fcol = colfromatomload(fcol);
if(lcol)iemgui->x_lcol = colfromatomload(lcol);
}

int iemgui_compatible_colorarg(int index, int argc, t_atom* argv)
{
if (index < 0 || index >= argc)
return 0;
if(IS_A_FLOAT(argv,index))
{
int col=atom_getfloatarg(index, argc, argv);
if(col >= 0)
{
int idx = iemgui_modulo_color(col);
return(iemgui_color_hex[(idx)]);
}
else
return((-1 -col)&0xffffff);
}
return iemgui_getcolorarg(index, argc, argv);
}

void iemgui_all_dollar2raute(t_symbol **srlsym)
{
srlsym[0] = iemgui_dollar2raute(srlsym[0]);
srlsym[1] = iemgui_dollar2raute(srlsym[1]);
srlsym[2] = iemgui_dollar2raute(srlsym[2]);
}

void iemgui_all_raute2dollar(t_symbol **srlsym)
{
srlsym[0] = iemgui_raute2dollar(srlsym[0]);
srlsym[1] = iemgui_raute2dollar(srlsym[1]);
srlsym[2] = iemgui_raute2dollar(srlsym[2]);
}

void iemgui_send(void *x, t_iemgui *iemgui, t_symbol *s)
{
t_symbol *snd;
int pargc, tail_len, nth_arg, sndable=1, oldsndrcvable=0;
t_atom *pargv;

if(iemgui->x_fsf.x_rcv_able)
oldsndrcvable += IEM_GUI_OLD_RCV_FLAG;
if(iemgui->x_fsf.x_snd_able)
oldsndrcvable += IEM_GUI_OLD_SND_FLAG;

if(!strcmp(s->s_name, "empty")) sndable = 0;
snd = iemgui_raute2dollar(s);
iemgui->x_snd_unexpanded = snd;
iemgui->x_snd = snd = canvas_realizedollar(iemgui->x_glist, snd);
iemgui->x_fsf.x_snd_able = sndable;
iemgui_verify_snd_ne_rcv(iemgui);
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_IO + oldsndrcvable);
}

void iemgui_receive(void *x, t_iemgui *iemgui, t_symbol *s)
{
t_symbol *rcv;
int pargc, tail_len, nth_arg, rcvable=1, oldsndrcvable=0;
t_atom *pargv;

if(iemgui->x_fsf.x_rcv_able)
oldsndrcvable += IEM_GUI_OLD_RCV_FLAG;
if(iemgui->x_fsf.x_snd_able)
oldsndrcvable += IEM_GUI_OLD_SND_FLAG;

if(!strcmp(s->s_name, "empty")) rcvable = 0;
rcv = iemgui_raute2dollar(s);
iemgui->x_rcv_unexpanded = rcv;
rcv = canvas_realizedollar(iemgui->x_glist, rcv);
if(rcvable)
{
if(strcmp(rcv->s_name, iemgui->x_rcv->s_name))
{
if(iemgui->x_fsf.x_rcv_able)
pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv);
iemgui->x_rcv = rcv;
pd_bind(&iemgui->x_obj.ob_pd, iemgui->x_rcv);
}
}
else if(!rcvable && iemgui->x_fsf.x_rcv_able)
{
pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv);
iemgui->x_rcv = rcv;
}
iemgui->x_fsf.x_rcv_able = rcvable;
iemgui_verify_snd_ne_rcv(iemgui);
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_IO + oldsndrcvable);
}

void iemgui_label(void *x, t_iemgui *iemgui, t_symbol *s)
{
t_symbol *old;
int pargc, tail_len, nth_arg;
t_atom *pargv;

/* tb: fix for empty label { */
if (s == gensym(""))
s = gensym("empty");
/* tb } */

old = iemgui->x_lab;
iemgui->x_lab_unexpanded = iemgui_raute2dollar(s);
iemgui->x_lab = canvas_realizedollar(iemgui->x_glist, iemgui->x_lab_unexpanded);

if(glist_isvisible(iemgui->x_glist) && iemgui->x_lab != old)
sys_vgui(".x%lx.c itemconfigure %lxLABEL -text {%s} \n",
glist_getcanvas(iemgui->x_glist), x,
strcmp(s->s_name, "empty")?iemgui->x_lab->s_name:"");
}

void iemgui_label_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
{
int zoom = glist_getzoom(iemgui->x_glist);
iemgui->x_ldx = (int)atom_getfloatarg(0, ac, av);
iemgui->x_ldy = (int)atom_getfloatarg(1, ac, av);
if(glist_isvisible(iemgui->x_glist))
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
glist_getcanvas(iemgui->x_glist), x,
text_xpix((t_object *)x, iemgui->x_glist) + iemgui->x_ldx*zoom,
text_ypix((t_object *)x, iemgui->x_glist) + iemgui->x_ldy*zoom);
}

void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
{
int zoom = glist_getzoom(iemgui->x_glist);
int f = (int)atom_getfloatarg(0, ac, av);

if(f == 1) strcpy(iemgui->x_font, "helvetica");
else if(f == 2) strcpy(iemgui->x_font, "times");
else
{
f = 0;
strcpy(iemgui->x_font, sys_font);
}
iemgui->x_fsf.x_font_style = f;
f = (int)atom_getfloatarg(1, ac, av);
if(f < 4)
f = 4;
iemgui->x_fontsize = f;
if(glist_isvisible(iemgui->x_glist))
sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s}\n",
glist_getcanvas(iemgui->x_glist), x, iemgui->x_font,
iemgui->x_fontsize*zoom, sys_fontweight);
}

void iemgui_size(void *x, t_iemgui *iemgui)
{
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}

void iemgui_delta(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
{
int zoom = glist_getzoom(iemgui->x_glist);
iemgui->x_obj.te_xpix += (int)atom_getfloatarg(0, ac, av)*zoom;
iemgui->x_obj.te_ypix += (int)atom_getfloatarg(1, ac, av)*zoom;
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}

void iemgui_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
{
int zoom = glist_getzoom(iemgui->x_glist);
iemgui->x_obj.te_xpix = (int)atom_getfloatarg(0, ac, av)*zoom;
iemgui->x_obj.te_ypix = (int)atom_getfloatarg(1, ac, av)*zoom;
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}

void iemgui_color(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
{
if (ac >= 1)
iemgui->x_bcol = iemgui_compatible_colorarg(0, ac, av);
if (ac == 2 && pd_compatibilitylevel < 47)
/* old versions of Pd updated foreground and label color
if only two args; now we do it more coherently. */
iemgui->x_lcol = iemgui_compatible_colorarg(1, ac, av);
else if (ac >= 2)
iemgui->x_fcol = iemgui_compatible_colorarg(1, ac, av);
if (ac >= 3)
iemgui->x_lcol = iemgui_compatible_colorarg(2, ac, av);
if(glist_isvisible(iemgui->x_glist))
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_CONFIG);
}

void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy)
{
t_iemgui *x = (t_iemgui *)z;

x->x_obj.te_xpix += dx;
x->x_obj.te_ypix += dy;
(*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(glist, (t_text *)z);
}

void iemgui_select(t_gobj *z, t_glist *glist, int selected)
{
t_iemgui *x = (t_iemgui *)z;

x->x_fsf.x_selected = selected;
(*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_SELECT);
}

void iemgui_delete(t_gobj *z, t_glist *glist)
{
canvas_deletelinesfor(glist, (t_text *)z);
}

void iemgui_vis(t_gobj *z, t_glist *glist, int vis)
{
t_iemgui *x = (t_iemgui *)z;

if (vis)
(*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_NEW);
else
{
(*x->x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_ERASE);
sys_unqueuegui(z);
}
}

void iemgui_save(t_iemgui *iemgui, t_symbol **srl, t_symbol**bflcol)
{
srl[0] = iemgui->x_snd;
srl[1] = iemgui->x_rcv;
srl[2] = iemgui->x_lab;
iemgui_all_sym2dollararg(iemgui, srl);
iemgui_all_col2save(iemgui, bflcol);
}

/* inform GUIs that glist's zoom is about to change. The glist will
take care of x,y locations but we have to adjust width and height */
void iemgui_zoom(t_iemgui *iemgui, t_floatarg zoom)
{
int oldzoom = iemgui->x_glist->gl_zoom;
if (oldzoom < 1)
oldzoom = 1;
iemgui->x_w = (int)(iemgui->x_w)/oldzoom*(int)zoom;
iemgui->x_h = (int)(iemgui->x_h)/oldzoom*(int)zoom;
}

/* when creating a new GUI from menu onto a zoomed canvas, pretend to
change the canvas's zoom so we'll get properly sized */
void iemgui_newzoom(t_iemgui *iemgui)
{
if (iemgui->x_glist->gl_zoom != 1)
{
int newzoom = iemgui->x_glist->gl_zoom;
iemgui->x_glist->gl_zoom = 1;
iemgui_zoom(iemgui, (t_floatarg)newzoom);
iemgui->x_glist->gl_zoom = newzoom;
}
}

void iemgui_properties(t_iemgui *iemgui, t_symbol **srl)
{
srl[0] = iemgui->x_snd;
srl[1] = iemgui->x_rcv;
srl[2] = iemgui->x_lab;
iemgui_all_sym2dollararg(iemgui, srl);
iemgui_all_dollar2raute(srl);
}

int iemgui_dialog(t_iemgui *iemgui, t_symbol **srl, int argc, t_atom *argv)
{
char str[144];
int init = (int)atom_getfloatarg(5, argc, argv);
int ldx = (int)atom_getfloatarg(10, argc, argv);
int ldy = (int)atom_getfloatarg(11, argc, argv);
int f = (int)atom_getfloatarg(12, argc, argv);
int fs = (int)atom_getfloatarg(13, argc, argv);
int bcol = (int)iemgui_getcolorarg(14, argc, argv);
int fcol = (int)iemgui_getcolorarg(15, argc, argv);
int lcol = (int)iemgui_getcolorarg(16, argc, argv);
int sndable=1, rcvable=1, oldsndrcvable=0;

if(iemgui->x_fsf.x_rcv_able)
oldsndrcvable += IEM_GUI_OLD_RCV_FLAG;
if(iemgui->x_fsf.x_snd_able)
oldsndrcvable += IEM_GUI_OLD_SND_FLAG;
if(IS_A_SYMBOL(argv,7))
srl[0] = atom_getsymbolarg(7, argc, argv);
else if(IS_A_FLOAT(argv,7))
{
sprintf(str, "%d", (int)atom_getfloatarg(7, argc, argv));
srl[0] = gensym(str);
}
if(IS_A_SYMBOL(argv,8))
srl[1] = atom_getsymbolarg(8, argc, argv);
else if(IS_A_FLOAT(argv,8))
{
sprintf(str, "%d", (int)atom_getfloatarg(8, argc, argv));
srl[1] = gensym(str);
}
if(IS_A_SYMBOL(argv,9))
srl[2] = atom_getsymbolarg(9, argc, argv);
else if(IS_A_FLOAT(argv,9))
{
sprintf(str, "%d", (int)atom_getfloatarg(9, argc, argv));
srl[2] = gensym(str);
}
if(init != 0) init = 1;
iemgui->x_isa.x_loadinit = init;
if(!strcmp(srl[0]->s_name, "empty")) sndable = 0;
if(!strcmp(srl[1]->s_name, "empty")) rcvable = 0;
iemgui_all_raute2dollar(srl);
iemgui_all_dollararg2sym(iemgui, srl);
if(rcvable)
{
if(strcmp(srl[1]->s_name, iemgui->x_rcv->s_name))
{
if(iemgui->x_fsf.x_rcv_able)
pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv);
iemgui->x_rcv = srl[1];
pd_bind(&iemgui->x_obj.ob_pd, iemgui->x_rcv);
}
}
else if(!rcvable && iemgui->x_fsf.x_rcv_able)
{
pd_unbind(&iemgui->x_obj.ob_pd, iemgui->x_rcv);
iemgui->x_rcv = srl[1];
}
iemgui->x_snd = srl[0];
iemgui->x_fsf.x_snd_able = sndable;
iemgui->x_fsf.x_rcv_able = rcvable;
iemgui->x_lcol = lcol & 0xffffff;
iemgui->x_fcol = fcol & 0xffffff;
iemgui->x_bcol = bcol & 0xffffff;
iemgui->x_lab = srl[2];
iemgui->x_ldx = ldx;
iemgui->x_ldy = ldy;
if(f == 1) strcpy(iemgui->x_font, "helvetica");
else if(f == 2) strcpy(iemgui->x_font, "times");
else
{
f = 0;
strcpy(iemgui->x_font, sys_font);
}
iemgui->x_fsf.x_font_style = f;
if(fs < 4)
fs = 4;
iemgui->x_fontsize = fs;
iemgui_verify_snd_ne_rcv(iemgui);
canvas_dirty(iemgui->x_glist, 1);
return(oldsndrcvable);
}

/* pre-0.46 the flags were 1 for 'loadinit' and 1<<20 for 'scale'.
Starting in 0.46, take either 1<<20 or 1<<1 for 'scale' and save to both
bits (so that old versions can read files we write). In the future (2015?)
we can stop writing the annoying 1<<20 bit. */
#define LOADINIT 1
#define SCALE 2
#define SCALEBIS (1<<20)

void iem_inttosymargs(t_iem_init_symargs *symargp, int n)
{
memset(symargp, 0, sizeof(*symargp));
symargp->x_loadinit = ((n & LOADINIT) != 0);
symargp->x_scale = ((n & SCALE) || (n & SCALEBIS)) ;
symargp->x_flashed = 0;
symargp->x_locked = 0;
}

int iem_symargstoint(t_iem_init_symargs *symargp)
{
return ((symargp->x_loadinit ? LOADINIT : 0) |
(symargp->x_scale ? (SCALE | SCALEBIS) : 0));
}

void iem_inttofstyle(t_iem_fstyle_flags *fstylep, int n)
{
memset(fstylep, 0, sizeof(*fstylep));
fstylep->x_font_style = (n >> 0);
fstylep->x_shiftdown = 0;
fstylep->x_selected = 0;
fstylep->x_finemoved = 0;
fstylep->x_put_in2out = 0;
fstylep->x_change = 0;
fstylep->x_thick = 0;
fstylep->x_lin0_log1 = 0;
fstylep->x_steady = 0;
}

int iem_fstyletoint(t_iem_fstyle_flags *fstylep)
{
return ((fstylep->x_font_style << 0) & 63);
}

/* for compatibility with pre-0.47 unofficial IEM GUIS like "knob". */
void iemgui_all_colfromload(t_iemgui *iemgui, int *bflcol)
{
static int warned;
if (!warned)
{
post("warning:\
external GUI object uses obsolete Pd function iemgui_all_colfromload()");
warned = 1;
}
if(bflcol[0] < 0)
{
bflcol[0] = -1 - bflcol[0];
iemgui->x_bcol = ((bflcol[0] & 0x3f000) << 6)|((bflcol[0] & 0xfc0) << 4)|
((bflcol[0] & 0x3f) << 2);
}
else
{
bflcol[0] = iemgui_modulo_color(bflcol[0]);
iemgui->x_bcol = iemgui_color_hex[bflcol[0]];
}
if(bflcol[1] < 0)
{
bflcol[1] = -1 - bflcol[1];
iemgui->x_fcol = ((bflcol[1] & 0x3f000) << 6)|((bflcol[1] & 0xfc0) << 4)|
((bflcol[1] & 0x3f) << 2);
}
else
{
bflcol[1] = iemgui_modulo_color(bflcol[1]);
iemgui->x_fcol = iemgui_color_hex[bflcol[1]];
}
if(bflcol[2] < 0)
{
bflcol[2] = -1 - bflcol[2];
iemgui->x_lcol = ((bflcol[2] & 0x3f000) << 6)|((bflcol[2] & 0xfc0) << 4)|
((bflcol[2] & 0x3f) << 2);
}
else
{
bflcol[2] = iemgui_modulo_color(bflcol[2]);
iemgui->x_lcol = iemgui_color_hex[bflcol[2]];
}
}


+ 324
- 0
ports/camomile/source/LibPd/pure-data/src/g_all_guis.h View File

@@ -0,0 +1,324 @@
/* 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. */
/* g_7_guis.h written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */

#define IEM_GUI_COLNR_WHITE 0
#define IEM_GUI_COLNR_ML_GREY 1
#define IEM_GUI_COLNR_D_GREY 2
#define IEM_GUI_COLNR_L_RED 3
#define IEM_GUI_COLNR_L_ORANGE 4
#define IEM_GUI_COLNR_L_YELLOW 5
#define IEM_GUI_COLNR_L_GREEN 6
#define IEM_GUI_COLNR_L_CYAN 7
#define IEM_GUI_COLNR_L_BLUE 8
#define IEM_GUI_COLNR_L_MAGENTA 9

#define IEM_GUI_COLNR_LL_GREY 10
#define IEM_GUI_COLNR_M_GREY 11
#define IEM_GUI_COLNR_DD_GREY 12
#define IEM_GUI_COLNR_RED 13
#define IEM_GUI_COLNR_ORANGE 14
#define IEM_GUI_COLNR_YELLOW 15
#define IEM_GUI_COLNR_GREEN 16
#define IEM_GUI_COLNR_CYAN 17
#define IEM_GUI_COLNR_BLUE 18
#define IEM_GUI_COLNR_MAGENTA 19

#define IEM_GUI_COLNR_L_GREY 20
#define IEM_GUI_COLNR_MD_GREY 21
#define IEM_GUI_COLNR_BLACK 22
#define IEM_GUI_COLNR_D_RED 23
#define IEM_GUI_COLNR_D_ORANGE 24
#define IEM_GUI_COLNR_D_YELLOW 25
#define IEM_GUI_COLNR_D_GREEN 26
#define IEM_GUI_COLNR_D_CYAN 27
#define IEM_GUI_COLNR_D_BLUE 28
#define IEM_GUI_COLNR_D_MAGENTA 29

#define IEM_GUI_COLOR_SELECTED 255
#define IEM_GUI_COLOR_NORMAL 0

#define IEM_GUI_MAX_COLOR 30

#define IEM_GUI_DEFAULTSIZE 15
#define IEM_GUI_MINSIZE 8
#define IEM_GUI_MAXSIZE 1000
#define IEM_SL_DEFAULTSIZE 128
#define IEM_SL_MINSIZE 2
#define IEM_FONT_MINSIZE 4

#define IEM_BNG_DEFAULTHOLDFLASHTIME 250
#define IEM_BNG_DEFAULTBREAKFLASHTIME 50
#define IEM_BNG_MINHOLDFLASHTIME 50
#define IEM_BNG_MINBREAKFLASHTIME 10

#define IEM_VU_DEFAULTSIZE 3
#define IEM_VU_LARGESMALL 2
#define IEM_VU_MINSIZE 2
#define IEM_VU_MAXSIZE 25
#define IEM_VU_STEPS 40

#define IEM_VU_MINDB -99.9
#define IEM_VU_MAXDB 12.0
#define IEM_VU_OFFSET 100.0

#define IEM_RADIO_MAX 128

#define IEM_SYM_UNIQUE_SND 256
#define IEM_SYM_UNIQUE_RCV 512
#define IEM_SYM_UNIQUE_LAB 1024
#define IEM_SYM_UNIQUE_ALL 1792
#define IEM_FONT_STYLE_ALL 255

#define IEM_MAX_SYM_LEN 127

#define IEM_GUI_DRAW_MODE_UPDATE 0
#define IEM_GUI_DRAW_MODE_MOVE 1
#define IEM_GUI_DRAW_MODE_NEW 2
#define IEM_GUI_DRAW_MODE_SELECT 3
#define IEM_GUI_DRAW_MODE_ERASE 4
#define IEM_GUI_DRAW_MODE_CONFIG 5
#define IEM_GUI_DRAW_MODE_IO 6

#define IEM_GUI_IOHEIGHT 2

#define IS_A_POINTER(atom,index) ((atom+index)->a_type == A_POINTER)
#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT)
#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL)
#define IS_A_DOLLAR(atom,index) ((atom+index)->a_type == A_DOLLAR)
#define IS_A_DOLLSYM(atom,index) ((atom+index)->a_type == A_DOLLSYM)

#define IEM_FSTYLE_FLAGS_ALL 0x007fffff
#define IEM_INIT_ARGS_ALL 0x01ffffff

#define IEM_GUI_OLD_SND_FLAG 1
#define IEM_GUI_OLD_RCV_FLAG 2

#define IEM_GUI_COLOR_EDITED 16711680
#define IEMGUI_MAX_NUM_LEN 32

#define IEMGUI_ZOOM(x) ((x)->x_gui.x_glist->gl_zoom)

typedef struct _iem_fstyle_flags
{
unsigned int x_font_style:6;
unsigned int x_rcv_able:1;
unsigned int x_snd_able:1;
unsigned int x_lab_is_unique:1;
unsigned int x_rcv_is_unique:1;
unsigned int x_snd_is_unique:1;
unsigned int x_lab_arg_tail_len:6;
unsigned int x_lab_is_arg_num:6;
unsigned int x_shiftdown:1;
unsigned int x_selected:1;
unsigned int x_finemoved:1;
unsigned int x_put_in2out:1;
unsigned int x_change:1;
unsigned int x_thick:1;
unsigned int x_lin0_log1:1;
unsigned int x_steady:1;
} t_iem_fstyle_flags;

typedef struct _iem_init_symargs
{
unsigned int x_loadinit:1;
unsigned int x_rcv_arg_tail_len:6;
unsigned int x_snd_arg_tail_len:6;
unsigned int x_rcv_is_arg_num:6;
unsigned int x_snd_is_arg_num:6;
unsigned int x_scale:1;
unsigned int x_flashed:1;
unsigned int x_locked:1;
} t_iem_init_symargs;

typedef void (*t_iemfunptr)(void *x, t_glist *glist, int mode);

typedef struct _iemgui
{
t_object x_obj;
t_glist *x_glist;
t_iemfunptr x_draw;
int x_h;
int x_w;
int x_ldx;
int x_ldy;
char x_font[MAXPDSTRING]; /* font names can be long! */
t_iem_fstyle_flags x_fsf;
int x_fontsize;
t_iem_init_symargs x_isa;
int x_fcol;
int x_bcol;
int x_lcol;
t_symbol *x_snd; /* send symbol */
t_symbol *x_rcv; /* receive */
t_symbol *x_lab; /* label */
t_symbol *x_snd_unexpanded; /* same 3, with '$' unexpanded */
t_symbol *x_rcv_unexpanded;
t_symbol *x_lab_unexpanded;
int x_binbufindex; /* where in binbuf to find these */
int x_labelbindex; /* where in binbuf to find label */
} t_iemgui;

typedef struct _bng
{
t_iemgui x_gui;
int x_flashed;
int x_flashtime_break;
int x_flashtime_hold;
t_clock *x_clock_hld;
t_clock *x_clock_brk;
t_clock *x_clock_lck;
double x_lastflashtime;
} t_bng;

typedef struct _hslider
{
t_iemgui x_gui;
int x_pos;
int x_val;
int x_lin0_log1;
int x_steady;
double x_min;
double x_max;
double x_k;
t_float x_fval;
} t_hslider;

typedef struct _hdial
{
t_iemgui x_gui;
int x_on;
int x_on_old; /* LATER delete this; it's used for old version */
int x_change;
int x_number;
int x_drawn;
t_float x_fval;
t_atom x_at[2];
} t_hdial;

typedef struct _toggle
{
t_iemgui x_gui;
t_float x_on;
t_float x_nonzero;
} t_toggle;

typedef struct _my_canvas
{
t_iemgui x_gui;
t_atom x_at[3];
int x_vis_w;
int x_vis_h;
} t_my_canvas;

typedef struct _vslider
{
t_iemgui x_gui;
int x_pos;
int x_val;
int x_lin0_log1;
int x_steady;
double x_min;
double x_max;
double x_k;
t_float x_fval;
} t_vslider;

typedef struct _vu
{
t_iemgui x_gui;
int x_led_size;
int x_peak;
int x_rms;
t_float x_fp;
t_float x_fr;
int x_scale;
void *x_out_rms;
void *x_out_peak;
unsigned int x_updaterms:1;
unsigned int x_updatepeak:1;
} t_vu;

typedef struct _my_numbox
{
t_iemgui x_gui;
t_clock *x_clock_reset;
t_clock *x_clock_wait;
double x_val;
double x_min;
double x_max;
double x_k;
int x_lin0_log1;
char x_buf[IEMGUI_MAX_NUM_LEN];
int x_numwidth;
int x_log_height;
} t_my_numbox;

typedef struct _vdial
{
t_iemgui x_gui;
int x_on;
int x_on_old;
int x_change;
int x_number;
int x_drawn;
t_float x_fval;
t_atom x_at[2];
} t_vdial;

#define t_vradio t_vdial
#define t_hradio t_hdial

extern int iemgui_color_hex[];
extern int iemgui_vu_db2i[];
extern int iemgui_vu_col[];
extern char *iemgui_vu_scale_str[];

EXTERN int iemgui_clip_size(int size);
EXTERN int iemgui_clip_font(int size);
EXTERN t_symbol *iemgui_unique2dollarzero(t_symbol *s, int unique_num, int and_unique_flag);
EXTERN t_symbol *iemgui_sym2dollararg(t_symbol *s, int nth_arg, int tail_len);
EXTERN t_symbol *iemgui_dollarzero2unique(t_symbol *s, int unique_num);
EXTERN t_symbol *iemgui_dollararg2sym(t_symbol *s, int nth_arg, int tail_len, int pargc, t_atom *pargv);
EXTERN int iemgui_is_dollarzero(t_symbol *s);
EXTERN int iemgui_is_dollararg(t_symbol *s, int *tail_len);
EXTERN void iemgui_fetch_unique(t_iemgui *iemgui);
EXTERN void iemgui_fetch_parent_args(t_iemgui *iemgui, int *pargc, t_atom **pargv);
EXTERN void iemgui_verify_snd_ne_rcv(t_iemgui *iemgui);
EXTERN void iemgui_all_unique2dollarzero(t_iemgui *iemgui, t_symbol **srlsym);
EXTERN void iemgui_all_sym2dollararg(t_iemgui *iemgui, t_symbol **srlsym);
EXTERN void iemgui_all_dollarzero2unique(t_iemgui *iemgui, t_symbol **srlsym);
EXTERN t_symbol *iemgui_new_dogetname(t_iemgui *iemgui, int indx, t_atom *argv);
EXTERN void iemgui_new_getnames(t_iemgui *iemgui, int indx, t_atom *argv);
EXTERN void iemgui_all_dollararg2sym(t_iemgui *iemgui, t_symbol **srlsym);
EXTERN void iemgui_all_loadcolors(t_iemgui *iemgui, t_atom*bcol, t_atom*fcol, t_atom*lcol);
EXTERN void iemgui_all_dollar2raute(t_symbol **srlsym);
EXTERN void iemgui_all_raute2dollar(t_symbol **srlsym);
EXTERN void iemgui_send(void *x, t_iemgui *iemgui, t_symbol *s);
EXTERN void iemgui_receive(void *x, t_iemgui *iemgui, t_symbol *s);
EXTERN void iemgui_label(void *x, t_iemgui *iemgui, t_symbol *s);
EXTERN void iemgui_label_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av);
EXTERN void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av);
EXTERN void iemgui_size(void *x, t_iemgui *iemgui);
EXTERN void iemgui_delta(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av);
EXTERN void iemgui_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av);
EXTERN void iemgui_color(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av);
EXTERN int iemgui_list(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av);
EXTERN void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy);
EXTERN void iemgui_select(t_gobj *z, t_glist *glist, int selected);
EXTERN void iemgui_delete(t_gobj *z, t_glist *glist);
EXTERN void iemgui_vis(t_gobj *z, t_glist *glist, int vis);
EXTERN void iemgui_save(t_iemgui *iemgui, t_symbol **srl, t_symbol **bflcol);
EXTERN void iemgui_zoom(t_iemgui *iemgui, t_floatarg zoom);
EXTERN void iemgui_newzoom(t_iemgui *iemgui);
EXTERN void iemgui_properties(t_iemgui *iemgui, t_symbol **srl);
EXTERN int iemgui_dialog(t_iemgui *iemgui, t_symbol **srl, int argc, t_atom *argv);

EXTERN int canvas_getdollarzero(void);
EXTERN void canvas_getargs(int *argcp, t_atom **argvp);

EXTERN void iem_inttosymargs(t_iem_init_symargs *symargp, int n);
EXTERN int iem_symargstoint(t_iem_init_symargs *symargp);
EXTERN void iem_inttofstyle(t_iem_fstyle_flags *fstylep, int n);
EXTERN int iem_fstyletoint(t_iem_fstyle_flags *fstylep);

+ 1252
- 0
ports/camomile/source/LibPd/pure-data/src/g_array.c
File diff suppressed because it is too large
View File


+ 578
- 0
ports/camomile/source/LibPd/pure-data/src/g_bang.c View File

@@ -0,0 +1,578 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

/* --------------- bng gui-bang ------------------------- */

t_widgetbehavior bng_widgetbehavior;
static t_class *bng_class;

/* widget helper functions */

void bng_draw_update(t_bng *x, t_glist *glist)
{
if(glist_isvisible(glist))
{
sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n",
glist_getcanvas(glist), x,
(x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol));
}
}

void bng_draw_new(t_bng *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int inset = IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%6.6x -tags %lxBASE\n",
canvas, xpos, ypos,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h,
IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create oval %d %d %d %d -width %d -fill #%6.6x -tags %lxBUT\n",
canvas, xpos + inset, ypos + inset,
xpos + x->x_gui.x_w - inset, ypos + x->x_gui.x_h - inset,
IEMGUI_ZOOM(x),
(x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol), x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

void bng_draw_move(t_bng *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int inset = IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x, xpos, ypos,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxBUT %d %d %d %d\n",
canvas, x, xpos + inset, ypos + inset,
xpos + x->x_gui.x_w - inset, ypos + x->x_gui.x_h - inset);
sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", canvas, x,
(x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol));
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
}

void bng_draw_erase(t_bng* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x);
sys_vgui(".x%lx.c delete %lxBUT\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void bng_draw_config(t_bng* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%6.6x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""));
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\n", canvas, x, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", canvas, x,
(x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol));
}

void bng_draw_io(t_bng* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) {
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
/* keep above outlet */
sys_vgui(".x%lx.c raise %lxLABEL %lxOUT%d\n", canvas, x, x, 0);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) {
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep above inlet */
sys_vgui(".x%lx.c raise %lxLABEL %lxIN%d\n", canvas, x, x, 0);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void bng_draw_select(t_bng* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxBUT -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxBUT -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n", canvas, x, x->x_gui.x_lcol);
}
}

void bng_draw(t_bng *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
bng_draw_update(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
bng_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
bng_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
bng_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
bng_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
bng_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
bng_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ bng widgetbehaviour----------------------------- */

static void bng_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_bng *x = (t_bng *)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h;
}

static void bng_save(t_gobj *z, t_binbuf *b)
{
t_bng *x = (t_bng *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiiisssiiiisss", gensym("#X"),gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("bng"), x->x_gui.x_w/IEMGUI_ZOOM(x),
x->x_flashtime_hold, x->x_flashtime_break,
iem_symargstoint(&x->x_gui.x_isa),
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2]);
binbuf_addv(b, ";");
}

void bng_check_minmax(t_bng *x, int ftbreak, int fthold)
{
if(ftbreak > fthold)
{
int h;

h = ftbreak;
ftbreak = fthold;
fthold = h;
}
if(ftbreak < IEM_BNG_MINBREAKFLASHTIME)
ftbreak = IEM_BNG_MINBREAKFLASHTIME;
if(fthold < IEM_BNG_MINHOLDFLASHTIME)
fthold = IEM_BNG_MINHOLDFLASHTIME;
x->x_flashtime_break = ftbreak;
x->x_flashtime_hold = fthold;
}

static void bng_properties(t_gobj *z, t_glist *owner)
{
t_bng *x = (t_bng *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);
sprintf(buf, "pdtk_iemgui_dialog %%s |bang| \
----------dimensions(pix):----------- %d %d size: 0 0 empty \
--------flash-time(ms)(ms):--------- %d intrrpt: %d hold: %d \
%d empty empty %d %d empty %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
x->x_flashtime_break, x->x_flashtime_hold, 2,/*min_max_schedule+clip*/
-1, x->x_gui.x_isa.x_loadinit, -1, -1,/*no linlog, no multi*/
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void bng_set(t_bng *x)
{
int holdtime = x->x_flashtime_hold;
int sincelast = clock_gettimesince(x->x_lastflashtime);
x->x_lastflashtime = clock_getsystime();
if (sincelast < x->x_flashtime_hold*2)
holdtime = sincelast/2;
if (holdtime < x->x_flashtime_break)
holdtime = x->x_flashtime_break;
x->x_flashed = 1;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
clock_delay(x->x_clock_hld, holdtime);
}

static void bng_bout1(t_bng *x) /*wird nur mehr gesendet, wenn snd != rcv*/
{
if(!x->x_gui.x_fsf.x_put_in2out)
{
x->x_gui.x_isa.x_locked = 1;
clock_delay(x->x_clock_lck, 2);
}
outlet_bang(x->x_gui.x_obj.ob_outlet);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing && x->x_gui.x_fsf.x_put_in2out)
pd_bang(x->x_gui.x_snd->s_thing);
}

static void bng_bout2(t_bng *x) /*wird immer gesendet, wenn moeglich*/
{
if(!x->x_gui.x_fsf.x_put_in2out)
{
x->x_gui.x_isa.x_locked = 1;
clock_delay(x->x_clock_lck, 2);
}
outlet_bang(x->x_gui.x_obj.ob_outlet);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_bang(x->x_gui.x_snd->s_thing);
}

static void bng_bang(t_bng *x) /*wird nur mehr gesendet, wenn snd != rcv*/
{
if(!x->x_gui.x_isa.x_locked)
{
bng_set(x);
bng_bout1(x);
}
}

static void bng_bang2(t_bng *x) /*wird immer gesendet, wenn moeglich*/
{
if(!x->x_gui.x_isa.x_locked)
{
bng_set(x);
bng_bout2(x);
}
}

static void bng_dialog(t_bng *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int a = (int)atom_getfloatarg(0, argc, argv);
int fthold = (int)atom_getfloatarg(2, argc, argv);
int ftbreak = (int)atom_getfloatarg(3, argc, argv);
int sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);

x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
bng_check_minmax(x, ftbreak, fthold);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

static void bng_click(t_bng *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
bng_set(x);
bng_bout2(x);
}

static int bng_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
if(doit)
bng_click((t_bng *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt);
return (1);
}

static void bng_float(t_bng *x, t_floatarg f)
{bng_bang2(x);}

static void bng_symbol(t_bng *x, t_symbol *s)
{bng_bang2(x);}

static void bng_pointer(t_bng *x, t_gpointer *gp)
{bng_bang2(x);}

static void bng_list(t_bng *x, t_symbol *s, int ac, t_atom *av)
{bng_bang2(x);}

static void bng_anything(t_bng *x, t_symbol *s, int argc, t_atom *argv)
{bng_bang2(x);}

static void bng_loadbang(t_bng *x, t_floatarg action)
{
if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
{
bng_set(x);
bng_bout2(x);
}
}

static void bng_size(t_bng *x, t_symbol *s, int ac, t_atom *av)
{
x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_size((void *)x, &x->x_gui);
}

static void bng_delta(t_bng *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void bng_pos(t_bng *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void bng_flashtime(t_bng *x, t_symbol *s, int ac, t_atom *av)
{
bng_check_minmax(x, (int)atom_getfloatarg(0, ac, av),
(int)atom_getfloatarg(1, ac, av));
}

static void bng_color(t_bng *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void bng_send(t_bng *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void bng_receive(t_bng *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void bng_label(t_bng *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void bng_label_pos(t_bng *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void bng_label_font(t_bng *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void bng_init(t_bng *x, t_floatarg f)
{
x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;
}

static void bng_tick_hld(t_bng *x)
{
x->x_flashed = 0;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}

static void bng_tick_lck(t_bng *x)
{
x->x_gui.x_isa.x_locked = 0;
}

static void *bng_new(t_symbol *s, int argc, t_atom *argv)
{
t_bng *x = (t_bng *)pd_new(bng_class);
int a = IEM_GUI_DEFAULTSIZE;
int ldx = 17, ldy = 7;
int fs = 10;
int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME,
fthold = IEM_BNG_DEFAULTHOLDFLASHTIME;
char str[144];

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if((argc == 14)&&IS_A_FLOAT(argv,0)
&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2)
&&IS_A_FLOAT(argv,3)
&&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4))
&&(IS_A_SYMBOL(argv,5)||IS_A_FLOAT(argv,5))
&&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
&&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8)
&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10))
{

a = (int)atom_getfloatarg(0, argc, argv);
fthold = (int)atom_getfloatarg(1, argc, argv);
ftbreak = (int)atom_getfloatarg(2, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(3, argc, argv));
iemgui_new_getnames(&x->x_gui, 4, argv);
ldx = (int)atom_getfloatarg(7, argc, argv);
ldy = (int)atom_getfloatarg(8, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(9, argc, argv));
fs = (int)atom_getfloatarg(10, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+11, argv+12, argv+13);
}
else iemgui_new_getnames(&x->x_gui, 4, 0);

x->x_gui.x_draw = (t_iemfunptr)bng_draw;

x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_flashed = 0;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if (!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if (!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }

if (x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;

if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_w = iemgui_clip_size(a);
x->x_gui.x_h = x->x_gui.x_w;
bng_check_minmax(x, ftbreak, fthold);
x->x_gui.x_isa.x_locked = 0;
iemgui_verify_snd_ne_rcv(&x->x_gui);
x->x_lastflashtime = clock_getsystime();
x->x_clock_hld = clock_new(x, (t_method)bng_tick_hld);
x->x_clock_lck = clock_new(x, (t_method)bng_tick_lck);
iemgui_newzoom(&x->x_gui);
outlet_new(&x->x_gui.x_obj, &s_bang);
return (x);
}

static void bng_ff(t_bng *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
clock_free(x->x_clock_lck);
clock_free(x->x_clock_hld);
gfxstub_deleteforkey(x);
}

void g_bang_setup(void)
{
bng_class = class_new(gensym("bng"), (t_newmethod)bng_new,
(t_method)bng_ff, sizeof(t_bng), 0, A_GIMME, 0);
class_addbang(bng_class, bng_bang);
class_addfloat(bng_class, bng_float);
class_addsymbol(bng_class, bng_symbol);
class_addpointer(bng_class, bng_pointer);
class_addlist(bng_class, bng_list);
class_addanything(bng_class, bng_anything);
class_addmethod(bng_class, (t_method)bng_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(bng_class, (t_method)bng_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(bng_class, (t_method)bng_size,
gensym("size"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_flashtime,
gensym("flashtime"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_color,
gensym("color"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(bng_class, (t_method)bng_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(bng_class, (t_method)bng_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(bng_class, (t_method)bng_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(bng_class, (t_method)bng_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(bng_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
bng_widgetbehavior.w_getrectfn = bng_getrect;
bng_widgetbehavior.w_displacefn = iemgui_displace;
bng_widgetbehavior.w_selectfn = iemgui_select;
bng_widgetbehavior.w_activatefn = NULL;
bng_widgetbehavior.w_deletefn = iemgui_delete;
bng_widgetbehavior.w_visfn = iemgui_vis;
bng_widgetbehavior.w_clickfn = bng_newclick;
class_setwidget(bng_class, &bng_widgetbehavior);
class_sethelpsymbol(bng_class, gensym("bng"));
class_setsavefn(bng_class, bng_save);
class_setpropertiesfn(bng_class, bng_properties);
}

+ 1845
- 0
ports/camomile/source/LibPd/pure-data/src/g_canvas.c
File diff suppressed because it is too large
View File


+ 663
- 0
ports/camomile/source/LibPd/pure-data/src/g_canvas.h View File

@@ -0,0 +1,663 @@
/* 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", also called "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. */

#ifndef G_CANVAS_H
#define G_CANVAS_H

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
extern "C" {
#endif

/* --------------------- geometry ---------------------------- */
#define IOWIDTH 7 /* width of an inlet/outlet in pixels */
#define IHEIGHT 3 /* height of an inlet in pixels */
#define OHEIGHT 3 /* height of an 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

EXTERN_STRUCT _fielddesc;
#define t_fielddesc struct _fielddesc

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_clock *e_clock; /* clock to filter GUI move messages */
int e_xnew; /* xpos for next move event */
int e_ynew; /* ypos, similarly */
} t_editor;

#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
#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 */
#define MA_RESIZE 6 /* drag to resize */

/* 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 */
{
t_float k_point; /* one point to draw a big tick at */
t_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;
t_float gl_x1; /* bounding rectangle in our own coordinates */
t_float gl_y1;
t_float gl_x2;
t_float gl_y2;
int gl_screenx1; /* screen coordinates when toplevel */
int gl_screeny1;
int gl_screenx2;
int gl_screeny2;
int gl_xmargin; /* origin for GOP rectangle */
int gl_ymargin;
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 */
t_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;
t_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_goprect:1; /* draw rectangle for graph-on-parent */
unsigned int gl_isgraph:1; /* show as graph on parent */
unsigned int gl_hidetext:1; /* hide object-name + args when doing graph on parent */
unsigned int gl_private:1; /* private flag used in x_scalar.c */
unsigned int gl_isclone:1; /* exists as part of a clone object */
int gl_zoom; /* zoom factor (integer zoom-in only) */
};

#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_TEXT 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;

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; /* stub for pointing into this array */
};

/* 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;

struct _instancecanvas
{
struct _instanceeditor *i_editor;
struct _instancetemplate *i_template;
t_symbol *i_newfilename;
t_symbol *i_newdirectory;
int i_newargc;
t_atom *i_newargv;
t_glist *i_reloadingabstraction;
int i_dspstate;
int i_dollarzero;
t_float i_graph_lastxpix, i_graph_lastypix;
};

void g_editor_newpdinstance( void);
void g_template_newpdinstance( void);
void g_editor_freepdinstance( void);
void g_template_freepdinstance( void);

#define THISGUI (pd_this->pd_gui)
#define EDITOR (pd_this->pd_gui->i_editor)
#define TEMPLATE (pd_this->pd_gui->i_template)

/* 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, t_float basex, t_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, t_float basex, t_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, t_float basex, t_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, t_float basex, t_float basey,
int state);
/* making visible or invisible */
typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist,
t_word *data, t_template *tmpl, t_float basex, t_float basey,
int flag);
/* field a mouse click */
typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist,
t_word *data, t_template *tmpl, t_scalar *sc, t_array *ap,
t_float basex, t_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
#define CURSOR_EDITMODE_RESIZE 7
EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);

extern t_canvas *canvas_whichfind; /* last canvas we did a find in */
extern t_class *vinlet_class, *voutlet_class;
extern int glist_valid; /* incremented when pointers might be stale */

#define PLOTSTYLE_POINTS 0 /* plotting styles for arrays */
#define PLOTSTYLE_POLY 1
#define PLOTSTYLE_BEZ 2

/* ------------------- 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 int gobj_shouldvis(t_gobj *x, struct _glist *glist);

/* -------------------- 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_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 int glist_fontwidth(t_glist *x);
EXTERN int glist_fontheight(t_glist *x);
EXTERN int glist_getzoom(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 t_float glist_pixelstox(t_glist *x, t_float xpix);
EXTERN t_float glist_pixelstoy(t_glist *x, t_float ypix);
EXTERN t_float glist_xtopixels(t_glist *x, t_float xval);
EXTERN t_float glist_ytopixels(t_glist *x, t_float yval);
EXTERN t_float glist_dpixtodx(t_glist *x, t_float dxpix);
EXTERN t_float glist_dpixtody(t_glist *x, t_float dypix);

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,
t_float x1, t_float y1, t_float x2, t_float y2,
t_float px1, t_float py1, t_float px2, t_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);
EXTERN void canvas_destroy_editor(t_glist *x);
void canvas_deletelinesforio(t_canvas *x, t_text *text,
t_inlet *inp, t_outlet *outp);
extern int glist_amreloadingabstractions; /* stop GUI changes while reloading */

/* -------------------- 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_xpix(t_text *x, t_glist *glist);
EXTERN int text_ypix(t_text *x, t_glist *glist);
extern const t_widgetbehavior text_widgetbehavior;

/* -------------------- 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 char *rtext_gettag(t_rtext *x);
EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
EXTERN void rtext_getseltext(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 void canvas_closebang(t_canvas *x);
EXTERN void canvas_initbang(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_template *tmpl, int action);
EXTERN void canvas_redrawallfortemplatecanvas(t_canvas *x, int action);
EXTERN void canvas_zapallfortemplate(t_canvas *tmpl);
EXTERN void canvas_setusedastemplate(t_canvas *x);
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_floatarg 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 state);
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);

#define LB_LOAD 0 /* "loadbang" actions - 0 for original meaning */
#define LB_INIT 1 /* loaded but not yet connected to parent patch */
#define LB_CLOSE 2 /* about to close */

/* Pointer to canvas that was saved necessitating a reload of abstractions
of that name. We use as a flag to stop canvases from being marked "dirty"
if we have to touch them to reload; also suppress window list update.
"clone~" uses this to identify which copy NOT to reload */
EXTERN t_glist *glist_reloadingabstraction;

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);

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,
t_float index1, t_float outno, t_float index2, t_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);

EXTERN t_glist *pd_checkglist(t_pd *x);
typedef int (*t_canvas_path_iterator)(const char *path, void *user_data);
EXTERN int canvas_path_iterate(t_canvas *x, t_canvas_path_iterator fun,
void *user_data);

/* ---- 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 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, int n);
EXTERN void array_free(t_array *x);
EXTERN void array_redraw(t_array *a, t_glist *glist);
EXTERN void array_resize_and_redraw(t_array *array, t_glist *glist, int n);

/* --------------------- 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);
EXTERN void gpointer_setarray(t_gpointer *gp, t_array *array, t_word *w);

/* --------------------- 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 word_free(t_word *wp, t_template *tmpl);
EXTERN void scalar_getbasexy(t_scalar *x, t_float *basex, t_float *basey);
EXTERN void scalar_redraw(t_scalar *x, t_glist *glist);
EXTERN void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
int amarrayelement);
EXTERN int canvas_readscalar(t_glist *x, int natoms, t_atom *vec,
int *p_nextmsg, int selectit);

/* ------helper routines for "garrays" and "plots" -------------- */
EXTERN void array_getcoordinate(t_glist *glist,
char *elem, int xonset, int yonset, int wonset, int indx,
t_float basex, t_float basey, t_float xinc,
t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
t_float *xp, t_float *yp, t_float *wp);

EXTERN int array_getfields(t_symbol *elemtemplatesym,
t_canvas **elemtemplatecanvasp,
t_template **elemtemplatep, int *elemsizep,
t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
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 void template_notify(t_template *tmpl,
t_symbol *s, int argc, t_atom *argv);

EXTERN t_float fielddesc_getcoord(t_fielddesc *f, t_template *tmpl,
t_word *wp, int loud);
EXTERN void fielddesc_setcoord(t_fielddesc *f, t_template *tmpl,
t_word *wp, t_float pix, int loud);
EXTERN t_float fielddesc_cvttocoord(t_fielddesc *f, t_float val);
EXTERN t_float fielddesc_cvtfromcoord(t_fielddesc *f, t_float coord);


/* ----------------------- 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);

/*------------- g_clone.c ------------- */
extern t_class *clone_class;

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif

#endif // G_CANVAS_H

+ 464
- 0
ports/camomile/source/LibPd/pure-data/src/g_clone.c View File

@@ -0,0 +1,464 @@
#include "m_pd.h"
#include "g_canvas.h"
#include "m_imp.h"
#include <string.h>

/* ---------- clone - maintain copies of a patch ----------------- */
/* OOPS - have to add outlet vector to each copy to disambiguate */
/* next: feed each instance its serial number */
/* next next: DSP method */


#ifdef _WIN32
# include <malloc.h> /* MSVC or mingw on windows */
#elif defined(__linux__) || defined(__APPLE__)
# include <alloca.h> /* linux, mac, mingw, cygwin */
#else
# include <stdlib.h> /* BSDs for example */
#endif
#define LIST_NGETBYTE 100 /* bigger that this we use alloc, not alloca */

#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ? \
alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom))))
#define ATOMS_FREEA(x, n) ( \
((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0)))

t_class *clone_class;
static t_class *clone_in_class, *clone_out_class;

typedef struct _copy
{
t_glist *c_gl;
int c_on; /* DSP running */
} t_copy;

typedef struct _in
{
t_class *i_pd;
struct _clone *i_owner;
int i_signal;
int i_n;
} t_in;

typedef struct _out
{
t_class *o_pd;
t_outlet *o_outlet;
int o_signal;
int o_n;
} t_out;

typedef struct _clone
{
t_object x_obj;
int x_n; /* number of copies */
t_copy *x_vec; /* the copies */
int x_nin;
t_in *x_invec;
int x_nout;
t_out **x_outvec;
t_symbol *x_s; /* name of abstraction */
int x_argc; /* creation arguments for abstractions */
t_atom *x_argv;
int x_phase;
int x_startvoice; /* number of first voice, 0 by default */
int x_suppressvoice; /* suppress voice number as $1 arg */
} t_clone;

int clone_match(t_pd *z, t_symbol *name, t_symbol *dir)
{
t_clone *x = (t_clone *)z;
if (!x->x_n)
return (0);
return (x->x_vec[0].c_gl->gl_name == name &&
canvas_getdir(x->x_vec[0].c_gl) == dir);
}

void obj_sendinlet(t_object *x, int n, t_symbol *s, int argc, t_atom *argv);

static void clone_in_list(t_in *x, t_symbol *s, int argc, t_atom *argv)
{
int n;
if (argc < 1 || argv[0].a_type != A_FLOAT)
pd_error(x->i_owner, "clone: no instance number in message");
else if ((n = argv[0].a_w.w_float - x->i_owner->x_startvoice) < 0 ||
n >= x->i_owner->x_n)
pd_error(x->i_owner, "clone: instance number %d out of range",
n + x->i_owner->x_startvoice);
else if (argc > 1 && argv[1].a_type == A_SYMBOL)
obj_sendinlet(&x->i_owner->x_vec[n].c_gl->gl_obj, x->i_n,
argv[1].a_w.w_symbol, argc-2, argv+2);
else obj_sendinlet(&x->i_owner->x_vec[n].c_gl->gl_obj, x->i_n,
&s_list, argc-1, argv+1);
}

static void clone_in_this(t_in *x, t_symbol *s, int argc, t_atom *argv)
{
int phase = x->i_owner->x_phase;
if (phase < 0 || phase >= x->i_owner->x_n)
phase = 0;
if (argc <= 0)
return;
else if (argv->a_type == A_SYMBOL)
obj_sendinlet(&x->i_owner->x_vec[phase].c_gl->gl_obj, x->i_n,
argv[0].a_w.w_symbol, argc-1, argv+1);
else obj_sendinlet(&x->i_owner->x_vec[phase].c_gl->gl_obj, x->i_n,
&s_list, argc, argv);
}

static void clone_in_next(t_in *x, t_symbol *s, int argc, t_atom *argv)
{
int phase = x->i_owner->x_phase + 1;
if (phase < 0 || phase >= x->i_owner->x_n)
phase = 0;
x->i_owner->x_phase = phase;
clone_in_this(x, s, argc, argv);
}

static void clone_in_set(t_in *x, t_floatarg f)
{
int phase = f;
if (phase < 0 || phase >= x->i_owner->x_n)
phase = 0;
x->i_owner->x_phase = phase;
}

static void clone_in_all(t_in *x, t_symbol *s, int argc, t_atom *argv)
{
int phasewas = x->i_owner->x_phase, i;
for (i = 0; i < x->i_owner->x_n; i++)
{
x->i_owner->x_phase = i;
clone_in_this(x, s, argc, argv);
}
x->i_owner->x_phase = phasewas;
}

static void clone_in_vis(t_in *x, t_floatarg fn, t_floatarg vis)
{
int n = fn - x->i_owner->x_startvoice;
if (n < 0)
n = 0;
else if (n >= x->i_owner->x_n)
n = x->i_owner->x_n - 1;
canvas_vis(x->i_owner->x_vec[n].c_gl, (vis != 0));
}

static void clone_out_anything(t_out *x, t_symbol *s, int argc, t_atom *argv)
{
t_atom *outv, *ap;
int first =
1 + (s != &s_list && s != &s_float && s != &s_symbol && s != &s_bang),
outc = argc + first;
ATOMS_ALLOCA(outv, outc);
SETFLOAT(outv, x->o_n);
if (first == 2)
SETSYMBOL(outv + 1, s);
memcpy(outv+first, argv, sizeof(t_atom) * argc);
outlet_list(x->o_outlet, 0, outc, outv);
ATOMS_FREEA(outv, outc);
}

static void clone_free(t_clone *x)
{
if (x->x_vec)
{
int i;
for (i = 0; i < x->x_n; i++)
{
canvas_closebang(x->x_vec[i].c_gl);
pd_free(&x->x_vec[i].c_gl->gl_pd);
t_freebytes(x->x_outvec[i],
x->x_nout * sizeof(*x->x_outvec[i]));
}
t_freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
t_freebytes(x->x_argv, x->x_argc * sizeof(*x->x_argv));
t_freebytes(x->x_invec, x->x_nin * sizeof(*x->x_invec));
t_freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec));
}
}

static t_canvas *clone_makeone(t_symbol *s, int argc, t_atom *argv)
{
t_canvas *retval;
pd_this->pd_newest = 0;
typedmess(&pd_objectmaker, s, argc, argv);
if (pd_this->pd_newest == 0)
{
error("clone: can't create subpatch '%s'",
s->s_name);
return (0);
}
if (*pd_this->pd_newest != canvas_class)
{
error("clone: can't clone '%s' because it's not an abstraction",
s->s_name);
pd_free(pd_this->pd_newest);
pd_this->pd_newest = 0;
return (0);
}
retval = (t_canvas *)pd_this->pd_newest;
pd_this->pd_newest = 0;
retval->gl_owner = 0;
retval->gl_isclone = 1;
return (retval);
}

void clone_setn(t_clone *x, t_floatarg f)
{
int dspstate = canvas_suspend_dsp();
int nwas = x->x_n, wantn = f, i, j;
if (wantn < 1)
{
pd_error(x, "can't resize to zero or negative number; setting to 1");
wantn = 1;
}
if (wantn > nwas)
for (i = nwas; i < wantn; i++)
{
t_canvas *c;
t_out *outvec;
SETFLOAT(x->x_argv, x->x_startvoice + i);
if (!(c = clone_makeone(x->x_s, x->x_argc - x->x_suppressvoice,
x->x_argv + x->x_suppressvoice)))
{
pd_error(x, "clone: couldn't create '%s'", x->x_s->s_name);
goto done;
}
x->x_vec = (t_copy *)t_resizebytes(x->x_vec, i * sizeof(t_copy),
(i+1) * sizeof(t_copy));
x->x_vec[i].c_gl = c;
x->x_vec[i].c_on = 0;
x->x_outvec = (t_out **)t_resizebytes(x->x_outvec,
i * sizeof(*x->x_outvec), (i+1) * sizeof(*x->x_outvec));
x->x_outvec[i] = outvec =
(t_out *)getbytes(x->x_nout * sizeof(*outvec));
for (j = 0; j < x->x_nout; j++)
{
outvec[j].o_pd = clone_out_class;
outvec[j].o_signal =
obj_issignaloutlet(&x->x_vec[0].c_gl->gl_obj, i);
outvec[j].o_n = x->x_startvoice + i;
outvec[j].o_outlet =
x->x_outvec[0][j].o_outlet;
obj_connect(&x->x_vec[i].c_gl->gl_obj, j,
(t_object *)(&outvec[j]), 0);
}
x->x_n++;
}
if (wantn < nwas)
{
for (i = wantn; i < nwas; i++)
{
canvas_closebang(x->x_vec[i].c_gl);
pd_free(&x->x_vec[i].c_gl->gl_pd);
}
x->x_vec = (t_copy *)t_resizebytes(x->x_vec, nwas * sizeof(t_copy),
wantn * sizeof(*x->x_vec));
x->x_n = wantn;
}
done:
canvas_resume_dsp(dspstate);
}

static void clone_click(t_clone *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
if (!x->x_n)
return;
canvas_vis(x->x_vec[0].c_gl, 1);
}

static void clone_loadbang(t_clone *x, t_floatarg f)
{
int i;
if (f == LB_LOAD)
for (i = 0; i < x->x_n; i++)
canvas_loadbang(x->x_vec[i].c_gl);
else if (f == LB_CLOSE)
for (i = 0; i < x->x_n; i++)
canvas_closebang(x->x_vec[i].c_gl);
}

void canvas_dodsp(t_canvas *x, int toplevel, t_signal **sp);
t_signal *signal_newfromcontext(int borrowed);
void signal_makereusable(t_signal *sig);

static void clone_dsp(t_clone *x, t_signal **sp)
{
int i, j, nin, nout;
t_signal **tempsigs;
if (!x->x_n)
return;
for (i = nin = 0; i < x->x_nin; i++)
if (x->x_invec[i].i_signal)
nin++;
for (i = nout = 0; i < x->x_nout; i++)
if (x->x_outvec[0][i].o_signal)
nout++;
for (j = 0; j < x->x_n; j++)
{
if (obj_ninlets(&x->x_vec[j].c_gl->gl_obj) != x->x_nin ||
obj_noutlets(&x->x_vec[j].c_gl->gl_obj) != x->x_nout ||
obj_nsiginlets(&x->x_vec[j].c_gl->gl_obj) != nin ||
obj_nsigoutlets(&x->x_vec[j].c_gl->gl_obj) != nout)
{
pd_error(x, "clone: can't do DSP until edited copy is saved");
for (i = 0; i < nout; i++)
dsp_add_zero(sp[nin+i]->s_vec, sp[nin+i]->s_n);
return;
}
}
tempsigs = (t_signal **)alloca((nin + 3 * nout) * sizeof(*tempsigs));
/* load input signals into signal vector to send subpatches */
for (i = 0; i < nin; i++)
{
/* we already have one reference "counted" for our presumed
use of this input signal but we must add the others. */
sp[i]->s_refcount += x->x_n-1;
tempsigs[2 * nout + i] = sp[i];
}
/* for first copy, write output to first nout temp sigs */
for (i = 0; i < nout; i++)
tempsigs[i] = tempsigs[2 * nout + nin + i] = signal_newfromcontext(1);
canvas_dodsp(x->x_vec[0].c_gl, 0, tempsigs + 2*nout);
/* for remaining copies, write to second nout temp sigs */
for (j = 1; j < x->x_n; j++)
{
for (i = 0; i < nout; i++)
tempsigs[nout+i] = tempsigs[2 * nout + nin + i] =
signal_newfromcontext(1);
canvas_dodsp(x->x_vec[j].c_gl, 0, tempsigs + 2*nout);
for (i = 0; i < nout; i++)
{
dsp_add_plus(tempsigs[nout + i]->s_vec, tempsigs[i]->s_vec,
tempsigs[i]->s_vec, tempsigs[i]->s_n);
signal_makereusable(tempsigs[nout + i]);
}
}
/* copy to output signsls */
for (i = 0; i < nout; i++)
{
dsp_add_copy(tempsigs[i]->s_vec, sp[nin+i]->s_vec, tempsigs[i]->s_n);
signal_makereusable(tempsigs[i]);
}
}

static void *clone_new(t_symbol *s, int argc, t_atom *argv)
{
t_clone *x = (t_clone *)pd_new(clone_class);
t_canvas *c;
int wantn, dspstate, i;
t_out *outvec;
x->x_invec = 0;
x->x_outvec = 0;
x->x_startvoice = 0;
x->x_suppressvoice = 0;
if (argc == 0)
{
x->x_vec = 0;
x->x_n = 0;
return (x);
}
dspstate = canvas_suspend_dsp();
while (argc > 0 && argv[0].a_type == A_SYMBOL &&
argv[0].a_w.w_symbol->s_name[0] == '-')
{
if (!strcmp(argv[0].a_w.w_symbol->s_name, "-s") && argc > 1 &&
argv[1].a_type == A_FLOAT)
{
x->x_startvoice = argv[1].a_w.w_float;
argc -= 2; argv += 2;
}
else if (!strcmp(argv[0].a_w.w_symbol->s_name, "-x"))
x->x_suppressvoice = 1, argc--, argv++;
else goto usage;
}
if (argc >= 2 && (wantn = atom_getfloatarg(0, argc, argv)) >= 0
&& argv[1].a_type == A_SYMBOL)
x->x_s = argv[1].a_w.w_symbol;
else if (argc >= 2 && (wantn = atom_getfloatarg(1, argc, argv)) >= 0
&& argv[0].a_type == A_SYMBOL)
x->x_s = argv[0].a_w.w_symbol;
else goto usage;
/* store a copy of the argmuents with an extra space (argc+1) for
supplying an instance number, which we'll bash as we go. */
x->x_argc = argc - 1;
x->x_argv = getbytes(x->x_argc * sizeof(*x->x_argv));
memcpy(x->x_argv, argv+1, x->x_argc * sizeof(*x->x_argv));
SETFLOAT(x->x_argv, x->x_startvoice);
if (!(c = clone_makeone(x->x_s, x->x_argc - x->x_suppressvoice,
x->x_argv + x->x_suppressvoice)))
goto fail;
x->x_vec = (t_copy *)getbytes(sizeof(*x->x_vec));
x->x_vec[0].c_gl = c;
x->x_n = 1;
x->x_nin = obj_ninlets(&x->x_vec[0].c_gl->gl_obj);
x->x_invec = (t_in *)getbytes(x->x_nin * sizeof(*x->x_invec));
for (i = 0; i < x->x_nin; i++)
{
x->x_invec[i].i_pd = clone_in_class;
x->x_invec[i].i_owner = x;
x->x_invec[i].i_signal =
obj_issignalinlet(&x->x_vec[0].c_gl->gl_obj, i);
x->x_invec[i].i_n = i;
if (x->x_invec[i].i_signal)
signalinlet_new(&x->x_obj, 0);
else inlet_new(&x->x_obj, &x->x_invec[i].i_pd, 0, 0);
}
x->x_nout = obj_noutlets(&x->x_vec[0].c_gl->gl_obj);
x->x_outvec = (t_out **)getbytes(sizeof(*x->x_outvec));
x->x_outvec[0] = outvec =
(t_out *)getbytes(x->x_nout * sizeof(*outvec));
for (i = 0; i < x->x_nout; i++)
{
outvec[i].o_pd = clone_out_class;
outvec[i].o_signal =
obj_issignaloutlet(&x->x_vec[0].c_gl->gl_obj, i);
outvec[i].o_n = x->x_startvoice;
outvec[i].o_outlet =
outlet_new(&x->x_obj, (outvec[i].o_signal ? &s_signal : 0));
obj_connect(&x->x_vec[0].c_gl->gl_obj, i,
(t_object *)(&outvec[i]), 0);
}
clone_setn(x, (t_floatarg)(wantn));
x->x_phase = wantn-1;
canvas_resume_dsp(dspstate);
return (x);
usage:
error("usage: clone [-s starting-number] <number> <name> [arguments]");
fail:
freebytes(x, sizeof(t_clone));
canvas_resume_dsp(dspstate);
return (0);
}

void clone_setup(void)
{
clone_class = class_new(gensym("clone"), (t_newmethod)clone_new,
(t_method)clone_free, sizeof(t_clone), CLASS_NOINLET, A_GIMME, 0);
class_addmethod(clone_class, (t_method)clone_click, gensym("click"),
A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(clone_class, (t_method)clone_loadbang, gensym("loadbang"),
A_FLOAT, 0);
class_addmethod(clone_class, (t_method)clone_dsp,
gensym("dsp"), A_CANT, 0);

clone_in_class = class_new(gensym("clone-inlet"), 0, 0,
sizeof(t_in), CLASS_PD, 0);
class_addmethod(clone_in_class, (t_method)clone_in_next, gensym("next"),
A_GIMME, 0);
class_addmethod(clone_in_class, (t_method)clone_in_this, gensym("this"),
A_GIMME, 0);
class_addmethod(clone_in_class, (t_method)clone_in_set, gensym("set"),
A_FLOAT, 0);
class_addmethod(clone_in_class, (t_method)clone_in_all, gensym("all"),
A_GIMME, 0);
class_addmethod(clone_in_class, (t_method)clone_in_vis, gensym("vis"),
A_FLOAT, A_FLOAT, 0);
class_addlist(clone_in_class, (t_method)clone_in_list);

clone_out_class = class_new(gensym("clone-outlet"), 0, 0,
sizeof(t_in), CLASS_PD, 0);
class_addanything(clone_out_class, (t_method)clone_out_anything);
}

+ 2990
- 0
ports/camomile/source/LibPd/pure-data/src/g_editor.c
File diff suppressed because it is too large
View File


+ 1111
- 0
ports/camomile/source/LibPd/pure-data/src/g_graph.c
File diff suppressed because it is too large
View File


+ 97
- 0
ports/camomile/source/LibPd/pure-data/src/g_guiconnect.c View File

@@ -0,0 +1,97 @@
/* Copyright (c) 1997-2000 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* a thing to forward messages from the GUI, dealing with race conditions
in which the "target" gets deleted while the GUI is sending it something.

See also the gfxstub object that doesn't oblige the owner to keep a pointer
around (so is better suited to one-off dialogs)
*/

#include "m_pd.h"
#include "g_canvas.h"

struct _guiconnect
{
t_object x_obj;
t_pd *x_who;
t_symbol *x_sym;
t_clock *x_clock;
};

static t_class *guiconnect_class;

t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym)
{
t_guiconnect *x = (t_guiconnect *)pd_new(guiconnect_class);
x->x_who = who;
x->x_sym = sym;
pd_bind(&x->x_obj.ob_pd, sym);
return (x);
}

/* cleanup routine; delete any resources we have */
static void guiconnect_free(t_guiconnect *x)
{
if (x->x_sym)
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
if (x->x_clock)
clock_free(x->x_clock);
}

/* this is called when the clock times out to indicate the GUI should
be gone by now. */
static void guiconnect_tick(t_guiconnect *x)
{
pd_free(&x->x_obj.ob_pd);
}

/* the target calls this to disconnect. If the gui has "signed off"
we're ready to delete the object; otherwise we wait either for signoff
or for a timeout. */
void guiconnect_notarget(t_guiconnect *x, double timedelay)
{
if (!x->x_sym)
pd_free(&x->x_obj.ob_pd);
else
{
x->x_who = 0;
if (timedelay > 0)
{
x->x_clock = clock_new(x, (t_method)guiconnect_tick);
clock_delay(x->x_clock, timedelay);
}
}
}

/* the GUI calls this to send messages to the target. */
static void guiconnect_anything(t_guiconnect *x,
t_symbol *s, int ac, t_atom *av)
{
if (x->x_who)
typedmess(x->x_who, s, ac, av);
}

/* the GUI calls this when it disappears. (If there's any chance the
GUI will fail to do this, the "target", when it signs off, should specify
a timeout after which the guiconnect will disappear.) */
static void guiconnect_signoff(t_guiconnect *x)
{
if (!x->x_who)
pd_free(&x->x_obj.ob_pd);
else
{
pd_unbind(&x->x_obj.ob_pd, x->x_sym);
x->x_sym = 0;
}
}

void g_guiconnect_setup(void)
{
guiconnect_class = class_new(gensym("guiconnect"), 0,
(t_method)guiconnect_free, sizeof(t_guiconnect), CLASS_PD, 0);
class_addanything(guiconnect_class, guiconnect_anything);
class_addmethod(guiconnect_class, (t_method)guiconnect_signoff,
gensym("signoff"), 0);
}

+ 775
- 0
ports/camomile/source/LibPd/pure-data/src/g_hdial.c View File

@@ -0,0 +1,775 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */

/* name change to hradio by MSP and changed to
put out a "float" as in sliders, toggles, etc. */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

/* ------------- hdl gui-horizontal dial ---------------------- */

t_widgetbehavior hradio_widgetbehavior;
static t_class *hradio_class, *hradio_old_class;

/* widget helper functions */

void hradio_draw_update(t_gobj *client, t_glist *glist)
{
t_hradio *x = (t_hradio *)client;
if(glist_isvisible(glist))
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n",
canvas, x, x->x_drawn,
x->x_gui.x_bcol, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n",
canvas, x, x->x_on,
x->x_gui.x_fcol, x->x_gui.x_fcol);
x->x_drawn = x->x_on;
}
}

void hradio_draw_new(t_hradio *x, t_glist *glist)
{
int n = x->x_number, i, dx = x->x_gui.x_w, s4 = dx / 4;
int yy11 = text_ypix(&x->x_gui.x_obj, glist), yy12 = yy11 + dx;
int yy21 = yy11 + s4, yy22 = yy12 - s4;
int xx11b = text_xpix(&x->x_gui.x_obj, glist), xx11 = xx11b, xx21 = xx11b + s4;
int xx22 = xx11b + dx - s4;
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE%d\n",
canvas, xx11, yy11, xx11 + dx, yy12, IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x, i);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxBUT%d\n",
canvas, xx21, yy21, xx22, yy22,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x, i);
xx11 += dx;
xx21 += dx;
xx22 += dx;
x->x_drawn = x->x_on;
}
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xx11b, yy12 + IEMGUI_ZOOM(x) - ioh,
xx11b + iow, yy12,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xx11b, yy11,
xx11b + iow, yy11 - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xx11b + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
yy11 + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

void hradio_draw_move(t_hradio *x, t_glist *glist)
{
int n = x->x_number, i, dx = x->x_gui.x_w, s4 = dx / 4;
int yy11 = text_ypix(&x->x_gui.x_obj, glist), yy12 = yy11 + dx;
int yy21 = yy11 + s4, yy22 = yy12 - s4;
int xx11b = text_xpix(&x->x_gui.x_obj, glist), xx11 = xx11b, xx21 = xx11b + s4;
int xx22 = xx11b + dx - s4;
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

xx11 = xx11b;
xx21 = xx11b + s4;
xx22 = xx11b + dx - s4;
for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c coords %lxBASE%d %d %d %d %d\n",
canvas, x, i, xx11, yy11, xx11 + dx, yy12);
sys_vgui(".x%lx.c coords %lxBUT%d %d %d %d %d\n",
canvas, x, i, xx21, yy21, xx22, yy22);
xx11 += dx;
xx21 += dx;
xx22 += dx;
}
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xx11b + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
yy11 + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xx11b, yy12 + IEMGUI_ZOOM(x) - ioh,
xx11b + iow, yy12);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xx11b, yy11,
xx11b + iow, yy11 - IEMGUI_ZOOM(x) + ioh);
}

void hradio_draw_erase(t_hradio* x, t_glist* glist)
{
int n = x->x_number, i;
t_canvas *canvas = glist_getcanvas(glist);

for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c delete %lxBASE%d\n", canvas, x, i);
sys_vgui(".x%lx.c delete %lxBUT%d\n", canvas, x, i);
}
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void hradio_draw_config(t_hradio* x, t_glist* glist)
{
int n = x->x_number, i;
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED:x->x_gui.x_lcol,
strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "");
for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -fill #%06x\n", canvas, x, i,
x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", canvas, x, i,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol);
}
}

void hradio_draw_io(t_hradio* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
/* keep these above outlet */
if(x->x_on == 0) {
sys_vgui(".x%lx.c raise %lxBUT%d %lxOUT%d\n", canvas, x, x->x_on, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on);
}
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep these above inlet */
if(x->x_on == 0) {
sys_vgui(".x%lx.c raise %lxBUT%d %lxIN%d\n", canvas, x, x->x_on, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on);
}
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void hradio_draw_select(t_hradio* x, t_glist* glist)
{
int n = x->x_number, i;
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i,
IEM_GUI_COLOR_SELECTED);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i,
IEM_GUI_COLOR_NORMAL);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x,
x->x_gui.x_lcol);
}
}

void hradio_draw(t_hradio *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
sys_queuegui(x, glist, hradio_draw_update);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
hradio_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
hradio_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
hradio_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
hradio_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
hradio_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
hradio_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ hdl widgetbehaviour----------------------------- */

static void hradio_getrect(t_gobj *z, t_glist *glist, int *xp1, int *yp1, int *xp2, int *yp2)
{
t_hradio *x = (t_hradio *)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w * x->x_number;
*yp2 = *yp1 + x->x_gui.x_h;
}

static void hradio_save(t_gobj *z, t_binbuf *b)
{
t_hradio *x = (t_hradio *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiiisssiiiisssf", gensym("#X"),gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class ?
gensym("hdl") : gensym("hradio")),
x->x_gui.x_w/IEMGUI_ZOOM(x),
x->x_change, iem_symargstoint(&x->x_gui.x_isa), x->x_number,
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2], x->x_fval);
binbuf_addv(b, ";");
}

static void hradio_properties(t_gobj *z, t_glist *owner)
{
t_hradio *x = (t_hradio *)z;
char buf[800];
t_symbol *srl[3];
int hchange = -1;

iemgui_properties(&x->x_gui, srl);
if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class)
hchange = x->x_change;
sprintf(buf, "pdtk_iemgui_dialog %%s |hradio| \
----------dimensions(pix):----------- %d %d size: 0 0 empty \
empty 0.0 empty 0.0 empty %d \
%d new-only new&old %d %d number: %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
0,/*no_schedule*/
hchange, x->x_gui.x_isa.x_loadinit, -1, x->x_number,
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void hradio_dialog(t_hradio *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int a = (int)atom_getfloatarg(0, argc, argv);
int chg = (int)atom_getfloatarg(4, argc, argv);
int num = (int)atom_getfloatarg(6, argc, argv);
int sr_flags;

if(chg != 0) chg = 1;
x->x_change = chg;
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
if(x->x_number != num)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE);
x->x_number = num;
if(x->x_on >= x->x_number)
{
x->x_on = x->x_number - 1;
x->x_on_old = x->x_on;
}
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW);
}
else
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

}

static void hradio_set(t_hradio *x, t_floatarg f)
{
int i = (int)f;
int old = x->x_on_old;

x->x_fval = f;
if(i < 0)
i = 0;
if(i >= x->x_number)
i = x->x_number - 1;
if(x->x_on != x->x_on_old)
{
old = x->x_on_old;
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
x->x_on_old = old;
}
else
{
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}
}

static void hradio_bang(t_hradio *x)
{
/* compatibility with earlier "hdial" behavior */
if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class)
{
if((x->x_change) && (x->x_on != x->x_on_old))
{
SETFLOAT(x->x_at, (t_float)x->x_on_old);
SETFLOAT(x->x_at+1, 0.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
x->x_on_old = x->x_on;
SETFLOAT(x->x_at, (t_float)x->x_on);
SETFLOAT(x->x_at+1, 1.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
else
{
float outval = (pd_compatibilitylevel < 46 ? x->x_on : x->x_fval);
outlet_float(x->x_gui.x_obj.ob_outlet, outval);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, outval);
}
}

static void hradio_fout(t_hradio *x, t_floatarg f)
{
int i = (int)f;

x->x_fval = f;
if(i < 0)
i = 0;
if(i >= x->x_number)
i = x->x_number - 1;

if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class)
{
if((x->x_change) && (i != x->x_on_old))
{
SETFLOAT(x->x_at, (t_float)x->x_on_old);
SETFLOAT(x->x_at+1, 0.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
if(x->x_on != x->x_on_old)
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
x->x_on_old = x->x_on;
SETFLOAT(x->x_at, (t_float)x->x_on);
SETFLOAT(x->x_at+1, 1.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
else
{
float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval);
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
outlet_float(x->x_gui.x_obj.ob_outlet, outval);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, outval);
}
}

static void hradio_float(t_hradio *x, t_floatarg f)
{
int i = (int)f;
x->x_fval = f;
if(i < 0)
i = 0;
if(i >= x->x_number)
i = x->x_number - 1;

if(pd_class(&x->x_gui.x_obj.ob_pd) == hradio_old_class)
{
/* compatibility with earlier "hdial" behavior */
if((x->x_change) && (i != x->x_on_old))
{
if(x->x_gui.x_fsf.x_put_in2out)
{
SETFLOAT(x->x_at, (t_float)x->x_on_old);
SETFLOAT(x->x_at+1, 0.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
}
if(x->x_on != x->x_on_old)
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
x->x_on_old = x->x_on;
if(x->x_gui.x_fsf.x_put_in2out)
{
SETFLOAT(x->x_at, (t_float)x->x_on);
SETFLOAT(x->x_at+1, 1.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
}
else
{
float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval);
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
if(x->x_gui.x_fsf.x_put_in2out)
{
outlet_float(x->x_gui.x_obj.ob_outlet, outval);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, outval);
}
}
}

static void hradio_click(t_hradio *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
int xx = (int)xpos - (int)text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist);

hradio_fout(x, (t_float)(xx / x->x_gui.x_w));
}

static int hradio_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
if(doit)
hradio_click((t_hradio *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt);
return (1);
}

static void hradio_loadbang(t_hradio *x, t_floatarg action)
{
if(action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
hradio_bang(x);
}

static void hradio_number(t_hradio *x, t_floatarg num)
{
int n = (int)num;

if(n < 1)
n = 1;
if(n > IEM_RADIO_MAX)
n = IEM_RADIO_MAX;
if(n != x->x_number)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE);
x->x_number = n;
if(x->x_on >= x->x_number)
x->x_on = x->x_number - 1;
x->x_on_old = x->x_on;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}

static void hradio_size(t_hradio *x, t_symbol *s, int ac, t_atom *av)
{
x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_size((void *)x, &x->x_gui);
}

static void hradio_delta(t_hradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void hradio_pos(t_hradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void hradio_color(t_hradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void hradio_send(t_hradio *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void hradio_receive(t_hradio *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void hradio_label(t_hradio *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void hradio_label_pos(t_hradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void hradio_label_font(t_hradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void hradio_init(t_hradio *x, t_floatarg f)
{x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;}

static void hradio_double_change(t_hradio *x)
{x->x_change = 1;}

static void hradio_single_change(t_hradio *x)
{x->x_change = 0;}

static void *hradio_donew(t_symbol *s, int argc, t_atom *argv, int old)
{
t_hradio *x = (t_hradio *)pd_new(old ? hradio_old_class : hradio_class);
int a=IEM_GUI_DEFAULTSIZE, on = 0, f = 0;
int ldx = 0, ldy = -8, chg = 1, num = 8;
int fs = 10;
int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, fthold = IEM_BNG_DEFAULTHOLDFLASHTIME;
char str[144];
float fval = 0;

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if((argc == 15)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2)
&&IS_A_FLOAT(argv,3)
&&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4))
&&(IS_A_SYMBOL(argv,5)||IS_A_FLOAT(argv,5))
&&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
&&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8)
&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)&&IS_A_FLOAT(argv,14))
{
a = (int)atom_getfloatarg(0, argc, argv);
chg = (int)atom_getfloatarg(1, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(2, argc, argv));
num = (int)atom_getfloatarg(3, argc, argv);
iemgui_new_getnames(&x->x_gui, 4, argv);
ldx = (int)atom_getfloatarg(7, argc, argv);
ldy = (int)atom_getfloatarg(8, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(9, argc, argv));
fs = (int)atom_getfloatarg(10, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+11, argv+12, argv+13);
fval = atom_getfloatarg(14, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 4, 0);
x->x_gui.x_draw = (t_iemfunptr)hradio_draw;
x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if(!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if(!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if(num < 1)
num = 1;
if(num > IEM_RADIO_MAX)
num = IEM_RADIO_MAX;
x->x_number = num;
x->x_fval = fval;
on = fval;
if(on < 0)
on = 0;
if(on >= x->x_number)
on = x->x_number - 1;
if(x->x_gui.x_isa.x_loadinit)
x->x_on = on;
else
x->x_on = 0;
x->x_on_old = x->x_on;
x->x_change = (chg == 0) ? 0 : 1;
if(x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_w = iemgui_clip_size(a);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_verify_snd_ne_rcv(&x->x_gui);
iemgui_newzoom(&x->x_gui);
outlet_new(&x->x_gui.x_obj, &s_list);
return (x);
}

static void *hradio_new(t_symbol *s, int argc, t_atom *argv)
{
return (hradio_donew(s, argc, argv, 0));
}

static void *hdial_new(t_symbol *s, int argc, t_atom *argv)
{
return (hradio_donew(s, argc, argv, 1));
}

static void hradio_ff(t_hradio *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_hradio_setup(void)
{
hradio_class = class_new(gensym("hradio"), (t_newmethod)hradio_new,
(t_method)hradio_ff, sizeof(t_hradio), 0, A_GIMME, 0);
class_addbang(hradio_class, hradio_bang);
class_addfloat(hradio_class, hradio_float);
class_addmethod(hradio_class, (t_method)hradio_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(hradio_class, (t_method)hradio_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(hradio_class, (t_method)hradio_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(hradio_class, (t_method)hradio_size,
gensym("size"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_color,
gensym("color"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(hradio_class, (t_method)hradio_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(hradio_class, (t_method)hradio_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(hradio_class, (t_method)hradio_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(hradio_class, (t_method)hradio_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(hradio_class, (t_method)hradio_number,
gensym("number"), A_FLOAT, 0);
class_addmethod(hradio_class, (t_method)hradio_single_change,
gensym("single_change"), 0);
class_addmethod(hradio_class, (t_method)hradio_double_change,
gensym("double_change"), 0);
class_addmethod(hradio_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
hradio_widgetbehavior.w_getrectfn = hradio_getrect;
hradio_widgetbehavior.w_displacefn = iemgui_displace;
hradio_widgetbehavior.w_selectfn = iemgui_select;
hradio_widgetbehavior.w_activatefn = NULL;
hradio_widgetbehavior.w_deletefn = iemgui_delete;
hradio_widgetbehavior.w_visfn = iemgui_vis;
hradio_widgetbehavior.w_clickfn = hradio_newclick;
class_setwidget(hradio_class, &hradio_widgetbehavior);
class_sethelpsymbol(hradio_class, gensym("hradio"));
class_setsavefn(hradio_class, hradio_save);
class_setpropertiesfn(hradio_class, hradio_properties);

/*obsolete version (0.34-0.35) */
hradio_old_class = class_new(gensym("hdl"), (t_newmethod)hdial_new,
(t_method)hradio_ff, sizeof(t_hradio), 0, A_GIMME, 0);
class_addcreator((t_newmethod)hradio_new, gensym("rdb"), A_GIMME, 0);
class_addcreator((t_newmethod)hradio_new, gensym("radiobut"), A_GIMME, 0);
class_addcreator((t_newmethod)hradio_new, gensym("radiobutton"),
A_GIMME, 0);
class_addbang(hradio_old_class, hradio_bang);
class_addfloat(hradio_old_class, hradio_float);
class_addmethod(hradio_old_class, (t_method)hradio_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(hradio_old_class, (t_method)hradio_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_loadbang,
gensym("loadbang"), 0);
class_addmethod(hradio_old_class, (t_method)hradio_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(hradio_old_class, (t_method)hradio_size,
gensym("size"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_color,
gensym("color"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(hradio_old_class, (t_method)hradio_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(hradio_old_class, (t_method)hradio_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(hradio_old_class, (t_method)hradio_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(hradio_old_class, (t_method)hradio_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(hradio_old_class, (t_method)hradio_number,
gensym("number"), A_FLOAT, 0);
class_addmethod(hradio_old_class, (t_method)hradio_single_change,
gensym("single_change"), 0);
class_addmethod(hradio_old_class, (t_method)hradio_double_change,
gensym("double_change"), 0);
class_addmethod(hradio_old_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
class_setwidget(hradio_old_class, &hradio_widgetbehavior);
class_sethelpsymbol(hradio_old_class, gensym("hradio"));
}

+ 691
- 0
ports/camomile/source/LibPd/pure-data/src/g_hslider.c View File

@@ -0,0 +1,691 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#define LMARGIN 3
#define RMARGIN 2

/* ------------ hsl gui-horizontal slider ----------------------- */

t_widgetbehavior hslider_widgetbehavior;
static t_class *hslider_class;

/* widget helper functions */

static void hslider_draw_update(t_gobj *client, t_glist *glist)
{
t_hslider *x = (t_hslider *)client;
if (glist_isvisible(glist))
{
int r = text_xpix(&x->x_gui.x_obj, glist) + ((x->x_val + 50)/100);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
t_canvas *canvas = glist_getcanvas(glist);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, r, ypos + IEMGUI_ZOOM(x),
r, ypos + x->x_gui.x_h - IEMGUI_ZOOM(x));
}
}

static void hslider_draw_new(t_hslider *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int lmargin = LMARGIN * IEMGUI_ZOOM(x), rmargin = RMARGIN * IEMGUI_ZOOM(x);
int r = xpos + (x->x_val + 50)/100;
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n",
canvas, xpos - lmargin, ypos,
xpos + x->x_gui.x_w + rmargin, ypos + x->x_gui.x_h,
IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xpos - lmargin, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos - lmargin + iow, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos - lmargin, ypos,
xpos - lmargin + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxKNOB\n",
canvas, r, ypos + IEMGUI_ZOOM(x),
r, ypos + x->x_gui.x_h - IEMGUI_ZOOM(x),
1 + 2 * IEMGUI_ZOOM(x), x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

static void hslider_draw_move(t_hslider *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int lmargin = LMARGIN * IEMGUI_ZOOM(x), rmargin = RMARGIN * IEMGUI_ZOOM(x);
int r = xpos + (x->x_val + 50)/100;
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x,
xpos - lmargin, ypos,
xpos + x->x_gui.x_w + rmargin, ypos + x->x_gui.x_h);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xpos - lmargin, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos - lmargin + iow, ypos + x->x_gui.x_h);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xpos - lmargin, ypos,
xpos - lmargin + iow, ypos - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, r, ypos + IEMGUI_ZOOM(x),
r, ypos + x->x_gui.x_h - IEMGUI_ZOOM(x));
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos+x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos+x->x_gui.x_ldy * IEMGUI_ZOOM(x));
}

static void hslider_draw_erase(t_hslider* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x);
sys_vgui(".x%lx.c delete %lxKNOB\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

static void hslider_draw_config(t_hslider* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""));
sys_vgui(".x%lx.c itemconfigure %lxKNOB -fill #%06x\n", canvas, x, x->x_gui.x_fcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, x, x->x_gui.x_bcol);
}

static void hslider_draw_io(t_hslider* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int lmargin = LMARGIN * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos - lmargin, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos - lmargin + iow, ypos + x->x_gui.x_h,
x, 0);
/* keep these above outlet */
sys_vgui(".x%lx.c raise %lxKNOB %lxOUT%d\n", canvas, x, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos - lmargin, ypos,
xpos - lmargin + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep these above inlet */
sys_vgui(".x%lx.c raise %lxKNOB %lxIN%d\n", canvas, x, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

static void hslider_draw_select(t_hslider* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol);
}
}

void hslider_draw(t_hslider *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
sys_queuegui(x, glist, hslider_draw_update);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
hslider_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
hslider_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
hslider_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
hslider_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
hslider_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
hslider_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ hsl widgetbehaviour----------------------------- */


static void hslider_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_hslider* x = (t_hslider*)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist) - LMARGIN*glist_getzoom(glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w + (LMARGIN + RMARGIN)*glist_getzoom(glist);
*yp2 = *yp1 + x->x_gui.x_h;
}

static void hslider_save(t_gobj *z, t_binbuf *b)
{
t_hslider *x = (t_hslider *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiffiisssiiiisssii", gensym("#X"), gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("hsl"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_gui.x_h/IEMGUI_ZOOM(x),
(t_float)x->x_min, (t_float)x->x_max,
x->x_lin0_log1, iem_symargstoint(&x->x_gui.x_isa),
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2],
x->x_val, x->x_steady);
binbuf_addv(b, ";");
}

void hslider_check_width(t_hslider *x, int w)
{
if(w < IEM_SL_MINSIZE * IEMGUI_ZOOM(x))
w = IEM_SL_MINSIZE * IEMGUI_ZOOM(x);
x->x_gui.x_w = w;
if(x->x_val > (x->x_gui.x_w*100 - 100))
{
x->x_pos = x->x_gui.x_w*100 - 100;
x->x_val = x->x_pos;
}
if(x->x_lin0_log1)
x->x_k = log(x->x_max/x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1);
else
x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1);
}

void hslider_check_minmax(t_hslider *x, double min, double max)
{
if(x->x_lin0_log1)
{
if((min == 0.0) && (max == 0.0))
max = 1.0;
if(max > 0.0)
{
if(min <= 0.0)
min = 0.01*max;
}
else
{
if(min > 0.0)
max = 0.01*min;
}
}
x->x_min = min;
x->x_max = max;
if(x->x_lin0_log1)
x->x_k = log(x->x_max/x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1);
else
x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1);
}

static void hslider_properties(t_gobj *z, t_glist *owner)
{
t_hslider *x = (t_hslider *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);
sprintf(buf, "pdtk_iemgui_dialog %%s |hsl| \
--------dimensions(pix)(pix):-------- %d %d width: %d %d height: \
-----------output-range:----------- %g left: %g right: %g \
%d lin log %d %d empty %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_SL_MINSIZE, x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
x->x_min, x->x_max, 0.0,/*no_schedule*/
x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void hslider_set(t_hslider *x, t_floatarg f) /* bugfix */
{
int old = x->x_val;
double g;

x->x_fval = f;
if (x->x_min > x->x_max)
{
if(f > x->x_min)
f = x->x_min;
if(f < x->x_max)
f = x->x_max;
}
else
{
if(f > x->x_max)
f = x->x_max;
if(f < x->x_min)
f = x->x_min;
}
if(x->x_lin0_log1)
g = log(f/x->x_min) / x->x_k;
else
g = (f - x->x_min) / x->x_k;
x->x_val = IEMGUI_ZOOM(x) * (int)(100.0*g + 0.49999);
x->x_pos = x->x_val;
if(x->x_val != old)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}

/* compute numeric value (fval) from pixel location (val) and range */
static t_float hslider_getfval(t_hslider *x)
{
t_float fval;
int zoomval = (x->x_gui.x_fsf.x_finemoved) ?
x->x_val/IEMGUI_ZOOM(x) : (x->x_val / (100*IEMGUI_ZOOM(x))) * 100;

if (x->x_lin0_log1)
fval = x->x_min * exp(x->x_k * (double)(zoomval) * 0.01);
else fval = (double)(zoomval) * 0.01 * x->x_k + x->x_min;
if ((fval < 1.0e-10) && (fval > -1.0e-10))
fval = 0.0;
return (fval);
}

static void hslider_bang(t_hslider *x)
{
double out;

if (pd_compatibilitylevel < 46)
out = hslider_getfval(x);
else out = x->x_fval;
outlet_float(x->x_gui.x_obj.ob_outlet, out);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, out);
}

static void hslider_dialog(t_hslider *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int w = (int)atom_getfloatarg(0, argc, argv) * IEMGUI_ZOOM(x);
int h = (int)atom_getfloatarg(1, argc, argv);
double min = (double)atom_getfloatarg(2, argc, argv);
double max = (double)atom_getfloatarg(3, argc, argv);
int lilo = (int)atom_getfloatarg(4, argc, argv);
int steady = (int)atom_getfloatarg(17, argc, argv);
int sr_flags;

if(lilo != 0) lilo = 1;
x->x_lin0_log1 = lilo;
if(steady)
x->x_steady = 1;
else
x->x_steady = 0;
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
x->x_gui.x_h = iemgui_clip_size(h) * IEMGUI_ZOOM(x);
hslider_check_width(x, w);
hslider_check_minmax(x, min, max);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

static void hslider_motion(t_hslider *x, t_floatarg dx, t_floatarg dy)
{
int old = x->x_val;

if(x->x_gui.x_fsf.x_finemoved)
x->x_pos += (int)dx;
else
x->x_pos += 100 * (int)dx;
x->x_val = x->x_pos;
if(x->x_val > (100*x->x_gui.x_w - 100))
{
x->x_val = 100*x->x_gui.x_w - 100;
x->x_pos += 50;
x->x_pos -= x->x_pos % 100;
}
if(x->x_val < 0)
{
x->x_val = 0;
x->x_pos -= 50;
x->x_pos -= x->x_pos % 100;
}
x->x_fval = hslider_getfval(x);
if (old != x->x_val)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
hslider_bang(x);
}
}

static void hslider_click(t_hslider *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
if(!x->x_steady)
x->x_val = (int)(100.0 * (xpos - text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)));
if(x->x_val > (100*x->x_gui.x_w - 100))
x->x_val = 100*x->x_gui.x_w - 100;
if(x->x_val < 0)
x->x_val = 0;
x->x_fval = hslider_getfval(x);
x->x_pos = x->x_val;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
hslider_bang(x);
glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)hslider_motion,
0, xpos, ypos);
}

static int hslider_newclick(t_gobj *z, struct _glist *glist,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
t_hslider* x = (t_hslider *)z;

if(doit)
{
hslider_click(x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift,
0, (t_floatarg)alt);
if(shift)
x->x_gui.x_fsf.x_finemoved = 1;
else
x->x_gui.x_fsf.x_finemoved = 0;
}
return (1);
}

static void hslider_size(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{
hslider_check_width(x, (int)atom_getfloatarg(0, ac, av)*IEMGUI_ZOOM(x));
if(ac > 1)
x->x_gui.x_h = iemgui_clip_size((int)atom_getfloatarg(1, ac, av))*IEMGUI_ZOOM(x);
iemgui_size((void *)x, &x->x_gui);
}

static void hslider_delta(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void hslider_pos(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void hslider_range(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{
hslider_check_minmax(x, (double)atom_getfloatarg(0, ac, av),
(double)atom_getfloatarg(1, ac, av));
}

static void hslider_color(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void hslider_send(t_hslider *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void hslider_receive(t_hslider *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void hslider_label(t_hslider *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void hslider_label_pos(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void hslider_label_font(t_hslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void hslider_log(t_hslider *x)
{
x->x_lin0_log1 = 1;
hslider_check_minmax(x, x->x_min, x->x_max);
}

static void hslider_lin(t_hslider *x)
{
x->x_lin0_log1 = 0;
x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_w/IEMGUI_ZOOM(x) - 1);
}

static void hslider_init(t_hslider *x, t_floatarg f)
{
x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;
}

static void hslider_steady(t_hslider *x, t_floatarg f)
{
x->x_steady = (f == 0.0) ? 0 : 1;
}

static void hslider_zoom(t_hslider *x, t_floatarg f)
{
/* scale current pixel value */
x->x_val = (IEMGUI_ZOOM(x) == 2 ? (x->x_val)/2 : (x->x_val)*2);
x->x_pos = x->x_val;
iemgui_zoom(&x->x_gui, f);
}

static void hslider_float(t_hslider *x, t_floatarg f)
{
hslider_set(x, f);
if(x->x_gui.x_fsf.x_put_in2out)
hslider_bang(x);
}

static void hslider_loadbang(t_hslider *x, t_floatarg action)
{
if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
hslider_bang(x);
}
}

static void *hslider_new(t_symbol *s, int argc, t_atom *argv)
{
t_hslider *x = (t_hslider *)pd_new(hslider_class);
int w = IEM_SL_DEFAULTSIZE, h = IEM_GUI_DEFAULTSIZE;
int lilo = 0, ldx = -2, ldy = -8, f = 0, steady = 1;
int fs = 10;
double min = 0.0, max = (double)(IEM_SL_DEFAULTSIZE-1);
char str[144];
float v = 0;

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
&&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3)
&&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
&&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
&&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7))
&&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8))
&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)
&&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,16))
{
w = (int)atom_getfloatarg(0, argc, argv);
h = (int)atom_getfloatarg(1, argc, argv);
min = (double)atom_getfloatarg(2, argc, argv);
max = (double)atom_getfloatarg(3, argc, argv);
lilo = (int)atom_getfloatarg(4, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(5, argc, argv));
iemgui_new_getnames(&x->x_gui, 6, argv);
ldx = (int)atom_getfloatarg(9, argc, argv);
ldy = (int)atom_getfloatarg(10, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(11, argc, argv));
fs = (int)atom_getfloatarg(12, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+13, argv+14, argv+15);
v = atom_getfloatarg(16, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 6, 0);
if((argc == 18)&&IS_A_FLOAT(argv,17))
steady = (int)atom_getfloatarg(17, argc, argv);
x->x_gui.x_draw = (t_iemfunptr)hslider_draw;
x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if (x->x_gui.x_isa.x_loadinit)
x->x_val = v;
else x->x_val = 0;
x->x_pos = x->x_val;
if(lilo != 0) lilo = 1;
x->x_lin0_log1 = lilo;
if(steady != 0) steady = 1;
x->x_steady = steady;
if (!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if (!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if (x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_h = iemgui_clip_size(h);
hslider_check_width(x, w);
iemgui_verify_snd_ne_rcv(&x->x_gui);
iemgui_newzoom(&x->x_gui);
hslider_check_minmax(x, min, max);
outlet_new(&x->x_gui.x_obj, &s_float);
x->x_fval = hslider_getfval(x);
return (x);
}

static void hslider_free(t_hslider *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_hslider_setup(void)
{
hslider_class = class_new(gensym("hsl"), (t_newmethod)hslider_new,
(t_method)hslider_free, sizeof(t_hslider), 0, A_GIMME, 0);
#ifndef GGEE_HSLIDER_COMPATIBLE
class_addcreator((t_newmethod)hslider_new, gensym("hslider"), A_GIMME, 0);
#endif
class_addbang(hslider_class, hslider_bang);
class_addfloat(hslider_class, hslider_float);
class_addmethod(hslider_class, (t_method)hslider_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(hslider_class, (t_method)hslider_motion,
gensym("motion"), A_FLOAT, A_FLOAT, 0);
class_addmethod(hslider_class, (t_method)hslider_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(hslider_class, (t_method)hslider_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(hslider_class, (t_method)hslider_size,
gensym("size"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_range,
gensym("range"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_color,
gensym("color"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(hslider_class, (t_method)hslider_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(hslider_class, (t_method)hslider_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(hslider_class, (t_method)hslider_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(hslider_class, (t_method)hslider_log,
gensym("log"), 0);
class_addmethod(hslider_class, (t_method)hslider_lin,
gensym("lin"), 0);
class_addmethod(hslider_class, (t_method)hslider_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(hslider_class, (t_method)hslider_steady,
gensym("steady"), A_FLOAT, 0);
class_addmethod(hslider_class, (t_method)hslider_zoom,
gensym("zoom"), A_CANT, 0);
hslider_widgetbehavior.w_getrectfn = hslider_getrect;
hslider_widgetbehavior.w_displacefn = iemgui_displace;
hslider_widgetbehavior.w_selectfn = iemgui_select;
hslider_widgetbehavior.w_activatefn = NULL;
hslider_widgetbehavior.w_deletefn = iemgui_delete;
hslider_widgetbehavior.w_visfn = iemgui_vis;
hslider_widgetbehavior.w_clickfn = hslider_newclick;
class_setwidget(hslider_class, &hslider_widgetbehavior);
class_sethelpsymbol(hslider_class, gensym("hslider"));
class_setsavefn(hslider_class, hslider_save);
class_setpropertiesfn(hslider_class, hslider_properties);
}

+ 599
- 0
ports/camomile/source/LibPd/pure-data/src/g_io.c View File

@@ -0,0 +1,599 @@
/* 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. */

/* graphical inlets and outlets, both for control and signals. */

/* This code is highly inefficient; messages actually have to be forwarded
by inlets and outlets. The outlet is in even worse shape than the inlet;
in order to avoid having a "signal" method in the class, the oulet actually
sprouts an inlet, which forwards the message to the "outlet" object, which
sends it on to the outlet proper. Another way to do it would be to have
separate classes for "signal" and "control" outlets, but this would complicate
life elsewhere. */


#include "m_pd.h"
#include "g_canvas.h"
#include <string.h>
void signal_setborrowed(t_signal *sig, t_signal *sig2);
void signal_makereusable(t_signal *sig);

/* ------------------------- vinlet -------------------------- */
t_class *vinlet_class;

typedef struct _vinlet
{
t_object x_obj;
t_canvas *x_canvas;
t_inlet *x_inlet;
int x_bufsize;
t_float *x_buf; /* signal buffer; zero if not a signal */
t_float *x_endbuf;
t_float *x_fill;
t_float *x_read;
int x_hop;
/* if not reblocking, the next slot communicates the parent's inlet
signal from the prolog to the DSP routine: */
t_signal *x_directsignal;

t_resample x_updown;
} t_vinlet;

static void *vinlet_new(t_symbol *s)
{
t_vinlet *x = (t_vinlet *)pd_new(vinlet_class);
x->x_canvas = canvas_getcurrent();
x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, 0);
x->x_bufsize = 0;
x->x_buf = 0;
outlet_new(&x->x_obj, 0);
return (x);
}

static void vinlet_bang(t_vinlet *x)
{
outlet_bang(x->x_obj.ob_outlet);
}

static void vinlet_pointer(t_vinlet *x, t_gpointer *gp)
{
outlet_pointer(x->x_obj.ob_outlet, gp);
}

static void vinlet_float(t_vinlet *x, t_float f)
{
outlet_float(x->x_obj.ob_outlet, f);
}

static void vinlet_symbol(t_vinlet *x, t_symbol *s)
{
outlet_symbol(x->x_obj.ob_outlet, s);
}

static void vinlet_list(t_vinlet *x, t_symbol *s, int argc, t_atom *argv)
{
outlet_list(x->x_obj.ob_outlet, s, argc, argv);
}

static void vinlet_anything(t_vinlet *x, t_symbol *s, int argc, t_atom *argv)
{
outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
}

static void vinlet_free(t_vinlet *x)
{
canvas_rminlet(x->x_canvas, x->x_inlet);
if (x->x_buf)
t_freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf));
resample_free(&x->x_updown);
}

t_inlet *vinlet_getit(t_pd *x)
{
if (pd_class(x) != vinlet_class) bug("vinlet_getit");
return (((t_vinlet *)x)->x_inlet);
}

/* ------------------------- signal inlet -------------------------- */
int vinlet_issignal(t_vinlet *x)
{
return (x->x_buf != 0);
}

t_int *vinlet_perform(t_int *w)
{
t_vinlet *x = (t_vinlet *)(w[1]);
t_float *out = (t_float *)(w[2]);
int n = (int)(w[3]);
t_float *in = x->x_read;
while (n--) *out++ = *in++;
if (in == x->x_endbuf) in = x->x_buf;
x->x_read = in;
return (w+4);
}

static void vinlet_dsp(t_vinlet *x, t_signal **sp)
{
t_signal *outsig;
/* no buffer means we're not a signal inlet */
if (!x->x_buf)
return;
outsig = sp[0];
if (x->x_directsignal)
{
signal_setborrowed(sp[0], x->x_directsignal);
}
else
{
dsp_add(vinlet_perform, 3, x, outsig->s_vec, outsig->s_vecsize);
x->x_read = x->x_buf;
}
}

/* prolog code: loads buffer from parent patch */
t_int *vinlet_doprolog(t_int *w)
{
t_vinlet *x = (t_vinlet *)(w[1]);
t_float *in = (t_float *)(w[2]);
int n = (int)(w[3]);
t_float *out = x->x_fill;
if (out == x->x_endbuf)
{
t_float *f1 = x->x_buf, *f2 = x->x_buf + x->x_hop;
int nshift = x->x_bufsize - x->x_hop;
out -= x->x_hop;
while (nshift--) *f1++ = *f2++;
}

while (n--) *out++ = *in++;
x->x_fill = out;
return (w+4);
}

int inlet_getsignalindex(t_inlet *x);

/* set up prolog DSP code */
void vinlet_dspprolog(struct _vinlet *x, t_signal **parentsigs,
int myvecsize, int calcsize, int phase, int period, int frequency,
int downsample, int upsample, int reblock, int switched)
{
t_signal *insig, *outsig;
/* no buffer means we're not a signal inlet */
if (!x->x_buf)
return;
x->x_updown.downsample = downsample;
x->x_updown.upsample = upsample;

/* if the "reblock" flag is set, arrange to copy data in from the
parent. */
if (reblock)
{
int parentvecsize, bufsize, oldbufsize, prologphase;
int re_parentvecsize; /* resampled parentvectorsize */
/* this should never happen: */
if (!x->x_buf) return;

/* the prolog code counts from 0 to period-1; the
phase is backed up by one so that AFTER the prolog code
runs, the "x_fill" phase is in sync with the "x_read" phase. */
prologphase = (phase - 1) & (period - 1);
if (parentsigs)
{
insig = parentsigs[inlet_getsignalindex(x->x_inlet)];
parentvecsize = insig->s_vecsize;
re_parentvecsize = parentvecsize * upsample / downsample;
}
else
{
insig = 0;
parentvecsize = 1;
re_parentvecsize = 1;
}

bufsize = re_parentvecsize;
if (bufsize < myvecsize) bufsize = myvecsize;
if (bufsize != (oldbufsize = x->x_bufsize))
{
t_float *buf = x->x_buf;
t_freebytes(buf, oldbufsize * sizeof(*buf));
buf = (t_float *)t_getbytes(bufsize * sizeof(*buf));
memset((char *)buf, 0, bufsize * sizeof(*buf));
x->x_bufsize = bufsize;
x->x_endbuf = buf + bufsize;
x->x_buf = buf;
}
if (parentsigs)
{
x->x_hop = period * re_parentvecsize;

x->x_fill = x->x_endbuf -
(x->x_hop - prologphase * re_parentvecsize);

if (upsample * downsample == 1)
dsp_add(vinlet_doprolog, 3, x, insig->s_vec,
re_parentvecsize);
else {
int method = (x->x_updown.method == 3?
(pd_compatibilitylevel < 44 ? 0 : 1) : x->x_updown.method);
resamplefrom_dsp(&x->x_updown, insig->s_vec, parentvecsize,
re_parentvecsize, method);
dsp_add(vinlet_doprolog, 3, x, x->x_updown.s_vec,
re_parentvecsize);
}

/* if the input signal's reference count is zero, we have
to free it here because we didn't in ugen_doit(). */
if (!insig->s_refcount)
signal_makereusable(insig);
}
else memset((char *)(x->x_buf), 0, bufsize * sizeof(*x->x_buf));
x->x_directsignal = 0;
}
else
{
/* no reblocking; in this case our output signal is "borrowed"
and merely needs to be pointed to the real one. */
x->x_directsignal = parentsigs[inlet_getsignalindex(x->x_inlet)];
}
}

static void *vinlet_newsig(t_symbol *s)
{
t_vinlet *x = (t_vinlet *)pd_new(vinlet_class);
x->x_canvas = canvas_getcurrent();
x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal);
x->x_endbuf = x->x_buf = (t_float *)getbytes(0);
x->x_bufsize = 0;
x->x_directsignal = 0;
outlet_new(&x->x_obj, &s_signal);

resample_init(&x->x_updown);

/* this should be though over:
* it might prove hard to provide consistency between labeled up- & downsampling methods
* maybe indices would be better...
*
* up till now we provide several upsampling methods and 1 single downsampling method (no filtering !)
*/
if (s == gensym("hold"))
x->x_updown.method=1; /* up: sample and hold */
else if (s == gensym("lin") || s == gensym("linear"))
x->x_updown.method=2; /* up: linear interpolation */
else if (s == gensym("pad"))
x->x_updown.method=0; /* up: zero-padding */
else x->x_updown.method=3; /* sample/hold unless version<0.44 */

return (x);
}

static void vinlet_setup(void)
{
vinlet_class = class_new(gensym("inlet"), (t_newmethod)vinlet_new,
(t_method)vinlet_free, sizeof(t_vinlet), CLASS_NOINLET, A_DEFSYM, 0);
class_addcreator((t_newmethod)vinlet_newsig, gensym("inlet~"), A_DEFSYM, 0);
class_addbang(vinlet_class, vinlet_bang);
class_addpointer(vinlet_class, vinlet_pointer);
class_addfloat(vinlet_class, vinlet_float);
class_addsymbol(vinlet_class, vinlet_symbol);
class_addlist(vinlet_class, vinlet_list);
class_addanything(vinlet_class, vinlet_anything);
class_addmethod(vinlet_class, (t_method)vinlet_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(vinlet_class, gensym("pd"));
}

/* ------------------------- voutlet -------------------------- */

t_class *voutlet_class;

typedef struct _voutlet
{
t_object x_obj;
t_canvas *x_canvas;
t_outlet *x_parentoutlet;
int x_bufsize;
t_sample *x_buf; /* signal buffer; zero if not a signal */
t_sample *x_endbuf;
t_sample *x_empty; /* next to read out of buffer in epilog code */
t_sample *x_write; /* next to write in to buffer */
int x_hop; /* hopsize */
/* vice versa from the inlet, if we don't block, this holds the
parent's outlet signal, valid between the prolog and the dsp setup
routines. */
t_signal *x_directsignal;
/* and here's a flag indicating that we aren't blocked but have to
do a copy (because we're switched). */
char x_justcopyout;
t_resample x_updown;
} t_voutlet;

static void *voutlet_new(t_symbol *s)
{
t_voutlet *x = (t_voutlet *)pd_new(voutlet_class);
x->x_canvas = canvas_getcurrent();
x->x_parentoutlet = canvas_addoutlet(x->x_canvas, &x->x_obj.ob_pd, 0);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, 0, 0);
x->x_bufsize = 0;
x->x_buf = 0;
return (x);
}

static void voutlet_bang(t_voutlet *x)
{
outlet_bang(x->x_parentoutlet);
}

static void voutlet_pointer(t_voutlet *x, t_gpointer *gp)
{
outlet_pointer(x->x_parentoutlet, gp);
}

static void voutlet_float(t_voutlet *x, t_float f)
{
outlet_float(x->x_parentoutlet, f);
}

static void voutlet_symbol(t_voutlet *x, t_symbol *s)
{
outlet_symbol(x->x_parentoutlet, s);
}

static void voutlet_list(t_voutlet *x, t_symbol *s, int argc, t_atom *argv)
{
outlet_list(x->x_parentoutlet, s, argc, argv);
}

static void voutlet_anything(t_voutlet *x, t_symbol *s, int argc, t_atom *argv)
{
outlet_anything(x->x_parentoutlet, s, argc, argv);
}

static void voutlet_free(t_voutlet *x)
{
canvas_rmoutlet(x->x_canvas, x->x_parentoutlet);
if (x->x_buf)
t_freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf));
resample_free(&x->x_updown);
}

t_outlet *voutlet_getit(t_pd *x)
{
if (pd_class(x) != voutlet_class) bug("voutlet_getit");
return (((t_voutlet *)x)->x_parentoutlet);
}

/* ------------------------- signal outlet -------------------------- */

int voutlet_issignal(t_voutlet *x)
{
return (x->x_buf != 0);
}

/* LATER optimize for non-overlapped case where the "+=" isn't needed */
t_int *voutlet_perform(t_int *w)
{
t_voutlet *x = (t_voutlet *)(w[1]);
t_float *in = (t_float *)(w[2]);
int n = (int)(w[3]);
t_sample *out = x->x_write, *outwas = out;
while (n--)
{
*out++ += *in++;
if (out == x->x_endbuf) out = x->x_buf;
}
outwas += x->x_hop;
if (outwas >= x->x_endbuf) outwas = x->x_buf;
x->x_write = outwas;
return (w+4);
}

/* epilog code for blocking: write buffer to parent patch */
static t_int *voutlet_doepilog(t_int *w)
{
t_voutlet *x = (t_voutlet *)(w[1]);
t_sample *out = (t_sample *)(w[2]);

int n = (int)(w[3]);
t_sample *in = x->x_empty;
if (x->x_updown.downsample != x->x_updown.upsample)
out = x->x_updown.s_vec;
for (; n--; in++) *out++ = *in, *in = 0;
if (in == x->x_endbuf) in = x->x_buf;
x->x_empty = in;
return (w+4);
}

static t_int *voutlet_doepilog_resampling(t_int *w)
{
t_voutlet *x = (t_voutlet *)(w[1]);
int n = (int)(w[2]);
t_sample *in = x->x_empty;
t_sample *out = x->x_updown.s_vec;
for (; n--; in++) *out++ = *in, *in = 0;
if (in == x->x_endbuf) in = x->x_buf;
x->x_empty = in;
return (w+3);
}

int outlet_getsignalindex(t_outlet *x);

/* prolog for outlets -- store pointer to the outlet on the
parent, which, if "reblock" is false, will want to refer
back to whatever we see on our input during the "dsp" method
called later. */
void voutlet_dspprolog(struct _voutlet *x, t_signal **parentsigs,
int myvecsize, int calcsize, int phase, int period, int frequency,
int downsample, int upsample, int reblock, int switched)
{
/* no buffer means we're not a signal outlet */
if (!x->x_buf)
return;
x->x_updown.downsample=downsample;
x->x_updown.upsample=upsample;
x->x_justcopyout = (switched && !reblock);
if (reblock)
{
x->x_directsignal = 0;
}
else
{
if (!parentsigs) bug("voutlet_dspprolog");
x->x_directsignal =
parentsigs[outlet_getsignalindex(x->x_parentoutlet)];
}
}

static void voutlet_dsp(t_voutlet *x, t_signal **sp)
{
t_signal *insig;
if (!x->x_buf) return;
insig = sp[0];
if (x->x_justcopyout)
dsp_add_copy(insig->s_vec, x->x_directsignal->s_vec, insig->s_n);
else if (x->x_directsignal)
{
/* if we're just going to make the signal available on the
parent patch, hand it off to the parent signal. */
/* this is done elsewhere--> sp[0]->s_refcount++; */
signal_setborrowed(x->x_directsignal, sp[0]);
}
else
dsp_add(voutlet_perform, 3, x, insig->s_vec, insig->s_n);
}

/* set up epilog DSP code. If we're reblocking, this is the
time to copy the samples out to the containing object's outlets.
If we aren't reblocking, there's nothing to do here. */
void voutlet_dspepilog(struct _voutlet *x, t_signal **parentsigs,
int myvecsize, int calcsize, int phase, int period, int frequency,
int downsample, int upsample, int reblock, int switched)
{
if (!x->x_buf) return; /* this shouldn't be necesssary... */
x->x_updown.downsample=downsample;
x->x_updown.upsample=upsample;
if (reblock)
{
t_signal *insig, *outsig;
int parentvecsize, bufsize, oldbufsize;
int re_parentvecsize;
int bigperiod, epilogphase, blockphase;
if (parentsigs)
{
outsig = parentsigs[outlet_getsignalindex(x->x_parentoutlet)];
parentvecsize = outsig->s_vecsize;
re_parentvecsize = parentvecsize * upsample / downsample;
}
else
{
outsig = 0;
parentvecsize = 1;
re_parentvecsize = 1;
}
bigperiod = myvecsize/re_parentvecsize;
if (!bigperiod) bigperiod = 1;
epilogphase = phase & (bigperiod - 1);
blockphase = (phase + period - 1) & (bigperiod - 1) & (- period);
bufsize = re_parentvecsize;
if (bufsize < myvecsize) bufsize = myvecsize;
if (bufsize != (oldbufsize = x->x_bufsize))
{
t_sample *buf = x->x_buf;
t_freebytes(buf, oldbufsize * sizeof(*buf));
buf = (t_sample *)t_getbytes(bufsize * sizeof(*buf));
memset((char *)buf, 0, bufsize * sizeof(*buf));
x->x_bufsize = bufsize;
x->x_endbuf = buf + bufsize;
x->x_buf = buf;
}
if (re_parentvecsize * period > bufsize) bug("voutlet_dspepilog");
x->x_write = x->x_buf + re_parentvecsize * blockphase;
if (x->x_write == x->x_endbuf) x->x_write = x->x_buf;
if (period == 1 && frequency > 1)
x->x_hop = re_parentvecsize / frequency;
else x->x_hop = period * re_parentvecsize;
/* post("phase %d, block %d, parent %d", phase & 63,
parentvecsize * blockphase, parentvecsize * epilogphase); */
if (parentsigs)
{
/* set epilog pointer and schedule it */
x->x_empty = x->x_buf + re_parentvecsize * epilogphase;
if (upsample * downsample == 1)
dsp_add(voutlet_doepilog, 3, x, outsig->s_vec,
re_parentvecsize);
else
{
int method = (x->x_updown.method == 3?
(pd_compatibilitylevel < 44 ? 0 : 1) : x->x_updown.method);
dsp_add(voutlet_doepilog_resampling, 2, x, re_parentvecsize);
resampleto_dsp(&x->x_updown, outsig->s_vec, re_parentvecsize,
parentvecsize, method);
}
}
}
/* if we aren't blocked but we are switched, the epilog code just
copies zeros to the output. In this case the blocking code actually
jumps over the epilog if the block is running. */
else if (switched)
{
if (parentsigs)
{
t_signal *outsig =
parentsigs[outlet_getsignalindex(x->x_parentoutlet)];
dsp_add_zero(outsig->s_vec, outsig->s_n);
}
}
}

static void *voutlet_newsig(t_symbol *s)
{
t_voutlet *x = (t_voutlet *)pd_new(voutlet_class);
x->x_canvas = canvas_getcurrent();
x->x_parentoutlet = canvas_addoutlet(x->x_canvas,
&x->x_obj.ob_pd, &s_signal);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_endbuf = x->x_buf = (t_sample *)getbytes(0);
x->x_bufsize = 0;

resample_init(&x->x_updown);

/* this should be though over:
* it might prove hard to provide consistency between labeled up- & downsampling methods
* maybe indices would be better...
*
* up till now we provide several upsampling methods and 1 single downsampling method (no filtering !)
*/
if (s == gensym("hold"))x->x_updown.method=1; /* up: sample and hold */
else if (s == gensym("lin"))x->x_updown.method=2; /* up: linear interpolation */
else if (s == gensym("linear"))x->x_updown.method=2; /* up: linear interpolation */
else if (s == gensym("pad"))x->x_updown.method=0; /* up: zero pad */
else x->x_updown.method=3; /* up: zero-padding; down: ignore samples inbetween */

return (x);
}


static void voutlet_setup(void)
{
voutlet_class = class_new(gensym("outlet"), (t_newmethod)voutlet_new,
(t_method)voutlet_free, sizeof(t_voutlet), CLASS_NOINLET, A_DEFSYM, 0);
class_addcreator((t_newmethod)voutlet_newsig, gensym("outlet~"), A_DEFSYM, 0);
class_addbang(voutlet_class, voutlet_bang);
class_addpointer(voutlet_class, voutlet_pointer);
class_addfloat(voutlet_class, (t_method)voutlet_float);
class_addsymbol(voutlet_class, voutlet_symbol);
class_addlist(voutlet_class, voutlet_list);
class_addanything(voutlet_class, voutlet_anything);
class_addmethod(voutlet_class, (t_method)voutlet_dsp,
gensym("dsp"), A_CANT, 0);
class_sethelpsymbol(voutlet_class, gensym("pd"));
}


/* ---------------------------- overall setup ----------------------------- */

void g_io_setup(void)
{
vinlet_setup();
voutlet_setup();
}

+ 406
- 0
ports/camomile/source/LibPd/pure-data/src/g_mycanvas.c View File

@@ -0,0 +1,406 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

/* ---------- cnv my gui-canvas for a window ---------------- */

t_widgetbehavior my_canvas_widgetbehavior;
static t_class *my_canvas_class;

/* widget helper functions */

void my_canvas_draw_new(t_my_canvas *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int offset = (IEMGUI_ZOOM(x) > 1 ? IEMGUI_ZOOM(x) : 0); /* keep zoomed border inside visible area */
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxRECT\n",
canvas, xpos, ypos,
xpos + x->x_vis_w * IEMGUI_ZOOM(x),
ypos + x->x_vis_h * IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -outline #%06x -tags %lxBASE\n",
canvas, xpos + offset, ypos + offset,
xpos + offset + x->x_gui.x_w, ypos + offset + x->x_gui.x_h,
IEMGUI_ZOOM(x), x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas,
xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

void my_canvas_draw_move(t_my_canvas *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int offset = (IEMGUI_ZOOM(x) > 1 ? IEMGUI_ZOOM(x) : 0);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxRECT %d %d %d %d\n",
canvas, x, xpos, ypos,
xpos + x->x_vis_w * IEMGUI_ZOOM(x),
ypos + x->x_vis_h * IEMGUI_ZOOM(x));
sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x, xpos + offset, ypos + offset,
xpos + offset + x->x_gui.x_w, ypos + offset + x->x_gui.x_h);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
}

void my_canvas_draw_erase(t_my_canvas* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x);
sys_vgui(".x%lx.c delete %lxRECT\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
}

void my_canvas_draw_config(t_my_canvas* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxRECT -fill #%06x -outline #%06x\n", canvas, x,
x->x_gui.x_bcol, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_bcol));
sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol,
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""));
}

void my_canvas_draw_select(t_my_canvas* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, x->x_gui.x_bcol);
}
}

void my_canvas_draw(t_my_canvas *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_MOVE)
my_canvas_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
my_canvas_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
my_canvas_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
my_canvas_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
my_canvas_draw_config(x, glist);
}

/* ------------------------ cnv widgetbehaviour----------------------------- */

static void my_canvas_getrect(t_gobj *z, t_glist *glist, int *xp1, int *yp1, int *xp2, int *yp2)
{
t_my_canvas *x = (t_my_canvas *)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h;
}

static void my_canvas_save(t_gobj *z, t_binbuf *b)
{
t_my_canvas *x = (t_my_canvas *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiisssiiiissi", gensym("#X"),gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("cnv"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_vis_w, x->x_vis_h,
srl[0], srl[1], srl[2], x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[2], iem_symargstoint(&x->x_gui.x_isa));
binbuf_addv(b, ";");
}

static void my_canvas_properties(t_gobj *z, t_glist *owner)
{
t_my_canvas *x = (t_my_canvas *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);
sprintf(buf, "pdtk_iemgui_dialog %%s |cnv| \
------selectable_dimensions(pix):------ %d %d size: 0.0 0.0 empty \
------visible_rectangle(pix)(pix):------ %d width: %d height: %d \
%d empty empty %d %d empty %d \
%s %s \
%s %d %d \
%d %d \
#%06x none #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), 1,
x->x_vis_w, x->x_vis_h, 0,/*no_schedule*/
-1, -1, -1, -1,/*no linlog, no init, no multi*/
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void my_canvas_get_pos(t_my_canvas *x)
{
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
{
x->x_at[0].a_w.w_float = text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)/IEMGUI_ZOOM(x);
x->x_at[1].a_w.w_float = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)/IEMGUI_ZOOM(x);
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
}

static void my_canvas_dialog(t_my_canvas *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int a = atom_getfloatarg(0, argc, argv);
int w = atom_getfloatarg(2, argc, argv);
int h = atom_getfloatarg(3, argc, argv);
int sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);

x->x_gui.x_isa.x_loadinit = 0;
if(a < 1)
a = 1;
x->x_gui.x_w = a * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
if(w < 1)
w = 1;
x->x_vis_w = w;
if(h < 1)
h = 1;
x->x_vis_h = h;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
}

static void my_canvas_size(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{
int i = atom_getfloatarg(0, ac, av);

if(i < 1)
i = 1;
x->x_gui.x_w = i*IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_size((void *)x, &x->x_gui);
}

static void my_canvas_delta(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void my_canvas_pos(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void my_canvas_vis_size(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{
int i;

i = atom_getfloatarg(0, ac, av);
if(i < 1)
i = 1;
x->x_vis_w = i;
if(ac > 1)
{
i = atom_getfloatarg(1, ac, av);
if(i < 1)
i = 1;
}
x->x_vis_h = i;
if(glist_isvisible(x->x_gui.x_glist))
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
}

static void my_canvas_color(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void my_canvas_send(t_my_canvas *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void my_canvas_receive(t_my_canvas *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void my_canvas_label(t_my_canvas *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void my_canvas_label_pos(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void my_canvas_label_font(t_my_canvas *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void *my_canvas_new(t_symbol *s, int argc, t_atom *argv)
{
t_my_canvas *x = (t_my_canvas *)pd_new(my_canvas_class);
int a = IEM_GUI_DEFAULTSIZE, w = 100, h = 60;
int ldx = 20, ldy = 12, f = 2, i = 0;
int fs = 14;
char str[144];

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0xE0E0E0;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x404040;

if(((argc >= 10)&&(argc <= 13))
&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2))
{
a = atom_getfloatarg(0, argc, argv);
w = atom_getfloatarg(1, argc, argv);
h = atom_getfloatarg(2, argc, argv);
}
if((argc >= 12)&&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3))&&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4)))
{
i = 2;
iemgui_new_getnames(&x->x_gui, 3, argv);
}
else if((argc == 11)&&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3)))
{
i = 1;
iemgui_new_getnames(&x->x_gui, 3, argv);
}
else iemgui_new_getnames(&x->x_gui, 3, 0);

if(((argc >= 10)&&(argc <= 13))
&&(IS_A_SYMBOL(argv,i+3)||IS_A_FLOAT(argv,i+3))&&IS_A_FLOAT(argv,i+4)
&&IS_A_FLOAT(argv,i+5)&&IS_A_FLOAT(argv,i+6)
&&IS_A_FLOAT(argv,i+7))
{
/* disastrously, the "label" sits in a different part of the
message. So we have to track its location separately (in
the slot x_labelbindex) and initialize it specially here. */
iemgui_new_dogetname(&x->x_gui, i+3, argv);
x->x_gui.x_labelbindex = i+4;
ldx = atom_getfloatarg(i+4, argc, argv);
ldy = atom_getfloatarg(i+5, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(i+6, argc, argv));
fs = atom_getfloatarg(i+7, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+i+8, 0, argv+i+9);
}
if((argc == 13)&&IS_A_FLOAT(argv,i+10))
{
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(i+10, argc, argv));
}
x->x_gui.x_draw = (t_iemfunptr)my_canvas_draw;
x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if (!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if (!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(a < 1)
a = 1;
x->x_gui.x_w = a;
x->x_gui.x_h = x->x_gui.x_w;
if(w < 1)
w = 1;
x->x_vis_w = w;
if(h < 1)
h = 1;
x->x_vis_h = h;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if (x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_at[0].a_type = A_FLOAT;
x->x_at[1].a_type = A_FLOAT;
iemgui_verify_snd_ne_rcv(&x->x_gui);
iemgui_newzoom(&x->x_gui);
return (x);
}

static void my_canvas_ff(t_my_canvas *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_mycanvas_setup(void)
{
my_canvas_class = class_new(gensym("cnv"), (t_newmethod)my_canvas_new,
(t_method)my_canvas_ff, sizeof(t_my_canvas), CLASS_NOINLET, A_GIMME, 0);
class_addcreator((t_newmethod)my_canvas_new, gensym("my_canvas"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_size,
gensym("size"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_vis_size,
gensym("vis_size"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_color,
gensym("color"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(my_canvas_class, (t_method)my_canvas_get_pos,
gensym("get_pos"), 0);
class_addmethod(my_canvas_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
my_canvas_widgetbehavior.w_getrectfn = my_canvas_getrect;
my_canvas_widgetbehavior.w_displacefn = iemgui_displace;
my_canvas_widgetbehavior.w_selectfn = iemgui_select;
my_canvas_widgetbehavior.w_activatefn = NULL;
my_canvas_widgetbehavior.w_deletefn = iemgui_delete;
my_canvas_widgetbehavior.w_visfn = iemgui_vis;
my_canvas_widgetbehavior.w_clickfn = NULL;
class_setwidget(my_canvas_class, &my_canvas_widgetbehavior);
class_sethelpsymbol(my_canvas_class, gensym("my_canvas"));
class_setsavefn(my_canvas_class, my_canvas_save);
class_setpropertiesfn(my_canvas_class, my_canvas_properties);
}

+ 926
- 0
ports/camomile/source/LibPd/pure-data/src/g_numbox.c View File

@@ -0,0 +1,926 @@
/* 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. */

/* my_numbox.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#define MINDIGITS 1
#define MINFONT 4

/*------------------ global functions -------------------------*/

static void my_numbox_key(void *z, t_floatarg fkey);
static void my_numbox_draw_update(t_gobj *client, t_glist *glist);

/* ------------ nbx gui-my number box ----------------------- */

t_widgetbehavior my_numbox_widgetbehavior;
static t_class *my_numbox_class;

/* widget helper functions */

static void my_numbox_tick_reset(t_my_numbox *x)
{
if(x->x_gui.x_fsf.x_change && x->x_gui.x_glist)
{
x->x_gui.x_fsf.x_change = 0;
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
}

static void my_numbox_tick_wait(t_my_numbox *x)
{
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}

void my_numbox_clip(t_my_numbox *x)
{
if(x->x_val < x->x_min)
x->x_val = x->x_min;
if(x->x_val > x->x_max)
x->x_val = x->x_max;
}

void my_numbox_calc_fontwidth(t_my_numbox *x)
{
int w, f = 31;

if(x->x_gui.x_fsf.x_font_style == 1)
f = 27;
else if(x->x_gui.x_fsf.x_font_style == 2)
f = 25;

w = x->x_gui.x_fontsize * f * x->x_numwidth;
w /= 36;
x->x_gui.x_w = (w + (x->x_gui.x_h/2)/IEMGUI_ZOOM(x) + 4) * IEMGUI_ZOOM(x);
}

void my_numbox_ftoa(t_my_numbox *x)
{
double f = x->x_val;
int bufsize, is_exp = 0, i, idecimal;

sprintf(x->x_buf, "%g", f);
bufsize = (int)strlen(x->x_buf);
if(bufsize >= 5)/* if it is in exponential mode */
{
i = bufsize - 4;
if((x->x_buf[i] == 'e') || (x->x_buf[i] == 'E'))
is_exp = 1;
}
if(bufsize > x->x_numwidth)/* if to reduce */
{
if(is_exp)
{
if(x->x_numwidth <= 5)
{
x->x_buf[0] = (f < 0.0 ? '-' : '+');
x->x_buf[1] = 0;
}
i = bufsize - 4;
for(idecimal = 0; idecimal < i; idecimal++)
if(x->x_buf[idecimal] == '.')
break;
if(idecimal > (x->x_numwidth - 4))
{
x->x_buf[0] = (f < 0.0 ? '-' : '+');
x->x_buf[1] = 0;
}
else
{
int new_exp_index = x->x_numwidth - 4;
int old_exp_index = bufsize - 4;

for(i = 0; i < 4; i++, new_exp_index++, old_exp_index++)
x->x_buf[new_exp_index] = x->x_buf[old_exp_index];
x->x_buf[x->x_numwidth] = 0;
}
}
else
{
for(idecimal = 0; idecimal < bufsize; idecimal++)
if(x->x_buf[idecimal] == '.')
break;
if(idecimal > x->x_numwidth)
{
x->x_buf[0] = (f < 0.0 ? '-' : '+');
x->x_buf[1] = 0;
}
else
x->x_buf[x->x_numwidth] = 0;
}
}
}

static void my_numbox_draw_update(t_gobj *client, t_glist *glist)
{
t_my_numbox *x = (t_my_numbox *)client;
if(glist_isvisible(glist))
{
if(x->x_gui.x_fsf.x_change)
{
if(x->x_buf[0])
{
char *cp = x->x_buf;
int sl = (int)strlen(x->x_buf);

x->x_buf[sl] = '>';
x->x_buf[sl+1] = 0;
if(sl >= x->x_numwidth)
cp += sl - x->x_numwidth + 1;
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x -text {%s} \n",
glist_getcanvas(glist), x,
IEM_GUI_COLOR_EDITED, cp);
x->x_buf[sl] = 0;
}
else
{
my_numbox_ftoa(x);
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x -text {%s} \n",
glist_getcanvas(glist), x,
IEM_GUI_COLOR_EDITED, x->x_buf);
x->x_buf[0] = 0;
}
}
else
{
my_numbox_ftoa(x);
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x -text {%s} \n",
glist_getcanvas(glist), x,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_fcol),
x->x_buf);
x->x_buf[0] = 0;
}
}
}

static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int w = x->x_gui.x_w, half = x->x_gui.x_h/2;
int d = IEMGUI_ZOOM(x) + x->x_gui.x_h/(34*IEMGUI_ZOOM(x));
int corner = x->x_gui.x_h/4;
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d %d %d "
"-width %d -outline #%06x -fill #%06x -tags %lxBASE1\n",
canvas,
xpos, ypos,
xpos + w - corner, ypos,
xpos + w, ypos + corner,
xpos + w, ypos + x->x_gui.x_h,
xpos, ypos + x->x_gui.x_h,
xpos, ypos,
IEMGUI_ZOOM(x), IEM_GUI_COLOR_NORMAL, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d %d %d -width %d -fill #%06x -tags %lxBASE2\n",
canvas,
xpos + IEMGUI_ZOOM(x), ypos + IEMGUI_ZOOM(x),
xpos + half, ypos + half,
xpos + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - IEMGUI_ZOOM(x),
IEMGUI_ZOOM(x), x->x_gui.x_fcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
my_numbox_ftoa(x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags %lxNUMBER\n",
canvas, xpos + half + 2*IEMGUI_ZOOM(x), ypos + half + d,
x->x_buf, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x),
sys_fontweight, (x->x_gui.x_fsf.x_change ? IEM_GUI_COLOR_EDITED : x->x_gui.x_fcol), x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int w = x->x_gui.x_w, half = x->x_gui.x_h/2;
int d = IEMGUI_ZOOM(x) + x->x_gui.x_h / (34 * IEMGUI_ZOOM(x));
int corner = x->x_gui.x_h/4;
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxBASE1 %d %d %d %d %d %d %d %d %d %d %d %d\n",
canvas, x,
xpos, ypos,
xpos + w - corner, ypos,
xpos + w, ypos + corner,
xpos + w, ypos + x->x_gui.x_h,
xpos, ypos + x->x_gui.x_h,
xpos, ypos);
sys_vgui(".x%lx.c coords %lxBASE2 %d %d %d %d %d %d\n",
canvas, x,
xpos + IEMGUI_ZOOM(x), ypos + IEMGUI_ZOOM(x),
xpos + half, ypos + half,
xpos + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - IEMGUI_ZOOM(x));
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x,
xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
sys_vgui(".x%lx.c coords %lxNUMBER %d %d\n",
canvas, x, xpos + half + 2*IEMGUI_ZOOM(x), ypos + half + d);
}

static void my_numbox_draw_erase(t_my_numbox* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE1\n", canvas, x);
sys_vgui(".x%lx.c delete %lxBASE2\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
sys_vgui(".x%lx.c delete %lxNUMBER\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

static void my_numbox_draw_config(t_my_numbox* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol),
strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name:"");
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -font {{%s} -%d %s} -fill #%06x \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_fcol));
sys_vgui(".x%lx.c itemconfigure %lxBASE1 -fill #%06x\n", canvas,
x, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%06x\n", canvas, x,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_fcol));
}

static void my_numbox_draw_io(t_my_numbox* x,t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) {
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
/* keep these above outlet */
sys_vgui(".x%lx.c raise %lxNUMBER %lxOUT%d\n", canvas, x, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxNUMBER\n", canvas, x, x);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) {
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep these above inlet */
sys_vgui(".x%lx.c raise %lxNUMBER %lxIN%d\n", canvas, x, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxNUMBER\n", canvas, x, x);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
if(x->x_gui.x_fsf.x_change)
{
x->x_gui.x_fsf.x_change = 0;
clock_unset(x->x_clock_reset);
x->x_buf[0] = 0;
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
sys_vgui(".x%lx.c itemconfigure %lxBASE1 -outline #%06x\n",
canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%06x\n",
canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n",
canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x\n",
canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE1 -outline #%06x\n",
canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%06x\n",
canvas, x, x->x_gui.x_fcol);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n",
canvas, x, x->x_gui.x_lcol);
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%06x\n",
canvas, x, x->x_gui.x_fcol);
}
}

void my_numbox_draw(t_my_numbox *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
sys_queuegui(x, glist, my_numbox_draw_update);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
my_numbox_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
my_numbox_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
my_numbox_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
my_numbox_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
my_numbox_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
my_numbox_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ nbx widgetbehaviour----------------------------- */

static void my_numbox_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_my_numbox* x = (t_my_numbox*)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h;
}

static void my_numbox_save(t_gobj *z, t_binbuf *b)
{
t_my_numbox *x = (t_my_numbox *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
if(x->x_gui.x_fsf.x_change)
{
x->x_gui.x_fsf.x_change = 0;
clock_unset(x->x_clock_reset);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
binbuf_addv(b, "ssiisiiffiisssiiiisssfi", gensym("#X"), gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("nbx"), x->x_numwidth, x->x_gui.x_h/IEMGUI_ZOOM(x),
(t_float)x->x_min, (t_float)x->x_max,
x->x_lin0_log1, iem_symargstoint(&x->x_gui.x_isa),
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2],
x->x_val, x->x_log_height);
binbuf_addv(b, ";");
}

int my_numbox_check_minmax(t_my_numbox *x, double min, double max)
{
int ret = 0;

if(x->x_lin0_log1)
{
if((min == 0.0) && (max == 0.0))
max = 1.0;
if(max > 0.0)
{
if(min <= 0.0)
min = 0.01 * max;
}
else
{
if(min > 0.0)
max = 0.01 * min;
}
}
x->x_min = min;
x->x_max = max;
if(x->x_val < x->x_min)
{
x->x_val = x->x_min;
ret = 1;
}
if(x->x_val > x->x_max)
{
x->x_val = x->x_max;
ret = 1;
}
if(x->x_lin0_log1)
x->x_k = exp(log(x->x_max/x->x_min) / (double)(x->x_log_height));
else
x->x_k = 1.0;
return(ret);
}

static void my_numbox_properties(t_gobj *z, t_glist *owner)
{
t_my_numbox *x = (t_my_numbox *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);
if(x->x_gui.x_fsf.x_change)
{
x->x_gui.x_fsf.x_change = 0;
clock_unset(x->x_clock_reset);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
sprintf(buf, "pdtk_iemgui_dialog %%s |nbx| \
-------dimensions(digits)(pix):------- %d %d width: %d %d height: \
-----------output-range:----------- %g min: %g max: %d \
%d lin log %d %d log-height: %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_numwidth, MINDIGITS, x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
x->x_min, x->x_max, 0,/*no_schedule*/
x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, -1,
x->x_log_height, /*no multi, but iem-characteristic*/
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol,
0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void my_numbox_bang(t_my_numbox *x)
{
outlet_float(x->x_gui.x_obj.ob_outlet, x->x_val);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, x->x_val);
}

static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc,
t_atom *argv)
{
t_symbol *srl[3];
int w = (int)atom_getfloatarg(0, argc, argv);
int h = (int)atom_getfloatarg(1, argc, argv);
double min = (double)atom_getfloatarg(2, argc, argv);
double max = (double)atom_getfloatarg(3, argc, argv);
int lilo = (int)atom_getfloatarg(4, argc, argv);
int log_height = (int)atom_getfloatarg(6, argc, argv);
int sr_flags;

if(lilo != 0) lilo = 1;
x->x_lin0_log1 = lilo;
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
if(w < MINDIGITS)
w = MINDIGITS;
x->x_numwidth = w;
if(h < IEM_GUI_MINSIZE)
h = IEM_GUI_MINSIZE;
x->x_gui.x_h = h * IEMGUI_ZOOM(x);
if(log_height < 10)
log_height = 10;
x->x_log_height = log_height;
my_numbox_calc_fontwidth(x);
/*if(my_numbox_check_minmax(x, min, max))
my_numbox_bang(x);*/
my_numbox_check_minmax(x, min, max);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy)
{
double k2 = 1.0;

if(x->x_gui.x_fsf.x_finemoved)
k2 = 0.01;
if(x->x_lin0_log1)
x->x_val *= pow(x->x_k, -k2*dy);
else
x->x_val -= k2*dy;
my_numbox_clip(x);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
my_numbox_bang(x);
clock_unset(x->x_clock_reset);
}

static void my_numbox_click(t_my_numbox *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g,
(t_glistmotionfn)my_numbox_motion, my_numbox_key, xpos, ypos);
}

static int my_numbox_newclick(t_gobj *z, struct _glist *glist,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
t_my_numbox* x = (t_my_numbox *)z;

if(doit)
{
my_numbox_click( x, (t_floatarg)xpix, (t_floatarg)ypix,
(t_floatarg)shift, 0, (t_floatarg)alt);
if(shift)
x->x_gui.x_fsf.x_finemoved = 1;
else
x->x_gui.x_fsf.x_finemoved = 0;
if(!x->x_gui.x_fsf.x_change)
{
clock_delay(x->x_clock_wait, 50);
x->x_gui.x_fsf.x_change = 1;
clock_delay(x->x_clock_reset, 3000);

x->x_buf[0] = 0;
}
else
{
x->x_gui.x_fsf.x_change = 0;
clock_unset(x->x_clock_reset);
x->x_buf[0] = 0;
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
}
return (1);
}

static void my_numbox_set(t_my_numbox *x, t_floatarg f)
{
if(x->x_val != f)
{
x->x_val = f;
my_numbox_clip(x);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
}

static void my_numbox_log_height(t_my_numbox *x, t_floatarg lh)
{
if(lh < 10.0)
lh = 10.0;
x->x_log_height = (int)lh;
if(x->x_lin0_log1)
x->x_k = exp(log(x->x_max/x->x_min)/(double)(x->x_log_height));
else
x->x_k = 1.0;
}

static void my_numbox_float(t_my_numbox *x, t_floatarg f)
{
my_numbox_set(x, f);
if(x->x_gui.x_fsf.x_put_in2out)
my_numbox_bang(x);
}

static void my_numbox_size(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{
int h, w;

w = (int)atom_getfloatarg(0, ac, av);
if(w < MINDIGITS)
w = MINDIGITS;
x->x_numwidth = w;
if(ac > 1)
{
h = (int)atom_getfloatarg(1, ac, av);
if(h < IEM_GUI_MINSIZE)
h = IEM_GUI_MINSIZE;
x->x_gui.x_h = h * IEMGUI_ZOOM(x);
}
my_numbox_calc_fontwidth(x);
iemgui_size((void *)x, &x->x_gui);
}

static void my_numbox_delta(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void my_numbox_pos(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void my_numbox_range(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{
if(my_numbox_check_minmax(x, (double)atom_getfloatarg(0, ac, av),
(double)atom_getfloatarg(1, ac, av)))
{
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
/*my_numbox_bang(x);*/
}
}

static void my_numbox_color(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void my_numbox_send(t_my_numbox *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void my_numbox_receive(t_my_numbox *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void my_numbox_label(t_my_numbox *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void my_numbox_label_pos(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void my_numbox_label_font(t_my_numbox *x,
t_symbol *s, int ac, t_atom *av)
{
int f = (int)atom_getfloatarg(1, ac, av);

if(f < 4)
f = 4;
x->x_gui.x_fontsize = f;
f = (int)atom_getfloatarg(0, ac, av);
if((f < 0) || (f > 2))
f = 0;
x->x_gui.x_fsf.x_font_style = f;
my_numbox_calc_fontwidth(x);
iemgui_label_font((void *)x, &x->x_gui, s, ac, av);
}

static void my_numbox_log(t_my_numbox *x)
{
x->x_lin0_log1 = 1;
if(my_numbox_check_minmax(x, x->x_min, x->x_max))
{
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
/*my_numbox_bang(x);*/
}
}

static void my_numbox_lin(t_my_numbox *x)
{
x->x_lin0_log1 = 0;
}

static void my_numbox_init(t_my_numbox *x, t_floatarg f)
{
x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;
}

static void my_numbox_loadbang(t_my_numbox *x, t_floatarg action)
{
if(action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
{
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
my_numbox_bang(x);
}
}

static void my_numbox_key(void *z, t_floatarg fkey)
{
t_my_numbox *x = z;
char c = fkey;
char buf[3];
buf[1] = 0;

if(c == 0)
{
x->x_gui.x_fsf.x_change = 0;
clock_unset(x->x_clock_reset);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
return;
}
if(((c >= '0') && (c <= '9')) || (c == '.') || (c == '-') ||
(c == 'e') || (c == '+') || (c == 'E'))
{
if(strlen(x->x_buf) < (IEMGUI_MAX_NUM_LEN-2))
{
buf[0] = c;
strcat(x->x_buf, buf);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
}
else if((c == '\b') || (c == 127))
{
int sl = (int)strlen(x->x_buf) - 1;

if(sl < 0)
sl = 0;
x->x_buf[sl] = 0;
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
else if((c == '\n') || (c == 13))
{
x->x_val = atof(x->x_buf);
x->x_buf[0] = 0;
x->x_gui.x_fsf.x_change = 0;
clock_unset(x->x_clock_reset);
my_numbox_clip(x);
my_numbox_bang(x);
sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}
clock_delay(x->x_clock_reset, 3000);
}

static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{
if(!ac) {
my_numbox_bang(x);
}
else if(IS_A_FLOAT(av, 0))
{
my_numbox_set(x, atom_getfloatarg(0, ac, av));
my_numbox_bang(x);
}
}

static void *my_numbox_new(t_symbol *s, int argc, t_atom *argv)
{
t_my_numbox *x = (t_my_numbox *)pd_new(my_numbox_class);
int w = 5, h = 14;
int lilo = 0, f = 0, ldx = 0, ldy = -8;
int fs = 10;
int log_height = 256;
double min = -1.0e+37, max = 1.0e+37, v = 0.0;
char str[144];

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if((argc >= 17)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
&&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3)
&&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
&&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
&&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7))
&&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8))
&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)
&&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,16))
{
w = (int)atom_getfloatarg(0, argc, argv);
h = (int)atom_getfloatarg(1, argc, argv);
min = (double)atom_getfloatarg(2, argc, argv);
max = (double)atom_getfloatarg(3, argc, argv);
lilo = (int)atom_getfloatarg(4, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(5, argc, argv));
iemgui_new_getnames(&x->x_gui, 6, argv);
ldx = (int)atom_getfloatarg(9, argc, argv);
ldy = (int)atom_getfloatarg(10, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(11, argc, argv));
fs = (int)atom_getfloatarg(12, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+13, argv+14, argv+15);
v = atom_getfloatarg(16, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 6, 0);
if((argc == 18)&&IS_A_FLOAT(argv,17))
{
log_height = (int)atom_getfloatarg(17, argc, argv);
}
x->x_gui.x_draw = (t_iemfunptr)my_numbox_draw;
x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if(x->x_gui.x_isa.x_loadinit)
x->x_val = v;
else
x->x_val = 0.0;
if(lilo != 0) lilo = 1;
x->x_lin0_log1 = lilo;
if(log_height < 10)
log_height = 10;
x->x_log_height = log_height;
if(!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if(!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if(x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < MINFONT)
fs = MINFONT;
x->x_gui.x_fontsize = fs;
if(w < MINDIGITS)
w = MINDIGITS;
x->x_numwidth = w;
if(h < IEM_GUI_MINSIZE)
h = IEM_GUI_MINSIZE;
x->x_gui.x_h = h;
x->x_buf[0] = 0;
my_numbox_check_minmax(x, min, max);
iemgui_verify_snd_ne_rcv(&x->x_gui);
x->x_clock_reset = clock_new(x, (t_method)my_numbox_tick_reset);
x->x_clock_wait = clock_new(x, (t_method)my_numbox_tick_wait);
x->x_gui.x_fsf.x_change = 0;
iemgui_newzoom(&x->x_gui);
my_numbox_calc_fontwidth(x);
outlet_new(&x->x_gui.x_obj, &s_float);
return (x);
}

static void my_numbox_free(t_my_numbox *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
clock_free(x->x_clock_reset);
clock_free(x->x_clock_wait);
gfxstub_deleteforkey(x);
}

void g_numbox_setup(void)
{
my_numbox_class = class_new(gensym("nbx"), (t_newmethod)my_numbox_new,
(t_method)my_numbox_free, sizeof(t_my_numbox), 0, A_GIMME, 0);
class_addcreator((t_newmethod)my_numbox_new, gensym("my_numbox"), A_GIMME, 0);
class_addbang(my_numbox_class, my_numbox_bang);
class_addfloat(my_numbox_class, my_numbox_float);
class_addlist(my_numbox_class, my_numbox_list);
class_addmethod(my_numbox_class, (t_method)my_numbox_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_motion,
gensym("motion"), A_FLOAT, A_FLOAT, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_size,
gensym("size"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_range,
gensym("range"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_color,
gensym("color"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_log,
gensym("log"), 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_lin,
gensym("lin"), 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(my_numbox_class, (t_method)my_numbox_log_height,
gensym("log_height"), A_FLOAT, 0);
class_addmethod(my_numbox_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
my_numbox_widgetbehavior.w_getrectfn = my_numbox_getrect;
my_numbox_widgetbehavior.w_displacefn = iemgui_displace;
my_numbox_widgetbehavior.w_selectfn = iemgui_select;
my_numbox_widgetbehavior.w_activatefn = NULL;
my_numbox_widgetbehavior.w_deletefn = iemgui_delete;
my_numbox_widgetbehavior.w_visfn = iemgui_vis;
my_numbox_widgetbehavior.w_clickfn = my_numbox_newclick;
class_setwidget(my_numbox_class, &my_numbox_widgetbehavior);
class_sethelpsymbol(my_numbox_class, gensym("numbox2"));
class_setsavefn(my_numbox_class, my_numbox_save);
class_setpropertiesfn(my_numbox_class, my_numbox_properties);
}

+ 811
- 0
ports/camomile/source/LibPd/pure-data/src/g_readwrite.c View File

@@ -0,0 +1,811 @@
/* Copyright (c) 1997-2002 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/*
Routines to read and write canvases to files:
canvas_savetofile() writes a root canvas to a "pd" file. (Reading "pd" files
is done simply by passing the contents to the pd message interpreter.)
Alternatively, the glist_read() and glist_write() routines read and write
"data" from and to files (reading reads into an existing canvas), using a
file format as in the dialog window for data.
*/

#include <stdlib.h>
#include <stdio.h>
#include "m_pd.h"
#include "g_canvas.h"
#include <string.h>

static t_class *declare_class;
void canvas_savedeclarationsto(t_canvas *x, t_binbuf *b);

/* the following routines read "scalars" from a file into a canvas. */

static int canvas_scanbinbuf(int natoms, t_atom *vec, int *p_indexout,
int *p_next)
{
int i, j;
int indexwas = *p_next;
*p_indexout = indexwas;
if (indexwas >= natoms)
return (0);
for (i = indexwas; i < natoms && vec[i].a_type != A_SEMI; i++)
;
if (i >= natoms)
*p_next = i;
else *p_next = i + 1;
return (i - indexwas);
}

int canvas_readscalar(t_glist *x, int natoms, t_atom *vec,
int *p_nextmsg, int selectit);

static void canvas_readerror(int natoms, t_atom *vec, int message,
int nline, char *s)
{
error("%s", s);
startpost("line was:");
postatom(nline, vec + message);
endpost();
}

/* fill in the contents of the scalar into the vector w. */

static void glist_readatoms(t_glist *x, int natoms, t_atom *vec,
int *p_nextmsg, t_symbol *templatesym, t_word *w, int argc, t_atom *argv)
{
int message, nline, n, i;

t_template *template = template_findbyname(templatesym);
if (!template)
{
error("%s: no such template", templatesym->s_name);
*p_nextmsg = natoms;
return;
}
word_restore(w, template, argc, argv);
n = template->t_n;
for (i = 0; i < n; i++)
{
if (template->t_vec[i].ds_type == DT_ARRAY)
{
int j;
t_array *a = w[i].w_array;
int elemsize = a->a_elemsize, nitems = 0;
t_symbol *arraytemplatesym = template->t_vec[i].ds_arraytemplate;
t_template *arraytemplate =
template_findbyname(arraytemplatesym);
if (!arraytemplate)
{
error("%s: no such template", arraytemplatesym->s_name);
}
else while (1)
{
t_word *element;
int nline = canvas_scanbinbuf(natoms, vec, &message, p_nextmsg);
/* empty line terminates array */
if (!nline)
break;
array_resize(a, nitems + 1);
element = (t_word *)(((char *)a->a_vec) +
nitems * elemsize);
glist_readatoms(x, natoms, vec, p_nextmsg, arraytemplatesym,
element, nline, vec + message);
nitems++;
}
}
else if (template->t_vec[i].ds_type == DT_TEXT)
{
t_binbuf *z = binbuf_new();
int first = *p_nextmsg, last;
for (last = first; last < natoms && vec[last].a_type != A_SEMI;
last++);
binbuf_restore(z, last-first, vec+first);
binbuf_add(w[i].w_binbuf, binbuf_getnatom(z), binbuf_getvec(z));
binbuf_free(z);
last++;
if (last > natoms) last = natoms;
*p_nextmsg = last;
}
}
}

int canvas_readscalar(t_glist *x, int natoms, t_atom *vec,
int *p_nextmsg, int selectit)
{
int message, i, j, nline;
t_template *template;
t_symbol *templatesym;
t_scalar *sc;
int nextmsg = *p_nextmsg;
int wasvis = glist_isvisible(x);

if (nextmsg >= natoms || vec[nextmsg].a_type != A_SYMBOL)
{
if (nextmsg < natoms)
post("stopping early: type %d", vec[nextmsg].a_type);
*p_nextmsg = natoms;
return (0);
}
templatesym = canvas_makebindsym(vec[nextmsg].a_w.w_symbol);
*p_nextmsg = nextmsg + 1;

if (!(template = template_findbyname(templatesym)))
{
error("canvas_read: %s: no such template", templatesym->s_name);
*p_nextmsg = natoms;
return (0);
}
sc = scalar_new(x, templatesym);
if (!sc)
{
error("couldn't create scalar \"%s\"", templatesym->s_name);
*p_nextmsg = natoms;
return (0);
}
if (wasvis)
{
/* temporarily lie about vis flag while this is built */
glist_getcanvas(x)->gl_mapped = 0;
}
glist_add(x, &sc->sc_gobj);

nline = canvas_scanbinbuf(natoms, vec, &message, p_nextmsg);
glist_readatoms(x, natoms, vec, p_nextmsg, templatesym, sc->sc_vec,
nline, vec + message);
if (wasvis)
{
/* reset vis flag as before */
glist_getcanvas(x)->gl_mapped = 1;
gobj_vis(&sc->sc_gobj, x, 1);
}
if (selectit)
{
glist_select(x, &sc->sc_gobj);
}
return (1);
}

void glist_readfrombinbuf(t_glist *x, t_binbuf *b, char *filename, int selectem)
{
t_canvas *canvas = glist_getcanvas(x);
int cr = 0, natoms, nline, message, nextmsg = 0, i, j, nitems;
t_atom *vec;
t_gobj *gobj;

natoms = binbuf_getnatom(b);
vec = binbuf_getvec(b);


/* check for file type */
nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg);
if (nline != 1 && vec[message].a_type != A_SYMBOL &&
strcmp(vec[message].a_w.w_symbol->s_name, "data"))
{
pd_error(x, "%s: file apparently of wrong type", filename);
return;
}
/* read in templates and check for consistency */
while (1)
{
t_template *newtemplate, *existtemplate;
t_symbol *templatesym;
t_atom *templateargs = getbytes(0);
int ntemplateargs = 0, newnargs;
nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg);
if (nline < 2)
{
t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs);
break;
}
else if (nline > 2)
canvas_readerror(natoms, vec, message, nline,
"extra items ignored");
else if (vec[message].a_type != A_SYMBOL ||
strcmp(vec[message].a_w.w_symbol->s_name, "template") ||
vec[message + 1].a_type != A_SYMBOL)
{
canvas_readerror(natoms, vec, message, nline,
"bad template header");
continue;
}
templatesym = canvas_makebindsym(vec[message + 1].a_w.w_symbol);
while (1)
{
nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg);
if (nline != 2 && nline != 3)
break;
newnargs = ntemplateargs + nline;
templateargs = (t_atom *)t_resizebytes(templateargs,
sizeof(*templateargs) * ntemplateargs,
sizeof(*templateargs) * newnargs);
templateargs[ntemplateargs] = vec[message];
templateargs[ntemplateargs + 1] = vec[message + 1];
if (nline == 3)
templateargs[ntemplateargs + 2] = vec[message + 2];
ntemplateargs = newnargs;
}
if (!(existtemplate = template_findbyname(templatesym)))
{
error("%s: template not found in current patch",
templatesym->s_name);
t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs);
return;
}
newtemplate = template_new(templatesym, ntemplateargs, templateargs);
t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs);
if (!template_match(existtemplate, newtemplate))
{
error("%s: template doesn't match current one",
templatesym->s_name);
pd_free(&newtemplate->t_pdobj);
return;
}
pd_free(&newtemplate->t_pdobj);
}
while (nextmsg < natoms)
{
canvas_readscalar(x, natoms, vec, &nextmsg, selectem);
}
}

static void glist_doread(t_glist *x, t_symbol *filename, t_symbol *format,
int clearme)
{
t_binbuf *b = binbuf_new();
t_canvas *canvas = glist_getcanvas(x);
int wasvis = glist_isvisible(canvas);
int cr = 0, natoms, nline, message, nextmsg = 0, i, j;
t_atom *vec;

if (!strcmp(format->s_name, "cr"))
cr = 1;
else if (*format->s_name)
error("qlist_read: unknown flag: %s", format->s_name);

if (binbuf_read_via_canvas(b, filename->s_name, canvas, cr))
{
pd_error(x, "read failed");
binbuf_free(b);
return;
}
if (wasvis)
canvas_vis(canvas, 0);
if (clearme)
glist_clear(x);
glist_readfrombinbuf(x, b, filename->s_name, 0);
if (wasvis)
canvas_vis(canvas, 1);
binbuf_free(b);
}

void glist_read(t_glist *x, t_symbol *filename, t_symbol *format)
{
glist_doread(x, filename, format, 1);
}

void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format)
{
glist_doread(x, filename, format, 0);
}

/* read text from a "properties" window, called from a gfxstub set
up in scalar_properties(). We try to restore the object; if successful
we either copy the data from the new scalar to the old one in place
(if their templates match) or else delete the old scalar and put the new
thing in its place on the list. */
void canvas_dataproperties(t_canvas *x, t_scalar *sc, t_binbuf *b)
{
int ntotal, nnew, scindex;
t_gobj *y, *y2 = 0, *newone, *oldone = 0;
t_template *template;
glist_noselect(x);
for (y = x->gl_list, ntotal = 0, scindex = -1; y; y = y->g_next)
{
if (y == &sc->sc_gobj)
scindex = ntotal, oldone = y;
ntotal++;
}

if (scindex == -1)
{
error("data_properties: scalar disappeared");
return;
}
glist_readfrombinbuf(x, b, "properties dialog", 0);
newone = 0;
/* take the new object off the list */
if (ntotal)
{
for (y = x->gl_list, nnew = 1; (y2 = y->g_next);
y = y2, nnew++)
if (nnew == ntotal)
{
newone = y2;
gobj_vis(newone, x, 0);
y->g_next = y2->g_next;
break;
}
}
else gobj_vis((newone = x->gl_list), x, 0), x->gl_list = newone->g_next;
if (!newone)
error("couldn't update properties (perhaps a format problem?)");
else if (!oldone)
bug("data_properties: couldn't find old element");
else if (newone->g_pd == scalar_class && oldone->g_pd == scalar_class
&& ((t_scalar *)newone)->sc_template ==
((t_scalar *)oldone)->sc_template
&& (template = template_findbyname(((t_scalar *)newone)->sc_template)))
{
/* swap new one with old one; then delete new one */
int i;
for (i = 0; i < template->t_n; i++)
{
t_word w = ((t_scalar *)newone)->sc_vec[i];
((t_scalar *)newone)->sc_vec[i] = ((t_scalar *)oldone)->sc_vec[i];
((t_scalar *)oldone)->sc_vec[i] = w;
}
pd_free(&newone->g_pd);
if (glist_isvisible(x))
{
gobj_vis(oldone, x, 0);
gobj_vis(oldone, x, 1);
}
}
else
{
/* delete old one; put new one where the old one was on glist */
glist_delete(x, oldone);
if (scindex > 0)
{
for (y = x->gl_list, nnew = 1; y;
y = y->g_next, nnew++)
if (nnew == scindex || !y->g_next)
{
newone->g_next = y->g_next;
y->g_next = newone;
goto didit;
}
bug("data_properties: can't reinsert");
}
else newone->g_next = x->gl_list, x->gl_list = newone;
}
didit:
;
}

/* ----------- routines to write data to a binbuf ----------- */

void canvas_doaddtemplate(t_symbol *templatesym,
int *p_ntemplates, t_symbol ***p_templatevec)
{
int n = *p_ntemplates, i;
t_symbol **templatevec = *p_templatevec;
for (i = 0; i < n; i++)
if (templatevec[i] == templatesym)
return;
templatevec = (t_symbol **)t_resizebytes(templatevec,
n * sizeof(*templatevec), (n+1) * sizeof(*templatevec));
templatevec[n] = templatesym;
*p_templatevec = templatevec;
*p_ntemplates = n+1;
}

static void glist_writelist(t_gobj *y, t_binbuf *b);

void binbuf_savetext(t_binbuf *bfrom, t_binbuf *bto);

void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
int amarrayelement)
{
t_dataslot *ds;
t_template *template = template_findbyname(templatesym);
t_atom *a = (t_atom *)t_getbytes(0);
int i, n = template?(template->t_n):0, natom = 0;
if (!amarrayelement)
{
t_atom templatename;
SETSYMBOL(&templatename, gensym(templatesym->s_name + 3));
binbuf_add(b, 1, &templatename);
}
if (!template)
bug("canvas_writescalar");
/* write the atoms (floats and symbols) */
for (i = 0; i < n; i++)
{
if (template->t_vec[i].ds_type == DT_FLOAT ||
template->t_vec[i].ds_type == DT_SYMBOL)
{
a = (t_atom *)t_resizebytes(a,
natom * sizeof(*a), (natom + 1) * sizeof (*a));
if (template->t_vec[i].ds_type == DT_FLOAT)
SETFLOAT(a + natom, w[i].w_float);
else SETSYMBOL(a + natom, w[i].w_symbol);
natom++;
}
}
/* array elements have to have at least something */
if (natom == 0 && amarrayelement)
SETSYMBOL(a + natom, &s_bang), natom++;
binbuf_add(b, natom, a);
binbuf_addsemi(b);
t_freebytes(a, natom * sizeof(*a));
for (i = 0; i < n; i++)
{
if (template->t_vec[i].ds_type == DT_ARRAY)
{
int j;
t_array *a = w[i].w_array;
int elemsize = a->a_elemsize, nitems = a->a_n;
t_symbol *arraytemplatesym = template->t_vec[i].ds_arraytemplate;
for (j = 0; j < nitems; j++)
canvas_writescalar(arraytemplatesym,
(t_word *)(((char *)a->a_vec) + elemsize * j), b, 1);
binbuf_addsemi(b);
}
else if (template->t_vec[i].ds_type == DT_TEXT)
binbuf_savetext(w[i].w_binbuf, b);
}
}

static void glist_writelist(t_gobj *y, t_binbuf *b)
{
for (; y; y = y->g_next)
{
if (pd_class(&y->g_pd) == scalar_class)
{
canvas_writescalar(((t_scalar *)y)->sc_template,
((t_scalar *)y)->sc_vec, b, 0);
}
}
}

/* ------------ routines to write out templates for data ------- */

static void canvas_addtemplatesforlist(t_gobj *y,
int *p_ntemplates, t_symbol ***p_templatevec);

static void canvas_addtemplatesforscalar(t_symbol *templatesym,
t_word *w, int *p_ntemplates, t_symbol ***p_templatevec)
{
t_dataslot *ds;
int i;
t_template *template = template_findbyname(templatesym);
canvas_doaddtemplate(templatesym, p_ntemplates, p_templatevec);
if (!template)
bug("canvas_addtemplatesforscalar");
else for (ds = template->t_vec, i = template->t_n; i--; ds++, w++)
{
if (ds->ds_type == DT_ARRAY)
{
int j;
t_array *a = w->w_array;
int elemsize = a->a_elemsize, nitems = a->a_n;
t_symbol *arraytemplatesym = ds->ds_arraytemplate;
canvas_doaddtemplate(arraytemplatesym, p_ntemplates, p_templatevec);
for (j = 0; j < nitems; j++)
canvas_addtemplatesforscalar(arraytemplatesym,
(t_word *)(((char *)a->a_vec) + elemsize * j),
p_ntemplates, p_templatevec);
}
}
}

static void canvas_addtemplatesforlist(t_gobj *y,
int *p_ntemplates, t_symbol ***p_templatevec)
{
for (; y; y = y->g_next)
{
if (pd_class(&y->g_pd) == scalar_class)
{
canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template,
((t_scalar *)y)->sc_vec, p_ntemplates, p_templatevec);
}
}
}

/* write all "scalars" in a glist to a binbuf. */
t_binbuf *glist_writetobinbuf(t_glist *x, int wholething)
{
int i;
t_symbol **templatevec = getbytes(0);
int ntemplates = 0;
t_gobj *y;
t_binbuf *b = binbuf_new();

for (y = x->gl_list; y; y = y->g_next)
{
if ((pd_class(&y->g_pd) == scalar_class) &&
(wholething || glist_isselected(x, y)))
{
canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template,
((t_scalar *)y)->sc_vec, &ntemplates, &templatevec);
}
}
binbuf_addv(b, "s;", gensym("data"));
for (i = 0; i < ntemplates; i++)
{
t_template *template = template_findbyname(templatevec[i]);
int j, m = template->t_n;
/* drop "pd-" prefix from template symbol to print it: */
binbuf_addv(b, "ss;", gensym("template"),
gensym(templatevec[i]->s_name + 3));
for (j = 0; j < m; j++)
{
t_symbol *type;
switch (template->t_vec[j].ds_type)
{
case DT_FLOAT: type = &s_float; break;
case DT_SYMBOL: type = &s_symbol; break;
case DT_ARRAY: type = gensym("array"); break;
case DT_TEXT: type = &s_list; break;
default: type = &s_float; bug("canvas_write");
}
if (template->t_vec[j].ds_type == DT_ARRAY)
binbuf_addv(b, "sss;", type, template->t_vec[j].ds_name,
gensym(template->t_vec[j].ds_arraytemplate->s_name + 3));
else binbuf_addv(b, "ss;", type, template->t_vec[j].ds_name);
}
binbuf_addsemi(b);
}
binbuf_addsemi(b);
/* now write out the objects themselves */
for (y = x->gl_list; y; y = y->g_next)
{
if ((pd_class(&y->g_pd) == scalar_class) &&
(wholething || glist_isselected(x, y)))
{
canvas_writescalar(((t_scalar *)y)->sc_template,
((t_scalar *)y)->sc_vec, b, 0);
}
}
t_freebytes(templatevec, ntemplates*sizeof(*templatevec));
return (b);
}

static void glist_write(t_glist *x, t_symbol *filename, t_symbol *format)
{
int cr = 0, i;
t_binbuf *b;
char buf[MAXPDSTRING];
t_gobj *y;
t_canvas *canvas = glist_getcanvas(x);
canvas_makefilename(canvas, filename->s_name, buf, MAXPDSTRING);
if (!strcmp(format->s_name, "cr"))
cr = 1;
else if (*format->s_name)
error("qlist_read: unknown flag: %s", format->s_name);

b = glist_writetobinbuf(x, 1);
if (b)
{
if (binbuf_write(b, buf, "", cr))
error("%s: write failed", filename->s_name);
binbuf_free(b);
}
}

/* ------ routines to save and restore canvases (patches) recursively. ----*/

typedef void (*t_zoomfn)(void *x, t_floatarg arg1);

/* save to a binbuf, called recursively; cf. canvas_savetofile() which
saves the document, and is only called on root canvases. */
static void canvas_saveto(t_canvas *x, t_binbuf *b)
{
t_gobj *y;
t_linetraverser t;
t_outconnect *oc;
int zoomwas = x->gl_zoom;

if (zoomwas > 1)
{
t_zoomfn zoommethod = (t_zoomfn)zgetfn(&x->gl_pd, gensym("zoom"));
if (zoommethod)
(*zoommethod)(&x->gl_pd, (t_floatarg)1);
}
/* subpatch */
if (x->gl_owner && !x->gl_env)
{
/* have to go to original binbuf to find out how we were named. */
t_binbuf *bz = binbuf_new();
t_symbol *patchsym;
binbuf_addbinbuf(bz, x->gl_obj.ob_binbuf);
patchsym = atom_getsymbolarg(1, binbuf_getnatom(bz), binbuf_getvec(bz));
binbuf_free(bz);
binbuf_addv(b, "ssiiiisi;", gensym("#N"), gensym("canvas"),
(int)(x->gl_screenx1),
(int)(x->gl_screeny1),
(int)(x->gl_screenx2 - x->gl_screenx1),
(int)(x->gl_screeny2 - x->gl_screeny1),
(patchsym != &s_ ? patchsym: gensym("(subpatch)")),
x->gl_mapped);
}
/* root or abstraction */
else
{
binbuf_addv(b, "ssiiiii;", gensym("#N"), gensym("canvas"),
(int)(x->gl_screenx1),
(int)(x->gl_screeny1),
(int)(x->gl_screenx2 - x->gl_screenx1),
(int)(x->gl_screeny2 - x->gl_screeny1),
(int)x->gl_font);
canvas_savedeclarationsto(x, b);
}
for (y = x->gl_list; y; y = y->g_next)
gobj_save(y, b);

linetraverser_start(&t, x);
while ((oc = linetraverser_next(&t)))
{
int srcno = canvas_getindex(x, &t.tr_ob->ob_g);
int sinkno = canvas_getindex(x, &t.tr_ob2->ob_g);
binbuf_addv(b, "ssiiii;", gensym("#X"), gensym("connect"),
srcno, t.tr_outno, sinkno, t.tr_inno);
}
/* unless everything is the default (as in ordinary subpatches)
print out a "coords" message to set up the coordinate systems */
if (x->gl_isgraph || x->gl_x1 || x->gl_y1 ||
x->gl_x2 != 1 || x->gl_y2 != 1 || x->gl_pixwidth || x->gl_pixheight)
{
if (x->gl_isgraph && x->gl_goprect)
/* if we have a graph-on-parent rectangle, we're new style.
The format is arranged so
that old versions of Pd can at least do something with it. */
binbuf_addv(b, "ssfffffffff;", gensym("#X"), gensym("coords"),
x->gl_x1, x->gl_y1,
x->gl_x2, x->gl_y2,
(t_float)x->gl_pixwidth, (t_float)x->gl_pixheight,
(t_float)((x->gl_hidetext)?2.:1.),
(t_float)x->gl_xmargin, (t_float)x->gl_ymargin);
/* otherwise write in 0.38-compatible form */
else binbuf_addv(b, "ssfffffff;", gensym("#X"), gensym("coords"),
x->gl_x1, x->gl_y1,
x->gl_x2, x->gl_y2,
(t_float)x->gl_pixwidth, (t_float)x->gl_pixheight,
(t_float)x->gl_isgraph);
}
if (zoomwas > 1)
{
t_zoomfn zoommethod = (t_zoomfn)zgetfn(&x->gl_pd, gensym("zoom"));
if (zoommethod)
(*zoommethod)(&x->gl_pd, (t_floatarg)zoomwas);
}
}

/* call this recursively to collect all the template names for
a canvas or for the selection. */
static void canvas_collecttemplatesfor(t_canvas *x, int *ntemplatesp,
t_symbol ***templatevecp, int wholething)
{
t_gobj *y;

for (y = x->gl_list; y; y = y->g_next)
{
if ((pd_class(&y->g_pd) == scalar_class) &&
(wholething || glist_isselected(x, y)))
canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template,
((t_scalar *)y)->sc_vec, ntemplatesp, templatevecp);
else if ((pd_class(&y->g_pd) == canvas_class) &&
(wholething || glist_isselected(x, y)))
canvas_collecttemplatesfor((t_canvas *)y,
ntemplatesp, templatevecp, 1);
}
}

/* save the templates needed by a canvas to a binbuf. */
static void canvas_savetemplatesto(t_canvas *x, t_binbuf *b, int wholething)
{
t_symbol **templatevec = getbytes(0);
int i, ntemplates = 0;
t_gobj *y;
canvas_collecttemplatesfor(x, &ntemplates, &templatevec, wholething);
for (i = 0; i < ntemplates; i++)
{
t_template *template = template_findbyname(templatevec[i]);
int j, m;
if (!template)
{
bug("canvas_savetemplatesto");
continue;
}
m = template->t_n;
/* drop "pd-" prefix from template symbol to print */
binbuf_addv(b, "sss", &s__N, gensym("struct"),
gensym(templatevec[i]->s_name + 3));
for (j = 0; j < m; j++)
{
t_symbol *type;
switch (template->t_vec[j].ds_type)
{
case DT_FLOAT: type = &s_float; break;
case DT_SYMBOL: type = &s_symbol; break;
case DT_ARRAY: type = gensym("array"); break;
case DT_TEXT: type = gensym("text"); break;
default: type = &s_float; bug("canvas_write");
}
if (template->t_vec[j].ds_type == DT_ARRAY)
binbuf_addv(b, "sss", type, template->t_vec[j].ds_name,
gensym(template->t_vec[j].ds_arraytemplate->s_name + 3));
else binbuf_addv(b, "ss", type, template->t_vec[j].ds_name);
}
binbuf_addsemi(b);
}
}

void canvas_reload(t_symbol *name, t_symbol *dir, t_glist *except);

/* save a "root" canvas to a file; cf. canvas_saveto() which saves the
body (and which is called recursively.) */
static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir,
float fdestroy)
{
t_binbuf *b = binbuf_new();
canvas_savetemplatesto(x, b, 1);
canvas_saveto(x, b);
if (binbuf_write(b, filename->s_name, dir->s_name, 0)) sys_ouch();
else
{
/* if not an abstraction, reset title bar and directory */
if (!x->gl_owner)
{
canvas_rename(x, filename, dir);
/* update window list in case Save As changed the window name */
canvas_updatewindowlist();
}
post("saved to: %s/%s", dir->s_name, filename->s_name);
canvas_dirty(x, 0);
canvas_reload(filename, dir, x);
if (fdestroy != 0)
vmess(&x->gl_pd, gensym("menuclose"), "f", 1.);
}
binbuf_free(b);
}

static void canvas_menusaveas(t_canvas *x, float fdestroy)
{
t_canvas *x2 = canvas_getrootfor(x);
sys_vgui("pdtk_canvas_saveas .x%lx {%s} {%s} %d\n", x2,
x2->gl_name->s_name, canvas_getdir(x2)->s_name, (fdestroy != 0));
}

static void canvas_menusave(t_canvas *x, float fdestroy)
{
t_canvas *x2 = canvas_getrootfor(x);
char *name = x2->gl_name->s_name;
if (*name && strncmp(name, "Untitled", 8)
&& (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat")
|| strcmp(name + strlen(name)-4, ".mxt")))
{
canvas_savetofile(x2, x2->gl_name, canvas_getdir(x2), fdestroy);
}
else canvas_menusaveas(x2, fdestroy);
}

void g_readwrite_setup(void)
{
class_addmethod(canvas_class, (t_method)glist_write,
gensym("write"), A_SYMBOL, A_DEFSYM, A_NULL);
class_addmethod(canvas_class, (t_method)glist_read,
gensym("read"), A_SYMBOL, A_DEFSYM, A_NULL);
class_addmethod(canvas_class, (t_method)glist_mergefile,
gensym("mergefile"), A_SYMBOL, A_DEFSYM, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_savetofile,
gensym("savetofile"), A_SYMBOL, A_SYMBOL, A_DEFFLOAT, 0);
class_addmethod(canvas_class, (t_method)canvas_saveto,
gensym("saveto"), A_CANT, 0);
/* ------------------ from the menu ------------------------- */
class_addmethod(canvas_class, (t_method)canvas_menusave,
gensym("menusave"), A_DEFFLOAT, 0);
class_addmethod(canvas_class, (t_method)canvas_menusaveas,
gensym("menusaveas"), A_DEFFLOAT, 0);
}

void canvas_readwrite_for_class(t_class *c)
{
class_addmethod(c, (t_method)canvas_menusave,
gensym("menusave"), A_DEFFLOAT, 0);
class_addmethod(c, (t_method)canvas_menusaveas,
gensym("menusaveas"), A_DEFFLOAT, 0);
}

+ 664
- 0
ports/camomile/source/LibPd/pure-data/src/g_rtext.c View File

@@ -0,0 +1,664 @@
/* 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. */

/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
/* have to insert gui-objects into editor-list */
/* all changes are labeled with iemlib */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "s_stuff.h"
#include "g_canvas.h"
#include "s_utf8.h"

#define LMARGIN 2
#define RMARGIN 2
#define TMARGIN 3
#define BMARGIN 2

#define SEND_FIRST 1
#define SEND_UPDATE 2
#define SEND_CHECK 0

struct _rtext
{
char *x_buf; /*-- raw byte string, assumed UTF-8 encoded (moo) --*/
int x_bufsize; /*-- byte length --*/
int x_selstart; /*-- byte offset --*/
int x_selend; /*-- byte offset --*/
int x_active;
int x_dragfrom;
int x_height;
int x_drawnwidth;
int x_drawnheight;
t_text *x_text;
t_glist *x_glist;
char x_tag[50];
struct _rtext *x_next;
};

t_rtext *rtext_new(t_glist *glist, t_text *who)
{
t_rtext *x = (t_rtext *)getbytes(sizeof *x);
int w = 0, h = 0, indx;
x->x_height = -1;
x->x_text = who;
x->x_glist = glist;
x->x_next = glist->gl_editor->e_rtext;
x->x_selstart = x->x_selend = x->x_active =
x->x_drawnwidth = x->x_drawnheight = 0;
binbuf_gettext(who->te_binbuf, &x->x_buf, &x->x_bufsize);
glist->gl_editor->e_rtext = x;
sprintf(x->x_tag, ".x%lx.t%lx", (t_int)glist_getcanvas(x->x_glist),
(t_int)x);
return (x);
}

void rtext_free(t_rtext *x)
{
if (x->x_glist->gl_editor->e_textedfor == x)
x->x_glist->gl_editor->e_textedfor = 0;
if (x->x_glist->gl_editor->e_rtext == x)
x->x_glist->gl_editor->e_rtext = x->x_next;
else
{
t_rtext *e2;
for (e2 = x->x_glist->gl_editor->e_rtext; e2; e2 = e2->x_next)
if (e2->x_next == x)
{
e2->x_next = x->x_next;
break;
}
}
freebytes(x->x_buf, x->x_bufsize);
freebytes(x, sizeof *x);
}

char *rtext_gettag(t_rtext *x)
{
return (x->x_tag);
}

void rtext_gettext(t_rtext *x, char **buf, int *bufsize)
{
*buf = x->x_buf;
*bufsize = x->x_bufsize;
}

void rtext_getseltext(t_rtext *x, char **buf, int *bufsize)
{
*buf = x->x_buf + x->x_selstart;
*bufsize = x->x_selend - x->x_selstart;
}

/* convert t_text te_type symbol for use as a Tk tag */
static t_symbol *rtext_gettype(t_rtext *x)
{
switch (x->x_text->te_type)
{
case T_TEXT: return gensym("text");
case T_OBJECT: return gensym("obj");
case T_MESSAGE: return gensym("msg");
case T_ATOM: return gensym("atom");
}
return (&s_);
}

/* LATER deal with tcl-significant characters */

/* firstone(), lastone()
* + returns byte offset of (first|last) occurrence of 'c' in 's[0..n-1]', or
* -1 if none was found
* + 's' is a raw byte string
* + 'c' is a byte value
* + 'n' is the length (in bytes) of the prefix of 's' to be searched.
* + we could make these functions work on logical characters in utf8 strings,
* but we don't really need to...
*/
static int firstone(char *s, int c, int n)
{
char *s2 = s + n;
int i = 0;
while (s != s2)
{
if (*s == c) return (i);
i++;
s++;
}
return (-1);
}

static int lastone(char *s, int c, int n)
{
char *s2 = s + n;
while (s2 != s)
{
s2--;
n--;
if (*s2 == c) return (n);
}
return (-1);
}

/* the following routine computes line breaks and carries out
some action which could be:
SEND_FIRST - draw the box for the first time
SEND_UPDATE - redraw the updated box
otherwise - don't draw, just calculate.
Called with *widthp and *heightp as coordinates of
a test point, the routine reports the index of the character found
there in *indexp. *widthp and *heightp are set to the width and height
of the entire text in pixels.
*/

/*-- moo:
* + some variables from the original version have been renamed
* + variables with a "_b" suffix are raw byte strings, lengths, or offsets
* + variables with a "_c" suffix are logical character lengths or offsets
* (assuming valid UTF-8 encoded byte string in x->x_buf)
* + a fair amount of O(n) computations required to convert between raw byte
* offsets (needed by the C side) and logical character offsets (needed by
* the GUI)
*/

/* LATER get this and sys_vgui to work together properly,
breaking up messages as needed. As of now, there's
a limit of 1950 characters, imposed by sys_vgui(). */
#define UPBUFSIZE 4000
#define BOXWIDTH 60

static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
int *indexp)
{
t_float dispx, dispy;
char smallbuf[200], *tempbuf;
int outchars_b = 0, nlines = 0, ncolumns = 0,
pixwide, pixhigh, font, fontwidth, fontheight, findx, findy;
int reportedindex = 0;
t_canvas *canvas = glist_getcanvas(x->x_glist);
int widthspec_c = x->x_text->te_width;
int widthlimit_c = (widthspec_c ? widthspec_c : BOXWIDTH);
int inindex_b = 0;
int inindex_c = 0;
int selstart_b = 0, selend_b = 0;
int x_bufsize_c = u8_charnum(x->x_buf, x->x_bufsize);
/* if we're a GOP (the new, "goprect" style) borrow the font size
from the inside to preserve the spacing */
if (pd_class(&x->x_text->te_pd) == canvas_class &&
((t_glist *)(x->x_text))->gl_isgraph &&
((t_glist *)(x->x_text))->gl_goprect)
{
font = glist_getfont((t_glist *)(x->x_text));
fontwidth = glist_fontwidth((t_glist *)(x->x_text));
fontheight = glist_fontheight((t_glist *)(x->x_text));
}
else
{
font = glist_getfont(x->x_glist);
fontwidth = glist_fontwidth(x->x_glist);
fontheight = glist_fontheight(x->x_glist);
}
findx = (*widthp + (fontwidth/2)) / fontwidth;
findy = *heightp / fontheight;
if (x->x_bufsize >= 100)
tempbuf = (char *)t_getbytes(2 * x->x_bufsize + 1);
else tempbuf = smallbuf;
while (x_bufsize_c - inindex_c > 0)
{
int inchars_b = x->x_bufsize - inindex_b;
int inchars_c = x_bufsize_c - inindex_c;
int maxindex_c = (inchars_c > widthlimit_c ? widthlimit_c : inchars_c);
int maxindex_b = u8_offset(x->x_buf + inindex_b, maxindex_c);
int eatchar = 1;
int foundit_b = firstone(x->x_buf + inindex_b, '\n', maxindex_b);
int foundit_c;
if (foundit_b < 0)
{
/* too much text to fit in one line? */
if (inchars_c > widthlimit_c)
{
/* is there a space to break the line at? OK if it's even
one byte past the end since in this context we know there's
more text */
foundit_b = lastone(x->x_buf + inindex_b, ' ', maxindex_b + 1);
if (foundit_b < 0)
{
foundit_b = maxindex_b;
foundit_c = maxindex_c;
eatchar = 0;
}
else
foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b);
}
else
{
foundit_b = inchars_b;
foundit_c = inchars_c;
eatchar = 0;
}
}
else
foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b);

if (nlines == findy)
{
int actualx = (findx < 0 ? 0 :
(findx > foundit_c ? foundit_c : findx));
*indexp = inindex_b + u8_offset(x->x_buf + inindex_b, actualx);
reportedindex = 1;
}
strncpy(tempbuf+outchars_b, x->x_buf + inindex_b, foundit_b);
if (x->x_selstart >= inindex_b &&
x->x_selstart <= inindex_b + foundit_b + eatchar)
selstart_b = x->x_selstart + outchars_b - inindex_b;
if (x->x_selend >= inindex_b &&
x->x_selend <= inindex_b + foundit_b + eatchar)
selend_b = x->x_selend + outchars_b - inindex_b;
outchars_b += foundit_b;
inindex_b += (foundit_b + eatchar);
inindex_c += (foundit_c + eatchar);
if (inindex_b < x->x_bufsize)
tempbuf[outchars_b++] = '\n';
if (foundit_c > ncolumns)
ncolumns = foundit_c;
nlines++;
}
if (!reportedindex)
*indexp = outchars_b;
dispx = text_xpix(x->x_text, x->x_glist);
dispy = text_ypix(x->x_text, x->x_glist);
if (nlines < 1) nlines = 1;
if (!widthspec_c)
{
while (ncolumns < (x->x_text->te_type == T_TEXT ? 1 : 3))
{
tempbuf[outchars_b++] = ' ';
ncolumns++;
}
}
else ncolumns = widthspec_c;
pixwide = ncolumns * fontwidth;
pixhigh = nlines * fontheight;
if (glist_getzoom(x->x_glist) > 1)
{
/* zoom margins */
pixwide += (LMARGIN + RMARGIN) * glist_getzoom(x->x_glist);
pixhigh += (TMARGIN + BMARGIN) * glist_getzoom(x->x_glist);
}
else
{
pixwide += LMARGIN + RMARGIN;
pixhigh += TMARGIN + BMARGIN;
}

if (action && x->x_text->te_width && x->x_text->te_type != T_ATOM)
{
/* if our width is specified but the "natural" width is the
same as the specified width, set specified width to zero
so future text editing will automatically change width.
Except atoms whose content changes at runtime. */
int widthwas = x->x_text->te_width, newwidth = 0, newheight = 0,
newindex = 0;
x->x_text->te_width = 0;
rtext_senditup(x, 0, &newwidth, &newheight, &newindex);
if (newwidth/fontwidth != widthwas)
x->x_text->te_width = widthwas;
else x->x_text->te_width = 0;
}
if (action == SEND_FIRST)
{
int lmargin = LMARGIN, tmargin = TMARGIN;
if (glist_getzoom(x->x_glist) > 1)
{
/* zoom margins */
lmargin *= glist_getzoom(x->x_glist);
tmargin *= glist_getzoom(x->x_glist);
}
sys_vgui("pdtk_text_new .x%lx.c {%s %s text} %f %f {%.*s} %d %s\n",
canvas, x->x_tag, rtext_gettype(x)->s_name,
dispx + lmargin, dispy + tmargin,
outchars_b, tempbuf,
sys_hostfontsize(font, glist_getzoom(x->x_glist)),
(glist_isselected(x->x_glist,
&x->x_glist->gl_gobj)? "blue" : "black"));
}
else if (action == SEND_UPDATE)
{
sys_vgui("pdtk_text_set .x%lx.c %s {%.*s}\n",
canvas, x->x_tag, outchars_b, tempbuf);
if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight)
text_drawborder(x->x_text, x->x_glist, x->x_tag,
pixwide, pixhigh, 0);
if (x->x_active)
{
if (selend_b > selstart_b)
{
sys_vgui(".x%lx.c select from %s %d\n", canvas,
x->x_tag, u8_charnum(x->x_buf, selstart_b));
sys_vgui(".x%lx.c select to %s %d\n", canvas,
x->x_tag, u8_charnum(x->x_buf, selend_b) - 1);
sys_vgui(".x%lx.c focus \"\"\n", canvas);
}
else
{
sys_vgui(".x%lx.c select clear\n", canvas);
sys_vgui(".x%lx.c icursor %s %d\n", canvas, x->x_tag,
u8_charnum(x->x_buf, selstart_b));
sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag);
}
}
}
x->x_drawnwidth = pixwide;
x->x_drawnheight = pixhigh;

*widthp = pixwide;
*heightp = pixhigh;
if (tempbuf != smallbuf)
t_freebytes(tempbuf, 2 * x->x_bufsize + 1);
}

void rtext_retext(t_rtext *x)
{
int w = 0, h = 0, indx;
t_text *text = x->x_text;
t_freebytes(x->x_buf, x->x_bufsize);
binbuf_gettext(text->te_binbuf, &x->x_buf, &x->x_bufsize);
/* special case: for number boxes, try to pare the number down
to the specified width of the box. */
if (text->te_width > 0 && text->te_type == T_ATOM &&
x->x_bufsize > text->te_width)
{
t_atom *atomp = binbuf_getvec(text->te_binbuf);
int natom = binbuf_getnatom(text->te_binbuf);
int bufsize = x->x_bufsize;
if (natom == 1 && atomp->a_type == A_FLOAT)
{
/* try to reduce size by dropping decimal digits */
int wantreduce = bufsize - text->te_width;
char *decimal = 0, *nextchar, *ebuf = x->x_buf + bufsize,
*s1, *s2;
int ndecimals;
for (decimal = x->x_buf; decimal < ebuf; decimal++)
if (*decimal == '.')
break;
if (decimal >= ebuf)
goto giveup;
for (nextchar = decimal + 1; nextchar < ebuf; nextchar++)
if (*nextchar < '0' || *nextchar > '9')
break;
if (nextchar - decimal - 1 < wantreduce)
goto giveup;
for (s1 = nextchar - wantreduce, s2 = s1 + wantreduce;
s2 < ebuf; s1++, s2++)
*s1 = *s2;
x->x_buf = t_resizebytes(x->x_buf, bufsize, text->te_width);
bufsize = text->te_width;
goto done;
giveup:
/* give up and bash it to "+" or "-" */
x->x_buf[0] = (atomp->a_w.w_float < 0 ? '-' : '+');
x->x_buf = t_resizebytes(x->x_buf, bufsize, 1);
bufsize = 1;
}
else if (bufsize > text->te_width)
{
x->x_buf[text->te_width - 1] = '>';
x->x_buf = t_resizebytes(x->x_buf, bufsize, text->te_width);
bufsize = text->te_width;
}
done:
x->x_bufsize = bufsize;
}
rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
}

/* find the rtext that goes with a text item */
t_rtext *glist_findrtext(t_glist *gl, t_text *who)
{
t_rtext *x;
if (!gl->gl_editor)
canvas_create_editor(gl);
{
int i = 0;
for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next)
i++;
// post("i=%d", i);
}
for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next)
;
return (x);
}

int rtext_width(t_rtext *x)
{
int w = 0, h = 0, indx;
rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
return (w);
}

int rtext_height(t_rtext *x)
{
int w = 0, h = 0, indx;
rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
return (h);
}

void rtext_draw(t_rtext *x)
{
int w = 0, h = 0, indx;
rtext_senditup(x, SEND_FIRST, &w, &h, &indx);
}

void rtext_erase(t_rtext *x)
{
sys_vgui(".x%lx.c delete %s\n", glist_getcanvas(x->x_glist), x->x_tag);
}

void rtext_displace(t_rtext *x, int dx, int dy)
{
sys_vgui(".x%lx.c move %s %d %d\n", glist_getcanvas(x->x_glist),
x->x_tag, dx, dy);
}

void rtext_select(t_rtext *x, int state)
{
t_glist *glist = x->x_glist;
t_canvas *canvas = glist_getcanvas(glist);
sys_vgui(".x%lx.c itemconfigure %s -fill %s\n", canvas,
x->x_tag, (state? "blue" : "black"));
}

void rtext_activate(t_rtext *x, int state)
{
int w = 0, h = 0, indx;
t_glist *glist = x->x_glist;
t_canvas *canvas = glist_getcanvas(glist);
if (state)
{
sys_vgui("pdtk_text_editing .x%lx %s 1\n", canvas, x->x_tag);
glist->gl_editor->e_textedfor = x;
glist->gl_editor->e_textdirty = 0;
x->x_dragfrom = x->x_selstart = 0;
x->x_selend = x->x_bufsize;
x->x_active = 1;
}
else
{
sys_vgui("pdtk_text_editing .x%lx {} 0\n", canvas);
if (glist->gl_editor->e_textedfor == x)
glist->gl_editor->e_textedfor = 0;
x->x_active = 0;
}
rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
}

void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
{
int w = 0, h = 0, indx, i, newsize, ndel;
char *s1, *s2;
if (keynum)
{
int n = keynum;
if (n == '\r') n = '\n';
if (n == '\b') /* backspace */
{
/* LATER delete the box if all text is selected...
this causes reentrancy problems now. */
/* if ((!x->x_selstart) && (x->x_selend == x->x_bufsize))
{
....
} */
if (x->x_selstart && (x->x_selstart == x->x_selend))
u8_dec(x->x_buf, &x->x_selstart);
}
else if (n == 127) /* delete */
{
if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend))
u8_inc(x->x_buf, &x->x_selend);
}

ndel = x->x_selend - x->x_selstart;
for (i = x->x_selend; i < x->x_bufsize; i++)
x->x_buf[i- ndel] = x->x_buf[i];
newsize = x->x_bufsize - ndel;
x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
x->x_bufsize = newsize;

/* at Guenter's suggestion, use 'n>31' to test wither a character might
be printable in whatever 8-bit character set we find ourselves. */

/*-- moo:
... but test with "<" rather than "!=" in order to accommodate unicode
codepoints for n (which we get since Tk is sending the "%A" substitution
for bind <Key>), effectively reducing the coverage of this clause to 7
bits. Case n>127 is covered by the next clause.
*/
if (n == '\n' || (n > 31 && n < 127))
{
newsize = x->x_bufsize+1;
x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
for (i = x->x_bufsize; i > x->x_selstart; i--)
x->x_buf[i] = x->x_buf[i-1];
x->x_buf[x->x_selstart] = n;
x->x_bufsize = newsize;
x->x_selstart = x->x_selstart + 1;
}
/*--moo: check for unicode codepoints beyond 7-bit ASCII --*/
else if (n > 127)
{
int ch_nbytes = u8_wc_nbytes(n);
newsize = x->x_bufsize + ch_nbytes;
x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
for (i = newsize-1; i > x->x_selstart; i--)
x->x_buf[i] = x->x_buf[i-ch_nbytes];
x->x_bufsize = newsize;
/*-- moo: assume canvas_key() has encoded keysym as UTF-8 */
strncpy(x->x_buf+x->x_selstart, keysym->s_name, ch_nbytes);
x->x_selstart = x->x_selstart + ch_nbytes;
}
x->x_selend = x->x_selstart;
x->x_glist->gl_editor->e_textdirty = 1;
}
else if (!strcmp(keysym->s_name, "Right"))
{
if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize)
{
u8_inc(x->x_buf, &x->x_selstart);
x->x_selend = x->x_selstart;
}
else
x->x_selstart = x->x_selend;
}
else if (!strcmp(keysym->s_name, "Left"))
{
if (x->x_selend == x->x_selstart && x->x_selstart > 0)
{
u8_dec(x->x_buf, &x->x_selstart);
x->x_selend = x->x_selstart;
}
else
x->x_selend = x->x_selstart;
}
/* this should be improved... life's too short */
else if (!strcmp(keysym->s_name, "Up"))
{
if (x->x_selstart)
u8_dec(x->x_buf, &x->x_selstart);
while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
u8_dec(x->x_buf, &x->x_selstart);
x->x_selend = x->x_selstart;
}
else if (!strcmp(keysym->s_name, "Down"))
{
while (x->x_selend < x->x_bufsize &&
x->x_buf[x->x_selend] != '\n')
u8_inc(x->x_buf, &x->x_selend);
if (x->x_selend < x->x_bufsize)
u8_inc(x->x_buf, &x->x_selend);
x->x_selstart = x->x_selend;
}
rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
}

void rtext_mouse(t_rtext *x, int xval, int yval, int flag)
{
int w = xval, h = yval, indx;
rtext_senditup(x, SEND_CHECK, &w, &h, &indx);
if (flag == RTEXT_DOWN)
{
x->x_dragfrom = x->x_selstart = x->x_selend = indx;
}
else if (flag == RTEXT_DBL)
{
int whereseparator, newseparator;
x->x_dragfrom = -1;
whereseparator = 0;
if ((newseparator = lastone(x->x_buf, ' ', indx)) > whereseparator)
whereseparator = newseparator+1;
if ((newseparator = lastone(x->x_buf, '\n', indx)) > whereseparator)
whereseparator = newseparator+1;
if ((newseparator = lastone(x->x_buf, ';', indx)) > whereseparator)
whereseparator = newseparator+1;
if ((newseparator = lastone(x->x_buf, ',', indx)) > whereseparator)
whereseparator = newseparator+1;
x->x_selstart = whereseparator;

whereseparator = x->x_bufsize - indx;
if ((newseparator =
firstone(x->x_buf+indx, ' ', x->x_bufsize - indx)) >= 0 &&
newseparator < whereseparator)
whereseparator = newseparator;
if ((newseparator =
firstone(x->x_buf+indx, '\n', x->x_bufsize - indx)) >= 0 &&
newseparator < whereseparator)
whereseparator = newseparator;
if ((newseparator =
firstone(x->x_buf+indx, ';', x->x_bufsize - indx)) >= 0 &&
newseparator < whereseparator)
whereseparator = newseparator;
if ((newseparator =
firstone(x->x_buf+indx, ',', x->x_bufsize - indx)) >= 0 &&
newseparator < whereseparator)
whereseparator = newseparator;
x->x_selend = indx + whereseparator;
}
else if (flag == RTEXT_SHIFT)
{
if (indx * 2 > x->x_selstart + x->x_selend)
x->x_dragfrom = x->x_selstart, x->x_selend = indx;
else
x->x_dragfrom = x->x_selend, x->x_selstart = indx;
}
else if (flag == RTEXT_DRAG)
{
if (x->x_dragfrom < 0)
return;
x->x_selstart = (x->x_dragfrom < indx ? x->x_dragfrom : indx);
x->x_selend = (x->x_dragfrom > indx ? x->x_dragfrom : indx);
}
rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
}

+ 452
- 0
ports/camomile/source/LibPd/pure-data/src/g_scalar.c View File

@@ -0,0 +1,452 @@
/* 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 "scalar" object, which is not a text object, just a
"gobj". Scalars have templates which describe their structures, which
can contain numbers, sublists, and arrays.

*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h> /* for read/write to files */
#include "m_pd.h"
#include "g_canvas.h"

t_class *scalar_class;

void word_init(t_word *wp, t_template *template, t_gpointer *gp)
{
int i, nitems = template->t_n;
t_dataslot *datatypes = template->t_vec;
for (i = 0; i < nitems; i++, datatypes++, wp++)
{
int type = datatypes->ds_type;
if (type == DT_FLOAT)
wp->w_float = 0;
else if (type == DT_SYMBOL)
wp->w_symbol = &s_symbol;
else if (type == DT_ARRAY)
wp->w_array = array_new(datatypes->ds_arraytemplate, gp);
else if (type == DT_TEXT)
wp->w_binbuf = binbuf_new();
}
}

void word_restore(t_word *wp, t_template *template,
int argc, t_atom *argv)
{
int i, nitems = template->t_n;
t_dataslot *datatypes = template->t_vec;
for (i = 0; i < nitems; i++, datatypes++, wp++)
{
int type = datatypes->ds_type;
if (type == DT_FLOAT)
{
t_float f;
if (argc)
{
f = atom_getfloat(argv);
argv++, argc--;
}
else f = 0;
wp->w_float = f;
}
else if (type == DT_SYMBOL)
{
t_symbol *s;
if (argc)
{
s = atom_getsymbol(argv);
argv++, argc--;
}
else s = &s_;
wp->w_symbol = s;
}
}
if (argc)
post("warning: word_restore: extra arguments");
}

void word_free(t_word *wp, t_template *template)
{
int i;
t_dataslot *dt;
for (dt = template->t_vec, i = 0; i < template->t_n; i++, dt++)
{
if (dt->ds_type == DT_ARRAY)
array_free(wp[i].w_array);
else if (dt->ds_type == DT_TEXT)
binbuf_free(wp[i].w_binbuf);
}
}

static int template_cancreate(t_template *template)
{
int i, type, nitems = template->t_n;
t_dataslot *datatypes = template->t_vec;
t_template *elemtemplate;
for (i = 0; i < nitems; i++, datatypes++)
if (datatypes->ds_type == DT_ARRAY &&
(!(elemtemplate = template_findbyname(datatypes->ds_arraytemplate))
|| !template_cancreate(elemtemplate)))
{
error("%s: no such template", datatypes->ds_arraytemplate->s_name);
return (0);
}
return (1);
}

/* make a new scalar and add to the glist. We create a "gp" here which
will be used for array items to point back here. This gp doesn't do
reference counting or "validation" updates though; the parent won't go away
without the contained arrays going away too. The "gp" is copied out
by value in the word_init() routine so we can throw our copy away. */

t_scalar *scalar_new(t_glist *owner, t_symbol *templatesym)
{
t_scalar *x;
t_template *template;
t_gpointer gp;
gpointer_init(&gp);
template = template_findbyname(templatesym);
if (!template)
{
error("scalar: couldn't find template %s", templatesym->s_name);
return (0);
}
if (!template_cancreate(template))
return (0);
x = (t_scalar *)getbytes(sizeof(t_scalar) +
(template->t_n - 1) * sizeof(*x->sc_vec));
x->sc_gobj.g_pd = scalar_class;
x->sc_template = templatesym;
gpointer_setglist(&gp, owner, x);
word_init(x->sc_vec, template, &gp);
return (x);
}

/* Pd method to create a new scalar, add it to a glist, and initialize
it from the message arguments. */

void glist_scalar(t_glist *glist,
t_symbol *classname, int argc, t_atom *argv)
{
t_symbol *templatesym =
canvas_makebindsym(atom_getsymbolarg(0, argc, argv));
t_binbuf *b;
int natoms, nextmsg = 0;
t_atom *vec;
if (!template_findbyname(templatesym))
{
pd_error(glist, "%s: no such template",
atom_getsymbolarg(0, argc, argv)->s_name);
return;
}

b = binbuf_new();
binbuf_restore(b, argc, argv);
natoms = binbuf_getnatom(b);
vec = binbuf_getvec(b);
canvas_readscalar(glist, natoms, vec, &nextmsg, 0);
binbuf_free(b);
}

/* -------------------- widget behavior for scalar ------------ */
void scalar_getbasexy(t_scalar *x, t_float *basex, t_float *basey)
{
t_template *template = template_findbyname(x->sc_template);
*basex = template_getfloat(template, gensym("x"), x->sc_vec, 0);
*basey = template_getfloat(template, gensym("y"), x->sc_vec, 0);
}

static void scalar_getrect(t_gobj *z, t_glist *owner,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_scalar *x = (t_scalar *)z;
t_template *template = template_findbyname(x->sc_template);
t_canvas *templatecanvas = template_findcanvas(template);
int x1 = 0x7fffffff, x2 = -0x7fffffff, y1 = 0x7fffffff, y2 = -0x7fffffff;
t_gobj *y;
t_float basex, basey;
scalar_getbasexy(x, &basex, &basey);
/* if someone deleted the template canvas, we're just a point */
if (!templatecanvas)
{
x1 = x2 = glist_xtopixels(owner, basex);
y1 = y2 = glist_ytopixels(owner, basey);
}
else
{
x1 = y1 = 0x7fffffff;
x2 = y2 = -0x7fffffff;
for (y = templatecanvas->gl_list; y; y = y->g_next)
{
const t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
int nx1, ny1, nx2, ny2;
if (!wb) continue;
(*wb->w_parentgetrectfn)(y, owner,
x->sc_vec, template, basex, basey,
&nx1, &ny1, &nx2, &ny2);
if (nx1 < x1) x1 = nx1;
if (ny1 < y1) y1 = ny1;
if (nx2 > x2) x2 = nx2;
if (ny2 > y2) y2 = ny2;
}
if (x2 < x1 || y2 < y1)
x1 = y1 = x2 = y2 = 0;
}
/* post("scalar x1 %d y1 %d x2 %d y2 %d", x1, y1, x2, y2); */
*xp1 = x1;
*yp1 = y1;
*xp2 = x2;
*yp2 = y2;
}

static void scalar_drawselectrect(t_scalar *x, t_glist *glist, int state)
{
if (state)
{
int x1, y1, x2, y2;

scalar_getrect(&x->sc_gobj, glist, &x1, &y1, &x2, &y2);
x1--; x2++; y1--; y2++;
sys_vgui(".x%lx.c create line %d %d %d %d %d %d %d %d %d %d \
-width 0 -fill blue -tags select%lx\n",
glist_getcanvas(glist), x1, y1, x1, y2, x2, y2, x2, y1, x1, y1,
x);
}
else
{
sys_vgui(".x%lx.c delete select%lx\n", glist_getcanvas(glist), x);
}
}

static void scalar_select(t_gobj *z, t_glist *owner, int state)
{
t_scalar *x = (t_scalar *)z;
t_template *tmpl;
t_symbol *templatesym = x->sc_template;
t_atom at;
t_gpointer gp;
gpointer_init(&gp);
gpointer_setglist(&gp, owner, x);
SETPOINTER(&at, &gp);
if ((tmpl = template_findbyname(templatesym)))
template_notify(tmpl, (state ? gensym("select") : gensym("deselect")),
1, &at);
gpointer_unset(&gp);
scalar_drawselectrect(x, owner, state);
}

static void scalar_displace(t_gobj *z, t_glist *glist, int dx, int dy)
{
t_scalar *x = (t_scalar *)z;
t_symbol *templatesym = x->sc_template;
t_template *template = template_findbyname(templatesym);
t_symbol *zz;
t_atom at[3];
t_gpointer gp;
int xonset, yonset, xtype, ytype, gotx, goty;
if (!template)
{
error("scalar: couldn't find template %s", templatesym->s_name);
return;
}
gotx = template_find_field(template, gensym("x"), &xonset, &xtype, &zz);
if (gotx && (xtype != DT_FLOAT))
gotx = 0;
goty = template_find_field(template, gensym("y"), &yonset, &ytype, &zz);
if (goty && (ytype != DT_FLOAT))
goty = 0;
if (gotx)
*(t_float *)(((char *)(x->sc_vec)) + xonset) +=
dx * (glist_pixelstox(glist, 1) - glist_pixelstox(glist, 0));
if (goty)
*(t_float *)(((char *)(x->sc_vec)) + yonset) +=
dy * (glist_pixelstoy(glist, 1) - glist_pixelstoy(glist, 0));
gpointer_init(&gp);
gpointer_setglist(&gp, glist, x);
SETPOINTER(&at[0], &gp);
SETFLOAT(&at[1], (t_float)dx);
SETFLOAT(&at[2], (t_float)dy);
template_notify(template, gensym("displace"), 2, at);
scalar_redraw(x, glist);
}

static void scalar_activate(t_gobj *z, t_glist *owner, int state)
{
/* post("scalar_activate %d", state); */
/* later */
}

static void scalar_delete(t_gobj *z, t_glist *glist)
{
/* nothing to do */
}

static void scalar_vis(t_gobj *z, t_glist *owner, int vis)
{
t_scalar *x = (t_scalar *)z;
t_template *template = template_findbyname(x->sc_template);
t_canvas *templatecanvas = template_findcanvas(template);
t_gobj *y;
t_float basex, basey;
scalar_getbasexy(x, &basex, &basey);
/* if we don't know how to draw it, make a small rectangle */
if (!templatecanvas)
{
if (vis)
{
int x1 = glist_xtopixels(owner, basex);
int y1 = glist_ytopixels(owner, basey);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags scalar%lx\n",
glist_getcanvas(owner), x1-1, y1-1, x1+1, y1+1, x);
}
else sys_vgui(".x%lx.c delete scalar%lx\n", glist_getcanvas(owner), x);
return;
}

for (y = templatecanvas->gl_list; y; y = y->g_next)
{
const t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
if (!wb) continue;
(*wb->w_parentvisfn)(y, owner, x->sc_vec, template, basex, basey, vis);
}
if (glist_isselected(owner, &x->sc_gobj))
{
scalar_drawselectrect(x, owner, 0);
scalar_drawselectrect(x, owner, 1);
}
sys_unqueuegui(x);
}

static void scalar_doredraw(t_gobj *client, t_glist *glist)
{
if (glist_isvisible(glist))
{
scalar_vis(client, glist, 0);
scalar_vis(client, glist, 1);
}
}

void scalar_redraw(t_scalar *x, t_glist *glist)
{
if (glist_isvisible(glist))
sys_queuegui(x, glist, scalar_doredraw);
}

extern void template_notifyforscalar(t_template *template, t_glist *owner,
t_scalar *sc, t_symbol *s, int argc, t_atom *argv);

int scalar_doclick(t_word *data, t_template *template, t_scalar *sc,
t_array *ap, struct _glist *owner,
t_float xloc, t_float yloc, int xpix, int ypix,
int shift, int alt, int dbl, int doit)
{
int hit = 0;
t_canvas *templatecanvas = template_findcanvas(template);
t_gobj *y;
t_atom at[2];
t_float basex = template_getfloat(template, gensym("x"), data, 0);
t_float basey = template_getfloat(template, gensym("y"), data, 0);
SETFLOAT(at, basex + xloc);
SETFLOAT(at+1, basey + yloc);
if (doit)
template_notifyforscalar(template, owner,
sc, gensym("click"), 2, at);
for (y = templatecanvas->gl_list; y; y = y->g_next)
{
const t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd);
if (!wb) continue;
if ((hit = (*wb->w_parentclickfn)(y, owner,
data, template, sc, ap, basex + xloc, basey + yloc,
xpix, ypix, shift, alt, dbl, doit)))
return (hit);
}
return (0);
}

static int scalar_click(t_gobj *z, struct _glist *owner,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
t_scalar *x = (t_scalar *)z;
t_template *template = template_findbyname(x->sc_template);
return (scalar_doclick(x->sc_vec, template, x, 0,
owner, 0, 0, xpix, ypix, shift, alt, dbl, doit));
}

static void scalar_save(t_gobj *z, t_binbuf *b)
{
t_scalar *x = (t_scalar *)z;
t_binbuf *b2 = binbuf_new();
t_atom a, *argv;
int i, argc;
canvas_writescalar(x->sc_template, x->sc_vec, b2, 0);
binbuf_addv(b, "ss", &s__X, gensym("scalar"));
binbuf_addbinbuf(b, b2);
binbuf_addsemi(b);
binbuf_free(b2);
}

static void scalar_properties(t_gobj *z, struct _glist *owner)
{
t_scalar *x = (t_scalar *)z;
char *buf, buf2[80];
int bufsize;
t_binbuf *b;
glist_noselect(owner);
glist_select(owner, z);
b = glist_writetobinbuf(owner, 0);
binbuf_gettext(b, &buf, &bufsize);
binbuf_free(b);
buf = t_resizebytes(buf, bufsize, bufsize+1);
buf[bufsize] = 0;
sprintf(buf2, "pdtk_data_dialog %%s {");
gfxstub_new((t_pd *)owner, x, buf2);
sys_gui(buf);
sys_gui("}\n");
t_freebytes(buf, bufsize+1);
}

static const t_widgetbehavior scalar_widgetbehavior =
{
scalar_getrect,
scalar_displace,
scalar_select,
scalar_activate,
scalar_delete,
scalar_vis,
scalar_click,
};

static void scalar_free(t_scalar *x)
{
int i;
t_dataslot *datatypes, *dt;
t_symbol *templatesym = x->sc_template;
t_template *template = template_findbyname(templatesym);
sys_unqueuegui(x);
if (!template)
{
error("scalar: couldn't find template %s", templatesym->s_name);
return;
}
word_free(x->sc_vec, template);
gfxstub_deleteforkey(x);
/* the "size" field in the class is zero, so Pd doesn't try to free
us automatically (see pd_free()) */
freebytes(x, sizeof(t_scalar) + (template->t_n - 1) * sizeof(*x->sc_vec));
}

/* ----------------- setup function ------------------- */

void g_scalar_setup(void)
{
scalar_class = class_new(gensym("scalar"), 0, (t_method)scalar_free, 0,
CLASS_GOBJ, 0);
class_setwidget(scalar_class, &scalar_widgetbehavior);
class_setsavefn(scalar_class, scalar_save);
class_setpropertiesfn(scalar_class, scalar_properties);
}

+ 2772
- 0
ports/camomile/source/LibPd/pure-data/src/g_template.c
File diff suppressed because it is too large
View File


+ 1489
- 0
ports/camomile/source/LibPd/pure-data/src/g_text.c
File diff suppressed because it is too large
View File


+ 520
- 0
ports/camomile/source/LibPd/pure-data/src/g_toggle.c View File

@@ -0,0 +1,520 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

/* --------------- tgl gui-toggle ------------------------- */

t_widgetbehavior toggle_widgetbehavior;
static t_class *toggle_class;

/* widget helper functions */

void toggle_draw_update(t_toggle *x, t_glist *glist)
{
if(glist_isvisible(glist))
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxX1 -fill #%06x\n", canvas, x,
(x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxX2 -fill #%06x\n", canvas, x,
(x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol);
}
}

void toggle_draw_new(t_toggle *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int crossw = 1, w = x->x_gui.x_w / IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);
if(w >= 30)
crossw = 2;
if(w >= 60)
crossw = 3;
crossw *= IEMGUI_ZOOM(x);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n",
canvas, xpos, ypos,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h,
IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxX1\n",
canvas,
xpos + crossw + IEMGUI_ZOOM(x), ypos + crossw + IEMGUI_ZOOM(x),
xpos + x->x_gui.x_w - crossw - IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - crossw - IEMGUI_ZOOM(x),
crossw, (x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxX2\n",
canvas,
xpos + crossw + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - crossw - IEMGUI_ZOOM(x),
xpos + x->x_gui.x_w - crossw - IEMGUI_ZOOM(x), ypos + crossw + IEMGUI_ZOOM(x),
crossw, (x->x_on != 0.0) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

void toggle_draw_move(t_toggle *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);
int crossw = 1, w = x->x_gui.x_w / IEMGUI_ZOOM(x);
if(w >= 30)
crossw = 2;
if(w >= 60)
crossw = 3;
crossw *= IEMGUI_ZOOM(x);

sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x, xpos, ypos,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h);
sys_vgui(".x%lx.c itemconfigure %lxX1 -width %d\n", canvas, x, crossw);
sys_vgui(".x%lx.c coords %lxX1 %d %d %d %d\n",
canvas, x,
xpos + crossw + IEMGUI_ZOOM(x), ypos + crossw + IEMGUI_ZOOM(x),
xpos + x->x_gui.x_w - crossw, ypos + x->x_gui.x_h - crossw);
sys_vgui(".x%lx.c itemconfigure %lxX2 -width %d\n", canvas, x, crossw);
sys_vgui(".x%lx.c coords %lxX2 %d %d %d %d\n",
canvas, x,
xpos + crossw + IEMGUI_ZOOM(x), ypos + x->x_gui.x_h - crossw - IEMGUI_ZOOM(x),
xpos + x->x_gui.x_w - crossw, ypos + crossw);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x,
xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
}

void toggle_draw_erase(t_toggle* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x);
sys_vgui(".x%lx.c delete %lxX1\n", canvas, x);
sys_vgui(".x%lx.c delete %lxX2\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void toggle_draw_config(t_toggle* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""));
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, x,
x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxX1 -fill #%06x\n", canvas, x,
x->x_on ? x->x_gui.x_fcol : x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxX2 -fill #%06x\n", canvas, x,
x->x_on ? x->x_gui.x_fcol : x->x_gui.x_bcol);
}

void toggle_draw_io(t_toggle* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) {
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
/* keep above outlet */
sys_vgui(".x%lx.c raise %lxLABEL %lxOUT%d\n", canvas, x, x, 0);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) {
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep above inlet */
sys_vgui(".x%lx.c raise %lxLABEL %lxIN%d\n", canvas, x, x, 0);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void toggle_draw_select(t_toggle* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol);
}
}

void toggle_draw(t_toggle *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
toggle_draw_update(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
toggle_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
toggle_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
toggle_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
toggle_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
toggle_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
toggle_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ tgl widgetbehaviour----------------------------- */

static void toggle_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_toggle *x = (t_toggle *)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h;
}

static void toggle_save(t_gobj *z, t_binbuf *b)
{
t_toggle *x = (t_toggle *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiisssiiiisssff", gensym("#X"), gensym("obj"),
(int)x->x_gui.x_obj.te_xpix,
(int)x->x_gui.x_obj.te_ypix,
gensym("tgl"), x->x_gui.x_w/IEMGUI_ZOOM(x),
iem_symargstoint(&x->x_gui.x_isa),
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2], x->x_on, x->x_nonzero);
binbuf_addv(b, ";");
}

static void toggle_properties(t_gobj *z, t_glist *owner)
{
t_toggle *x = (t_toggle *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);
sprintf(buf, "pdtk_iemgui_dialog %%s |tgl| \
----------dimensions(pix):----------- %d %d size: 0 0 empty \
-----------non-zero-value:----------- %g value: 0.0 empty %g \
-1 lin log %d %d empty %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
x->x_nonzero, 1.0,/*non_zero-schedule*/
x->x_gui.x_isa.x_loadinit, -1, -1,/*no multi*/
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void toggle_bang(t_toggle *x)
{
x->x_on = (x->x_on == 0.0) ? x->x_nonzero : 0.0;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
outlet_float(x->x_gui.x_obj.ob_outlet, x->x_on);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, x->x_on);
}

static void toggle_dialog(t_toggle *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int a = (int)atom_getfloatarg(0, argc, argv);
t_float nonzero = (t_float)atom_getfloatarg(2, argc, argv);
int sr_flags;

if(nonzero == 0.0)
nonzero = 1.0;
x->x_nonzero = nonzero;
if(x->x_on != 0.0)
x->x_on = x->x_nonzero;
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

static void toggle_click(t_toggle *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{toggle_bang(x);}

static int toggle_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
if(doit)
toggle_click((t_toggle *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt);
return (1);
}

static void toggle_set(t_toggle *x, t_floatarg f)
{
int old = (x->x_on != 0);
x->x_on = f;
if (f != 0.0 && pd_compatibilitylevel < 46)
x->x_nonzero = f;
if ((x->x_on != 0) != old)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}

static void toggle_float(t_toggle *x, t_floatarg f)
{
toggle_set(x, f);
if(x->x_gui.x_fsf.x_put_in2out)
{
outlet_float(x->x_gui.x_obj.ob_outlet, x->x_on);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, x->x_on);
}
}

static void toggle_fout(t_toggle *x, t_floatarg f)
{
toggle_set(x, f);
outlet_float(x->x_gui.x_obj.ob_outlet, x->x_on);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, x->x_on);
}

static void toggle_loadbang(t_toggle *x, t_floatarg action)
{
if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
toggle_fout(x, (t_float)x->x_on);
}

static void toggle_size(t_toggle *x, t_symbol *s, int ac, t_atom *av)
{
x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_size((void *)x, &x->x_gui);
}

static void toggle_delta(t_toggle *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void toggle_pos(t_toggle *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void toggle_color(t_toggle *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void toggle_send(t_toggle *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void toggle_receive(t_toggle *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void toggle_label(t_toggle *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void toggle_label_font(t_toggle *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void toggle_label_pos(t_toggle *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void toggle_init(t_toggle *x, t_floatarg f)
{
x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;
}

static void toggle_nonzero(t_toggle *x, t_floatarg f)
{
if(f != 0.0)
x->x_nonzero = f;
}

static void *toggle_new(t_symbol *s, int argc, t_atom *argv)
{
t_toggle *x = (t_toggle *)pd_new(toggle_class);
int a = IEM_GUI_DEFAULTSIZE, f = 0;
int ldx = 17, ldy = 7;
int fs = 10;
t_float on = 0.0, nonzero = 1.0;
char str[144];

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if(((argc == 13)||(argc == 14))&&IS_A_FLOAT(argv,0)
&&IS_A_FLOAT(argv,1)
&&(IS_A_SYMBOL(argv,2)||IS_A_FLOAT(argv,2))
&&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3))
&&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4))
&&IS_A_FLOAT(argv,5)&&IS_A_FLOAT(argv,6)
&&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8)&&IS_A_FLOAT(argv,12))
{
a = (int)atom_getfloatarg(0, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(1, argc, argv));
iemgui_new_getnames(&x->x_gui, 2, argv);
ldx = (int)atom_getfloatarg(5, argc, argv);
ldy = (int)atom_getfloatarg(6, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(7, argc, argv));
fs = (int)atom_getfloatarg(8, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+9, argv+10, argv+11);
on = (t_float)atom_getfloatarg(12, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 2, 0);
if((argc == 14)&&IS_A_FLOAT(argv,13))
nonzero = (t_float)atom_getfloatarg(13, argc, argv);
x->x_gui.x_draw = (t_iemfunptr)toggle_draw;

x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if (!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if (!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
x->x_nonzero = (nonzero != 0.0) ? nonzero : 1.0;
if(x->x_gui.x_isa.x_loadinit)
x->x_on = (on != 0.0) ? nonzero : 0.0;
else
x->x_on = 0.0;
if (x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_w = iemgui_clip_size(a);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_verify_snd_ne_rcv(&x->x_gui);
iemgui_newzoom(&x->x_gui);
outlet_new(&x->x_gui.x_obj, &s_float);
return (x);
}

static void toggle_ff(t_toggle *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_toggle_setup(void)
{
toggle_class = class_new(gensym("tgl"), (t_newmethod)toggle_new,
(t_method)toggle_ff, sizeof(t_toggle), 0, A_GIMME, 0);
class_addcreator((t_newmethod)toggle_new, gensym("toggle"), A_GIMME, 0);
class_addbang(toggle_class, toggle_bang);
class_addfloat(toggle_class, toggle_float);
class_addmethod(toggle_class, (t_method)toggle_click, gensym("click"),
A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(toggle_class, (t_method)toggle_dialog, gensym("dialog"),
A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(toggle_class, (t_method)toggle_set, gensym("set"), A_FLOAT, 0);
class_addmethod(toggle_class, (t_method)toggle_size, gensym("size"), A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_delta, gensym("delta"), A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_pos, gensym("pos"), A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_color, gensym("color"), A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_send, gensym("send"), A_DEFSYM, 0);
class_addmethod(toggle_class, (t_method)toggle_receive, gensym("receive"), A_DEFSYM, 0);
class_addmethod(toggle_class, (t_method)toggle_label, gensym("label"), A_DEFSYM, 0);
class_addmethod(toggle_class, (t_method)toggle_label_pos, gensym("label_pos"), A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_label_font, gensym("label_font"), A_GIMME, 0);
class_addmethod(toggle_class, (t_method)toggle_init, gensym("init"), A_FLOAT, 0);
class_addmethod(toggle_class, (t_method)toggle_nonzero, gensym("nonzero"), A_FLOAT, 0);
class_addmethod(toggle_class, (t_method)iemgui_zoom, gensym("zoom"),
A_CANT, 0);
toggle_widgetbehavior.w_getrectfn = toggle_getrect;
toggle_widgetbehavior.w_displacefn = iemgui_displace;
toggle_widgetbehavior.w_selectfn = iemgui_select;
toggle_widgetbehavior.w_activatefn = NULL;
toggle_widgetbehavior.w_deletefn = iemgui_delete;
toggle_widgetbehavior.w_visfn = iemgui_vis;
toggle_widgetbehavior.w_clickfn = toggle_newclick;
class_setwidget(toggle_class, &toggle_widgetbehavior);
class_sethelpsymbol(toggle_class, gensym("toggle"));
class_setsavefn(toggle_class, toggle_save);
class_setpropertiesfn(toggle_class, toggle_properties);
}

+ 1278
- 0
ports/camomile/source/LibPd/pure-data/src/g_traversal.c
File diff suppressed because it is too large
View File


+ 767
- 0
ports/camomile/source/LibPd/pure-data/src/g_vdial.c View File

@@ -0,0 +1,767 @@
/* 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. */

/* vdial.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */

/* name change to vradio by MSP (it's a radio button really) and changed to
put out a "float" as in sliders, toggles, etc. */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

/* ------------- vdl gui-vertical radio button ---------------------- */

t_widgetbehavior vradio_widgetbehavior;
static t_class *vradio_class, *vradio_old_class;

/* widget helper functions */

void vradio_draw_update(t_gobj *client, t_glist *glist)
{
t_hradio *x = (t_hradio *)client;
if(glist_isvisible(glist))
{
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n",
canvas, x, x->x_drawn,
x->x_gui.x_bcol, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n",
canvas, x, x->x_on,
x->x_gui.x_fcol, x->x_gui.x_fcol);
x->x_drawn = x->x_on;
}
}

void vradio_draw_new(t_vradio *x, t_glist *glist)
{
int n = x->x_number, i, dy = x->x_gui.x_h, s4 = dy / 4;
int yy11b = text_ypix(&x->x_gui.x_obj, glist);
int yy11 = yy11b, yy12 = yy11 + dy;
int yy21 = yy11 + s4, yy22 = yy12 - s4;
int xx11 = text_xpix(&x->x_gui.x_obj, glist), xx12 = xx11 + dy;
int xx21 = xx11 + s4, xx22 = xx12 - s4;
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE%d\n",
canvas, xx11, yy11, xx12, yy12, IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x, i);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxBUT%d\n",
canvas, xx21, yy21, xx22, yy22,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol, x, i);
yy11 += dy;
yy12 += dy;
yy21 += dy;
yy22 += dy;
x->x_drawn = x->x_on;
}
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xx11, yy11 + IEMGUI_ZOOM(x) - ioh,
xx11 + iow, yy11,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xx11, yy11b,
xx11 + iow, yy11b - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w -font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xx11 + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
yy11b + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

void vradio_draw_move(t_vradio *x, t_glist *glist)
{
int n = x->x_number, i, dy = x->x_gui.x_h, s4 = dy / 4;
int yy11b = text_ypix(&x->x_gui.x_obj, glist);
int yy11 = yy11b, yy12 = yy11 + dy;
int yy21 = yy11 + s4, yy22 = yy12 - s4;
int xx11 = text_xpix(&x->x_gui.x_obj, glist), xx12 = xx11 + dy;
int xx21 = xx11 + s4, xx22 = xx12 - s4;
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c coords %lxBASE%d %d %d %d %d\n",
canvas, x, i, xx11, yy11, xx12, yy12);
sys_vgui(".x%lx.c coords %lxBUT%d %d %d %d %d\n",
canvas, x, i, xx21, yy21, xx22, yy22);
yy11 += dy;
yy12 += dy;
yy21 += dy;
yy22 += dy;
}
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xx11, yy11 + IEMGUI_ZOOM(x) - ioh,
xx11 + iow, yy11);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xx11, yy11b,
xx11 + iow, yy11b - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xx11 + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
yy11b + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
}

void vradio_draw_erase(t_vradio* x, t_glist* glist)
{
int n = x->x_number, i;
t_canvas *canvas = glist_getcanvas(glist);

for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c delete %lxBASE%d\n", canvas, x, i);
sys_vgui(".x%lx.c delete %lxBUT%d\n", canvas, x, i);
}
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void vradio_draw_config(t_vradio* x, t_glist* glist)
{
int n = x->x_number, i;
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol,
strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "");
for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -fill #%06x\n", canvas, x, i,
x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%06x -outline #%06x\n", canvas, x, i,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol,
(x->x_on == i) ? x->x_gui.x_fcol : x->x_gui.x_bcol);
}
}

void vradio_draw_io(t_vradio* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h,
x, 0);
/* keep these above outlet */
if(x->x_on == 0) {
sys_vgui(".x%lx.c raise %lxBUT%d %lxOUT%d\n", canvas, x, x->x_on, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on);
}
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos + iow, ypos - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep these above inlet */
if(x->x_on == 0) {
sys_vgui(".x%lx.c raise %lxBUT%d %lxIN%d\n", canvas, x, x->x_on, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxBUT%d\n", canvas, x, x, x->x_on);
}
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

void vradio_draw_select(t_vradio* x, t_glist* glist)
{
int n = x->x_number, i;
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i,
IEM_GUI_COLOR_SELECTED);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
for(i = 0; i < n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%06x\n", canvas, x, i,
IEM_GUI_COLOR_NORMAL);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x,
x->x_gui.x_lcol);
}
}

void vradio_draw(t_vradio *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
sys_queuegui(x, glist, vradio_draw_update);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
vradio_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
vradio_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
vradio_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
vradio_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
vradio_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
vradio_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ vdl widgetbehaviour----------------------------- */

static void vradio_getrect(t_gobj *z, t_glist *glist, int *xp1, int *yp1, int *xp2, int *yp2)
{
t_vradio *x = (t_vradio *)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h * x->x_number;
}

static void vradio_save(t_gobj *z, t_binbuf *b)
{
t_vradio *x = (t_vradio *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiiisssiiiisssf", gensym("#X"), gensym("obj"),
(int)x->x_gui.x_obj.te_xpix,
(int)x->x_gui.x_obj.te_ypix,
(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class ?
gensym("vdl") : gensym("vradio")),
x->x_gui.x_w/IEMGUI_ZOOM(x),
x->x_change, iem_symargstoint(&x->x_gui.x_isa), x->x_number,
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2], x->x_fval);
binbuf_addv(b, ";");
}

static void vradio_properties(t_gobj *z, t_glist *owner)
{
t_vradio *x = (t_vradio *)z;
char buf[800];
t_symbol *srl[3];
int hchange = -1;

iemgui_properties(&x->x_gui, srl);
if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class)
hchange = x->x_change;
sprintf(buf, "pdtk_iemgui_dialog %%s |vradio| \
----------dimensions(pix):----------- %d %d size: 0 0 empty \
empty 0.0 empty 0.0 empty %d \
%d new-only new&old %d %d number: %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
0,/*no_schedule*/
hchange, x->x_gui.x_isa.x_loadinit, -1, x->x_number,
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void vradio_dialog(t_vradio *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int a = (int)atom_getfloatarg(0, argc, argv);
int chg = (int)atom_getfloatarg(4, argc, argv);
int num = (int)atom_getfloatarg(6, argc, argv);
int sr_flags;

if(chg != 0) chg = 1;
x->x_change = chg;
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
x->x_gui.x_w = iemgui_clip_size(a) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
if(x->x_number != num)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE);
x->x_number = num;
if(x->x_on >= x->x_number)
{
x->x_on = x->x_number - 1;
x->x_on_old = x->x_on;
}
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW);
}
else
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}

static void vradio_set(t_vradio *x, t_floatarg f)
{
int i = (int)f;
int old;

x->x_fval = f;
if(i < 0)
i = 0;
if(i >= x->x_number)
i = x->x_number - 1;
if(x->x_on != x->x_on_old)
{
old = x->x_on_old;
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
x->x_on_old = old;
}
else
{
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}
}

static void vradio_bang(t_vradio *x)
{
/* compatibility with earlier "vdial" behavior */
if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class)
{
if((x->x_change) && (x->x_on != x->x_on_old))
{
SETFLOAT(x->x_at, (t_float)x->x_on_old);
SETFLOAT(x->x_at+1, 0.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
x->x_on_old = x->x_on;
SETFLOAT(x->x_at, (t_float)x->x_on);
SETFLOAT(x->x_at+1, 1.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
else
{
float outval = (pd_compatibilitylevel < 46 ? x->x_on : x->x_fval);
outlet_float(x->x_gui.x_obj.ob_outlet, outval);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, outval);
}
}

static void vradio_fout(t_vradio *x, t_floatarg f)
{
int i = (int)f;

x->x_fval = f;
if(i < 0)
i = 0;
if(i >= x->x_number)
i = x->x_number - 1;

if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class)
{
/* compatibility with earlier "vdial" behavior */
if((x->x_change) && (i != x->x_on_old))
{
SETFLOAT(x->x_at, (t_float)x->x_on_old);
SETFLOAT(x->x_at+1, 0.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
if(x->x_on != x->x_on_old)
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
x->x_on_old = x->x_on;
SETFLOAT(x->x_at, (t_float)x->x_on);
SETFLOAT(x->x_at+1, 1.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
else
{
float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval);
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
outlet_float(x->x_gui.x_obj.ob_outlet, outval);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, outval);
}
}

static void vradio_float(t_vradio *x, t_floatarg f)
{
int i = (int)f;

x->x_fval = f;
if(i < 0)
i = 0;
if(i >= x->x_number)
i = x->x_number - 1;

if(pd_class(&x->x_gui.x_obj.ob_pd) == vradio_old_class)
{
/* compatibility with earlier "vdial" behavior */
if((x->x_change) && (i != x->x_on_old))
{
if(x->x_gui.x_fsf.x_put_in2out)
{
SETFLOAT(x->x_at, (t_float)x->x_on_old);
SETFLOAT(x->x_at+1, 0.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
}
if(x->x_on != x->x_on_old)
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
x->x_on_old = x->x_on;
if(x->x_gui.x_fsf.x_put_in2out)
{
SETFLOAT(x->x_at, (t_float)x->x_on);
SETFLOAT(x->x_at+1, 1.0);
outlet_list(x->x_gui.x_obj.ob_outlet, &s_list, 2, x->x_at);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_list(x->x_gui.x_snd->s_thing, &s_list, 2, x->x_at);
}
}
else
{
float outval = (pd_compatibilitylevel < 46 ? i : x->x_fval);
x->x_on_old = x->x_on;
x->x_on = i;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
if(x->x_gui.x_fsf.x_put_in2out)
{
outlet_float(x->x_gui.x_obj.ob_outlet, outval);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, outval);
}
}
}

static void vradio_click(t_vradio *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
int yy = (int)ypos - text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist);

vradio_fout(x, (t_float)(yy / x->x_gui.x_h));
}

static int vradio_newclick(t_gobj *z, struct _glist *glist,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
if(doit)
vradio_click((t_vradio *)z, (t_floatarg)xpix, (t_floatarg)ypix,
(t_floatarg)shift, 0, (t_floatarg)alt);
return (1);
}

static void vradio_loadbang(t_vradio *x, t_floatarg action)
{
if(action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
vradio_bang(x);
}

static void vradio_number(t_vradio *x, t_floatarg num)
{
int n = (int)num;

if(n < 1)
n = 1;
if(n > IEM_RADIO_MAX)
n = IEM_RADIO_MAX;
if(n != x->x_number)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_ERASE);
x->x_number = n;
if(x->x_on >= x->x_number)
x->x_on = x->x_number - 1;
x->x_on_old = x->x_on;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_NEW);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}

static void vradio_size(t_vradio *x, t_symbol *s, int ac, t_atom *av)
{
x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_size((void *)x, &x->x_gui);
}

static void vradio_delta(t_vradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void vradio_pos(t_vradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void vradio_color(t_vradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void vradio_send(t_vradio *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void vradio_receive(t_vradio *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void vradio_label(t_vradio *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void vradio_label_pos(t_vradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void vradio_label_font(t_vradio *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void vradio_init(t_vradio *x, t_floatarg f)
{x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;}

static void vradio_double_change(t_vradio *x)
{x->x_change = 1;}

static void vradio_single_change(t_vradio *x)
{x->x_change = 0;}

static void *vradio_donew(t_symbol *s, int argc, t_atom *argv, int old)
{
t_vradio *x = (t_vradio *)pd_new(old ? vradio_old_class : vradio_class);
int a = IEM_GUI_DEFAULTSIZE, on = 0, f = 0;
int ldx = 0, ldy = -8, chg = 1, num = 8;
int fs = 10;
int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, fthold = IEM_BNG_DEFAULTHOLDFLASHTIME;
char str[144];
float fval = 0;

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if((argc == 15)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2)
&&IS_A_FLOAT(argv,3)
&&(IS_A_SYMBOL(argv,4)||IS_A_FLOAT(argv,4))
&&(IS_A_SYMBOL(argv,5)||IS_A_FLOAT(argv,5))
&&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
&&IS_A_FLOAT(argv,7)&&IS_A_FLOAT(argv,8)
&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)&&IS_A_FLOAT(argv,14))
{
a = (int)atom_getfloatarg(0, argc, argv);
chg = (int)atom_getfloatarg(1, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(2, argc, argv));
num = (int)atom_getfloatarg(3, argc, argv);
iemgui_new_getnames(&x->x_gui, 4, argv);
ldx = (int)atom_getfloatarg(7, argc, argv);
ldy = (int)atom_getfloatarg(8, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(9, argc, argv));
fs = (int)atom_getfloatarg(10, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+11, argv+12, argv+13);
fval = atom_getfloatarg(14, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 4, 0);
x->x_gui.x_draw = (t_iemfunptr)vradio_draw;
x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if(!strcmp(x->x_gui.x_snd->s_name, "empty"))
x->x_gui.x_fsf.x_snd_able = 0;
if(!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if(num < 1)
num = 1;
if(num > IEM_RADIO_MAX)
num = IEM_RADIO_MAX;
x->x_number = num;
x->x_fval = fval;
on = fval;
if(on < 0)
on = 0;
if(on >= x->x_number)
on = x->x_number - 1;
if(x->x_gui.x_isa.x_loadinit)
x->x_on = on;
else
x->x_on = 0;
x->x_on_old = x->x_on;
x->x_change = (chg == 0) ? 0 : 1;
if(x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_w = iemgui_clip_size(a);
x->x_gui.x_h = x->x_gui.x_w;
iemgui_verify_snd_ne_rcv(&x->x_gui);
iemgui_newzoom(&x->x_gui);
outlet_new(&x->x_gui.x_obj, &s_list);
return (x);
}

static void *vradio_new(t_symbol *s, int argc, t_atom *argv)
{
return (vradio_donew(s, argc, argv, 0));
}

static void *vdial_new(t_symbol *s, int argc, t_atom *argv)
{
return (vradio_donew(s, argc, argv, 1));
}

static void vradio_ff(t_vradio *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_vradio_setup(void)
{
vradio_class = class_new(gensym("vradio"), (t_newmethod)vradio_new,
(t_method)vradio_ff, sizeof(t_vradio), 0, A_GIMME, 0);
class_addbang(vradio_class, vradio_bang);
class_addfloat(vradio_class, vradio_float);
class_addmethod(vradio_class, (t_method)vradio_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(vradio_class, (t_method)vradio_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(vradio_class, (t_method)vradio_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(vradio_class, (t_method)vradio_size,
gensym("size"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_color,
gensym("color"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(vradio_class, (t_method)vradio_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(vradio_class, (t_method)vradio_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(vradio_class, (t_method)vradio_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(vradio_class, (t_method)vradio_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(vradio_class, (t_method)vradio_number,
gensym("number"), A_FLOAT, 0);
class_addmethod(vradio_class, (t_method)vradio_single_change,
gensym("single_change"), 0);
class_addmethod(vradio_class, (t_method)vradio_double_change,
gensym("double_change"), 0);
class_addmethod(vradio_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
vradio_widgetbehavior.w_getrectfn = vradio_getrect;
vradio_widgetbehavior.w_displacefn = iemgui_displace;
vradio_widgetbehavior.w_selectfn = iemgui_select;
vradio_widgetbehavior.w_activatefn = NULL;
vradio_widgetbehavior.w_deletefn = iemgui_delete;
vradio_widgetbehavior.w_visfn = iemgui_vis;
vradio_widgetbehavior.w_clickfn = vradio_newclick;
class_setwidget(vradio_class, &vradio_widgetbehavior);
class_sethelpsymbol(vradio_class, gensym("vradio"));
class_setsavefn(vradio_class, vradio_save);
class_setpropertiesfn(vradio_class, vradio_properties);

/* obsolete version (0.34-0.35) */
vradio_old_class = class_new(gensym("vdl"), (t_newmethod)vdial_new,
(t_method)vradio_ff, sizeof(t_vradio), 0, A_GIMME, 0);
class_addbang(vradio_old_class, vradio_bang);
class_addfloat(vradio_old_class, vradio_float);
class_addmethod(vradio_old_class, (t_method)vradio_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(vradio_old_class, (t_method)vradio_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_loadbang,
gensym("loadbang"), 0);
class_addmethod(vradio_old_class, (t_method)vradio_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(vradio_old_class, (t_method)vradio_size,
gensym("size"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_color,
gensym("color"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(vradio_old_class, (t_method)vradio_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(vradio_old_class, (t_method)vradio_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(vradio_old_class, (t_method)vradio_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(vradio_old_class, (t_method)vradio_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(vradio_old_class, (t_method)vradio_number,
gensym("number"), A_FLOAT, 0);
class_addmethod(vradio_old_class, (t_method)vradio_single_change,
gensym("single_change"), 0);
class_addmethod(vradio_old_class, (t_method)vradio_double_change,
gensym("double_change"), 0);
class_addmethod(vradio_old_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
class_setwidget(vradio_old_class, &vradio_widgetbehavior);
class_sethelpsymbol(vradio_old_class, gensym("vradio"));
}

+ 690
- 0
ports/camomile/source/LibPd/pure-data/src/g_vslider.c View File

@@ -0,0 +1,690 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#define TMARGIN 2
#define BMARGIN 3

/* ------------ vsl gui-vertical slider ----------------------- */

t_widgetbehavior vslider_widgetbehavior;
static t_class *vslider_class;

/* widget helper functions */

static void vslider_draw_update(t_gobj *client, t_glist *glist)
{
t_vslider *x = (t_vslider *)client;
if (glist_isvisible(glist))
{
int r = text_ypix(&x->x_gui.x_obj, glist) + x->x_gui.x_h -
((x->x_val + 50)/100);
int xpos = text_xpix(&x->x_gui.x_obj, glist);

sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
glist_getcanvas(glist), x, xpos + IEMGUI_ZOOM(x), r,
xpos + x->x_gui.x_w - IEMGUI_ZOOM(x), r);
}
}

static void vslider_draw_new(t_vslider *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int tmargin = TMARGIN * IEMGUI_ZOOM(x), bmargin = BMARGIN * IEMGUI_ZOOM(x);
int r = ypos + x->x_gui.x_h - ((x->x_val + 50)/100);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n",
canvas, xpos, ypos - tmargin,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h + bmargin,
IEMGUI_ZOOM(x),
x->x_gui.x_bcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h + bmargin + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h + bmargin,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos - tmargin,
xpos + iow, ypos - tmargin - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxKNOB\n",
canvas, xpos + IEMGUI_ZOOM(x), r,
xpos + x->x_gui.x_w - IEMGUI_ZOOM(x), r,
1 + 2 * IEMGUI_ZOOM(x), x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
x->x_gui.x_lcol, x);
}

static void vslider_draw_move(t_vslider *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int tmargin = TMARGIN * IEMGUI_ZOOM(x), bmargin = BMARGIN * IEMGUI_ZOOM(x);
int r = ypos + x->x_gui.x_h - ((x->x_val+ 50)/100);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x,
xpos, ypos - tmargin,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h + bmargin);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos + x->x_gui.x_h + bmargin + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h + bmargin);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xpos, ypos - tmargin,
xpos + iow, ypos - tmargin - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, xpos + IEMGUI_ZOOM(x), r,
xpos + x->x_gui.x_w - IEMGUI_ZOOM(x), r);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos+x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos+x->x_gui.x_ldy * IEMGUI_ZOOM(x));
}

static void vslider_draw_erase(t_vslider* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x);
sys_vgui(".x%lx.c delete %lxKNOB\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

static void vslider_draw_config(t_vslider* x, t_glist* glist)
{
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize * IEMGUI_ZOOM(x), sys_fontweight,
(x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""));
sys_vgui(".x%lx.c itemconfigure %lxKNOB -fill #%06x\n", canvas,
x, x->x_gui.x_fcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas,
x, x->x_gui.x_bcol);
}

static void vslider_draw_io(t_vslider* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int tmargin = TMARGIN * IEMGUI_ZOOM(x), bmargin = BMARGIN * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h + bmargin + IEMGUI_ZOOM(x) - ioh,
xpos + iow, ypos + x->x_gui.x_h + bmargin,
x, 0);
/* keep these above outlet */
sys_vgui(".x%lx.c raise %lxKNOB %lxOUT%d\n", canvas, x, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos, ypos - tmargin,
xpos + iow, ypos - tmargin - IEMGUI_ZOOM(x) + ioh,
x, 0);
/* keep these above inlet */
sys_vgui(".x%lx.c raise %lxKNOB %lxIN%d\n", canvas, x, x, 0);
sys_vgui(".x%lx.c raise %lxLABEL %lxKNOB\n", canvas, x, x);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
}

static void vslider_draw_select(t_vslider *x, t_glist *glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol);
}
}

void vslider_draw(t_vslider *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_UPDATE)
sys_queuegui(x, glist, vslider_draw_update);
else if(mode == IEM_GUI_DRAW_MODE_MOVE)
vslider_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
vslider_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
vslider_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
vslider_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
vslider_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
vslider_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ vsl widgetbehaviour----------------------------- */


static void vslider_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_vslider* x = (t_vslider*)z;

*xp1 = text_xpix(&x->x_gui.x_obj, glist);
*yp1 = text_ypix(&x->x_gui.x_obj, glist) - TMARGIN*glist_getzoom(glist);
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h + (TMARGIN + BMARGIN)*glist_getzoom(glist);
}

static void vslider_save(t_gobj *z, t_binbuf *b)
{
t_vslider *x = (t_vslider *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiffiisssiiiisssii", gensym("#X"), gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("vsl"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_gui.x_h/IEMGUI_ZOOM(x),
(t_float)x->x_min, (t_float)x->x_max,
x->x_lin0_log1, iem_symargstoint(&x->x_gui.x_isa),
srl[0], srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[1], bflcol[2],
x->x_val, x->x_steady);
binbuf_addv(b, ";");
}

void vslider_check_height(t_vslider *x, int h)
{
if(h < IEM_SL_MINSIZE * IEMGUI_ZOOM(x))
h = IEM_SL_MINSIZE * IEMGUI_ZOOM(x);
x->x_gui.x_h = h;
if(x->x_val > (x->x_gui.x_h*100 - 100))
{
x->x_pos = x->x_gui.x_h*100 - 100;
x->x_val = x->x_pos;
}
if(x->x_lin0_log1)
x->x_k = log(x->x_max / x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1);
else
x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1);
}

void vslider_check_minmax(t_vslider *x, double min, double max)
{
if(x->x_lin0_log1)
{
if((min == 0.0) && (max == 0.0))
max = 1.0;
if(max > 0.0)
{
if(min <= 0.0)
min = 0.01 * max;
}
else
{
if(min > 0.0)
max = 0.01 * min;
}
}
x->x_min = min;
x->x_max = max;
if(x->x_lin0_log1)
x->x_k = log(x->x_max/x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1);
else
x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1);
}

static void vslider_properties(t_gobj *z, t_glist *owner)
{
t_vslider *x = (t_vslider *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);

sprintf(buf, "pdtk_iemgui_dialog %%s |vsl| \
--------dimensions(pix)(pix):-------- %d %d width: %d %d height: \
-----------output-range:----------- %g bottom: %g top: %d \
%d lin log %d %d empty %d \
%s %s \
%s %d %d \
%d %d \
#%06x #%06x #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE, x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_SL_MINSIZE,
x->x_min, x->x_max, 0,/*no_schedule*/
x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/
srl[0]->s_name, srl[1]->s_name,
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

/* compute numeric value (fval) from pixel location (val) and range */
static t_float vslider_getfval(t_vslider *x)
{
t_float fval;
int zoomval = (x->x_gui.x_fsf.x_finemoved) ?
x->x_val/IEMGUI_ZOOM(x) : (x->x_val / (100*IEMGUI_ZOOM(x))) * 100;

if (x->x_lin0_log1)
fval = x->x_min * exp(x->x_k * (double)(zoomval) * 0.01);
else fval = (double)(zoomval) * 0.01 * x->x_k + x->x_min;
if ((fval < 1.0e-10) && (fval > -1.0e-10))
fval = 0.0;
return (fval);
}

static void vslider_bang(t_vslider *x)
{
double out;

if (pd_compatibilitylevel < 46)
out = vslider_getfval(x);
else out = x->x_fval;
outlet_float(x->x_gui.x_obj.ob_outlet, out);
if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
pd_float(x->x_gui.x_snd->s_thing, out);
}

static void vslider_dialog(t_vslider *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int w = (int)atom_getfloatarg(0, argc, argv);
int h = (int)atom_getfloatarg(1, argc, argv) * IEMGUI_ZOOM(x);
double min = (double)atom_getfloatarg(2, argc, argv);
double max = (double)atom_getfloatarg(3, argc, argv);
int lilo = (int)atom_getfloatarg(4, argc, argv);
int steady = (int)atom_getfloatarg(17, argc, argv);
int sr_flags;

if(lilo != 0) lilo = 1;
x->x_lin0_log1 = lilo;
if(steady)
x->x_steady = 1;
else
x->x_steady = 0;
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
x->x_gui.x_w = iemgui_clip_size(w) * IEMGUI_ZOOM(x);
vslider_check_height(x, h);
vslider_check_minmax(x, min, max);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

static void vslider_motion(t_vslider *x, t_floatarg dx, t_floatarg dy)
{
int old = x->x_val;

if(x->x_gui.x_fsf.x_finemoved)
x->x_pos -= (int)dy;
else
x->x_pos -= 100 * (int)dy;
x->x_val = x->x_pos;
if(x->x_val > (100*x->x_gui.x_h - 100))
{
x->x_val = 100*x->x_gui.x_h - 100;
x->x_pos += 50;
x->x_pos -= x->x_pos % 100;
}
if(x->x_val < 0)
{
x->x_val = 0;
x->x_pos -= 50;
x->x_pos -= x->x_pos % 100;
}
x->x_fval = vslider_getfval(x);
if (old != x->x_val)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
vslider_bang(x);
}
}

static void vslider_click(t_vslider *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
if(!x->x_steady)
x->x_val = (int)(100.0 * (x->x_gui.x_h + text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist) - ypos));
if(x->x_val > (100*x->x_gui.x_h - 100))
x->x_val = 100*x->x_gui.x_h - 100;
if(x->x_val < 0)
x->x_val = 0;
x->x_fval = vslider_getfval(x);
x->x_pos = x->x_val;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
vslider_bang(x);
glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g,
(t_glistmotionfn)vslider_motion, 0, xpos, ypos);
}

static int vslider_newclick(t_gobj *z, struct _glist *glist,
int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
t_vslider* x = (t_vslider *)z;

if(doit)
{
vslider_click(x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift,
0, (t_floatarg)alt);
if(shift)
x->x_gui.x_fsf.x_finemoved = 1;
else
x->x_gui.x_fsf.x_finemoved = 0;
}
return (1);
}

static void vslider_set(t_vslider *x, t_floatarg f)
{
int old = x->x_val;
double g;

x->x_fval = f;
if (x->x_min > x->x_max)
{
if(f > x->x_min)
f = x->x_min;
if(f < x->x_max)
f = x->x_max;
}
else
{
if(f > x->x_max)
f = x->x_max;
if(f < x->x_min)
f = x->x_min;
}
if(x->x_lin0_log1)
g = log(f/x->x_min) / x->x_k;
else
g = (f - x->x_min) / x->x_k;
x->x_val = IEMGUI_ZOOM(x) * (int)(100.0*g + 0.49999);
x->x_pos = x->x_val;
if(x->x_val != old)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}

static void vslider_float(t_vslider *x, t_floatarg f)
{
vslider_set(x, f);
if(x->x_gui.x_fsf.x_put_in2out)
vslider_bang(x);
}

static void vslider_size(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{
x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av))*IEMGUI_ZOOM(x);
if(ac > 1)
vslider_check_height(x, (int)atom_getfloatarg(1, ac, av)*IEMGUI_ZOOM(x));
iemgui_size((void *)x, &x->x_gui);
}

static void vslider_delta(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void vslider_pos(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void vslider_range(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{
vslider_check_minmax(x, (double)atom_getfloatarg(0, ac, av),
(double)atom_getfloatarg(1, ac, av));
}

static void vslider_color(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void vslider_send(t_vslider *x, t_symbol *s)
{iemgui_send(x, &x->x_gui, s);}

static void vslider_receive(t_vslider *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void vslider_label(t_vslider *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void vslider_label_pos(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void vslider_label_font(t_vslider *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void vslider_log(t_vslider *x)
{
x->x_lin0_log1 = 1;
vslider_check_minmax(x, x->x_min, x->x_max);
}

static void vslider_lin(t_vslider *x)
{
x->x_lin0_log1 = 0;
x->x_k = (x->x_max - x->x_min) / (double)(x->x_gui.x_h/IEMGUI_ZOOM(x) - 1);
}

static void vslider_init(t_vslider *x, t_floatarg f)
{
x->x_gui.x_isa.x_loadinit = (f == 0.0) ? 0 : 1;
}

static void vslider_steady(t_vslider *x, t_floatarg f)
{
x->x_steady = (f == 0.0) ? 0 : 1;
}

static void vslider_zoom(t_vslider *x, t_floatarg f)
{
/* scale current pixel value */
x->x_val = (IEMGUI_ZOOM(x) == 2 ? (x->x_val)/2 : (x->x_val)*2);
x->x_pos = x->x_val;
iemgui_zoom(&x->x_gui, f);
}

static void vslider_loadbang(t_vslider *x, t_floatarg action)
{
if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
vslider_bang(x);
}
}

static void *vslider_new(t_symbol *s, int argc, t_atom *argv)
{
t_vslider *x = (t_vslider *)pd_new(vslider_class);
int w = IEM_GUI_DEFAULTSIZE, h = IEM_SL_DEFAULTSIZE;
int lilo = 0, f = 0, ldx = 0, ldy = -9;
int fs = 10, steady = 1;
double min = 0.0, max = (double)(IEM_SL_DEFAULTSIZE-1);
char str[144];
float v = 0;

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0xFCFCFC;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
&&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3)
&&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
&&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
&&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7))
&&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8))
&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)
&&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,16))
{
w = (int)atom_getfloatarg(0, argc, argv);
h = (int)atom_getfloatarg(1, argc, argv);
min = (double)atom_getfloatarg(2, argc, argv);
max = (double)atom_getfloatarg(3, argc, argv);
lilo = (int)atom_getfloatarg(4, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(5, argc, argv));
iemgui_new_getnames(&x->x_gui, 6, argv);
ldx = (int)atom_getfloatarg(9, argc, argv);
ldy = (int)atom_getfloatarg(10, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(11, argc, argv));
fs = (int)atom_getfloatarg(12, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+13, argv+14, argv+15);
v = atom_getfloatarg(16, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 6, 0);
if((argc == 18)&&IS_A_FLOAT(argv,17))
steady = (int)atom_getfloatarg(17, argc, argv);
x->x_gui.x_draw = (t_iemfunptr)vslider_draw;
x->x_gui.x_fsf.x_snd_able = 1;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if (x->x_gui.x_isa.x_loadinit)
x->x_val = v;
else x->x_val = 0;
x->x_pos = x->x_val;
if(lilo != 0) lilo = 1;
x->x_lin0_log1 = lilo;
if(steady != 0) steady = 1;
x->x_steady = steady;
if(!strcmp(x->x_gui.x_snd->s_name, "empty")) x->x_gui.x_fsf.x_snd_able = 0;
if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) x->x_gui.x_fsf.x_rcv_able = 0;
if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if(x->x_gui.x_fsf.x_rcv_able) pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_w = iemgui_clip_size(w);
vslider_check_height(x, h);
iemgui_verify_snd_ne_rcv(&x->x_gui);
iemgui_newzoom(&x->x_gui);
vslider_check_minmax(x, min, max);
outlet_new(&x->x_gui.x_obj, &s_float);
x->x_fval = vslider_getfval(x);
return (x);
}

static void vslider_free(t_vslider *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_vslider_setup(void)
{
vslider_class = class_new(gensym("vsl"), (t_newmethod)vslider_new,
(t_method)vslider_free, sizeof(t_vslider), 0, A_GIMME, 0);
class_addcreator((t_newmethod)vslider_new, gensym("vslider"), A_GIMME, 0);
class_addbang(vslider_class,vslider_bang);
class_addfloat(vslider_class,vslider_float);
class_addmethod(vslider_class, (t_method)vslider_click,
gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
class_addmethod(vslider_class, (t_method)vslider_motion,
gensym("motion"), A_FLOAT, A_FLOAT, 0);
class_addmethod(vslider_class, (t_method)vslider_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_loadbang,
gensym("loadbang"), A_DEFFLOAT, 0);
class_addmethod(vslider_class, (t_method)vslider_set,
gensym("set"), A_FLOAT, 0);
class_addmethod(vslider_class, (t_method)vslider_size,
gensym("size"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_range,
gensym("range"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_color,
gensym("color"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_send,
gensym("send"), A_DEFSYM, 0);
class_addmethod(vslider_class, (t_method)vslider_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(vslider_class, (t_method)vslider_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(vslider_class, (t_method)vslider_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(vslider_class, (t_method)vslider_log,
gensym("log"), 0);
class_addmethod(vslider_class, (t_method)vslider_lin,
gensym("lin"), 0);
class_addmethod(vslider_class, (t_method)vslider_init,
gensym("init"), A_FLOAT, 0);
class_addmethod(vslider_class, (t_method)vslider_steady,
gensym("steady"), A_FLOAT, 0);
class_addmethod(vslider_class, (t_method)vslider_zoom,
gensym("zoom"), A_CANT, 0);
vslider_widgetbehavior.w_getrectfn = vslider_getrect;
vslider_widgetbehavior.w_displacefn = iemgui_displace;
vslider_widgetbehavior.w_selectfn = iemgui_select;
vslider_widgetbehavior.w_activatefn = NULL;
vslider_widgetbehavior.w_deletefn = iemgui_delete;
vslider_widgetbehavior.w_visfn = iemgui_vis;
vslider_widgetbehavior.w_clickfn = vslider_newclick;
class_setwidget(vslider_class, &vslider_widgetbehavior);
class_sethelpsymbol(vslider_class, gensym("vslider"));
class_setsavefn(vslider_class, vslider_save);
class_setpropertiesfn(vslider_class, vslider_properties);
}

+ 773
- 0
ports/camomile/source/LibPd/pure-data/src/g_vumeter.c View File

@@ -0,0 +1,773 @@
/* 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. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

#include "g_all_guis.h"
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#define HMARGIN 1
#define VMARGIN 2
#define PEAKHEIGHT 10

/* ----- vu gui-peak- & rms- vu-meter-display ---------- */

t_widgetbehavior vu_widgetbehavior;
static t_class *vu_class;

/* widget helper functions */

static void vu_update_rms(t_vu *x, t_glist *glist)
{
if(glist_isvisible(glist))
{
int w4 = x->x_gui.x_w / 4, off = text_ypix(&x->x_gui.x_obj, glist) - IEMGUI_ZOOM(x);
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int quad1 = xpos + w4 - IEMGUI_ZOOM(x), quad3 = xpos + x->x_gui.x_w - w4 + IEMGUI_ZOOM(x);

sys_vgui(".x%lx.c coords %lxRCOVER %d %d %d %d\n",
glist_getcanvas(glist), x, quad1, off, quad3,
off + (x->x_led_size+1)*IEMGUI_ZOOM(x)*(IEM_VU_STEPS-x->x_rms));
}
}

static void vu_update_peak(t_vu *x, t_glist *glist)
{
t_canvas *canvas = glist_getcanvas(glist);

if(glist_isvisible(glist))
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);

if(x->x_peak)
{
int i = iemgui_vu_col[x->x_peak];
int j = ypos +
(x->x_led_size+1)*IEMGUI_ZOOM(x)*(IEM_VU_STEPS+1-x->x_peak) -
(x->x_led_size+1)*IEMGUI_ZOOM(x)/2;

sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n", canvas, x,
xpos, j, xpos + x->x_gui.x_w + IEMGUI_ZOOM(x), j);
sys_vgui(".x%lx.c itemconfigure %lxPLED -fill #%06x\n", canvas, x,
iemgui_color_hex[i]);
}
else
{
int mid = xpos + x->x_gui.x_w/2;
int pkh = PEAKHEIGHT * IEMGUI_ZOOM(x);

sys_vgui(".x%lx.c itemconfigure %lxPLED -fill #%06x\n",
canvas, x, x->x_gui.x_bcol);
sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n",
canvas, x, mid, ypos + pkh, mid, ypos + pkh);
}
}
}

static void vu_draw_update(t_gobj *client, t_glist *glist)
{
t_vu *x = (t_vu *)client;
if (x->x_updaterms)
{
vu_update_rms(x, glist);
x->x_updaterms = 0;
}
if (x->x_updatepeak)
{
vu_update_peak(x, glist);
x->x_updatepeak = 0;
}
}

static void vu_draw_new(t_vu *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int w4 = x->x_gui.x_w/4, mid = xpos + x->x_gui.x_w/2,
quad1 = xpos + w4 + IEMGUI_ZOOM(x);
int quad3 = xpos + x->x_gui.x_w - w4,
end = xpos + x->x_gui.x_w + 4*IEMGUI_ZOOM(x);
int k1 = (x->x_led_size+1)*IEMGUI_ZOOM(x), k2 = IEM_VU_STEPS+1, k3 = k1/2;
int led_col, yyy, i, k4 = ypos - k3;
int ledw = x->x_led_size * IEMGUI_ZOOM(x);
int fs = x->x_gui.x_fontsize * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -width %d -fill #%06x -tags %lxBASE\n",
canvas, xpos - hmargin, ypos - vmargin,
xpos+x->x_gui.x_w + hmargin,
ypos+x->x_gui.x_h + vmargin, IEMGUI_ZOOM(x), x->x_gui.x_bcol, x);
for(i = 1; i <= IEM_VU_STEPS; i++)
{
led_col = iemgui_vu_col[i];
yyy = k4 + k1*(k2-i);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxRLED%d\n",
canvas, quad1, yyy, quad3, yyy, ledw,
iemgui_color_hex[led_col], x, i);
if(((i+2) & 3) && (x->x_scale))
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n",
canvas, end, yyy + k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, fs,
sys_fontweight, x->x_gui.x_lcol, x, i);
}
if(x->x_scale)
{
i = IEM_VU_STEPS + 1;
yyy = k4 + k1 * (k2 - i);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n",
canvas, end, yyy + k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, fs,
sys_fontweight, x->x_gui.x_lcol, x, i);
}
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%06x -outline #%06x -tags %lxRCOVER\n",
canvas, quad1 - IEMGUI_ZOOM(x), ypos - IEMGUI_ZOOM(x), quad3 + IEMGUI_ZOOM(x),
ypos - IEMGUI_ZOOM(x) + k1*IEM_VU_STEPS, x->x_gui.x_bcol, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%06x -tags %lxPLED\n",
canvas, mid, ypos + PEAKHEIGHT * IEMGUI_ZOOM(x),
mid, ypos + PEAKHEIGHT * IEMGUI_ZOOM(x),
(x->x_led_size+1)*IEMGUI_ZOOM(x), x->x_gui.x_bcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]\n",
canvas,
xpos - hmargin, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh,
xpos - hmargin + iow, ypos + x->x_gui.x_h + vmargin,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxOUT%d outlet]x\n",
canvas,
xpos + x->x_gui.x_w + hmargin - iow, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh,
xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin,
x, 1);
}
if(!x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos - hmargin, ypos - vmargin,
xpos - hmargin + iow, ypos - vmargin - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags [list %lxIN%d inlet]\n",
canvas,
xpos + x->x_gui.x_w + hmargin - iow, ypos - vmargin,
xpos + x->x_gui.x_w + hmargin, ypos - vmargin - IEMGUI_ZOOM(x) + ioh,
x, 1);
}
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx * IEMGUI_ZOOM(x), ypos+x->x_gui.x_ldy * IEMGUI_ZOOM(x),
(strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : ""),
x->x_gui.x_font, fs, sys_fontweight,
x->x_gui.x_lcol, x);
x->x_updaterms = x->x_updatepeak = 1;
sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
}

static void vu_draw_move(t_vu *x, t_glist *glist)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
int w4 = x->x_gui.x_w/4, quad1 = xpos + w4 + IEMGUI_ZOOM(x);
int quad3 = xpos + x->x_gui.x_w - w4,
end = xpos + x->x_gui.x_w + 4*IEMGUI_ZOOM(x);
int k1 = (x->x_led_size+1)*IEMGUI_ZOOM(x), k2 = IEM_VU_STEPS+1, k3 = k1/2;
int yyy, i, k4 = ypos - k3;
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x, xpos - hmargin, ypos - vmargin,
xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin);
for(i = 1; i <= IEM_VU_STEPS; i++)
{
yyy = k4 + k1 * (k2 - i);
sys_vgui(".x%lx.c coords %lxRLED%d %d %d %d %d\n",
canvas, x, i, quad1, yyy, quad3, yyy);
if(((i+2) & 3) && (x->x_scale))
sys_vgui(".x%lx.c coords %lxSCALE%d %d %d\n",
canvas, x, i, end, yyy + k3);
}
if(x->x_scale)
{
i = IEM_VU_STEPS + 1;
yyy = k4 + k1 * (k2 - i);
sys_vgui(".x%lx.c coords %lxSCALE%d %d %d\n",
canvas, x, i, end, yyy + k3);
}
x->x_updaterms = x->x_updatepeak = 1;
sys_queuegui(x, glist, vu_draw_update);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos + x->x_gui.x_ldx * IEMGUI_ZOOM(x),
ypos + x->x_gui.x_ldy * IEMGUI_ZOOM(x));
if(!x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 0,
xpos - hmargin, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh,
xpos - hmargin + iow, ypos + x->x_gui.x_h + vmargin);
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 1,
xpos + x->x_gui.x_w + hmargin - iow, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh,
xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin);
}
if(!x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 0,
xpos - hmargin, ypos - vmargin,
xpos - hmargin + iow, ypos - vmargin - IEMGUI_ZOOM(x) + ioh);
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 1,
xpos + x->x_gui.x_w + hmargin - iow, ypos - vmargin,
xpos + x->x_gui.x_w + hmargin, ypos - vmargin - IEMGUI_ZOOM(x) + ioh);
}
}

static void vu_draw_erase(t_vu* x,t_glist* glist)
{
int i;
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c delete %lxBASE\n", canvas, x);
for(i = 1; i <= IEM_VU_STEPS; i++)
{
sys_vgui(".x%lx.c delete %lxRLED%d\n", canvas, x, i);
if(((i+2) & 3) && (x->x_scale))
sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i);
}
if(x->x_scale)
{
i = IEM_VU_STEPS + 1;
sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i);
}
sys_vgui(".x%lx.c delete %lxPLED\n", canvas, x);
sys_vgui(".x%lx.c delete %lxRCOVER\n", canvas, x);
sys_vgui(".x%lx.c delete %lxLABEL\n", canvas, x);
if(!x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 1);
}
if(!x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 1);
}
}

static void vu_draw_config(t_vu* x, t_glist* glist)
{
int i;
int ledw = x->x_led_size * IEMGUI_ZOOM(x);
int fs = x->x_gui.x_fontsize * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%06x\n", canvas, x, x->x_gui.x_bcol);
for(i = 1; i <= IEM_VU_STEPS; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxRLED%d -width %d\n", canvas, x, i, ledw);
if(((i+2) & 3) && (x->x_scale))
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} -font {{%s} -%d %s} -fill #%06x\n",
canvas, x, i, iemgui_vu_scale_str[i], x->x_gui.x_font,
fs, sys_fontweight,
x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol);
}
if(x->x_scale)
{
i = IEM_VU_STEPS + 1;
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} -font {{%s} -%d %s} -fill #%06x\n",
canvas, x, i, iemgui_vu_scale_str[i], x->x_gui.x_font,
fs, sys_fontweight,
x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -font {{%s} -%d %s} -fill #%06x -text {%s} \n",
canvas, x, x->x_gui.x_font, fs, sys_fontweight,
x->x_gui.x_fsf.x_selected ? IEM_GUI_COLOR_SELECTED : x->x_gui.x_lcol,
strcmp(x->x_gui.x_lab->s_name, "empty") ? x->x_gui.x_lab->s_name : "");

sys_vgui(".x%lx.c itemconfigure %lxRCOVER -fill #%06x -outline #%06x\n", canvas,
x, x->x_gui.x_bcol, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxPLED -width %d\n", canvas, x, ledw);
}

static void vu_draw_io(t_vu* x, t_glist* glist, int old_snd_rcv_flags)
{
int xpos = text_xpix(&x->x_gui.x_obj, glist);
int ypos = text_ypix(&x->x_gui.x_obj, glist);
int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x);
int iow = IOWIDTH * IEMGUI_ZOOM(x), ioh = IEM_GUI_IOHEIGHT * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(glist);

if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos - hmargin, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh,
xpos - hmargin + iow, ypos + x->x_gui.x_h + vmargin,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxOUT%d\n",
canvas,
xpos + x->x_gui.x_w + hmargin - iow, ypos + x->x_gui.x_h + vmargin + IEMGUI_ZOOM(x) - ioh,
xpos + x->x_gui.x_w + hmargin, ypos + x->x_gui.x_h + vmargin,
x, 1);
/* keep above outlets */
sys_vgui(".x%lx.c raise %lxLABEL %lxOUT%d\n", canvas, x, x, 1);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 0);
sys_vgui(".x%lx.c delete %lxOUT%d\n", canvas, x, 1);
}
if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos - hmargin, ypos - vmargin,
xpos - hmargin + iow, ypos - vmargin - IEMGUI_ZOOM(x) + ioh,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill black -tags %lxIN%d\n",
canvas,
xpos + x->x_gui.x_w + hmargin - iow, ypos - vmargin,
xpos + x->x_gui.x_w + hmargin, ypos - vmargin - IEMGUI_ZOOM(x) + ioh,
x, 1);
/* keep above inlets */
sys_vgui(".x%lx.c raise %lxLABEL %lxIN%d\n", canvas, x, x, 1);
}
if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 0);
sys_vgui(".x%lx.c delete %lxIN%d\n", canvas, x, 1);
}
}

static void vu_draw_select(t_vu* x,t_glist* glist)
{
int i;
t_canvas *canvas = glist_getcanvas(glist);

if(x->x_gui.x_fsf.x_selected)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
for(i = 1; i <= IEM_VU_STEPS; i++)
{
if(((i+2) & 3) && (x->x_scale))
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n",
canvas, x, i, IEM_GUI_COLOR_SELECTED);
}
if(x->x_scale)
{
i = IEM_VU_STEPS + 1;
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n",
canvas, x, i, IEM_GUI_COLOR_SELECTED);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%06x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
for(i = 1; i <= IEM_VU_STEPS; i++)
{
if(((i+2) & 3) && (x->x_scale))
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n",
canvas, x, i, x->x_gui.x_lcol);
}
if(x->x_scale)
{
i = IEM_VU_STEPS+1;
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%06x\n",
canvas, x, i, x->x_gui.x_lcol);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%06x\n", canvas, x, x->x_gui.x_lcol);
}
}

void vu_draw(t_vu *x, t_glist *glist, int mode)
{
if(mode == IEM_GUI_DRAW_MODE_MOVE)
vu_draw_move(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_NEW)
vu_draw_new(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_SELECT)
vu_draw_select(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_ERASE)
vu_draw_erase(x, glist);
else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
vu_draw_config(x, glist);
else if(mode >= IEM_GUI_DRAW_MODE_IO)
vu_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
}

/* ------------------------ vu widgetbehaviour----------------------------- */

static void vu_getrect(t_gobj *z, t_glist *glist,
int *xp1, int *yp1, int *xp2, int *yp2)
{
t_vu* x = (t_vu*)z;
int hmargin = HMARGIN * IEMGUI_ZOOM(x), vmargin = VMARGIN * IEMGUI_ZOOM(x);

*xp1 = text_xpix(&x->x_gui.x_obj, glist) - hmargin;
*yp1 = text_ypix(&x->x_gui.x_obj, glist) - vmargin;
*xp2 = *xp1 + x->x_gui.x_w + hmargin*2;
*yp2 = *yp1 + x->x_gui.x_h + vmargin*2;
}

static void vu_save(t_gobj *z, t_binbuf *b)
{
t_vu *x = (t_vu *)z;
t_symbol *bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiissiiiissii", gensym("#X"), gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("vu"), x->x_gui.x_w/IEMGUI_ZOOM(x), x->x_gui.x_h/IEMGUI_ZOOM(x),
srl[1], srl[2],
x->x_gui.x_ldx, x->x_gui.x_ldy,
iem_fstyletoint(&x->x_gui.x_fsf), x->x_gui.x_fontsize,
bflcol[0], bflcol[2], x->x_scale,
iem_symargstoint(&x->x_gui.x_isa));
binbuf_addv(b, ";");
}

void vu_check_height(t_vu *x, int h)
{
int n;

n = h / IEM_VU_STEPS;
if(n < IEM_VU_MINSIZE)
n = IEM_VU_MINSIZE;
x->x_led_size = n - 1;
x->x_gui.x_h = (IEM_VU_STEPS * n) * IEMGUI_ZOOM(x);
}

static void vu_scale(t_vu *x, t_floatarg fscale)
{
int i, scale = (int)fscale;

if(scale != 0) scale = 1;
if(x->x_scale && !scale)
{
t_canvas *canvas = glist_getcanvas(x->x_gui.x_glist);

x->x_scale = (int)scale;
if(glist_isvisible(x->x_gui.x_glist))
{
for(i = 1; i <= IEM_VU_STEPS; i++)
{
if((i+2) & 3)
sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i);
}
i = IEM_VU_STEPS + 1;
sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i);
}
}
if(!x->x_scale && scale)
{
int w4 = x->x_gui.x_w/4;
int end = text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist) + x->x_gui.x_w + 4*IEMGUI_ZOOM(x);
int k1 = (x->x_led_size+1)*IEMGUI_ZOOM(x), k2 = IEM_VU_STEPS+1, k3 = k1/2;
int yyy, k4 = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist) - k3;
int fs = x->x_gui.x_fontsize * IEMGUI_ZOOM(x);
t_canvas *canvas = glist_getcanvas(x->x_gui.x_glist);

x->x_scale = (int)scale;
if(glist_isvisible(x->x_gui.x_glist))
{
for(i = 1; i <= IEM_VU_STEPS; i++)
{
yyy = k4 + k1 * (k2 - i);
if((i+2) & 3)
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n",
canvas, end, yyy + k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, fs,
sys_fontweight, x->x_gui.x_lcol, x, i);
}
i = IEM_VU_STEPS + 1;
yyy = k4 + k1 * (k2 - i);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%06x -tags %lxSCALE%d\n",
canvas, end, yyy + k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, fs,
sys_fontweight, x->x_gui.x_lcol, x, i);
}
}
}

static void vu_properties(t_gobj *z, t_glist *owner)
{
t_vu *x = (t_vu *)z;
char buf[800];
t_symbol *srl[3];

iemgui_properties(&x->x_gui, srl);
sprintf(buf, "pdtk_iemgui_dialog %%s |vu| \
--------dimensions(pix)(pix):-------- %d %d width: %d %d height: \
empty 0.0 empty 0.0 empty %d \
%d no_scale scale %d %d empty %d \
%s %s \
%s %d %d \
%d %d \
#%06x none #%06x\n",
x->x_gui.x_w/IEMGUI_ZOOM(x), IEM_GUI_MINSIZE,
x->x_gui.x_h/IEMGUI_ZOOM(x), IEM_VU_STEPS*IEM_VU_MINSIZE,
0,/*no_schedule*/
x->x_scale, -1, -1, -1,/*no linlog, no init, no multi*/
"nosndno", srl[1]->s_name,/*no send*/
srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_lcol);
gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void vu_dialog(t_vu *x, t_symbol *s, int argc, t_atom *argv)
{
t_symbol *srl[3];
int w = (int)atom_getfloatarg(0, argc, argv);
int h = (int)atom_getfloatarg(1, argc, argv);
int scale = (int)atom_getfloatarg(4, argc, argv);
int sr_flags;

srl[0] = gensym("empty");
sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
x->x_gui.x_fsf.x_snd_able = 0;
x->x_gui.x_isa.x_loadinit = 0;
x->x_gui.x_w = iemgui_clip_size(w) * IEMGUI_ZOOM(x);
vu_check_height(x, h);
if(scale != 0)
scale = 1;
vu_scale(x, (t_float)scale);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}

static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av)
{
x->x_gui.x_w = iemgui_clip_size((int)atom_getfloatarg(0, ac, av)) * IEMGUI_ZOOM(x);
if(ac > 1)
vu_check_height(x, (int)atom_getfloatarg(1, ac, av));
if(glist_isvisible(x->x_gui.x_glist))
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}

static void vu_delta(t_vu *x, t_symbol *s, int ac, t_atom *av)
{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}

static void vu_pos(t_vu *x, t_symbol *s, int ac, t_atom *av)
{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}

static void vu_color(t_vu *x, t_symbol *s, int ac, t_atom *av)
{iemgui_color((void *)x, &x->x_gui, s, ac, av);}

static void vu_receive(t_vu *x, t_symbol *s)
{iemgui_receive(x, &x->x_gui, s);}

static void vu_label(t_vu *x, t_symbol *s)
{iemgui_label((void *)x, &x->x_gui, s);}

static void vu_label_pos(t_vu *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}

static void vu_label_font(t_vu *x, t_symbol *s, int ac, t_atom *av)
{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}

static void vu_float(t_vu *x, t_floatarg rms)
{
int i;
int old = x->x_rms;
if(rms <= IEM_VU_MINDB)
x->x_rms = 0;
else if(rms >= IEM_VU_MAXDB)
x->x_rms = IEM_VU_STEPS;
else
{
int i = (int)(2.0*(rms + IEM_VU_OFFSET));
x->x_rms = iemgui_vu_db2i[i];
}
i = (int)(100.0*rms + 10000.5);
rms = 0.01*(t_float)(i - 10000);
x->x_fr = rms;
outlet_float(x->x_out_rms, rms);
x->x_updaterms = 1;
if(x->x_rms != old)
sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
}

static void vu_ft1(t_vu *x, t_floatarg peak)
{
int i;
int old = x->x_peak;
if(peak <= IEM_VU_MINDB)
x->x_peak = 0;
else if(peak >= IEM_VU_MAXDB)
x->x_peak = IEM_VU_STEPS;
else
{
int i = (int)(2.0*(peak + IEM_VU_OFFSET));
x->x_peak = iemgui_vu_db2i[i];
}
i = (int)(100.0*peak + 10000.5);
peak = 0.01*(t_float)(i - 10000);
x->x_fp = peak;
x->x_updatepeak = 1;
if(x->x_peak != old)
sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
outlet_float(x->x_out_peak, peak);
}

static void vu_bang(t_vu *x)
{
outlet_float(x->x_out_peak, x->x_fp);
outlet_float(x->x_out_rms, x->x_fr);
x->x_updaterms = x->x_updatepeak = 1;
sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
}

static void *vu_new(t_symbol *s, int argc, t_atom *argv)
{
t_vu *x = (t_vu *)pd_new(vu_class);
int w = IEM_GUI_DEFAULTSIZE, h = IEM_VU_STEPS*IEM_VU_DEFAULTSIZE;
int ldx = -1, ldy = -8, f = 0, fs = 10, scale =1;
int ftbreak = IEM_BNG_DEFAULTBREAKFLASHTIME, fthold = IEM_BNG_DEFAULTHOLDFLASHTIME;
char str[144];

iem_inttosymargs(&x->x_gui.x_isa, 0);
iem_inttofstyle(&x->x_gui.x_fsf, 0);

x->x_gui.x_bcol = 0x404040;
x->x_gui.x_fcol = 0x00;
x->x_gui.x_lcol = 0x00;

if((argc >= 11)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
&&(IS_A_SYMBOL(argv,2)||IS_A_FLOAT(argv,2))
&&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3))
&&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
&&IS_A_FLOAT(argv,6)&&IS_A_FLOAT(argv,7)
&&IS_A_FLOAT(argv,10))
{
w = (int)atom_getfloatarg(0, argc, argv);
h = (int)atom_getfloatarg(1, argc, argv);
iemgui_new_getnames(&x->x_gui, 1, argv);
ldx = (int)atom_getfloatarg(4, argc, argv);
ldy = (int)atom_getfloatarg(5, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getfloatarg(6, argc, argv));
fs = (int)atom_getfloatarg(7, argc, argv);
iemgui_all_loadcolors(&x->x_gui, argv+8, NULL, argv+9);
scale = (int)atom_getfloatarg(10, argc, argv);
}
else iemgui_new_getnames(&x->x_gui, 1, 0);
if((argc == 12)&&IS_A_FLOAT(argv,11))
iem_inttosymargs(&x->x_gui.x_isa, atom_getfloatarg(11, argc, argv));
x->x_gui.x_draw = (t_iemfunptr)vu_draw;

x->x_gui.x_fsf.x_snd_able = 0;
x->x_gui.x_fsf.x_rcv_able = 1;
x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
if (!strcmp(x->x_gui.x_rcv->s_name, "empty"))
x->x_gui.x_fsf.x_rcv_able = 0;
if (x->x_gui.x_fsf.x_font_style == 1)
strcpy(x->x_gui.x_font, "helvetica");
else if(x->x_gui.x_fsf.x_font_style == 2)
strcpy(x->x_gui.x_font, "times");
else { x->x_gui.x_fsf.x_font_style = 0;
strcpy(x->x_gui.x_font, sys_font); }
if(x->x_gui.x_fsf.x_rcv_able)
pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
x->x_gui.x_ldx = ldx;
x->x_gui.x_ldy = ldy;
if(fs < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
x->x_gui.x_w = iemgui_clip_size(w);
vu_check_height(x, h);
if(scale != 0)
scale = 1;
x->x_scale = scale;
x->x_peak = 0;
x->x_rms = 0;
x->x_fp = -101.0;
x->x_fr = -101.0;
iemgui_verify_snd_ne_rcv(&x->x_gui);
inlet_new(&x->x_gui.x_obj, &x->x_gui.x_obj.ob_pd, &s_float, gensym("ft1"));
x->x_out_rms = outlet_new(&x->x_gui.x_obj, &s_float);
x->x_out_peak = outlet_new(&x->x_gui.x_obj, &s_float);
iemgui_newzoom(&x->x_gui);
return (x);
}

static void vu_free(t_vu *x)
{
if(x->x_gui.x_fsf.x_rcv_able)
pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
gfxstub_deleteforkey(x);
}

void g_vumeter_setup(void)
{
vu_class = class_new(gensym("vu"), (t_newmethod)vu_new,
(t_method)vu_free, sizeof(t_vu), 0, A_GIMME, 0);
class_addbang(vu_class,vu_bang);
class_addfloat(vu_class,vu_float);
class_addmethod(vu_class, (t_method)vu_ft1,
gensym("ft1"), A_FLOAT, 0);
class_addmethod(vu_class, (t_method)vu_dialog,
gensym("dialog"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)vu_size,
gensym("size"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)vu_scale,
gensym("scale"), A_DEFFLOAT, 0);
class_addmethod(vu_class, (t_method)vu_delta,
gensym("delta"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)vu_pos,
gensym("pos"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)vu_color,
gensym("color"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)vu_receive,
gensym("receive"), A_DEFSYM, 0);
class_addmethod(vu_class, (t_method)vu_label,
gensym("label"), A_DEFSYM, 0);
class_addmethod(vu_class, (t_method)vu_label_pos,
gensym("label_pos"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)vu_label_font,
gensym("label_font"), A_GIMME, 0);
class_addmethod(vu_class, (t_method)iemgui_zoom,
gensym("zoom"), A_CANT, 0);
vu_widgetbehavior.w_getrectfn = vu_getrect;
vu_widgetbehavior.w_displacefn = iemgui_displace;
vu_widgetbehavior.w_selectfn = iemgui_select;
vu_widgetbehavior.w_activatefn = NULL;
vu_widgetbehavior.w_deletefn = iemgui_delete;
vu_widgetbehavior.w_visfn = iemgui_vis;
vu_widgetbehavior.w_clickfn = NULL;
class_setwidget(vu_class,&vu_widgetbehavior);
class_sethelpsymbol(vu_class, gensym("vu"));
class_setsavefn(vu_class, vu_save);
class_setpropertiesfn(vu_class, vu_properties);
}

+ 128
- 0
ports/camomile/source/LibPd/pure-data/src/m_atom.c View File

@@ -0,0 +1,128 @@
/* 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. */

#include "m_pd.h"
#include <stdio.h>
#include <string.h>

/* convenience routines for checking and getting values of
atoms. There's no "pointer" version since there's nothing
safe to return if there's an error. */

t_float atom_getfloat(t_atom *a)
{
if (a->a_type == A_FLOAT) return (a->a_w.w_float);
else return (0);
}

t_int atom_getint(t_atom *a)
{
return (atom_getfloat(a));
}

t_symbol *atom_getsymbol(t_atom *a) /* LATER think about this more carefully */
{
if (a->a_type == A_SYMBOL) return (a->a_w.w_symbol);
else return (&s_float);
}

t_symbol *atom_gensym(t_atom *a) /* this works better for graph labels */
{
char buf[30];
if (a->a_type == A_SYMBOL) return (a->a_w.w_symbol);
else if (a->a_type == A_FLOAT)
sprintf(buf, "%g", a->a_w.w_float);
else strcpy(buf, "???");
return (gensym(buf));
}

t_float atom_getfloatarg(int which, int argc, t_atom *argv)
{
if (argc <= which) return (0);
argv += which;
if (argv->a_type == A_FLOAT) return (argv->a_w.w_float);
else return (0);
}

t_int atom_getintarg(int which, int argc, t_atom *argv)
{
return (atom_getfloatarg(which, argc, argv));
}

t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv)
{
if (argc <= which) return (&s_);
argv += which;
if (argv->a_type == A_SYMBOL) return (argv->a_w.w_symbol);
else return (&s_);
}

/* convert an atom into a string, in the reverse sense of binbuf_text (q.v.)
* special attention is paid to symbols containing the special characters
* ';', ',', '$', and '\'; these are quoted with a preceding '\', except that
* the '$' only gets quoted at the beginning of the string.
*/

void atom_string(t_atom *a, char *buf, unsigned int bufsize)
{
char tbuf[30];
switch(a->a_type)
{
case A_SEMI: strcpy(buf, ";"); break;
case A_COMMA: strcpy(buf, ","); break;
case A_POINTER:
strcpy(buf, "(pointer)");
break;
case A_FLOAT:
sprintf(tbuf, "%g", a->a_w.w_float);
if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf);
else if (a->a_w.w_float < 0) strcpy(buf, "-");
else strcpy(buf, "+");
break;
case A_SYMBOL:
{
char *sp;
unsigned int len;
int quote;
for (sp = a->a_w.w_symbol->s_name, len = 0, quote = 0; *sp; sp++, len++)
if (*sp == ';' || *sp == ',' || *sp == '\\' ||
(*sp == '$' && sp[1] >= '0' && sp[1] <= '9'))
quote = 1;
if (quote)
{
char *bp = buf, *ep = buf + (bufsize-2);
sp = a->a_w.w_symbol->s_name;
while (bp < ep && *sp)
{
if (*sp == ';' || *sp == ',' || *sp == '\\' ||
(*sp == '$' && sp[1] >= '0' && sp[1] <= '9'))
*bp++ = '\\';
*bp++ = *sp++;
}
if (*sp) *bp++ = '*';
*bp = 0;
/* post("quote %s -> %s", a->a_w.w_symbol->s_name, buf); */
}
else
{
if (len < bufsize-1) strcpy(buf, a->a_w.w_symbol->s_name);
else
{
strncpy(buf, a->a_w.w_symbol->s_name, bufsize - 2);
strcpy(buf + (bufsize - 2), "*");
}
}
}
break;
case A_DOLLAR:
sprintf(buf, "$%d", a->a_w.w_index);
break;
case A_DOLLSYM:
strncpy(buf, a->a_w.w_symbol->s_name, bufsize);
buf[bufsize-1] = 0;
break;
default:
bug("atom_string");
}
}

+ 1546
- 0
ports/camomile/source/LibPd/pure-data/src/m_binbuf.c
File diff suppressed because it is too large
View File


+ 1080
- 0
ports/camomile/source/LibPd/pure-data/src/m_class.c
File diff suppressed because it is too large
View File


+ 110
- 0
ports/camomile/source/LibPd/pure-data/src/m_conf.c View File

@@ -0,0 +1,110 @@
/* 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. */

/* changes by Thomas Musil IEM KUG Graz Austria 2001 */
/* all changes are labeled with iemlib */

#include "m_pd.h"

void g_array_setup(void);
void g_canvas_setup(void);
void g_guiconnect_setup(void);
/* iemlib */
void g_bang_setup(void);
void g_hradio_setup(void);
void g_hslider_setup(void);
void g_mycanvas_setup(void);
void g_numbox_setup(void);
void g_toggle_setup(void);
void g_vradio_setup(void);
void g_vslider_setup(void);
void g_vumeter_setup(void);
/* iemlib */
void g_io_setup(void);
void g_scalar_setup(void);
void g_template_setup(void);
void g_text_setup(void);
void g_traversal_setup(void);
void clone_setup(void);
void m_pd_setup(void);
void x_acoustics_setup(void);
void x_interface_setup(void);
void x_connective_setup(void);
void x_time_setup(void);
void x_arithmetic_setup(void);
void x_array_setup(void);
void x_midi_setup(void);
void x_misc_setup(void);
void x_net_setup(void);
void x_qlist_setup(void);
void x_gui_setup(void);
void x_list_setup(void);
void x_scalar_setup(void);
void expr_setup(void);
void d_arithmetic_setup(void);
void d_array_setup(void);
void d_ctl_setup(void);
void d_dac_setup(void);
void d_delay_setup(void);
void d_fft_setup(void);
void d_filter_setup(void);
void d_global_setup(void);
void d_math_setup(void);
void d_misc_setup(void);
void d_osc_setup(void);
void d_soundfile_setup(void);
void d_ugen_setup(void);

void conf_init(void)
{
g_array_setup();
g_canvas_setup();
g_guiconnect_setup();
/* iemlib */
g_bang_setup();
g_hradio_setup();
g_hslider_setup();
g_mycanvas_setup();
g_numbox_setup();
g_toggle_setup();
g_vradio_setup();
g_vslider_setup();
g_vumeter_setup();
/* iemlib */
g_io_setup();
g_scalar_setup();
g_template_setup();
g_text_setup();
g_traversal_setup();
clone_setup();
m_pd_setup();
x_acoustics_setup();
x_interface_setup();
x_connective_setup();
x_time_setup();
x_arithmetic_setup();
x_array_setup();
x_midi_setup();
x_misc_setup();
x_net_setup();
x_qlist_setup();
x_gui_setup();
x_list_setup();
x_scalar_setup();
expr_setup();
d_arithmetic_setup();
d_array_setup();
d_ctl_setup();
d_dac_setup();
d_delay_setup();
d_fft_setup();
d_filter_setup();
d_global_setup();
d_math_setup();
d_misc_setup();
d_osc_setup();
d_soundfile_setup();
d_ugen_setup();
}


+ 216
- 0
ports/camomile/source/LibPd/pure-data/src/m_glob.c View File

@@ -0,0 +1,216 @@
/* 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. */

#include "m_pd.h"
#include "m_imp.h"
#include "s_stuff.h"

t_class *glob_pdobject;
static t_class *maxclass;

int sys_perf; /* true if we should query user on close and quit */
int pd_compatibilitylevel = 100000; /* e.g., 43 for pd 0.43 compatibility */

/* These "glob" routines, which implement messages to Pd, are from all
over. Some others are prototyped in m_imp.h as well. */

void glob_menunew(void *dummy, t_symbol *name, t_symbol *dir);
void glob_verifyquit(void *dummy, t_floatarg f);
void glob_dsp(void *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_meters(void *dummy, t_floatarg f);
void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av);
void glob_audiostatus(void *dummy);
void glob_finderror(t_pd *dummy);
void glob_findinstance(t_pd *dummy, t_symbol*s);
void glob_audio_properties(t_pd *dummy, t_floatarg flongform);
void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_audio_setapi(t_pd *dummy, t_floatarg f);
void glob_midi_properties(t_pd *dummy, t_floatarg flongform);
void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_midi_setapi(t_pd *dummy, t_floatarg f);
void glob_start_path_dialog(t_pd *dummy, t_floatarg flongform);
void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_addtopath(t_pd *dummy, t_symbol *path, t_float saveit);
void glob_start_startup_dialog(t_pd *dummy, t_floatarg flongform);
void glob_startup_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_ping(t_pd *dummy);
void glob_plugindispatch(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_watchdog(t_pd *dummy);
void glob_loadpreferences(t_pd *dummy, t_symbol *s);
void glob_savepreferences(t_pd *dummy, t_symbol *s);
void glob_forgetpreferences(t_pd *dummy);

static void glob_helpintro(t_pd *dummy)
{
open_via_helppath("intro.pd", "");
}

static void glob_compatibility(t_pd *dummy, t_floatarg level)
{
int dspwas = canvas_suspend_dsp();
pd_compatibilitylevel = 0.5 + 100. * level;
canvas_resume_dsp(dspwas);
}

#ifdef _WIN32
void glob_audio(void *dummy, t_floatarg adc, t_floatarg dac);
#endif

/* a method you add for debugging printout */
void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv);

#if 0
void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
{
post("foo 1");
printf("barbarbar 2\n");
post("foo 3");
}
#endif

static void glob_version(t_pd *dummy, float f)
{
if (f > (PD_MAJOR_VERSION + 0.01*PD_MINOR_VERSION + 0.001))
{
static int warned;
if (warned < 1)
post("warning: file format (%g) newer than this version (%g) of Pd",
f, PD_MAJOR_VERSION + 0.01*PD_MINOR_VERSION);
else if (warned < 2)
post("(... more file format messages suppressed)");
warned++;
}
}

static void glob_perf(t_pd *dummy, float f)
{
sys_perf = (f != 0);
}

void max_default(t_pd *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
char str[80];
startpost("%s: unknown message %s ", class_getname(pd_class(x)),
s->s_name);
for (i = 0; i < argc; i++)
{
atom_string(argv+i, str, 80);
poststring(str);
}
endpost();
}

void glob_plugindispatch(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
{
int i;
char str[80];
sys_vgui("pdtk_plugin_dispatch ");
for (i = 0; i < argc; i++)
{
atom_string(argv+i, str, 80);
sys_vgui("%s", str);
if (i < argc-1) {
sys_vgui(" ");
}
}
sys_vgui("\n");
}

int sys_zoom_open = 1;
void glob_zoom_open(t_pd *dummy, t_floatarg f)
{
sys_zoom_open = (f != 0 ? 2 : 1);
}

void glob_init(void)
{
maxclass = class_new(gensym("max"), 0, 0, sizeof(t_pd),
CLASS_DEFAULT, A_NULL);
class_addanything(maxclass, max_default);
pd_bind(&maxclass, gensym("max"));

glob_pdobject = class_new(gensym("pd"), 0, 0, sizeof(t_pd),
CLASS_DEFAULT, A_NULL);
class_addmethod(glob_pdobject, (t_method)glob_initfromgui, gensym("init"),
A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_menunew, gensym("menunew"),
A_SYMBOL, A_SYMBOL, 0);
class_addmethod(glob_pdobject, (t_method)glob_evalfile, gensym("open"),
A_SYMBOL, A_SYMBOL, 0);
class_addmethod(glob_pdobject, (t_method)glob_quit, gensym("quit"), 0);
class_addmethod(glob_pdobject, (t_method)glob_verifyquit,
gensym("verifyquit"), A_DEFFLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_foo, gensym("foo"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_dsp, gensym("dsp"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_meters, gensym("meters"),
A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_key, gensym("key"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_audiostatus,
gensym("audiostatus"), 0);
class_addmethod(glob_pdobject, (t_method)glob_finderror,
gensym("finderror"), 0);
class_addmethod(glob_pdobject, (t_method)glob_findinstance,
gensym("findinstance"), A_SYMBOL, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_properties,
gensym("audio-properties"), A_DEFFLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_dialog,
gensym("audio-dialog"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_setapi,
gensym("audio-setapi"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_midi_setapi,
gensym("midi-setapi"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_midi_properties,
gensym("midi-properties"), A_DEFFLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_midi_dialog,
gensym("midi-dialog"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_start_path_dialog,
gensym("start-path-dialog"), 0);
class_addmethod(glob_pdobject, (t_method)glob_path_dialog,
gensym("path-dialog"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_addtopath,
gensym("add-to-path"), A_SYMBOL, A_DEFFLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_start_startup_dialog,
gensym("start-startup-dialog"), 0);
class_addmethod(glob_pdobject, (t_method)glob_startup_dialog,
gensym("startup-dialog"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_ping, gensym("ping"), 0);
class_addmethod(glob_pdobject, (t_method)glob_loadpreferences,
gensym("load-preferences"), A_DEFSYM, 0);
class_addmethod(glob_pdobject, (t_method)glob_savepreferences,
gensym("save-preferences"), A_DEFSYM, 0);
class_addmethod(glob_pdobject, (t_method)glob_forgetpreferences,
gensym("forget-preferences"), A_DEFSYM, 0);
class_addmethod(glob_pdobject, (t_method)glob_zoom_open,
gensym("zoom-open"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_version,
gensym("version"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_perf,
gensym("perf"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_compatibility,
gensym("compatibility"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_plugindispatch,
gensym("plugin-dispatch"), A_GIMME, 0);
class_addmethod(glob_pdobject, (t_method)glob_helpintro,
gensym("help-intro"), A_GIMME, 0);
#if defined(__linux__) || defined(__FreeBSD_kernel__)
class_addmethod(glob_pdobject, (t_method)glob_watchdog,
gensym("watchdog"), 0);
#endif
class_addanything(glob_pdobject, max_default);
pd_bind(&glob_pdobject, gensym("pd"));
}

/* function to return version number at run time. Any of the
calling pointers may be zero in case you don't need all of them. */
void sys_getversion(int *major, int *minor, int *bugfix)
{
if (major)
*major = PD_MAJOR_VERSION;
if (minor)
*minor = PD_MINOR_VERSION;
if (bugfix)
*bugfix = PD_BUGFIX_VERSION;
}


+ 98
- 0
ports/camomile/source/LibPd/pure-data/src/m_imp.h View File

@@ -0,0 +1,98 @@
/* 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 contains function prototypes and data types used to implement
Pd, but not shared with Pd objects. */

/* NOTE: this file describes Pd implementation details which may change
in future releases. The public (stable) API is in m_pd.h. */

/* LATER consider whether to use 'char' for method arg types to save space */
#ifndef __m_imp_h_

/* the structure for a method handler ala Max */
typedef struct _methodentry
{
t_symbol *me_name;
t_gotfn me_fun;
t_atomtype me_arg[MAXPDARG+1];
} t_methodentry;

EXTERN_STRUCT _widgetbehavior;

typedef void (*t_bangmethod)(t_pd *x);
typedef void (*t_pointermethod)(t_pd *x, t_gpointer *gp);
typedef void (*t_floatmethod)(t_pd *x, t_float f);
typedef void (*t_symbolmethod)(t_pd *x, t_symbol *s);
typedef void (*t_listmethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv);
typedef void (*t_anymethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv);

struct _class
{
t_symbol *c_name; /* name (mostly for error reporting) */
t_symbol *c_helpname; /* name of help file */
t_symbol *c_externdir; /* directory extern was loaded from */
size_t c_size; /* size of an instance */
#ifdef PDINSTANCE
t_methodentry **c_methods; /* methods other than bang, etc below */
#else
t_methodentry *c_methods;
#endif
int c_nmethod; /* number of methods */
t_method c_freemethod; /* function to call before freeing */
t_bangmethod c_bangmethod; /* common methods */
t_pointermethod c_pointermethod;
t_floatmethod c_floatmethod;
t_symbolmethod c_symbolmethod;
t_listmethod c_listmethod;
t_anymethod c_anymethod;
const struct _widgetbehavior *c_wb; /* "gobjs" only */
const struct _parentwidgetbehavior *c_pwb;/* widget behavior in parent */
t_savefn c_savefn; /* function to call when saving */
t_propertiesfn c_propertiesfn; /* function to start prop dialog */
struct _class *c_next;
int c_floatsignalin; /* onset to float for signal input */
char c_gobj; /* true if is a gobj */
char c_patchable; /* true if we have a t_object header */
char c_firstin; /* if patchable, true if draw first inlet */
char c_drawcommand; /* a drawing command for a template */
};

/* m_class.c */
EXTERN void pd_emptylist(t_pd *x);

/* m_obj.c */
EXTERN int obj_noutlets(t_object *x);
EXTERN int obj_ninlets(t_object *x);
EXTERN t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op,
int nout);
EXTERN t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect,
t_object **destp, t_inlet **inletp, int *whichp);
EXTERN t_outconnect *obj_connect(t_object *source, int outno,
t_object *sink, int inno);
EXTERN void obj_disconnect(t_object *source, int outno, t_object *sink,
int inno);
EXTERN void outlet_setstacklim(void);
EXTERN int obj_issignalinlet(t_object *x, int m);
EXTERN int obj_issignaloutlet(t_object *x, int m);
EXTERN int obj_nsiginlets(t_object *x);
EXTERN int obj_nsigoutlets(t_object *x);
EXTERN int obj_siginletindex(t_object *x, int m);
EXTERN int obj_sigoutletindex(t_object *x, int m);

/* s_inter.c */
void pd_globallock( void);
void pd_globalunlock( void);

/* misc */
#define SYMTABHASHSIZE 1024

EXTERN t_pd *glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir);
EXTERN void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv);
EXTERN void glob_quit(void *dummy);
EXTERN void open_via_helppath(const char *name, const char *dir);


#define __m_imp_h_
#endif /* __m_imp_h_ */

+ 89
- 0
ports/camomile/source/LibPd/pure-data/src/m_memory.c View File

@@ -0,0 +1,89 @@
/* 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. */

#include <stdlib.h>
#include <string.h>
#include "m_pd.h"
#include "m_imp.h"

/* #define LOUD */
#ifdef LOUD
#include <stdio.h>
#endif

/* #define DEBUGMEM */
#ifdef DEBUGMEM
static int totalmem = 0;
#endif

void *getbytes(size_t nbytes)
{
void *ret;
if (nbytes < 1) nbytes = 1;
ret = (void *)calloc(nbytes, 1);
#ifdef LOUD
fprintf(stderr, "new %lx %d\n", (int)ret, nbytes);
#endif /* LOUD */
#ifdef DEBUGMEM
totalmem += nbytes;
#endif
if (!ret)
post("pd: getbytes() failed -- out of memory");
return (ret);
}

void *getzbytes(size_t nbytes) /* obsolete name */
{
return (getbytes(nbytes));
}

void *copybytes(void *src, size_t nbytes)
{
void *ret;
ret = getbytes(nbytes);
if (nbytes)
memcpy(ret, src, nbytes);
return (ret);
}

void *resizebytes(void *old, size_t oldsize, size_t newsize)
{
void *ret;
if (newsize < 1) newsize = 1;
if (oldsize < 1) oldsize = 1;
ret = (void *)realloc((char *)old, newsize);
if (newsize > oldsize && ret)
memset(((char *)ret) + oldsize, 0, newsize - oldsize);
#ifdef LOUD
fprintf(stderr, "resize %lx %d --> %lx %d\n", (int)old, oldsize, (int)ret, newsize);
#endif /* LOUD */
#ifdef DEBUGMEM
totalmem += (newsize - oldsize);
#endif
if (!ret)
post("pd: resizebytes() failed -- out of memory");
return (ret);
}

void freebytes(void *fatso, size_t nbytes)
{
if (nbytes == 0)
nbytes = 1;
#ifdef LOUD
fprintf(stderr, "free %lx %d\n", (int)fatso, nbytes);
#endif /* LOUD */
#ifdef DEBUGMEM
totalmem -= nbytes;
#endif
free(fatso);
}

#ifdef DEBUGMEM
#include <stdio.h>

void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
{
fprintf(stderr, "total mem %d\n", totalmem);
}
#endif

+ 756
- 0
ports/camomile/source/LibPd/pure-data/src/m_obj.c View File

@@ -0,0 +1,756 @@
/* 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 handles Max-style patchable objects, i.e., objects which
can interconnect via inlets and outlets; also, the (terse) generic
behavior for "gobjs" appears at the end of this file. */

#include "m_pd.h"
#include "m_imp.h"

union inletunion
{
t_symbol *iu_symto;
t_gpointer *iu_pointerslot;
t_float *iu_floatslot;
t_symbol **iu_symslot;
t_float iu_floatsignalvalue;
};

struct _inlet
{
t_pd i_pd;
struct _inlet *i_next;
t_object *i_owner;
t_pd *i_dest;
t_symbol *i_symfrom;
union inletunion i_un;
};

#define i_symto i_un.iu_symto
#define i_pointerslot i_un.iu_pointerslot
#define i_floatslot i_un.iu_floatslot
#define i_symslot i_un.iu_symslot

static t_class *inlet_class, *pointerinlet_class, *floatinlet_class,
*symbolinlet_class;

#define ISINLET(pd) ((*(pd) == inlet_class) || \
(*(pd) == pointerinlet_class) || \
(*(pd) == floatinlet_class) || \
(*(pd) == symbolinlet_class))

/* --------------------- generic inlets ala max ------------------ */

t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, t_symbol *s2)
{
t_inlet *x = (t_inlet *)pd_new(inlet_class), *y, *y2;
x->i_owner = owner;
x->i_dest = dest;
if (s1 == &s_signal)
x->i_un.iu_floatsignalvalue = 0;
else x->i_symto = s2;
x->i_symfrom = s1;
x->i_next = 0;
if ((y = owner->ob_inlet))
{
while ((y2 = y->i_next)) y = y2;
y->i_next = x;
}
else owner->ob_inlet = x;
return (x);
}

t_inlet *signalinlet_new(t_object *owner, t_float f)
{
t_inlet *x = inlet_new(owner, &owner->ob_pd, &s_signal, &s_signal);
x->i_un.iu_floatsignalvalue = f;
return (x);
}

static void inlet_wrong(t_inlet *x, t_symbol *s)
{
pd_error(x->i_owner, "inlet: expected '%s' but got '%s'",
x->i_symfrom->s_name, s->s_name);
}

static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv);

/* LATER figure out how to make these efficient: */
static void inlet_bang(t_inlet *x)
{
if (x->i_symfrom == &s_bang)
pd_vmess(x->i_dest, x->i_symto, "");
else if (!x->i_symfrom) pd_bang(x->i_dest);
else if (x->i_symfrom == &s_list)
inlet_list(x, &s_bang, 0, 0);
else inlet_wrong(x, &s_bang);
}

static void inlet_pointer(t_inlet *x, t_gpointer *gp)
{
if (x->i_symfrom == &s_pointer)
pd_vmess(x->i_dest, x->i_symto, "p", gp);
else if (!x->i_symfrom) pd_pointer(x->i_dest, gp);
else if (x->i_symfrom == &s_list)
{
t_atom a;
SETPOINTER(&a, gp);
inlet_list(x, &s_pointer, 1, &a);
}
else inlet_wrong(x, &s_pointer);
}

static void inlet_float(t_inlet *x, t_float f)
{
if (x->i_symfrom == &s_float)
pd_vmess(x->i_dest, x->i_symto, "f", (t_floatarg)f);
else if (x->i_symfrom == &s_signal)
x->i_un.iu_floatsignalvalue = f;
else if (!x->i_symfrom)
pd_float(x->i_dest, f);
else if (x->i_symfrom == &s_list)
{
t_atom a;
SETFLOAT(&a, f);
inlet_list(x, &s_float, 1, &a);
}
else inlet_wrong(x, &s_float);
}

static void inlet_symbol(t_inlet *x, t_symbol *s)
{
if (x->i_symfrom == &s_symbol)
pd_vmess(x->i_dest, x->i_symto, "s", s);
else if (!x->i_symfrom) pd_symbol(x->i_dest, s);
else if (x->i_symfrom == &s_list)
{
t_atom a;
SETSYMBOL(&a, s);
inlet_list(x, &s_symbol, 1, &a);
}
else inlet_wrong(x, &s_symbol);
}

static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
{
t_atom at;
if (x->i_symfrom == &s_list || x->i_symfrom == &s_float
|| x->i_symfrom == &s_symbol || x->i_symfrom == &s_pointer)
typedmess(x->i_dest, x->i_symto, argc, argv);
else if (!x->i_symfrom) pd_list(x->i_dest, s, argc, argv);
else if (!argc)
inlet_bang(x);
else if (argc==1 && argv->a_type == A_FLOAT)
inlet_float(x, atom_getfloat(argv));
else if (argc==1 && argv->a_type == A_SYMBOL)
inlet_symbol(x, atom_getsymbol(argv));
else inlet_wrong(x, &s_list);
}

static void inlet_anything(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
{
if (x->i_symfrom == s)
typedmess(x->i_dest, x->i_symto, argc, argv);
else if (!x->i_symfrom)
typedmess(x->i_dest, s, argc, argv);
else inlet_wrong(x, s);
}

void inlet_free(t_inlet *x)
{
t_object *y = x->i_owner;
t_inlet *x2;
if (y->ob_inlet == x) y->ob_inlet = x->i_next;
else for (x2 = y->ob_inlet; x2; x2 = x2->i_next)
if (x2->i_next == x)
{
x2->i_next = x->i_next;
break;
}
t_freebytes(x, sizeof(*x));
}

/* ----- pointerinlets, floatinlets, syminlets: optimized inlets ------- */

static void pointerinlet_pointer(t_inlet *x, t_gpointer *gp)
{
gpointer_unset(x->i_pointerslot);
*(x->i_pointerslot) = *gp;
if (gp->gp_stub) gp->gp_stub->gs_refcount++;
}

t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp)
{
t_inlet *x = (t_inlet *)pd_new(pointerinlet_class), *y, *y2;
x->i_owner = owner;
x->i_dest = 0;
x->i_symfrom = &s_pointer;
x->i_pointerslot = gp;
x->i_next = 0;
if ((y = owner->ob_inlet))
{
while ((y2 = y->i_next)) y = y2;
y->i_next = x;
}
else owner->ob_inlet = x;
return (x);
}

static void floatinlet_float(t_inlet *x, t_float f)
{
*(x->i_floatslot) = f;
}

t_inlet *floatinlet_new(t_object *owner, t_float *fp)
{
t_inlet *x = (t_inlet *)pd_new(floatinlet_class), *y, *y2;
x->i_owner = owner;
x->i_dest = 0;
x->i_symfrom = &s_float;
x->i_floatslot = fp;
x->i_next = 0;
if ((y = owner->ob_inlet))
{
while ((y2 = y->i_next)) y = y2;
y->i_next = x;
}
else owner->ob_inlet = x;
return (x);
}

static void symbolinlet_symbol(t_inlet *x, t_symbol *s)
{
*(x->i_symslot) = s;
}

t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp)
{
t_inlet *x = (t_inlet *)pd_new(symbolinlet_class), *y, *y2;
x->i_owner = owner;
x->i_dest = 0;
x->i_symfrom = &s_symbol;
x->i_symslot = sp;
x->i_next = 0;
if ((y = owner->ob_inlet))
{
while ((y2 = y->i_next)) y = y2;
y->i_next = x;
}
else owner->ob_inlet = x;
return (x);
}

/* ---------------------- routine to handle lists ---------------------- */

/* objects interpret lists by feeding them to the individual inlets.
Before you call this check that the object doesn't have a more
specific way to handle lists. */
void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv)
{
t_atom *ap;
int count;
t_inlet *ip = ((t_object *)x)->ob_inlet;
if (!argc)
{
pd_emptylist(&x->ob_pd);
return;
}
for (count = argc-1, ap = argv+1; ip && count--; ap++, ip = ip->i_next)
{
if (ap->a_type == A_POINTER) pd_pointer(&ip->i_pd, ap->a_w.w_gpointer);
else if (ap->a_type == A_FLOAT) pd_float(&ip->i_pd, ap->a_w.w_float);
else pd_symbol(&ip->i_pd, ap->a_w.w_symbol);
}
if (argv->a_type == A_POINTER) pd_pointer(&x->ob_pd, argv->a_w.w_gpointer);
else if (argv->a_type == A_FLOAT) pd_float(&x->ob_pd, argv->a_w.w_float);
else pd_symbol(&x->ob_pd, argv->a_w.w_symbol);
}

void obj_init(void)
{
inlet_class = class_new(gensym("inlet"), 0, 0,
sizeof(t_inlet), CLASS_PD, 0);
class_addbang(inlet_class, inlet_bang);
class_addpointer(inlet_class, inlet_pointer);
class_addfloat(inlet_class, inlet_float);
class_addsymbol(inlet_class, inlet_symbol);
class_addlist(inlet_class, inlet_list);
class_addanything(inlet_class, inlet_anything);

pointerinlet_class = class_new(gensym("inlet"), 0, 0,
sizeof(t_inlet), CLASS_PD, 0);
class_addpointer(pointerinlet_class, pointerinlet_pointer);
class_addanything(pointerinlet_class, inlet_wrong);

floatinlet_class = class_new(gensym("inlet"), 0, 0,
sizeof(t_inlet), CLASS_PD, 0);
class_addfloat(floatinlet_class, (t_method)floatinlet_float);
class_addanything(floatinlet_class, inlet_wrong);

symbolinlet_class = class_new(gensym("inlet"), 0, 0,
sizeof(t_inlet), CLASS_PD, 0);
class_addsymbol(symbolinlet_class, symbolinlet_symbol);
class_addanything(symbolinlet_class, inlet_wrong);

}

/* --------------------------- outlets ------------------------------ */

static PERTHREAD int stackcount = 0; /* iteration counter */
#define STACKITER 1000 /* maximum iterations allowed */

static PERTHREAD int outlet_eventno;

/* set a stack limit (on each incoming event that can set off messages)
for the outlet functions to check to prevent stack overflow from message
recursion */

void outlet_setstacklim(void)
{
outlet_eventno++;
}

/* get a number unique to the (clock, MIDI, GUI, etc.) event we're on */
int sched_geteventno( void)
{
return (outlet_eventno);
}

struct _outconnect
{
struct _outconnect *oc_next;
t_pd *oc_to;
};

struct _outlet
{
t_object *o_owner;
struct _outlet *o_next;
t_outconnect *o_connections;
t_symbol *o_sym;
};

t_outlet *outlet_new(t_object *owner, t_symbol *s)
{
t_outlet *x = (t_outlet *)getbytes(sizeof(*x)), *y, *y2;
x->o_owner = owner;
x->o_next = 0;
if ((y = owner->ob_outlet))
{
while ((y2 = y->o_next)) y = y2;
y->o_next = x;
}
else owner->ob_outlet = x;
x->o_connections = 0;
x->o_sym = s;
return (x);
}

static void outlet_stackerror(t_outlet *x)
{
pd_error(x->o_owner, "stack overflow");
}

void outlet_bang(t_outlet *x)
{
t_outconnect *oc;
if(++stackcount >= STACKITER)
outlet_stackerror(x);
else
for (oc = x->o_connections; oc; oc = oc->oc_next)
pd_bang(oc->oc_to);
--stackcount;
}

void outlet_pointer(t_outlet *x, t_gpointer *gp)
{
t_outconnect *oc;
t_gpointer gpointer;
if(++stackcount >= STACKITER)
outlet_stackerror(x);
else
{
gpointer = *gp;
for (oc = x->o_connections; oc; oc = oc->oc_next)
pd_pointer(oc->oc_to, &gpointer);
}
--stackcount;
}

void outlet_float(t_outlet *x, t_float f)
{
t_outconnect *oc;
if(++stackcount >= STACKITER)
outlet_stackerror(x);
else
for (oc = x->o_connections; oc; oc = oc->oc_next)
pd_float(oc->oc_to, f);
--stackcount;
}

void outlet_symbol(t_outlet *x, t_symbol *s)
{
t_outconnect *oc;
if(++stackcount >= STACKITER)
outlet_stackerror(x);
else
for (oc = x->o_connections; oc; oc = oc->oc_next)
pd_symbol(oc->oc_to, s);
--stackcount;
}

void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
{
t_outconnect *oc;
if(++stackcount >= STACKITER)
outlet_stackerror(x);
else
for (oc = x->o_connections; oc; oc = oc->oc_next)
pd_list(oc->oc_to, s, argc, argv);
--stackcount;
}

void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
{
t_outconnect *oc;
if(++stackcount >= STACKITER)
outlet_stackerror(x);
else
for (oc = x->o_connections; oc; oc = oc->oc_next)
typedmess(oc->oc_to, s, argc, argv);
--stackcount;
}

/* get the outlet's declared symbol */
t_symbol *outlet_getsymbol(t_outlet *x)
{
return (x->o_sym);
}

void outlet_free(t_outlet *x)
{
t_object *y = x->o_owner;
t_outlet *x2;
if (y->ob_outlet == x) y->ob_outlet = x->o_next;
else for (x2 = y->ob_outlet; x2; x2 = x2->o_next)
if (x2->o_next == x)
{
x2->o_next = x->o_next;
break;
}
t_freebytes(x, sizeof(*x));
}

/* connect an outlet of one object to an inlet of another. The receiving
"pd" is usually a patchable object, but this may be used to add a
non-patchable pd to an outlet by specifying the 0th inlet. */
t_outconnect *obj_connect(t_object *source, int outno,
t_object *sink, int inno)
{
t_inlet *i;
t_outlet *o;
t_pd *to;
t_outconnect *oc, *oc2;

for (o = source->ob_outlet; o && outno; o = o->o_next, outno--) ;
if (!o) return (0);

if (sink->ob_pd->c_firstin)
{
if (!inno)
{
to = &sink->ob_pd;
goto doit;
}
else inno--;
}
for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ;
if (!i) return (0);
to = &i->i_pd;
doit:
oc = (t_outconnect *)t_getbytes(sizeof(*oc));
oc->oc_next = 0;
oc->oc_to = to;
/* append it to the end of the list */
/* LATER we might cache the last "oc" to make this faster. */
if ((oc2 = o->o_connections))
{
while (oc2->oc_next) oc2 = oc2->oc_next;
oc2->oc_next = oc;
}
else o->o_connections = oc;
if (o->o_sym == &s_signal) canvas_update_dsp();

return (oc);
}

void obj_disconnect(t_object *source, int outno, t_object *sink, int inno)
{
t_inlet *i;
t_outlet *o;
t_pd *to;
t_outconnect *oc, *oc2;

for (o = source->ob_outlet; o && outno; o = o->o_next, outno--) ;
if (!o) return;
if (sink->ob_pd->c_firstin)
{
if (!inno)
{
to = &sink->ob_pd;
goto doit;
}
else inno--;
}
for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ;
if (!i) return;
to = &i->i_pd;
doit:
if (!(oc = o->o_connections)) return;
if (oc->oc_to == to)
{
o->o_connections = oc->oc_next;
freebytes(oc, sizeof(*oc));
goto done;
}
while ((oc2 = oc->oc_next))
{
if (oc2->oc_to == to)
{
oc->oc_next = oc2->oc_next;
freebytes(oc2, sizeof(*oc2));
goto done;
}
oc = oc2;
}
done:
if (o->o_sym == &s_signal) canvas_update_dsp();
}

/* ------ traversal routines for code that can't see our structures ------ */

int obj_noutlets(t_object *x)
{
int n;
t_outlet *o;
for (o = x->ob_outlet, n = 0; o; o = o->o_next) n++;
return (n);
}

int obj_ninlets(t_object *x)
{
int n;
t_inlet *i;
for (i = x->ob_inlet, n = 0; i; i = i->i_next) n++;
if (x->ob_pd->c_firstin) n++;
return (n);
}

t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, int nout)
{
t_outlet *o = x->ob_outlet;
while (nout-- && o) o = o->o_next;
*op = o;
if (o) return (o->o_connections);
else return (0);
}

t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect,
t_object **destp, t_inlet **inletp, int *whichp)
{
t_pd *y;
y = lastconnect->oc_to;
if (ISINLET(y))
{
int n;
t_inlet *i = (t_inlet *)y, *i2;
t_object *dest = i->i_owner;
for (n = dest->ob_pd->c_firstin, i2 = dest->ob_inlet;
i2 && i2 != i; i2 = i2->i_next) n++;
*whichp = n;
*destp = dest;
*inletp = i;
}
else
{
*whichp = 0;
*inletp = 0;
*destp = ((t_object *)y);
}
return (lastconnect->oc_next);
}

/* this one checks that a pd is indeed a patchable object, and returns
it, correctly typed, or zero if the check failed. */
t_object *pd_checkobject(t_pd *x)
{
if ((*x)->c_patchable) return ((t_object *)x);
else return (0);
}

/* move an inlet or outlet to the head of the list */
void obj_moveinletfirst(t_object *x, t_inlet *i)
{
t_inlet *i2;
if (x->ob_inlet == i) return;
else for (i2 = x->ob_inlet; i2; i2 = i2->i_next)
if (i2->i_next == i)
{
i2->i_next = i->i_next;
i->i_next = x->ob_inlet;
x->ob_inlet = i;
return;
}
}

void obj_moveoutletfirst(t_object *x, t_outlet *o)
{
t_outlet *o2;
if (x->ob_outlet == o) return;
else for (o2 = x->ob_outlet; o2; o2 = o2->o_next)
if (o2->o_next == o)
{
o2->o_next = o->o_next;
o->o_next = x->ob_outlet;
x->ob_outlet = o;
return;
}
}

/* routines for DSP sorting, which are used in d_ugen.c and g_canvas.c */
/* LATER try to consolidate all the slightly different routines. */

int obj_nsiginlets(t_object *x)
{
int n;
t_inlet *i;
for (i = x->ob_inlet, n = 0; i; i = i->i_next)
if (i->i_symfrom == &s_signal) n++;
if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) n++;
return (n);
}

/* get the index, among signal inlets, of the mth inlet overall */
int obj_siginletindex(t_object *x, int m)
{
int n = 0;
t_inlet *i;
if (x->ob_pd->c_firstin)
{
if (!m--)
return (0);
if (x->ob_pd->c_floatsignalin)
n++;
}
for (i = x->ob_inlet; i; i = i->i_next, m--)
if (i->i_symfrom == &s_signal)
{
if (m == 0) return (n);
n++;
}
return (-1);
}

int obj_issignalinlet(t_object *x, int m)
{
t_inlet *i;
if (x->ob_pd->c_firstin)
{
if (!m)
return (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin);
else m--;
}
for (i = x->ob_inlet; i && m; i = i->i_next, m--)
;
return (i && (i->i_symfrom == &s_signal));
}

int obj_nsigoutlets(t_object *x)
{
int n;
t_outlet *o;
for (o = x->ob_outlet, n = 0; o; o = o->o_next)
if (o->o_sym == &s_signal) n++;
return (n);
}

int obj_sigoutletindex(t_object *x, int m)
{
int n;
t_outlet *o2;
for (o2 = x->ob_outlet, n = 0; o2; o2 = o2->o_next, m--)
if (o2->o_sym == &s_signal)
{
if (m == 0) return (n);
n++;
}
return (-1);
}

int obj_issignaloutlet(t_object *x, int m)
{
int n;
t_outlet *o2;
for (o2 = x->ob_outlet, n = 0; o2 && m--; o2 = o2->o_next);
return (o2 && (o2->o_sym == &s_signal));
}

t_float *obj_findsignalscalar(t_object *x, int m)
{
t_inlet *i;
if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin)
{
if (!m--)
return (x->ob_pd->c_floatsignalin > 0 ?
(t_float *)(((char *)x) + x->ob_pd->c_floatsignalin) : 0);
}
for (i = x->ob_inlet; i; i = i->i_next)
if (i->i_symfrom == &s_signal)
{
if (m-- == 0)
return (&i->i_un.iu_floatsignalvalue);
}
return (0);
}

/* and these are only used in g_io.c... */

int inlet_getsignalindex(t_inlet *x)
{
int n = 0;
t_inlet *i;
if (x->i_symfrom != &s_signal)
bug("inlet_getsignalindex");
for (i = x->i_owner->ob_inlet, n = 0; i && i != x; i = i->i_next)
if (i->i_symfrom == &s_signal) n++;
return (n);
}

int outlet_getsignalindex(t_outlet *x)
{
int n = 0;
t_outlet *o;
for (o = x->o_owner->ob_outlet, n = 0; o && o != x; o = o->o_next)
if (o->o_sym == &s_signal) n++;
return (n);
}

void obj_saveformat(t_object *x, t_binbuf *bb)
{
if (x->te_width)
binbuf_addv(bb, "ssf;", &s__X, gensym("f"), (float)x->te_width);
}

/* this one only in g_clone.c -- LATER consider sending the message
without having to chase the linked list every time? */
void obj_sendinlet(t_object *x, int n, t_symbol *s, int argc, t_atom *argv)
{
t_inlet *i;
for (i = x->ob_inlet; i && n; i = i->i_next, n--)
;
if (i)
typedmess(&i->i_pd, s, argc, argv);
else bug("obj_sendinlet");
}

+ 321
- 0
ports/camomile/source/LibPd/pure-data/src/m_pd.c View File

@@ -0,0 +1,321 @@
/* 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. */

#include <stdlib.h>
#include <string.h>
#include "m_pd.h"
#include "m_imp.h"
#include "g_canvas.h" /* just for LB_LOAD */

/* FIXME no out-of-memory testing yet! */

t_pd *pd_new(t_class *c)
{
t_pd *x;
if (!c)
bug ("pd_new: apparently called before setup routine");
x = (t_pd *)t_getbytes(c->c_size);
*x = c;
if (c->c_patchable)
{
((t_object *)x)->ob_inlet = 0;
((t_object *)x)->ob_outlet = 0;
}
return (x);
}

void pd_free(t_pd *x)
{
t_class *c = *x;
if (c->c_freemethod) (*(t_gotfn)(c->c_freemethod))(x);
if (c->c_patchable)
{
while (((t_object *)x)->ob_outlet)
outlet_free(((t_object *)x)->ob_outlet);
while (((t_object *)x)->ob_inlet)
inlet_free(((t_object *)x)->ob_inlet);
if (((t_object *)x)->ob_binbuf)
binbuf_free(((t_object *)x)->ob_binbuf);
}
if (c->c_size) t_freebytes(x, c->c_size);
}

void gobj_save(t_gobj *x, t_binbuf *b)
{
t_class *c = x->g_pd;
if (c->c_savefn)
(c->c_savefn)(x, b);
}

/* deal with several objects bound to the same symbol. If more than one, we
actually bind a collection object to the symbol, which forwards messages sent
to the symbol. */

static t_class *bindlist_class;

typedef struct _bindelem
{
t_pd *e_who;
struct _bindelem *e_next;
} t_bindelem;

typedef struct _bindlist
{
t_pd b_pd;
t_bindelem *b_list;
} t_bindlist;

static void bindlist_bang(t_bindlist *x)
{
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_bang(e->e_who);
}

static void bindlist_float(t_bindlist *x, t_float f)
{
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_float(e->e_who, f);
}

static void bindlist_symbol(t_bindlist *x, t_symbol *s)
{
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_symbol(e->e_who, s);
}

static void bindlist_pointer(t_bindlist *x, t_gpointer *gp)
{
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_pointer(e->e_who, gp);
}

static void bindlist_list(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_list(e->e_who, s, argc, argv);
}

static void bindlist_anything(t_bindlist *x, t_symbol *s,
int argc, t_atom *argv)
{
t_bindelem *e;
for (e = x->b_list; e; e = e->e_next)
pd_typedmess(e->e_who, s, argc, argv);
}

void m_pd_setup(void)
{
bindlist_class = class_new(gensym("bindlist"), 0, 0,
sizeof(t_bindlist), CLASS_PD, 0);
class_addbang(bindlist_class, bindlist_bang);
class_addfloat(bindlist_class, (t_method)bindlist_float);
class_addsymbol(bindlist_class, bindlist_symbol);
class_addpointer(bindlist_class, bindlist_pointer);
class_addlist(bindlist_class, bindlist_list);
class_addanything(bindlist_class, bindlist_anything);
}

void pd_bind(t_pd *x, t_symbol *s)
{
if (s->s_thing)
{
if (*s->s_thing == bindlist_class)
{
t_bindlist *b = (t_bindlist *)s->s_thing;
t_bindelem *e = (t_bindelem *)getbytes(sizeof(t_bindelem));
e->e_next = b->b_list;
e->e_who = x;
b->b_list = e;
}
else
{
t_bindlist *b = (t_bindlist *)pd_new(bindlist_class);
t_bindelem *e1 = (t_bindelem *)getbytes(sizeof(t_bindelem));
t_bindelem *e2 = (t_bindelem *)getbytes(sizeof(t_bindelem));
b->b_list = e1;
e1->e_who = x;
e1->e_next = e2;
e2->e_who = s->s_thing;
e2->e_next = 0;
s->s_thing = &b->b_pd;
}
}
else s->s_thing = x;
}

void pd_unbind(t_pd *x, t_symbol *s)
{
if (s->s_thing == x) s->s_thing = 0;
else if (s->s_thing && *s->s_thing == bindlist_class)
{
/* bindlists always have at least two elements... if the number
goes down to one, get rid of the bindlist and bind the symbol
straight to the remaining element. */

t_bindlist *b = (t_bindlist *)s->s_thing;
t_bindelem *e, *e2;
if ((e = b->b_list)->e_who == x)
{
b->b_list = e->e_next;
freebytes(e, sizeof(t_bindelem));
}
else for (e = b->b_list; (e2 = e->e_next); e = e2)
if (e2->e_who == x)
{
e->e_next = e2->e_next;
freebytes(e2, sizeof(t_bindelem));
break;
}
if (!b->b_list->e_next)
{
s->s_thing = b->b_list->e_who;
freebytes(b->b_list, sizeof(t_bindelem));
pd_free(&b->b_pd);
}
}
else pd_error(x, "%s: couldn't unbind", s->s_name);
}

t_pd *pd_findbyclass(t_symbol *s, t_class *c)
{
t_pd *x = 0;

if (!s->s_thing) return (0);
if (*s->s_thing == c) return (s->s_thing);
if (*s->s_thing == bindlist_class)
{
t_bindlist *b = (t_bindlist *)s->s_thing;
t_bindelem *e, *e2;
int warned = 0;
for (e = b->b_list; e; e = e->e_next)
if (*e->e_who == c)
{
if (x && !warned)
{
post("warning: %s: multiply defined", s->s_name);
warned = 1;
}
x = e->e_who;
}
}
return x;
}

/* stack for maintaining bindings for the #X symbol during nestable loads.
*/

typedef struct _gstack
{
t_pd *g_what;
t_symbol *g_loadingabstraction;
struct _gstack *g_next;
} t_gstack;

static t_gstack *gstack_head = 0;
static t_pd *lastpopped;
static t_symbol *pd_loadingabstraction;

int pd_setloadingabstraction(t_symbol *sym)
{
t_gstack *foo = gstack_head;
for (foo = gstack_head; foo; foo = foo->g_next)
if (foo->g_loadingabstraction == sym)
return (1);
pd_loadingabstraction = sym;
return (0);
}

void pd_pushsym(t_pd *x)
{
t_gstack *y = (t_gstack *)t_getbytes(sizeof(*y));
y->g_what = s__X.s_thing;
y->g_next = gstack_head;
y->g_loadingabstraction = pd_loadingabstraction;
pd_loadingabstraction = 0;
gstack_head = y;
s__X.s_thing = x;
}

void pd_popsym(t_pd *x)
{
if (!gstack_head || s__X.s_thing != x) bug("gstack_pop");
else
{
t_gstack *headwas = gstack_head;
s__X.s_thing = headwas->g_what;
gstack_head = headwas->g_next;
t_freebytes(headwas, sizeof(*headwas));
lastpopped = x;
}
}

void pd_doloadbang( void)
{
if (lastpopped)
pd_vmess(lastpopped, gensym("loadbang"), "f", LB_LOAD);
lastpopped = 0;
}

void pd_bang(t_pd *x)
{
(*(*x)->c_bangmethod)(x);
}

void pd_float(t_pd *x, t_float f)
{
(*(*x)->c_floatmethod)(x, f);
}

void pd_pointer(t_pd *x, t_gpointer *gp)
{
(*(*x)->c_pointermethod)(x, gp);
}

void pd_symbol(t_pd *x, t_symbol *s)
{
(*(*x)->c_symbolmethod)(x, s);
}

void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv)
{
(*(*x)->c_listmethod)(x, &s_list, argc, argv);
}

void mess_init(void);
void obj_init(void);
void conf_init(void);
void glob_init(void);
void garray_init(void);

void pd_init(void)
{
static int initted = 0;
if (initted)
return;
initted = 1;
#ifdef PDINSTANCE
pd_instances = (t_pdinstance **)getbytes(sizeof(*pd_instances));
pd_instances[0] = &pd_maininstance;
pd_ninstances = 1;
#endif
mess_init();
sys_lock();
obj_init();
conf_init();
glob_init();
garray_init();
sys_unlock();
}

EXTERN t_canvas *pd_getcanvaslist(void)
{
return (pd_this->pd_canvaslist);
}


+ 894
- 0
ports/camomile/source/LibPd/pure-data/src/m_pd.h View File

@@ -0,0 +1,894 @@
/* 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_MAJOR_VERSION 0
#define PD_MINOR_VERSION 48
#define PD_BUGFIX_VERSION 1
#define PD_TEST_VERSION ""
extern int pd_compatibilitylevel; /* e.g., 43 for pd 0.43 compatibility */

/* 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

/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */
#ifdef _MSC_VER
/* #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 /* _MSC_VER */

/* the external storage class is "extern" in UNIX; in MSW it's ugly. */
#ifdef _WIN32
#ifdef PD_INTERNAL
#define EXTERN __declspec(dllexport) extern
#else
#define EXTERN __declspec(dllimport) extern
#endif /* PD_INTERNAL */
#else
#define EXTERN extern
#endif /* _WIN32 */

/* On most c compilers, you can just say "struct foo;" to declare a
structure whose elements are defined elsewhere. On MSVC, when compiling
C (but not C++) code, you have to say "extern struct foo;". So we make
a stupid macro: */
#if defined(_MSC_VER) && !defined(_LANGUAGE_C_PLUS_PLUS) \
&& !defined(__cplusplus)
#define EXTERN_STRUCT extern struct
#else
#define EXTERN_STRUCT struct
#endif

/* Define some attributes, specific to the compiler */
#if defined(__GNUC__)
#define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b)))
#else
#define ATTRIBUTE_FORMAT_PRINTF(a, b)
#endif

#if !defined(_SIZE_T) && !defined(_SIZE_T_)
#include <stddef.h> /* just for size_t -- how lame! */
#endif

/* Microsoft Visual Studio is not C99, it does not provide stdint.h */
#ifdef _MSC_VER
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
# include <stdint.h>
#endif

/* for FILE, needed by sys_fopen() and sys_fclose() only */
#include <stdio.h>

#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: */
#if !defined(PD_LONGINTTYPE)
#if defined(_WIN32) && defined(__x86_64__)
#define PD_LONGINTTYPE long long
#else
#define PD_LONGINTTYPE long
#endif
#endif

#if !defined(PD_FLOATSIZE)
/* normally, our floats (t_float, t_sample,...) are 32bit */
# define PD_FLOATSIZE 32
#endif

#if PD_FLOATSIZE == 32
# define PD_FLOATTYPE float
/* an unsigned int of the same size as FLOATTYPE: */
# define PD_FLOATUINTTYPE unsigned int

#elif PD_FLOATSIZE == 64
# define PD_FLOATTYPE double
# define PD_FLOATUINTTYPE unsigned long
#else
# error invalid FLOATSIZE: must be 32 or 64
#endif

typedef PD_LONGINTTYPE t_int; /* pointer-size integer */
typedef PD_FLOATTYPE t_float; /* a float type at most the same size */
typedef PD_FLOATTYPE t_floatarg; /* float 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 _binbuf *w_binbuf;
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 type 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);

/* in ARM 64 a varargs prototype generates a different function call sequence
from a fixed one, so in that special case we make a more restrictive
definition for t_gotfn. This will break some code in the "chaos" package
in Pd extended. (that code will run incorrectly anyhow so why not catch it
at compile time anyhow.) */
#if defined(__APPLE__) && defined(__aarch64__)
typedef void (*t_gotfn)(void *x);
#else
typedef void (*t_gotfn)(void *x, ...);
#endif

/* ---------------- pre-defined objects and symbols --------------*/
EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */
EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */

/* --------- 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(const 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, ...);

/* the following macros are for sending non-type-checkable messages, i.e.,
using function lookup but circumventing type checking on arguments. Only
use for internal messaging protected by A_CANT so that the message can't
be generated at patch level. */
#define mess0(x, s) ((*getfn((x), (s)))((x)))
typedef void (*t_gotfn1)(void *x, void *arg1);
#define mess1(x, s, a) ((*(t_gotfn1)getfn((x), (s)))((x), (a)))
typedef void (*t_gotfn2)(void *x, void *arg1, void *arg2);
#define mess2(x, s, a,b) ((*(t_gotfn2)getfn((x), (s)))((x), (a),(b)))
typedef void (*t_gotfn3)(void *x, void *arg1, void *arg2, void *arg3);
#define mess3(x, s, a,b,c) ((*(t_gotfn3)getfn((x), (s)))((x), (a),(b),(c)))
typedef void (*t_gotfn4)(void *x,
void *arg1, void *arg2, void *arg3, void *arg4);
#define mess4(x, s, a,b,c,d) \
((*(t_gotfn4)getfn((x), (s)))((x), (a),(b),(c),(d)))
typedef void (*t_gotfn5)(void *x,
void *arg1, void *arg2, void *arg3, void *arg4, void *arg5);
#define mess5(x, s, a,b,c,d,e) \
((*(t_gotfn5)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, const 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 int binbuf_resize(t_binbuf *x, int newsize);
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_canvas(t_binbuf *b, char *filename, t_canvas *canvas,
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 --------------- */

EXTERN t_clock *clock_new(void *owner, t_method fn);
EXTERN void clock_set(t_clock *x, double systime);
EXTERN void clock_delay(t_clock *x, double delaytime);
EXTERN void clock_unset(t_clock *x);
EXTERN void clock_setunit(t_clock *x, double timeunit, int sampflag);
EXTERN double clock_getlogicaltime(void);
EXTERN double clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */
EXTERN double clock_gettimesince(double prevsystime);
EXTERN double clock_gettimesincewithunits(double prevsystime,
double units, int sampflag);
EXTERN double clock_getsystimeafter(double 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 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 t_inlet *signalinlet_new(t_object *owner, t_float f);
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 char sys_font[]; /* default typeface set in s_main.c */
EXTERN char sys_fontweight[]; /* default font weight set in s_main.c */
EXTERN int sys_hostfontsize(int fontsize, int zoom);
EXTERN int sys_zoomfontwidth(int fontsize, int zoom, int worstcase);
EXTERN int sys_zoomfontheight(int fontsize, int zoom, int worstcase);
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);
EXTERN int canvas_open(t_canvas *x, const char *name, const char *ext,
char *dirresult, char **nameresult, unsigned int size, int bin);

/* ---------------- widget behaviors ---------------------- */

EXTERN_STRUCT _widgetbehavior;
#define t_widgetbehavior struct _widgetbehavior

EXTERN_STRUCT _parentwidgetbehavior;
#define t_parentwidgetbehavior struct _parentwidgetbehavior
EXTERN const 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, const t_widgetbehavior *w);
EXTERN void class_setparentwidget(t_class *c, const t_parentwidgetbehavior *w);
EXTERN const t_parentwidgetbehavior *class_parentwidget(t_class *c);
EXTERN char *class_getname(t_class *c);
EXTERN char *class_gethelpname(t_class *c);
EXTERN char *class_gethelpdir(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);
EXTERN void class_set_extern_dir(t_symbol *s);
#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);
EXTERN void obj_saveformat(t_object *x, t_binbuf *bb); /* add format to bb */

/* 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(const char *fmt, ...);
EXTERN void startpost(const char *fmt, ...);
EXTERN void poststring(const char *s);
EXTERN void postfloat(t_floatarg f);
EXTERN void postatom(int argc, t_atom *argv);
EXTERN void endpost(void);
EXTERN void error(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
EXTERN void pd_error(void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
EXTERN void logpost(const void *object, const int level, const char *fmt, ...)
ATTRIBUTE_FORMAT_PRINTF(3, 4);
EXTERN void sys_logerror(const char *object, const char *s);
EXTERN void sys_unixerror(const char *object);
EXTERN void sys_ouch(void);


/* ------------ system interface routines ------------------- */
EXTERN int sys_isreadablefile(const char *name);
EXTERN int sys_isabsolutepath(const char *dir);
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 *dir, const char *name, const char *ext,
char *dirresult, char **nameresult, unsigned int size, int bin);
EXTERN int sched_geteventno(void);
EXTERN double sys_getrealtime(void);
EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */

/* Win32's open()/fopen() do not handle UTF-8 filenames so we need
* these internal versions that handle UTF-8 filenames the same across
* all platforms. They are recommended for use in external
* objectclasses as well so they work with Unicode filenames on Windows */
EXTERN int sys_open(const char *path, int oflag, ...);
EXTERN int sys_close(int fd);
EXTERN FILE *sys_fopen(const char *filename, const char *mode);
EXTERN int sys_fclose(FILE *stream);

/* ------------ threading ------------------- */
EXTERN void sys_lock(void);
EXTERN void sys_unlock(void);
EXTERN int sys_trylock(void);


/* --------------- signals ----------------------------------- */

typedef PD_FLOATTYPE t_sample;
typedef union _sampleint_union {
t_sample f;
PD_FLOATUINTTYPE i;
} t_sampleint_union;
#define MAXLOGSIG 32
#define MAXSIGSIZE (1 << MAXLOGSIG)

typedef struct _signal
{
int s_n; /* number of points in the array */
t_sample *s_vec; /* the array */
t_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 */
int s_vecsize; /* allocated size of array in points */
} 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_float *in, t_sample *out, int n);
EXTERN void dsp_add_zero(t_sample *out, int n);

EXTERN int sys_getblksize(void);
EXTERN t_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(t_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 float *cos_table;
#define LOGCOSTABSIZE 9
#define COSTABSIZE (1<<LOGCOSTABSIZE)

EXTERN int canvas_suspend_dsp(void);
EXTERN void canvas_resume_dsp(int oldstate);
EXTERN void canvas_update_dsp(void);
EXTERN int canvas_dspstate;

/* up/downsampling */
typedef struct _resample
{
int method; /* up/downsampling method ID */

int downsample; /* downsampling factor */
int upsample; /* upsampling factor */

t_sample *s_vec; /* here we hold the resampled data */
int s_n;

t_sample *coeffs; /* coefficients for filtering... */
int coefsize;

t_sample *buffer; /* buffer for filtering */
int bufsize;
} t_resample;

EXTERN void resample_init(t_resample *x);
EXTERN void resample_free(t_resample *x);

EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method);
EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method);
EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method);

/* ----------------------- utility functions for signals -------------- */
EXTERN t_float mtof(t_float);
EXTERN t_float ftom(t_float);
EXTERN t_float rmstodb(t_float);
EXTERN t_float powtodb(t_float);
EXTERN t_float dbtorms(t_float);
EXTERN t_float dbtopow(t_float);

EXTERN t_float q8_sqrt(t_float);
EXTERN t_float q8_rsqrt(t_float);
#ifndef N32
EXTERN t_float qsqrt(t_float); /* old names kept for extern compatibility */
EXTERN t_float qrsqrt(t_float);
#endif

/* --------------------- data --------------------------------- */

/* graphical arrays */
EXTERN_STRUCT _garray;
#define t_garray struct _garray

EXTERN t_class *garray_class;
EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec);
EXTERN int garray_getfloatwords(t_garray *x, int *size, t_word **vec);
EXTERN void garray_redraw(t_garray *x);
EXTERN int garray_npoints(t_garray *x);
EXTERN char *garray_vec(t_garray *x);
EXTERN void garray_resize(t_garray *x, t_floatarg f); /* avoid; use this: */
EXTERN void garray_resize_long(t_garray *x, long n); /* better version */
EXTERN void garray_usedindsp(t_garray *x);
EXTERN void garray_setsaveit(t_garray *x, int saveit);
EXTERN t_glist *garray_getglist(t_garray *x);
EXTERN t_array *garray_getarray(t_garray *x);
EXTERN t_class *scalar_class;

EXTERN t_float *value_get(t_symbol *s);
EXTERN void value_release(t_symbol *s);
EXTERN int value_getfloat(t_symbol *s, t_float *f);
EXTERN int value_setfloat(t_symbol *s, t_float f);

/* ------- GUI interface - functions to send strings to TK --------- */
typedef void (*t_guicallbackfn)(t_gobj *client, t_glist *glist);

EXTERN void sys_vgui(char *fmt, ...);
EXTERN void sys_gui(char *s);
EXTERN void sys_pretendguibytes(int n);
EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f);
EXTERN void sys_unqueuegui(void *client);
/* dialog window creation and destruction */
EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
EXTERN void gfxstub_deleteforkey(void *key);

extern t_class *glob_pdobject; /* object to send "pd" messages */

/*------------- Max 0.26 compatibility --------------------*/

/* the following reflects the new way classes are laid out, with the class
pointing to the messlist and not vice versa. Externs shouldn't feel it. */
typedef t_class *t_externclass;

EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine,
t_method freeroutine, t_symbol *name, size_t size, int tiny, \
t_atomtype arg1, ...);
EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...);

#define t_getbytes getbytes
#define t_freebytes freebytes
#define t_resizebytes resizebytes
#define typedmess pd_typedmess
#define vmess pd_vmess

/* A definition to help gui objects straddle 0.34-0.35 changes. If this is
defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */

#define PD_USE_TE_XPIX

#ifndef _MSC_VER /* Microoft compiler can't handle "inline" function/macros */
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
/* a test for NANs and denormals. Should only be necessary on i386. */
#if PD_FLOATSIZE == 32

typedef union
{
t_float f;
unsigned int ui;
}t_bigorsmall32;

static inline int PD_BADFLOAT(t_float f) /* malformed float */
{
t_bigorsmall32 pun;
pun.f = f;
pun.ui &= 0x7f800000;
return((pun.ui == 0) | (pun.ui == 0x7f800000));
}

static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-64,64) */
{
t_bigorsmall32 pun;
pun.f = f;
return((pun.ui & 0x20000000) == ((pun.ui >> 1) & 0x20000000));
}

#elif PD_FLOATSIZE == 64

typedef union
{
t_float f;
unsigned int ui[2];
}t_bigorsmall64;

static inline int PD_BADFLOAT(t_float f) /* malformed double */
{
t_bigorsmall64 pun;
pun.f = f;
pun.ui[1] &= 0x7ff00000;
return((pun.ui[1] == 0) | (pun.ui[1] == 0x7ff00000));
}

static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-512,512) */
{
t_bigorsmall64 pun;
pun.f = f;
return((pun.ui[1] & 0x20000000) == ((pun.ui[1] >> 1) & 0x20000000));
}

#endif /* PD_FLOATSIZE */
#else /* not INTEL or ARM */
#define PD_BADFLOAT(f) 0
#define PD_BIGORSMALL(f) 0
#endif

#else /* _MSC_VER */
#if PD_FLOATSIZE == 32
#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
(((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */
#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \
(((*(unsigned int*)&(f))&0x60000000)==0x60000000))
#else /* 64 bits... don't know what to do here */
#define PD_BADFLOAT(f) (!(((f) >= 0) || ((f) <= 0)))
#define PD_BIGORSMALL(f) ((f) > 1e150 || (f) < -1e150 \
|| (f) > -1e-150 && (f) < 1e-150 )
#endif
#endif /* _MSC_VER */
/* get version number at run time */
EXTERN void sys_getversion(int *major, int *minor, int *bugfix);

EXTERN_STRUCT _instancemidi;
#define t_instancemidi struct _instancemidi

EXTERN_STRUCT _instanceinter;
#define t_instanceinter struct _instanceinter

EXTERN_STRUCT _instancecanvas;
#define t_instancecanvas struct _instancecanvas

EXTERN_STRUCT _instanceugen;
#define t_instanceugen struct _instanceugen

EXTERN_STRUCT _instancestuff;
#define t_instancestuff struct _instancestuff

#ifndef PDTHREADS
#define PDTHREADS 1
#endif

struct _pdinstance
{
double pd_systime; /* global time in Pd ticks */
t_clock *pd_clock_setlist; /* list of set clocks */
t_canvas *pd_canvaslist; /* list of all root canvases */
int pd_instanceno; /* ordinal number of this instance */
t_symbol **pd_symhash; /* symbol table hash table */
t_instancemidi *pd_midi; /* private stuff for x_midi.c */
t_instanceinter *pd_inter; /* private stuff for s_inter.c */
t_instanceugen *pd_ugen; /* private stuff for d_ugen.c */
t_instancecanvas *pd_gui; /* semi-private stuff in g_canvas.h */
t_instancestuff *pd_stuff; /* semi-private stuff in s_stuff.h */
t_pd *pd_newest; /* most recently created object */
#ifdef PDINSTANCE
t_symbol pd_s_pointer;
t_symbol pd_s_float;
t_symbol pd_s_symbol;
t_symbol pd_s_bang;
t_symbol pd_s_list;
t_symbol pd_s_anything;
t_symbol pd_s_signal;
t_symbol pd_s__N;
t_symbol pd_s__X;
t_symbol pd_s_x;
t_symbol pd_s_y;
t_symbol pd_s_;
#endif
#if PDTHREADS
int pd_islocked;
#endif
};
#define t_pdinstance struct _pdinstance
EXTERN t_pdinstance pd_maininstance;

/* m_pd.c */
#ifdef PDINSTANCE
EXTERN t_pdinstance *pdinstance_new( void);
EXTERN void pd_setinstance(t_pdinstance *x);
EXTERN void pdinstance_free(t_pdinstance *x);
#endif /* PDINSTANCE */

#if defined(PDTHREADS) && defined(PDINSTANCE)
#ifdef _MSC_VER
#define PERTHREAD __declspec(thread)
#else
#define PERTHREAD __thread
#endif /* _MSC_VER */
#else
#define PERTHREAD
#endif

#ifdef PDINSTANCE
extern PERTHREAD t_pdinstance *pd_this;
EXTERN t_pdinstance **pd_instances;
EXTERN int pd_ninstances;
#else
#define pd_this (&pd_maininstance)
#endif /* PDINSTANCE */

#ifdef PDINSTANCE
#define s_pointer (pd_this->pd_s_pointer)
#define s_float (pd_this->pd_s_float)
#define s_symbol (pd_this->pd_s_symbol)
#define s_bang (pd_this->pd_s_bang)
#define s_list (pd_this->pd_s_list)
#define s_anything (pd_this->pd_s_anything)
#define s_signal (pd_this->pd_s_signal)
#define s__N (pd_this->pd_s__N)
#define s__X (pd_this->pd_s__X)
#define s_x (pd_this->pd_s_x)
#define s_y (pd_this->pd_s_y)
#define s_ (pd_this->pd_s_)
#else
EXTERN t_symbol s_pointer, s_float, s_symbol, s_bang, s_list, s_anything,
s_signal, s__N, s__X, s_x, s_y, s_;
#endif

EXTERN t_canvas *pd_getcanvaslist(void);
EXTERN int pd_getdspstate(void);

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif

#define __m_pd_h_
#endif /* __m_pd_h_ */

+ 620
- 0
ports/camomile/source/LibPd/pure-data/src/m_sched.c View File

@@ -0,0 +1,620 @@
/* 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. */

/* scheduling stuff */

#include "m_pd.h"
#include "m_imp.h"
#include "s_stuff.h"
#ifdef _WIN32
#include <windows.h>
#endif

/* LATER consider making this variable. It's now the LCM of all sample
rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
#define TIMEUNITPERMSEC (32. * 441.)
#define TIMEUNITPERSECOND (TIMEUNITPERMSEC * 1000.)

#define SYS_QUIT_QUIT 1
#define SYS_QUIT_RESTART 2
static int sys_quit;

int sys_usecsincelastsleep(void);
int sys_sleepgrain;

typedef void (*t_clockmethod)(void *client);

struct _clock
{
double c_settime; /* in TIMEUNITS; <0 if unset */
void *c_owner;
t_clockmethod c_fn;
struct _clock *c_next;
t_float c_unit; /* >0 if in TIMEUNITS; <0 if in samples */
};

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

t_clock *clock_new(void *owner, t_method fn)
{
t_clock *x = (t_clock *)getbytes(sizeof *x);
x->c_settime = -1;
x->c_owner = owner;
x->c_fn = (t_clockmethod)fn;
x->c_next = 0;
x->c_unit = TIMEUNITPERMSEC;
return (x);
}

void clock_unset(t_clock *x)
{
if (x->c_settime >= 0)
{
if (x == pd_this->pd_clock_setlist)
pd_this->pd_clock_setlist = x->c_next;
else
{
t_clock *x2 = pd_this->pd_clock_setlist;
while (x2->c_next != x) x2 = x2->c_next;
x2->c_next = x->c_next;
}
x->c_settime = -1;
}
}

/* set the clock to call back at an absolute system time */
void clock_set(t_clock *x, double setticks)
{
if (setticks < pd_this->pd_systime) setticks = pd_this->pd_systime;
clock_unset(x);
x->c_settime = setticks;
if (pd_this->pd_clock_setlist &&
pd_this->pd_clock_setlist->c_settime <= setticks)
{
t_clock *cbefore, *cafter;
for (cbefore = pd_this->pd_clock_setlist,
cafter = pd_this->pd_clock_setlist->c_next;
cbefore; cbefore = cafter, cafter = cbefore->c_next)
{
if (!cafter || cafter->c_settime > setticks)
{
cbefore->c_next = x;
x->c_next = cafter;
return;
}
}
}
else x->c_next = pd_this->pd_clock_setlist, pd_this->pd_clock_setlist = x;
}

/* set the clock to call back after a delay in msec */
void clock_delay(t_clock *x, double delaytime)
{
clock_set(x, (x->c_unit > 0 ?
pd_this->pd_systime + x->c_unit * delaytime :
pd_this->pd_systime -
(x->c_unit*(TIMEUNITPERSECOND/STUFF->st_dacsr)) * delaytime));
}

/* set the time unit in msec or (if 'samps' is set) in samples. This
is flagged by setting c_unit negative. If the clock is currently set,
recalculate the delay based on the new unit and reschedule */
void clock_setunit(t_clock *x, double timeunit, int sampflag)
{
double timeleft;
if (timeunit <= 0)
timeunit = 1;
/* if no change, return to avoid truncation errors recalculating delay */
if ((sampflag && (timeunit == -x->c_unit)) ||
(!sampflag && (timeunit == x->c_unit * TIMEUNITPERMSEC)))
return;

/* figure out time left in the units we were in */
timeleft = (x->c_settime < 0 ? -1 :
(x->c_settime - pd_this->pd_systime)/((x->c_unit > 0)? x->c_unit :
(x->c_unit*(TIMEUNITPERSECOND/STUFF->st_dacsr))));
if (sampflag)
x->c_unit = -timeunit; /* negate to flag sample-based */
else x->c_unit = timeunit * TIMEUNITPERMSEC;
if (timeleft >= 0) /* reschedule if already set */
clock_delay(x, timeleft);
}

/* get current logical time. We don't specify what units this is in;
use clock_gettimesince() to measure intervals from time of this call. */
double clock_getlogicaltime( void)
{
return (pd_this->pd_systime);
}

/* OBSOLETE (misleading) function name kept for compatibility */
double clock_getsystime( void) { return (pd_this->pd_systime); }

/* elapsed time in milliseconds since the given system time */
double clock_gettimesince(double prevsystime)
{
return ((pd_this->pd_systime - prevsystime)/TIMEUNITPERMSEC);
}

/* elapsed time in units, ala clock_setunit(), since given system time */
double clock_gettimesincewithunits(double prevsystime,
double units, int sampflag)
{
/* If in samples, divide TIMEUNITPERSECOND/sys_dacsr first (at
cost of an extra division) since it's probably an integer and if
units == 1 and (sys_time - prevsystime) is an integer number of
DSP ticks, the result will be exact. */
if (sampflag)
return ((pd_this->pd_systime - prevsystime)/
((TIMEUNITPERSECOND/STUFF->st_dacsr)*units));
else return ((pd_this->pd_systime - prevsystime)/(TIMEUNITPERMSEC*units));
}

/* what value the system clock will have after a delay */
double clock_getsystimeafter(double delaytime)
{
return (pd_this->pd_systime + TIMEUNITPERMSEC * delaytime);
}

void clock_free(t_clock *x)
{
clock_unset(x);
freebytes(x, sizeof *x);
}

/* the following routines maintain a real-execution-time histogram of the
various phases of real-time execution. */

static int sys_bin[] = {0, 2, 5, 10, 20, 30, 50, 100, 1000};
#define NBIN (sizeof(sys_bin)/sizeof(*sys_bin))
#define NHIST 10
static int sys_histogram[NHIST][NBIN];
static double sys_histtime;
static int sched_diddsp, sched_didpoll, sched_didnothing;

void sys_clearhist( void)
{
unsigned int i, j;
for (i = 0; i < NHIST; i++)
for (j = 0; j < NBIN; j++) sys_histogram[i][j] = 0;
sys_histtime = sys_getrealtime();
sched_diddsp = sched_didpoll = sched_didnothing = 0;
}

void sys_printhist( void)
{
unsigned int i, j;
for (i = 0; i < NHIST; i++)
{
int doit = 0;
for (j = 0; j < NBIN; j++) if (sys_histogram[i][j]) doit = 1;
if (doit)
{
post("%2d %8d %8d %8d %8d %8d %8d %8d %8d", i,
sys_histogram[i][0],
sys_histogram[i][1],
sys_histogram[i][2],
sys_histogram[i][3],
sys_histogram[i][4],
sys_histogram[i][5],
sys_histogram[i][6],
sys_histogram[i][7]);
}
}
post("dsp %d, pollgui %d, nothing %d",
sched_diddsp, sched_didpoll, sched_didnothing);
}

static int sys_histphase;

int sys_addhist(int phase)
{
int i, j, phasewas = sys_histphase;
double newtime = sys_getrealtime();
int msec = (newtime - sys_histtime) * 1000.;
for (j = NBIN-1; j >= 0; j--)
{
if (msec >= sys_bin[j])
{
sys_histogram[phasewas][j]++;
break;
}
}
sys_histtime = newtime;
sys_histphase = phase;
return (phasewas);
}

#define NRESYNC 20

typedef struct _resync
{
int r_ntick;
int r_error;
} t_resync;

static int oss_resyncphase = 0;
static int oss_nresync = 0;
static t_resync oss_resync[NRESYNC];


static char *(oss_errornames[]) = {
"unknown",
"ADC blocked",
"DAC blocked",
"A/D/A sync",
"data late"
};

void glob_audiostatus(void)
{
int dev, nresync, nresyncphase, i;
nresync = (oss_nresync >= NRESYNC ? NRESYNC : oss_nresync);
nresyncphase = oss_resyncphase - 1;
post("audio I/O error history:");
post("seconds ago\terror type");
for (i = 0; i < nresync; i++)
{
int errtype;
if (nresyncphase < 0)
nresyncphase += NRESYNC;
errtype = oss_resync[nresyncphase].r_error;
if (errtype < 0 || errtype > 4)
errtype = 0;

post("%9.2f\t%s",
(sched_diddsp - oss_resync[nresyncphase].r_ntick)
* ((double)STUFF->st_schedblocksize) / STUFF->st_dacsr,
oss_errornames[errtype]);
nresyncphase--;
}
}

static int sched_diored;
static int sched_dioredtime;
static int sched_meterson;

void sys_log_error(int type)
{
oss_resync[oss_resyncphase].r_ntick = sched_diddsp;
oss_resync[oss_resyncphase].r_error = type;
oss_nresync++;
if (++oss_resyncphase == NRESYNC) oss_resyncphase = 0;
if (type != ERR_NOTHING && !sched_diored &&
(sched_diddsp >= sched_dioredtime))
{
sys_vgui("pdtk_pd_dio 1\n");
sched_diored = 1;
}
sched_dioredtime =
sched_diddsp + (int)(STUFF->st_dacsr /(double)STUFF->st_schedblocksize);
}

static int sched_lastinclip, sched_lastoutclip,
sched_lastindb, sched_lastoutdb;

void glob_watchdog(t_pd *dummy);

static void sched_pollformeters( void)
{
int inclip, outclip, indb, outdb;
static int sched_nextmeterpolltime, sched_nextpingtime;

/* if there's no GUI but we're running in "realtime", here is
where we arrange to ping the watchdog every 2 seconds. */
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
if (!sys_havegui() && sys_hipriority &&
(sched_diddsp - sched_nextpingtime > 0))
{
glob_watchdog(0);
/* ping every 2 seconds */
sched_nextpingtime = sched_diddsp +
2 * (int)(STUFF->st_dacsr /(double)STUFF->st_schedblocksize);
}
#endif

if (sched_diddsp - sched_nextmeterpolltime < 0)
return;
if (sched_diored && (sched_diddsp - sched_dioredtime > 0))
{
sys_vgui("pdtk_pd_dio 0\n");
sched_diored = 0;
}
if (sched_meterson)
{
t_sample inmax, outmax;
sys_getmeters(&inmax, &outmax);
indb = 0.5 + rmstodb(inmax);
outdb = 0.5 + rmstodb(outmax);
inclip = (inmax > 0.999);
outclip = (outmax >= 1.0);
}
else
{
indb = outdb = 0;
inclip = outclip = 0;
}
if (inclip != sched_lastinclip || outclip != sched_lastoutclip
|| indb != sched_lastindb || outdb != sched_lastoutdb)
{
sys_vgui("pdtk_pd_meters %d %d %d %d\n", indb, outdb, inclip, outclip);
sched_lastinclip = inclip;
sched_lastoutclip = outclip;
sched_lastindb = indb;
sched_lastoutdb = outdb;
}
sched_nextmeterpolltime =
sched_diddsp + (int)(STUFF->st_dacsr /(double)STUFF->st_schedblocksize);
}

void glob_meters(void *dummy, t_float f)
{
if (f == 0)
sys_getmeters(0, 0);
sched_meterson = (f != 0);
sched_lastinclip = sched_lastoutclip = sched_lastindb = sched_lastoutdb =
-1;
}

#if 0
void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
{
if (argc) sys_clearhist();
else sys_printhist();
}
#endif

void dsp_tick(void);

static int sched_useaudio = SCHED_AUDIO_NONE;
static double sched_referencerealtime, sched_referencelogicaltime;

void sched_reopenmeplease(void) /* request from s_audio for deferred reopen */
{
sys_quit = SYS_QUIT_RESTART;
}

void sched_set_using_audio(int flag)
{
sched_useaudio = flag;
if (flag == SCHED_AUDIO_NONE)
{
sched_referencerealtime = sys_getrealtime();
sched_referencelogicaltime = clock_getlogicaltime();
}
if (flag == SCHED_AUDIO_CALLBACK &&
sched_useaudio != SCHED_AUDIO_CALLBACK)
sys_quit = SYS_QUIT_RESTART;
if (flag != SCHED_AUDIO_CALLBACK &&
sched_useaudio == SCHED_AUDIO_CALLBACK)
post("sorry, can't turn off callbacks yet; restart Pd");
/* not right yet! */

sys_vgui("pdtk_pd_audio %s\n", flag ? "on" : "off");
}

/* take the scheduler forward one DSP tick, also handling clock timeouts */
void sched_tick( void)
{
double next_sys_time = pd_this->pd_systime +
(STUFF->st_schedblocksize/STUFF->st_dacsr) * TIMEUNITPERSECOND;
int countdown = 5000;
while (pd_this->pd_clock_setlist &&
pd_this->pd_clock_setlist->c_settime < next_sys_time)
{
t_clock *c = pd_this->pd_clock_setlist;
pd_this->pd_systime = c->c_settime;
clock_unset(pd_this->pd_clock_setlist);
outlet_setstacklim();
(*c->c_fn)(c->c_owner);
if (!countdown--)
{
countdown = 5000;
sys_pollgui();
}
if (sys_quit)
return;
}
pd_this->pd_systime = next_sys_time;
dsp_tick();
sched_diddsp++;
}

/*
Here is Pd's "main loop." This routine dispatches clock timeouts and DSP
"ticks" deterministically, and polls for input from MIDI and the GUI. If
we're left idle we also poll for graphics updates; but these are considered
lower priority than the rest.

The time source is normally the audio I/O subsystem via the "sys_send_dacs()"
call. This call returns true if samples were transferred; false means that
the audio I/O system is still busy with previous transfers.
*/

void sys_pollmidiqueue( void);
void sys_initmidiqueue( void);

/* sys_idlehook is a hook the user can fill in to grab idle time. Return
nonzero if you actually used the time; otherwise we're really really idle and
will now sleep. */
int (*sys_idlehook)(void);

static void m_pollingscheduler( void)
{
int idlecount = 0;

/* delete this when I'm sure it's not needed for back compatibility? */
STUFF->st_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)STUFF->st_schedblocksize) / STUFF->st_dacsr;
sys_lock();
sys_clearhist();
if (sys_sleepgrain < 100)
sys_sleepgrain = sys_schedadvance/4;
if (sys_sleepgrain < 100)
sys_sleepgrain = 100;
else if (sys_sleepgrain > 5000)
sys_sleepgrain = 5000;
sys_initmidiqueue();
while (!sys_quit)
{
int didsomething = 0;
int timeforward;

sys_addhist(0);
waitfortick:
if (sched_useaudio != SCHED_AUDIO_NONE)
{
sys_unlock();
timeforward = sys_send_dacs();
sys_lock();
#if 0 /* in linux and windoes, sometimes audio devices would freeze, which
in turn would freeze Pd. This code unfroze things by closing
audio in such cases. But this seems no longer necessary, and
on Macs at least, this seems to cause audio to get dropped if
the machine sleeps. */
/* if dacs remain "idle" for 1 sec, they're hung up. */
if (timeforward != 0)
idlecount = 0;
else
{
idlecount++;
if (!(idlecount & 31))
{
static double idletime;
if (sched_useaudio != SCHED_AUDIO_POLL)
{
bug("m_pollingscheduler\n");
return;
}
/* on 32nd idle, start a clock watch; every
32 ensuing idles, check it */
if (idlecount == 32)
idletime = sys_getrealtime();
else if (sys_getrealtime() - idletime > 1.)
{
error("audio I/O stuck... closing audio\n");
sys_close_audio();
sched_set_using_audio(SCHED_AUDIO_NONE);
goto waitfortick;
}
}
}
#endif /* 0 */
}
else
{
if (1000. * (sys_getrealtime() - sched_referencerealtime)
> clock_gettimesince(sched_referencelogicaltime))
timeforward = SENDDACS_YES;
else timeforward = SENDDACS_NO;
}
sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
sys_addhist(1);
if (timeforward != SENDDACS_NO)
sched_tick();
if (timeforward == SENDDACS_YES)
didsomething = 1;

sys_addhist(2);
sys_pollmidiqueue();
if (sys_pollgui())
{
if (!didsomething)
sched_didpoll++;
didsomething = 1;
}
sys_addhist(3);
/* test for idle; if so, do graphics updates. */
if (!didsomething)
{
sched_pollformeters();
sys_reportidle();
sys_unlock(); /* unlock while we idle */
/* call externally installed idle function if any. */
if (!sys_idlehook || !sys_idlehook())
{
/* if even that had nothing to do, sleep. */
if (timeforward != SENDDACS_SLEPT)
sys_microsleep(sys_sleepgrain);
}
sys_lock();
sys_addhist(5);
sched_didnothing++;
}
}
sys_unlock();
}

void sched_audio_callbackfn(void)
{
sys_lock();
sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
sys_addhist(1);
sched_tick();
sys_addhist(2);
sys_pollmidiqueue();
sys_addhist(3);
sys_pollgui();
sys_addhist(5);
sched_pollformeters();
sys_addhist(0);
sys_unlock();
}

static void m_callbackscheduler(void)
{
sys_initmidiqueue();
while (!sys_quit)
{
double timewas = pd_this->pd_systime;
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
if (pd_this->pd_systime == timewas)
{
sys_lock();
sys_pollgui();
sched_tick();
sys_unlock();
}
if (sys_idlehook)
sys_idlehook();
}
}

int m_mainloop(void)
{
while (sys_quit != SYS_QUIT_QUIT)
{
if (sched_useaudio == SCHED_AUDIO_CALLBACK)
m_callbackscheduler();
else m_pollingscheduler();
if (sys_quit == SYS_QUIT_RESTART)
{
sys_quit = 0;
if (audio_isopen())
{
sys_close_audio();
sys_reopen_audio();
}
}
}
return (0);
}

int m_batchmain(void)
{
while (sys_quit != SYS_QUIT_QUIT)
sched_tick();
return (0);
}

void sys_exit(void)
{
sys_quit = SYS_QUIT_QUIT;
}

+ 271
- 0
ports/camomile/source/LibPd/pure-data/src/makefile.gnu View File

@@ -0,0 +1,271 @@
# You can use this makefile to compile Pd for Gnu/linux. Masochists and
# packagers might prefer the automake route as described in ../README.txt
# You can invoke this one as: $ make -f makefile.gnu
# You don't have to "make install" - you can just invoke Pd from ../bin.
#
# targets include:
# all: pd, pd-watchdog, pdsend, pdreceive, and all extras.
# bin: just pd, pd-watchdog, pdsend, pdreceive.
# local-clean: clean up for "bin" target"
# clean: clean everything
# depend: c header dependencies
# tags: tags file
# install: install to /usr/local (or elsewhere by setting "prefix" variable)
#
# You can get jack support ($ make -f makfile.gnu JACK=TRUE) or compile in
# the portaudio library (PA=TRUE). By default, both ALSA and OSS (BSD style)
# audio APIs are compiled in. You can disable them (e.g., OSS=FALSE). In
# Gnu/linux, you can also just install "alsa-oss."
#
# You can add compiler flags using CODECFLAGS, MORECFLAGS and/or MORELDFLAGS.
# For example, you can turn off optimizing and enable debugging: CODECFLAGS=-g
# or compile with native double precision: MORECFLAGS=-DPD_FLOATSIZE=64
# The MORECFLAGS variable is propagated to "extras" but CODECFLAGS and
# MORELDFLAGS are not.
#
# Packages you might need:
# tk-devel alsa-devel alsa-oss (unless you disable OSS).
# jack-audio-connection-kit-devel (if you want jack support)

VPATH = ../obj:./
OBJ_DIR = ../obj
BIN_DIR = ../bin
PDEXEC = $(BIN_DIR)/pd
EXT= pd_linux
ALSA=true
OSS=true

prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
includedir = ${prefix}/include
libdir = ${exec_prefix}/lib
mandir = ${prefix}/share/man

# varibles to match packages/Makefile.buildlayout so that they can be easily
# overridden when building Pd-extended builds. <hans@at.or.at>
libpddir = $(libdir)/pd
pddocdir = $(libpddir)/doc
libpdbindir = $(libpddir)/bin
libpdtcldir = $(libpddir)/tcl

# The C flags are separated into CPPFLAGS, CODECFLAGS, and MORECFLAGS
# to allow easy overriding of CODECFLAGS and to allow adding MORECFLAGS:

# C preprocessor flags, and flags controlling errors and warnings
CPPFLAGS = -DPD -DHAVE_LIBDL -DHAVE_UNISTD_H -DHAVE_ALLOCA_H \
-DPDGUIDIR=\"tcl/\" \
-D_LARGEFILE64_SOURCE -DINSTALL_PREFIX=\"$(prefix)\" \
-Wall -W -Wstrict-prototypes -Wno-address\
-Wno-unused -Wno-unused-parameter -Wno-parentheses -Wno-switch

# code generation flags (e.g., optimization).
CODECFLAGS = -g -O3 -ffast-math -funroll-loops -fomit-frame-pointer

# anything else you want to specify. Also passed on to "extra" makefiles.
MORECFLAGS =

# "standard" flags for linker
LDFLAGS = -Wl,-export-dynamic

# and another variable you can override to add more (like "-g").
MORELDFLAGS =

# libraries and system-dependent sources.
# These get added onto if JACK, etc., are defined below
LIB = -ldl -lm -lpthread
SYSSRC = s_midi_oss.c

# conditionally add code and flags for various audio APIs
ifeq ($(ALSA), true)
CPPFLAGS += -DUSEAPI_ALSA
SYSSRC += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c
LIB += -lasound
HAVEAUDIOAPI=true
endif
ifdef JACK
CPPFLAGS += -DUSEAPI_JACK
SYSSRC += s_audio_jack.c
LIB += -ljack
HAVEAUDIOAPI=true
endif
ifeq ($(OSS), true)
#error foo
CPPFLAGS += -DUSEAPI_OSS
SYSSRC += s_audio_oss.c
HAVEAUDIOAPI=true
endif
ifdef PA
CPPFLAGS += -DUSEAPI_PORTAUDIO
SYSSRC += s_audio_pa.c
LIB += -lportaudio
HAVEAUDIOAPI=true
endif
ifndef HAVEAUDIOAPI
CPPFLAGS += -DUSEAPI_DUMMY
SYSSRC += s_audio_dummy.c
endif

CFLAGS = $(CPPFLAGS) $(CODECFLAGS) $(MORECFLAGS)

SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \
g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c s_audio_paring.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \
d_delay.c d_resample.c d_soundfile.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \
x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c \
$(SYSSRC)

OBJ = $(SRC:.c=.o)

# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
ifneq ($(PD_TEST_VERSION),)
PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
endif

#
# ------------------ targets ------------------------------------
#

.PHONY: pd externs all depend

all: pd $(BIN_DIR)/pd-watchdog $(BIN_DIR)/pdsend $(BIN_DIR)/pdreceive externs \
makefile.dependencies

bin: pd $(BIN_DIR)/pd-watchdog $(BIN_DIR)/pdsend $(BIN_DIR)/pdreceive

$(OBJ) : %.o : %.c
$(CC) $(CFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c

pd: $(PDEXEC)

pd-watchdog: $(BIN_DIR)/pd-watchdog

$(BIN_DIR)/pd-watchdog: s_watchdog.c
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) -o $(BIN_DIR)/pd-watchdog s_watchdog.c

$(BIN_DIR)/pdsend: u_pdsend.c
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) -o $(BIN_DIR)/pdsend u_pdsend.c

$(BIN_DIR)/pdreceive: u_pdreceive.c
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) -o $(BIN_DIR)/pdreceive u_pdreceive.c

$(PDEXEC): $(OBJ_DIR) $(OBJ)
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
cd ../obj; $(CC) $(LDFLAGS) $(MORELDFLAGS) -o $(PDEXEC) $(OBJ) $(LIB)

externs:
make -C ../extra/bonk~ MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/choice MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/fiddle~ MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/loop~ MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/lrshift~ MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/pique MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/sigmund~ MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/pd~ MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/stdout MORECFLAGS="$(MORECFLAGS)"
make -C ../extra/bob~ MORECFLAGS="$(MORECFLAGS)"

BINARYMODE=-m755

ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
install: all
install -d $(DESTDIR)$(libpdbindir)
install $(BIN_DIR)/pd-watchdog $(DESTDIR)$(libpdbindir)/pd-watchdog
install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(libpdbindir)/pd
install -d $(DESTDIR)$(bindir)
install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(bindir)/pd
install -m755 $(BIN_DIR)/pdsend $(DESTDIR)$(bindir)/pdsend
install -m755 $(BIN_DIR)/pdreceive $(DESTDIR)$(bindir)/pdreceive
install -d $(DESTDIR)$(libpdtcldir)
install ../tcl/* $(DESTDIR)$(libpdtcldir)
for dir in $(shell ls -1 ../doc | grep -v CVS); do \
echo "installing $$dir"; \
install -d $(DESTDIR)$(pddocdir)/$$dir ; \
install -m644 -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
done
for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
echo "installing 7.stuff/$$dir"; \
install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
install -m644 -p ../doc/7.stuff/$$dir/*.* \
$(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
done
mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
> $(ABOUT_FILE)
rm $(ABOUT_FILE).tmp
cp -pr ../extra $(DESTDIR)$(libpddir)/
rm -f $(DESTDIR)$(libpddir)/extra/*/*.o
install -d $(DESTDIR)$(includedir)
install -m644 m_pd.h $(DESTDIR)$(includedir)/m_pd.h
install -d $(DESTDIR)$(mandir)/man1
gzip < ../man/pd.1 > $(DESTDIR)$(mandir)/man1/pd.1.gz
chmod 644 $(DESTDIR)$(mandir)/man1/pd.1.gz
gzip < ../man/pdsend.1 > $(DESTDIR)$(mandir)/man1/pdsend.1.gz
chmod 644 $(DESTDIR)$(mandir)/man1/pdsend.1.gz
gzip < ../man/pdreceive.1 > $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
chmod 644 $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
@echo "Pd install succeeded."

local-clean:
-rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c \
$(BIN_DIR)/*.tcl
-rm -f `find ../portaudio -name "*.o"`
-rm -f *~
-(cd ../doc/6.externs; rm -f *.pd_linux)
-rm -f makefile.dependencies

extra-clean:
-rm -f `find ../extra/ -name "*.pd_*"`
-rm -f tags

clean: extra-clean local-clean

distclean: clean
-rm -f config.cache config.log config.status makefile tags \
autom4te.cache/output.* autom4te.cache/traces.* autom4te.cache/requests
-rmdir autom4te.cache
-rm -rf autom4te-*.cache

tags: $(SRC) $(GSRC); ctags *.[ch]

depend: makefile.dependencies

$(OBJ_DIR):
test -d $(OBJ_DIR) || mkdir -p $(OBJ_DIR)

makefile.dependencies:
$(CC) $(CPPFLAGS) -M $(SRC) > makefile.dependencies

uninstall:
rm -f -r $(DESTDIR)$(libpddir)
rm -f $(DESTDIR)$(bindir)/pd
rm -f $(DESTDIR)$(bindir)/pdsend
rm -f $(DESTDIR)$(bindir)/pdreceive
rm -f $(DESTDIR)$(includedir)/m_pd.h
rm -f $(DESTDIR)$(mandir)/man1/pd.1.gz
rm -f $(DESTDIR)$(mandir)/man1/pdsend.1.gz
rm -f $(DESTDIR)$(mandir)/man1/pdreceive.1.gz

-include makefile.dependencies

+ 242
- 0
ports/camomile/source/LibPd/pure-data/src/makefile.mac View File

@@ -0,0 +1,242 @@
# On Mac OS X, this needs to be defined to enable dlopen and weak linking
# support. Its safe on other platforms since gcc only checks this env var on
# Apple's gcc. <hans@at.or.at>
export MACOSX_DEPLOYMENT_TARGET = 10.3

VPATH = ../obj:./
OBJ_DIR = ../obj
BIN_DIR = ../bin
PDEXEC = $(BIN_DIR)/pd
EXT= pd_darwin
GUINAME= libPdTcl.dylib
ARCH= -arch i386 -arch ppc
EXTRAARCH= -arch i386 -arch x86_64 -arch ppc

prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
includedir = ${prefix}/include
libdir = ${exec_prefix}/lib
mandir = ${prefix}/man

# varibles to match packages/Makefile.buildlayout so that they can be easily
# overridden when building Pd-extended builds. <hans@at.or.at>
libpddir = $(libdir)/pd
pddocdir = $(libpddir)/doc
libpdbindir = $(libpddir)/bin
libpdtcldir = $(libpddir)/tcl

PADIR = ../portaudio/portaudio
PMDIR = ../portmidi/portmidi

CPPFLAGS = -DPD -DINSTALL_PREFIX=\"$(prefix)\" \
-DHAVE_LIBDL -DMACOSX -DHAVE_UNISTD_H -I/usr/X11R6/include \
-I$(PADIR)/include -I$(PADIR)/src/common \
-I$(PADIR)/src/os/mac_osx/ -I$(PMDIR)/pm_common \
-I$(PMDIR)/pm_mac -I$(PMDIR)/porttime \
-DUSEAPI_PORTAUDIO -DPA_USE_COREAUDIO -DNEWBUFFER
ARCH_CFLAGS = $(ARCH)
WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused -Wno-unused-parameter \
-Wno-parentheses -Wno-switch
MORECFLAGS = -Wno-error -ffast-math -O3

LDFLAGS = -Wl -framework CoreAudio -framework AudioUnit \
-framework AudioToolbox -framework Carbon -framework CoreMIDI $(ARCH) \

LIB = -ldl -lm -lpthread

ifdef JACK
CPPFLAGS += -DUSEAPI_JACK
SYSSRC += s_audio_jack.c
LIB += -weak_framework Jackmp
endif

CFLAGS = $(ARCH_CFLAGS) $(WARN_CFLAGS) $(CPPFLAGS) $(MORECFLAGS)

# the sources

SYSSRC += s_midi_pm.c s_audio_pa.c s_audio_paring.c \
$(PADIR)/src/common/pa_allocation.c \
$(PADIR)/src/common/pa_converters.c \
$(PADIR)/src/common/pa_cpuload.c \
$(PADIR)/src/common/pa_dither.c \
$(PADIR)/src/common/pa_front.c \
$(PADIR)/src/common/pa_process.c \
$(PADIR)/src/common/pa_stream.c \
$(PADIR)/src/common/pa_trace.c \
$(PADIR)/src/common/pa_debugprint.c \
$(PADIR)/src/common/pa_ringbuffer.c \
$(PADIR)/src/os/unix/pa_unix_util.c \
$(PADIR)/src/os/mac_osx/pa_mac_hostapis.c \
$(PADIR)/src/hostapi/coreaudio/pa_mac_core.c \
$(PADIR)/src/hostapi/coreaudio/pa_mac_core_blocking.c \
$(PADIR)/src/hostapi/coreaudio/pa_mac_core_utilities.c \
$(PMDIR)/pm_mac/pmmac.c \
$(PMDIR)/pm_mac/pmmacosxcm.c \
$(PMDIR)/pm_mac/finddefault.c \
$(PMDIR)/pm_mac/readbinaryplist.c \
$(PMDIR)/pm_common/pmutil.c \
$(PMDIR)/pm_common/portmidi.c \
$(PMDIR)/porttime/ptmacosx_cf.c


SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \
g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \
d_delay.c d_resample.c d_soundfile.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \
x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c \
$(SYSSRC)

OBJ = $(SRC:.c=.o)

# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
ifneq ($(PD_TEST_VERSION),)
PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
endif

#
# ------------------ targets ------------------------------------
#

.PHONY: pd gui externs all

all: pd $(BIN_DIR)/pd-watchdog gui $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive externs

bin: pd $(BIN_DIR)/pd-watchdog gui $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive

$(OBJ) : %.o : %.c
$(CC) $(CFLAGS) $(INCLUDE) -c -o $(OBJ_DIR)/$*.o $*.c

pd: $(PDEXEC)

pd-watchdog: $(BIN_DIR)/pd-watchdog

$(BIN_DIR):
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)

$(BIN_DIR)/pd-watchdog: s_watchdog.c $(BIN_DIR)
$(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pd-watchdog s_watchdog.c

$(BIN_DIR)/pdsend: u_pdsend.c $(BIN_DIR)
$(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pdsend u_pdsend.c

$(BIN_DIR)/pdreceive: u_pdreceive.c $(BIN_DIR)
$(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pdreceive u_pdreceive.c

$(PDEXEC): $(OBJ) $(BIN_DIR)
cd ../obj; $(CC) $(LDFLAGS) $(DBG_CFLAGS) -o $(PDEXEC) $(OBJ) $(LIB)

externs:
make -C ../extra/bonk~ DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/choice DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/fiddle~ DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/loop~ DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/lrshift~ DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/pique DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/sigmund~ DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/pd~ DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/stdout DARWINARCH="$(EXTRAARCH)" d_fat
make -C ../extra/bob~ DARWINARCH="$(EXTRAARCH)" d_fat

BINARYMODE=-m755

ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
install: all
install -d $(DESTDIR)$(libpdbindir)
-install $(BIN_DIR)/$(GUINAME) $(DESTDIR)$(libpdbindir)/$(GUINAME)
install $(BIN_DIR)/pd-watchdog $(DESTDIR)$(libpdbindir)/pd-watchdog
install -d $(DESTDIR)$(bindir)
install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(bindir)/pd
install -m755 $(BIN_DIR)/pdsend $(DESTDIR)$(bindir)/pdsend
install -m755 $(BIN_DIR)/pdreceive $(DESTDIR)$(bindir)/pdreceive
install -d $(DESTDIR)$(libpdtcldir)
install ../tcl/* $(DESTDIR)$(libpdtcldir)
for dir in $(shell ls -1 ../doc | grep -v CVS); do \
echo "installing $$dir"; \
install -d $(DESTDIR)$(pddocdir)/$$dir ; \
install -m644 -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
done
for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
echo "installing 7.stuff/$$dir"; \
install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
install -m644 -p ../doc/7.stuff/$$dir/*.* \
$(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
done
mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
> $(ABOUT_FILE)
rm $(ABOUT_FILE).tmp
cp -pr ../extra $(DESTDIR)$(libpddir)/
rm -f $(DESTDIR)$(libpddir)/extra/*/*.o
install -d $(DESTDIR)$(includedir)
install -m644 m_pd.h $(DESTDIR)$(includedir)/m_pd.h
install -d $(DESTDIR)$(mandir)/man1
gzip < ../man/pd.1 > $(DESTDIR)$(mandir)/man1/pd.1.gz
chmod 644 $(DESTDIR)$(mandir)/man1/pd.1.gz
gzip < ../man/pdsend.1 > $(DESTDIR)$(mandir)/man1/pdsend.1.gz
chmod 644 $(DESTDIR)$(mandir)/man1/pdsend.1.gz
gzip < ../man/pdreceive.1 > $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
chmod 644 $(DESTDIR)$(mandir)/man1/pdreceive.1.gz
@echo "Pd install succeeded."

local-clean:
-rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c \
$(BIN_DIR)/*.tcl
-rm -f `find ../portaudio -name "*.o"`
-rm -f *~
-(cd ../doc/6.externs; rm -f *.pd_linux)
-rm -f makefile.dependencies
touch makefile.dependencies
chmod 666 makefile.dependencies

extra-clean:
-rm -f `find ../extra/ -name "*.pd_*"`
-rm -f tags

clean: extra-clean local-clean

distclean: clean
-rm -f config.cache config.log config.status makefile tags \
autom4te.cache/output.* autom4te.cache/traces.* autom4te.cache/requests
-rmdir autom4te.cache
-rm -rf autom4te-*.cache

tags: $(SRC) $(GSRC); ctags *.[ch]

depend: makefile.dependencies

makefile.dependencies:
$(CC) $(CPPFLAGS) -M $(SRC) > makefile.dependencies

uninstall:
rm -f -r $(DESTDIR)$(libpddir)
rm -f $(DESTDIR)$(bindir)/pd
rm -f $(DESTDIR)$(bindir)/pdsend
rm -f $(DESTDIR)$(bindir)/pdreceive
rm -f $(DESTDIR)$(includedir)/m_pd.h
rm -f $(DESTDIR)$(mandir)/man1/pd.1.gz
rm -f $(DESTDIR)$(mandir)/man1/pdsend.1.gz
rm -f $(DESTDIR)$(mandir)/man1/pdreceive.1.gz

include makefile.dependencies

+ 318
- 0
ports/camomile/source/LibPd/pure-data/src/makefile.mingw View File

@@ -0,0 +1,318 @@
# makefile to compile for windows using the mingw suite.
# To use this makefile to cross-compile from linux, type for example:
# make -f makefile.mingw CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-c++ \
# WINDRES=i686-w64-mingw32-windres

# Miller's Windows build uses Microsoft Visual C and makefile.msvc:
# http://lists.puredata.info/pipermail/pd-dev/2004-10/002981.html

CC = gcc
CXX = g++
WINDRES = windres

cvs_root_dir = ../..
pd_src = $(cvs_root_dir)/pd
DLL_DIR = $(pd_src)/src

BIN_DIR = ../bin

VPATH = $(pd_src)/src

prefix = /usr/local/pd
exec_prefix = $(prefix)
includedir = $(prefix)/include
libdir = $(exec_prefix)/lib
mandir = $(prefix)/man
bindir = $(exec_prefix)/bin

GFLAGS = -DINSTALL_PREFIX=\"$(prefix)\"

# varibles to match packages/Makefile.buildlayout so that they can be easily
# overridden when building Pd-extended builds. <hans@at.or.at>
libpddir = $(prefix)
pddocdir = $(libpddir)/doc
libpdbindir = $(libpddir)/bin

EXECDIR=../bin
PDEXEC = $(EXECDIR)/pd.exe
PDDLL = $(EXECDIR)/pd.dll
PDCOM = $(EXECDIR)/pd.com
PDRECEIVE = $(EXECDIR)/pdreceive.exe
PDSEND = $(EXECDIR)/pdsend.exe

DLLWRAP= dllwrap

MORECFLAGS = -O3 -funroll-loops -fomit-frame-pointer

PADIR = $(pd_src)/portaudio/portaudio
ASIODIR = $(pd_src)/lib/ASIOSDK
ASIOINC = -I$(ASIODIR)/common -I$(ASIODIR)/host -I$(ASIODIR)/host/pc
INCPA = -I$(PADIR)/include -I$(PADIR)/src/common -I$(PADIR)/src/os/win \
$(ASIOINC)
INCLUDE = -I$(pd_src)/src
GINCLUDE = -I/usr/local/include $(INCLUDE)

LDFLAGS =
LIBS = -lm -lwsock32 -lwinmm -lole32 -lpthread \
-static-libgcc -static-libstdc++

OPT_CFLAGS =

WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused \
-Wno-unused-parameter -Wno-parentheses -Wno-switch
# Some old code in asio/ASIOSDK/common/combase.h needs to be ignored,
# we do this by setting the WINVER macro to min Windows XP aka 5.1.
# Also, for SetDllDirectory() s_loader.c, we need a minium of Windows
# XP SP1. WINVER isnt' fine-grained enough for that, so we use the
# next minor version of Windows, 5.2.
ARCH_CFLAGS = -DPD -DPD_INTERNAL -DPA_USE_ASIO -DPA_USE_WMME -DWINVER=0x0502 \
-DUSEAPI_MMIO -DUSEAPI_PORTAUDIO -mms-bitfields -DWISH='"wish85.exe"'

CFLAGS += $(ARCH_CFLAGS) $(WARN_CFLAGS) $(OPT_CFLAGS) $(MORECFLAGS)

STRIP = strip --strip-unneeded -R .note -R .comment

# the sources

PASRC = s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c \
$(PADIR)/src/common/pa_stream.c \
$(PADIR)/src/common/pa_trace.c \
$(PADIR)/src/common/pa_process.c \
$(PADIR)/src/common/pa_front.c \
$(PADIR)/src/common/pa_dither.c \
$(PADIR)/src/common/pa_cpuload.c \
$(PADIR)/src/common/pa_converters.c \
$(PADIR)/src/common/pa_allocation.c \
$(PADIR)/src/common/pa_ringbuffer.c \
$(PADIR)/src/os/win/pa_win_coinitialize.c \
$(PADIR)/src/os/win/pa_win_hostapis.c \
$(PADIR)/src/os/win/pa_win_util.c \
$(PADIR)/src/os/win/pa_win_waveformat.c \
$(PADIR)/src/hostapi/wmme/pa_win_wmme.c

ASIOSRC = $(PADIR)/src/hostapi/asio/iasiothiscallresolver.cpp \
$(PADIR)/src/hostapi/asio/pa_asio.cpp \
$(ASIODIR)/common/asio.cpp \
$(ASIODIR)/host/asiodrivers.cpp \
$(ASIODIR)/host/pc/asiolist.cpp

#VSRC = s_audio_vst.c

PMDIR = ../portmidi/portmidi
PMINCLUDE = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime \
-DNEWBUFFER
PMSRC = s_midi_pm.c \
$(PMDIR)/pm_common/portmidi.c \
$(PMDIR)/pm_common/pmutil.c \
$(PMDIR)/porttime/porttime.c \
$(PMDIR)/porttime/ptwinmm.c \
$(PMDIR)/pm_win/pmwin.c \
$(PMDIR)/pm_win/pmwinmm.c

PMOBJ = $(PMSRC:.c=.o)

HEADERS = g_all_guis.h m_imp.h g_canvas.h m_pd.h s_stuff.h \
$(wildcard ../portaudio/common/*.h) s_audio_paring.h

SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \
g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \
d_delay.c d_resample.c d_soundfile.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \
x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c

SRSRC = u_pdsend.c u_pdreceive.c

OBJ = $(SRC:.c=.o)
SROBJ = $(SRSRC:.c=.o)
PAOBJ = $(PASRC:.c=.o)
ASIOOBJ = $(ASIOSRC:.cpp=.o)
#VOBJ = $(VSRC:.c=.o)
OBJC = $(OBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)


# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
ifneq ($(PD_TEST_VERSION),)
PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
endif


#
# ------------------ targets ------------------------------------
#

.PHONY: all install clean testbin

all: $(PDDLL) $(PDEXEC) $(PDSEND) $(PDRECEIVE) $(PDCOM)

$(OBJ) : %.o : %.c
$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c

$(GOBJ) : %.o : %.c
$(CC) $(CFLAGS) $(GFLAGS) $(GINCLUDE) -c -o $*.o $*.c

$(SROBJ) : %.o : %.c
$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c

$(PAOBJ) : %.o : %.c
$(CC) $(CFLAGS) $(GFLAGS) $(INCPA) -c -o $*.o $*.c

$(ASIOOBJ) : %.o : %.cpp
$(CXX) $(CFLAGS) $(INCPA) -c -o $*.o $*.cpp

$(PMOBJ) : %.o : %.c
$(CC) $(CFLAGS) $(GFLAGS) $(PMINCLUDE) -c -o $*.o $*.c

$(VOBJ) : %.o : %.c
$(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c

$(PDSEND): u_pdsend.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PDSEND) u_pdsend.o $(LIBS)
$(STRIP) $(PDSEND)

$(PDRECEIVE): u_pdreceive.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PDRECEIVE) u_pdreceive.o $(LIBS)
$(STRIP) $(PDRECEIVE)

$(PDEXEC): s_entry.o pd.res
$(CXX) $(LDFLAGS) -mwindows -o $(PDEXEC) s_entry.o pd.res $(LIBS) pd.a
$(STRIP) -s $(PDEXEC)

$(PDCOM): s_entry.o
$(CXX) $(LDFLAGS) -o $(PDCOM) s_entry.o $(LIBS) pd.a
$(STRIP) -s $(PDCOM)

$(PDDLL): $(OBJC)
$(CXX) -shared $(LDFLAGS) -o $(PDDLL) $(OBJC) $(LIBS) \
-Wl,--export-all-symbols -Wl,--out-implib=pd.a;
$(STRIP) $(PDDLL)

pd.res: pd.rc
$(WINDRES) pd.rc -O coff -o pd.res

../bin/pdstatic.exe: $(OBJC)
$(CXX) -static \
$(LDFLAGS) -o ../bin/pdstatic.exe $(OBJC) \
$(LIBS) -lole32 -static-libgcc -static-libstdc++
$(STRIP) -s ../bin/pdstatic.exe

#vstschedlib.dll: $(VOBJ)
# $(DLLWRAP) --export-all-symbols --output-def vst.def \
# --output-lib=vst.a --dllname=vstschedlib.dll s_audio_vst.o pd.a $(LIBS)

externs:
make -C ../extra all

# kludge to put stuff into the pd/bin dir for testing
testbin: $(PDEXEC) $(PDDLL) $(PDCOM)
echo "Copying files to $(BIN_DIR)"
install -d $(BIN_DIR)
install -p $(PDDLL) $(BIN_DIR)
install -p pd.ico $(BIN_DIR)
install -p $(PDCOM) $(BIN_DIR)
install -p $(PDEXEC) $(BIN_DIR)

ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
install: all
# locales
# make libpddir=$(libpddir) -C ../po install
# install extra stuff
# make libpddir=$(libpddir) -C ../extra install
# the real install
install -d $(DESTDIR)$(bindir)
install -p ../tcl/*.tcl $(DESTDIR)$(bindir)/
install -p $(PDEXEC) $(DESTDIR)$(bindir)/$(PDEXEC)
install -p $(PDCOM) $(DESTDIR)$(bindir)/$(PDCOM)
install -p pd.dll $(DESTDIR)$(bindir)/pd.dll
install -p pd.ico $(DESTDIR)$(bindir)/pd.ico
install -p $(PDSEND) $(DESTDIR)$(bindir)/$(PDSEND)
install -p $(PDRECEIVE) $(DESTDIR)$(bindir)/$(PDRECEIVE)
for dir in $(shell ls -1 ../doc | grep -v CVS); do \
echo "installing $$dir"; \
install -d $(DESTDIR)$(pddocdir)/$$dir ; \
install -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
done
for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
echo "installing 7.stuff/$$dir"; \
install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
install -p ../doc/7.stuff/$$dir/*.* $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
done
mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
> $(ABOUT_FILE)
rm $(ABOUT_FILE).tmp
install -d $(DESTDIR)$(libpddir)/extra
# install -p $(pd_src)/extra/*/*.dll $(DESTDIR)$(libpddir)/extra
install -p $(pd_src)/extra/*.pd $(DESTDIR)$(libpddir)/extra
install -d $(DESTDIR)$(pddocdir)/5.reference
install -p ../extra/*/*.pd $(DESTDIR)$(pddocdir)/5.reference
install -p ../extra/*-help.pd $(DESTDIR)$(pddocdir)/5.reference
install -d $(DESTDIR)$(includedir)
install -p m_pd.h $(DESTDIR)$(includedir)/m_pd.h
install -p s_stuff.h $(DESTDIR)$(includedir)/s_stuff.h
@echo "Pd install succeeded."


clean:
-rm -f -- $(BIN_DIR)/*.*
-rm -f -- *.o *.a *.def
-rm -f -- pd*.exe pd*.dll $(PDCOM)
-rm -f -- $(OBJ) $(GOBJ) $(SROBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)
-rm -f -- $(pd_src)/extra/*/*.dll $(pd_src)/extra/*/*.o
-rm -f makefile.dependencies

distclean: clean
rm -rf -- config.cache config.log config.status makefile tags \
autom4te-*.cache

tags: $(SRC) $(GSRC); ctags *.[ch]

depend: makefile.dependencies

makefile.dependencies: $(SRC) $(PASRC) $(HEADERS)
$(CC) $(INCLUDE) $(INCPA) $(CFLAGS) -M $(SRC) $(PASRC) $(HEADERS) \
> makefile.dependencies

uninstall:
-rm $(prefix)/bin/pd*.exe
-rm $(prefix)/bin/pd*.com
-rm $(prefix)/bin/pd*.dll
-rm $(prefix)/bin/*.tcl


test_locations:
@echo "PD_VERSION: $(PD_VERSION)"
@echo "PACKAGE_VERSION: $(PACKAGE_VERSION)"
@echo "CWD $(CWD)"
@echo "DESTDIR $(DESTDIR)"
@echo "PREFIX $(prefix)"
@echo "BINDIR $(bindir)"
@echo "LIBDIR $(libdir)"
@echo "OBJECTSDIR $(objectsdir)"
@echo "PDDOCDIR $(pddocdir)"
@echo "LIBPDDIR $(libpddir)"
@echo "LIBPDBINDIR $(libpdbindir)"
@echo "HELPDIR $(helpdir)"
@echo "MANUALSDIR $(manualsdir)"
@echo "EXAMPLESDIR $(examplesdir)"


include makefile.dependencies

+ 220
- 0
ports/camomile/source/LibPd/pure-data/src/makefile.msvc View File

@@ -0,0 +1,220 @@
# Makefile for PD using Microsoft Visual C/C++ (MSVC) -- note defines
# which will have to be adapted to whichever specific version of MSVC you
# have lying around.

MSCC = cl
MSLN = link
COPY = copy
DELETE = del

VCSDK = "C:/Program Files/Microsoft SDKs/Windows/v6.0A"
VC9 = "C:/Program Files/Microsoft Visual Studio 9.0/VC"

WISH = wish85.exe

EXTRA_LIBPATH=
EXTRA_INCLUDES=
## the following adds the search paths for compiler/linker
## if the build system hasn't been properly setup by calling
## the 'vcvarsall.bat' (MSVC) resp. 'SetEnv.bat' (MSSDK) scripts.
## the logic checks whether some variables are set/unset

## the code is a bit convoluted because we want it to work
## with both 'GNU make' and 'nmake'
## see https://stackoverflow.com/a/30906085/1169096

# \
!ifndef 0 # \
# nmake code here \
!IFNDEF VCINSTALLDIR # \
VCINSTALLDIR = $(VC9) # \
EXTRA_INCLUDES = /I$(VC9)/Include $(EXTRA_INCLUDES) # \
EXTRA_LIBPATH = /LIBPATH:$(VC9)/lib $(EXTRA_LIBPATH) # \
!ENDIF # \
!IFNDEF WINDOWSSDKDIR # \
WINDOWSSDKDIR = $(VCSDK) # \
EXTRA_INCLUDES = /I$(VCSDK)/Include $(EXTRA_INCLUDES) # \
EXTRA_LIBPATH = /LIBPATH:$(VCSDK)/lib $(EXTRA_LIBPATH)# \
!ENDIF # \
!else
# GNU make code here
ifndef VCINSTALLDIR
VCINSTALLDIR = $(VC9)
EXTRA_INCLUDES += /I$(VC9)/Include
EXTRA_LIBPATH += /LIBPATH:$(VC9)/lib
endif
ifndef WINDOWSSDKDIR
WINDOWSSDKDIR = $(VCSDK)
EXTRA_INCLUDES += /I$(VCSDK)/Include
EXTRA_LIBPATH += /LIBPATH:$(VCSDK)/lib
endif
# \
!endif

PDINCLUDE = /I./ $(EXTRA_INCLUDES)

PDLIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:libcpmt /NODEFAULTLIB:oldnames \
/NODEFAULTLIB:libc /NODEFAULTLIB:uuid /NODEFAULTLIB:ole32 \
$(EXTRA_LIBPATH) \
kernel32.lib \
wsock32.lib winmm.lib \
advapi32.lib setupapi.lib \
../bin/pthreadVC.lib \
libcmt.lib oldnames.lib

AFLAGS = /D__i386__
# MSW, NT: legacy defines of Pd
# WIN32: portmidi, portaudio
# WINDOWS: portaudio
# _WINDOWS: unused!
CFLAGS = /nologo \
/W3 /Ox $(AFLAGS) \
/DMSW /DNT /DWIN32 /DWINDOWS /D_WINDOWS \
/DWISH=\"$(WISH)\" \
/DPD /DPD_INTERNAL \
/DUSEAPI_MMIO /DUSEAPI_PORTAUDIO \
/DPA_LITTLE_ENDIAN /DPA19 \
/D_CRT_SECURE_NO_WARNINGS
LFLAGS = /nologo

SYSSRC = s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c s_midi_pm.c

SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c g_clone.c \
g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_fft_fftsg.c d_array.c d_global.c \
d_delay.c d_resample.c d_soundfile.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
x_time.c x_acoustics.c x_net.c x_text.c x_gui.c x_list.c x_array.c \
x_scalar.c x_vexp.c x_vexp_if.c x_vexp_fun.c \
$(SYSSRC)

PADIR = ../portaudio/portaudio
INCPA = -I$(PADIR)/include -I$(PADIR)/src/common -I$(PADIR)/src/os/win
PASRC = $(PADIR)/src

PAOBJ = pa_stream.obj pa_trace.obj pa_process.obj \
pa_front.obj pa_dither.obj pa_cpuload.obj pa_converters.obj \
pa_allocation.obj pa_ringbuffer.obj \
pa_win_hostapis.obj pa_win_util.obj pa_win_waveformat.obj \
pa_win_wmme.obj
# pa_win_wdmks.obj

PMDIR = ../portmidi/portmidi
INCPM = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime -DNEWBUFFER
SRCPM = $(PADIR)/pm_common/portmidi.c \
$(PMDIR)/pm_common/pmutil.c \
$(PMDIR)/porttime/porttime.c \
$(PMDIR)/porttime/ptwinmm.c \
$(PMDIR)/pm_win/pmwin.c \
$(PMDIR)/pm_win/pmwinmm.c

PMOBJ = portmidi.obj pmutil.obj porttime.obj ptwinmm.obj pmwin.obj pmwinmm.obj

OBJC = $(SRC:.c=.obj) $(PAOBJ) $(PMOBJ)

GSRC = t_main.c t_tkcmd.c

GOBJ = $(GSRC:.c=.obj)

ALLCF = $(CFLAGS) $(PDINCLUDE) $(INCPA) $(INCPM)

.SUFFIXES: .obj
.c.obj:
$(MSCC) /c $(ALLCF) /Tc$*.c

all: pd ../bin/pdsend.exe ../bin/pdreceive.exe

.PHONY: pd

pd: ../bin/pd.exe ../bin/pd.com

../bin/pd.exe: s_entry.obj ../bin/pd.lib
$(MSLN) $(LFLAGS) /OUT:../bin/pd.exe /INCREMENTAL:NO s_entry.obj \
../bin/pd.lib $(PDLIB)

../bin/pd.dll ../bin/pd.lib: $(OBJC)
$(MSLN) /DLL /OUT:../bin/pd.dll /EXPORT:sys_main $(LFLAGS) $(OBJC) \
$(PDLIB)

../bin/pdsend.exe: u_pdsend.obj
$(MSLN) $(LFLAGS) /out:../bin/pdsend.exe /INCREMENTAL:NO \
u_pdsend.obj $(PDLIB)

../bin/pdreceive.exe: u_pdreceive.obj
$(MSLN) $(LFLAGS) /out:../bin/pdreceive.exe /INCREMENTAL:NO \
u_pdreceive.obj $(PDLIB)

../bin/pd.com: s_entry_com.obj ../bin/pd.lib
$(MSLN) $(LFLAGS) /out:../bin/pd.com /INCREMENTAL:NO s_entry_com.obj \
../bin/pd.lib $(PDLIB)

s_entry_com.obj: s_entry.c
$(COPY) s_entry.c s_entry_com.c
$(MSCC) /c -DCOMMANDVERSION s_entry_com.c
$(DELETE) s_entry_com.c

PAAPI = -DPA_USE_WMME
PACF= $(PAAPI) $(ALLCF)
# explicit rules to compile portaudio sources:
pa_stream.obj: $(PASRC)/common/pa_stream.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_stream.c
pa_trace.obj: $(PASRC)/common/pa_trace.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_trace.c
pa_process.obj: $(PASRC)/common/pa_process.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_process.c
pa_front.obj: $(PASRC)/common/pa_front.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_front.c
pa_dither.obj: $(PASRC)/common/pa_dither.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_dither.c
pa_cpuload.obj: $(PASRC)/common/pa_cpuload.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_cpuload.c
pa_converters.obj: $(PASRC)/common/pa_converters.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_converters.c
pa_allocation.obj: $(PASRC)/common/pa_allocation.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_allocation.c
pa_ringbuffer.obj: $(PASRC)/common/pa_ringbuffer.c
$(MSCC) /c $(PACF) $(PASRC)/common/pa_ringbuffer.c

pa_win_hostapis.obj: $(PASRC)/os/win/pa_win_hostapis.c
$(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_hostapis.c
pa_win_util.obj: $(PASRC)/os/win/pa_win_util.c
$(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_util.c
pa_win_waveformat.obj: $(PASRC)/os/win/pa_win_waveformat.c
$(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_waveformat.c
pa_win_coinitialize.obj: $(PASRC)/os/win/pa_win_coinitialize.c
$(MSCC) /c $(PACF) $(PASRC)/os/win/pa_win_coinitialize.c
pa_win_wmme.obj: $(PASRC)/hostapi/wmme/pa_win_wmme.c
$(MSCC) /c $(PACF) $(PASRC)/hostapi/wmme/pa_win_wmme.c
pa_win_wdmks.obj: $(PADIR)/a_win_wdmks/pa_win_wdmks.c
$(MSCC) /c $(PACF) \
-DWINVER=0x400 -DKSAUDIO_SPEAKER_DIRECTOUT \
$(PADIR)/pa_win_wdmks/pa_win_wdmks.c
pa_asio.obj: $(PASRC)/hostapi/asio/pa_asio.cpp
$(MSCC) /c $(PACF) $(PASRC)/hostapi/asio/pa_asio.cpp

portmidi.obj: $(PMDIR)/pm_common/portmidi.c
$(MSCC) /c $(PACF) $(PMDIR)/pm_common/portmidi.c
pmutil.obj: $(PMDIR)/pm_common/pmutil.c
$(MSCC) /c $(PACF) $(PMDIR)/pm_common/pmutil.c
pmwin.obj: $(PMDIR)/pm_win/pmwin.c
$(MSCC) /c $(PACF) $(PMDIR)/pm_win/pmwin.c
pmwinmm.obj: $(PMDIR)/pm_win/pmwinmm.c
$(MSCC) /c $(PACF) $(PMDIR)/pm_win/pmwinmm.c
porttime.obj: $(PMDIR)/porttime/porttime.c
$(MSCC) /c $(PACF) $(PMDIR)/porttime/porttime.c
ptwinmm.obj: $(PMDIR)/porttime/ptwinmm.c
$(MSCC) /c $(PACF) $(PMDIR)/porttime/ptwinmm.c

# the following should also clean up "bin" but it doesn't because "bin" holds
# precious stuff from elsewhere (luckily, our stuff matches 'pd*')
clean:
$(DELETE) *.obj
$(DELETE) ../bin/pd*.*

+ 142
- 0
ports/camomile/source/LibPd/pure-data/src/notes.txt View File

@@ -0,0 +1,142 @@
---------------- dolist --------------------

GUIs: slider, etc "clip (pre-0.46) " (on for old ones, off by default)
toggle to get "track value (pre-0.46)"

x_text.c:
text dimension setting (message or creation arg - how to do it in structs?)
copying ala text_define_topointer
"open" and "save as" messages to open text window
how to integrate message boxes !?

x_array.c:
allow for lying about x and y labels
no-mouse, quantize and clip flags for plotting/mousing
save ticks, labels, other flags (and add dialog to set them)
array y range to reflect y increment sign (so no 1 to -1 range)
array search and array sort objects
maybe: array segment, array spline, array sinesum, etc? or array gen? or
array forward (forwards message to defining array)
Is there a way to generate a pointer to an anonymous array? (do we need that?)

OS specific:
linux:
rpm packages; BSD versions (set up VMs for testing)
windows:
put call to PA_Terminate back in where appropriate (first test on windows)
"-audiodev" with no args in registry can't start up?
mmio out of portaudio but consider adding wdmks
mac:
check if window titles wrong on Macintosh
clicking on windows seems sometimes not to open them
compile for jack on OSX by default (32 bit version at least).
turn on paMacCore_ChangeDeviceParameters for mac (pa_mac_core.h)

problems:
fix behavior when dragging object outside screen (stop the evil auto-scrolls)
pd~ "start" followed by messages gives race condition because of "fromgui" biz
pd~ deadlock protection
find asdf$1 (e.g.) doesn't work
objects on GOP don't erase if you edit the GOP while they're showing
add -stack option to make 'regular' stack larger
menu item to save help patches to directory
look again at array vis/invis conundrum, g_template.c
floor, ciel functions in expr misdeclared
graph names don't appear until graph moved? (invis/vis on new array/rename)
don't filter locked click() through getrect
patcher inlets don't deal with scalars (zbug.pd)
read xx.txt in "bad" gives warnings
Krzysztof's qlist_next reentrancy bug
don't draw in/outlets on gui objects in graph-on-parent
get rid of messages causing renaming; try to prevent patches closing themselves.
scofo reports error on reading score1.txt
better error message for adc~ / dac~ reblocking
fix limitations in number of array elements that can be graphed

more demonstration patches:
vibrato using variable delay
real-time spectrum grapher
document ||, |, etc, better

features:
-nomidibuf flag (Nicola Pandini on pd list Aug 8 2013)
add way to query readsf~ for fill pointer (sf feature request 3598776)
'route' object to sprout inlet if no args (like sel)
optionally suppress leading "." directories and files on "open"
"installation mode": flag or messages to suppress menus&accelerators,
and invisibilize Pd window
sigmund~: sort by pitch; pitch estimate to include pitch height; message
to lie about previous track output
expr to parse exponential notation
mem alignment for SSE
replace gatom_escapit with a quoting mechanism (handle '[', spaces, etc.)
poly inlet to turn stealing on/off, plus mode to handle note-with-duration
integrate video into tilde objects
think of a way to embed abstractions in a patch (zlib?)
delete-in-rectangle message to Pds
put serial object in main dist (see rat@telecoma, Apr. 25; winfried May 22)
see x_list.c for more "list" object ideas
open64() for linux (if 32 bits, close soundfile and open64 it)

paths:
fix declare to update current patch when changed
open_via_path call in d_soundfile.c isn't threadsafe
open/save panel to take messages to set extent list
new open_via_path to take list of extents

editing:
control-enter to deselect an object?
pasting should look at current mouse location
clickless connection (hit 'c' key? see Bouchard paper)
tab to jump to a connected object (first one?) (shift-tab to back up?)
arrow keys to shift connections left and right
menu item to connect selected objects
highlight connections (and I/Os) on mouse motion
select line and hit "insert" to interpolate an object
option-drag an outlet to make a new, connected object
make a way to make multiple connections
"fix width" menu item
close-subwindows menu item
canvas zooming (use tcl/tk canvas scale command?)

data:
add -x [-n?] flag to drawnumbers
flag to disable edits for arrays
make a 2-pass process for finding hot spot closest to any given click
hooks for table mousing, other changes (scalars?)
data to save as succession of "list" messages that textfile can store, etc.
data copy/paste doesn't check templates aren't changed
pointer == and select equivalents
cursor to show (x, y) location and/or what parameter is being set to what
improve typing at drawnumbers
append doesn't do symbols yet.
non-clickable arrays (plus arrays that respond more easily than default)
set -any, get -any
build out scalar object - naming; "scalar set/get" objects
pointer methods to search and delete
optimize by pre-fetching field name offsets in accessor objects
double-click on drawtext in scalar to create editor window

more features:
signal inlets to sense signals; fix +~ etc, vcf~, biquad~, other filters
message dialog not to disappear
show results of opening MIDI on dialog
new: abs~, nexttick~, extend threshold~ and snapshot~ (vthreshold~ etc)
netsend separate thread
in glist_delete, consider why this can't be just "vis 0" -- why do we need it?
closebang and initbang
put in something for tilde order forcing
extensible "toolbar" so people can add external GUI objects
number boxes to darken for typing and/or received messages
new message box look
dialog to give values of $1, ... for the canvas
bang at end of line~, tabwrite~, etc.
should sys_bail kill all "threads" on the way out?
allow backslashes (or else really disallow them)
icon & desktop integration
tools (reassigns meaning of primary click)

code style improvements:
-Wno-unused to -Wno-unused-paramter and clean up unused automatic variables
rewrite t_getbytes properly (m_newmemory.c in pd/attic)
obj_new should do a longjmp on out-of-memory

BIN
ports/camomile/source/LibPd/pure-data/src/pd.ico View File

Before After

+ 25
- 0
ports/camomile/source/LibPd/pure-data/src/pd.rc View File

@@ -0,0 +1,25 @@
id ICON "pd.ico"
1 VERSIONINFO
FILEVERSION 0,48,1,0
PRODUCTVERSION 0,48,1,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "puredata.info"
VALUE "FileDescription", "Pure Data Application"
VALUE "FileVersion", "0.48-1"
VALUE "InternalName", "pd.exe"
VALUE "LegalCopyright", "Miller Puckette, et al."
VALUE "OriginalFilename", "pd.exe"
VALUE "ProductName", "Pure Data"
VALUE "ProductVersion", "0.48-1"
END
END

BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

+ 1134
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio.c
File diff suppressed because it is too large
View File


+ 973
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.c View File

@@ -0,0 +1,973 @@
/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* this file inputs and outputs audio using the ALSA API available on linux. */

/* support for ALSA pcmv2 api by Karl MacMillan<karlmac@peabody.jhu.edu> */
/* support for ALSA MMAP noninterleaved by Winfried Ritsch, IEM */

#include <alsa/asoundlib.h>

#include "m_pd.h"
#include "s_stuff.h"
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mman.h>
#include "s_audio_alsa.h"
#include <endian.h>

/* Defines */
#define DEBUG(x) x
#define DEBUG2(x) {x;}

/* needed for alsa 0.9 compatibility: */
#if (SND_LIB_MAJOR < 1)
#define ALSAAPI9
#endif

static void alsa_checkiosync( void);
static void alsa_numbertoname(int iodev, char *devname, int nchar);
static int alsa_jittermax;
#define ALSA_DEFJITTERMAX 3

/* don't assume we can turn all 31 bits when doing float-to-fix;
otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
#define FMAX 0x7ffff000
#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))

static char *alsa_snd_buf;
static int alsa_snd_bufsize;
static int alsa_buf_samps;
static snd_pcm_status_t *alsa_status;
static int alsa_usemmap;

t_alsa_dev alsa_indev[ALSA_MAXDEV];
t_alsa_dev alsa_outdev[ALSA_MAXDEV];
int alsa_nindev;
int alsa_noutdev;

/* #define DEBUG_ALSA_XFER */
#ifdef DEBUG_ALSA_XFER
static int xferno = 0;
static int callno = 0;
#endif

/* report an error condition if an error was flagged in the argument "err".
"fn" is 0 for input, 1 for output, otherwise N/A. "why" indicates where
in the code the error was hit. */
static void check_error(int err, int fn, const char *why)
{
if (err < 0)
post("ALSA %serror (%s): %s",
(fn == 1? "output " : (fn == 0 ? "input ": "")),
why, snd_strerror(err));
}

/* figure out, when opening ALSA device, whether we should use the code in
this file or defer to Winfried Ritch's code to do mmaped transfers (handled
in s_audio_alsamm.c). */
static int alsaio_canmmap(t_alsa_dev *dev)
{
snd_pcm_hw_params_t *hw_params;
int err1, err2;

snd_pcm_hw_params_alloca(&hw_params);

err1 = snd_pcm_hw_params_any(dev->a_handle, hw_params);
if (err1 < 0) {
check_error(err1, -1, "snd_pcm_hw_params_any");
return (0);
}
err1 = snd_pcm_hw_params_set_access(dev->a_handle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err1 < 0)
{
err2 = snd_pcm_hw_params_set_access(dev->a_handle,
hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
}
else err2 = -1;
#if 0
post("err 1 %d (%s), err2 %d (%s)", err1, snd_strerror(err1),
err2, snd_strerror(err2));
#endif
return ((err1 < 0) && (err2 >= 0));
}

/* set up an input or output device. Return 0 on success, -1 on failure. */
static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
int nfrags, int frag_size)
{
int bufsizeforthis, err;
snd_pcm_hw_params_t* hw_params;
snd_pcm_sw_params_t* sw_params;
unsigned int tmp_uint;
snd_pcm_uframes_t tmp_snd_pcm_uframes;

snd_pcm_hw_params_alloca(&hw_params);
snd_pcm_sw_params_alloca(&sw_params);

if (sys_verbose)
post((out ? "configuring sound output..." :
"configuring sound input..."));

/* set hardware parameters... */

/* get the default params */
err = snd_pcm_hw_params_any(dev->a_handle, hw_params);
check_error(err, out, "snd_pcm_hw_params_any");

/* try to set interleaved access */
err = snd_pcm_hw_params_set_access(dev->a_handle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
return (-1);
check_error(err, out, "snd_pcm_hw_params_set_access");
#if 0 /* enable this to print out which formats are available */
{
int i;
for (i = 0; i <= SND_PCM_FORMAT_LAST; i++)
fprintf(stderr, "%d -> %d\n",
i, snd_pcm_hw_params_test_format(dev->a_handle, hw_params, i));
}
#endif
/* Try to set 32 bit format first */
err = snd_pcm_hw_params_set_format(dev->a_handle,
hw_params, SND_PCM_FORMAT_S32);
if (err < 0)
{
err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
SND_PCM_FORMAT_S24_3LE);
if (err < 0)
{
err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
SND_PCM_FORMAT_S16);
check_error(err, out, "_pcm_hw_params_set_format");
dev->a_sampwidth = 2;
}
else dev->a_sampwidth = 3;
}
else dev->a_sampwidth = 4;

if (sys_verbose)
post("Sample width set to %d bytes", dev->a_sampwidth);

/* set the subformat */
err = snd_pcm_hw_params_set_subformat(dev->a_handle,
hw_params, SND_PCM_SUBFORMAT_STD);
check_error(err, out, "snd_pcm_hw_params_set_subformat");

/* set the number of channels */
tmp_uint = *channels;
err = snd_pcm_hw_params_set_channels_near(dev->a_handle,
hw_params, &tmp_uint);
check_error(err, out, "snd_pcm_hw_params_set_channels");
if (tmp_uint != (unsigned)*channels)
post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint);
*channels = tmp_uint;
dev->a_channels = *channels;

/* set the sampling rate */
err = snd_pcm_hw_params_set_rate_near(dev->a_handle, hw_params,
(unsigned int *)rate, 0);
check_error(err, out, "snd_pcm_hw_params_set_rate_min");
#if 0
err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
post("input sample rate %d", err);
#endif

/* post("frag size %d, nfrags %d", frag_size, nfrags); */
/* set "period size" */
tmp_snd_pcm_uframes = frag_size;
err = snd_pcm_hw_params_set_period_size_near(dev->a_handle,
hw_params, &tmp_snd_pcm_uframes, 0);
check_error(err, out, "snd_pcm_hw_params_set_period_size_near");

/* set the buffer size */
tmp_snd_pcm_uframes = nfrags * frag_size;
err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle,
hw_params, &tmp_snd_pcm_uframes);
check_error(err, out, "snd_pcm_hw_params_set_buffer_size_near");

err = snd_pcm_hw_params(dev->a_handle, hw_params);
check_error(err, out, "snd_pcm_hw_params");

/* set up the buffer */
bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels;
if (alsa_snd_buf)
{
if (alsa_snd_bufsize < bufsizeforthis)
{
if (!(alsa_snd_buf = realloc(alsa_snd_buf, bufsizeforthis)))
{
post("out of memory");
return (-1);
}
memset(alsa_snd_buf, 0, bufsizeforthis);
alsa_snd_bufsize = bufsizeforthis;
}
}
else
{
if (!(alsa_snd_buf = (void *)malloc(bufsizeforthis)))
{
post("out of memory");
return (-1);
}
memset(alsa_snd_buf, 0, bufsizeforthis);
alsa_snd_bufsize = bufsizeforthis;
}

err = snd_pcm_sw_params_current(dev->a_handle, sw_params);
if (err < 0)
{
post("Unable to determine current swparams for %s: %s\n",
(out ? "output" : "input"), snd_strerror(err));
return (-1);
}
err = snd_pcm_sw_params_set_stop_threshold(dev->a_handle, sw_params,
0x7fffffff);
if (err < 0)
{
post("Unable to set start threshold mode for %s: %s\n",
(out ? "output" : "input"), snd_strerror(err));
return (-1);
}

err = snd_pcm_sw_params_set_avail_min(dev->a_handle, sw_params, 4);
if (err < 0)
{
post("Unable to set avail min for %s: %s\n",
(out ? "output" : "input"), snd_strerror(err));
return (-1);
}
err = snd_pcm_sw_params(dev->a_handle, sw_params);
if (err < 0)
{
post("Unable to set sw params for %s: %s\n",
(out ? "output" : "input"), snd_strerror(err));
return (-1);
}

return (0);
}


/* return 0 on success */
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
int *choutdev, int rate, int blocksize)
{
int err, inchans = 0, outchans = 0, subunitdir;
char devname[512];
snd_output_t* out;
int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE);
int nfrags, i, iodev, dev2;
int wantinchans, wantoutchans, device;

nfrags = sys_schedadvance * (float)rate / (1e6 * frag_size);
/* save our belief as to ALSA's buffer size for later */
alsa_buf_samps = nfrags * frag_size;
alsa_nindev = alsa_noutdev = 0;
alsa_jittermax = ALSA_DEFJITTERMAX;

if (sys_verbose)
post("audio buffer set to %d", (int)(0.001 * sys_schedadvance));

for (iodev = 0; iodev < naudioindev; iodev++)
{
alsa_numbertoname(audioindev[iodev], devname, 512);
err = snd_pcm_open(&alsa_indev[alsa_nindev].a_handle, devname,
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
check_error(err, 0, "snd_pcm_open");
if (err < 0)
continue;
alsa_indev[alsa_nindev].a_devno = audioindev[iodev];
snd_pcm_nonblock(alsa_indev[alsa_nindev].a_handle, 1);
if (sys_verbose)
post("opened input device name %s", devname);
alsa_nindev++;
}
for (iodev = 0; iodev < naudiooutdev; iodev++)
{
alsa_numbertoname(audiooutdev[iodev], devname, 512);
err = snd_pcm_open(&alsa_outdev[alsa_noutdev].a_handle, devname,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
check_error(err, 1, "snd_pcm_open");
if (err < 0)
continue;
alsa_outdev[alsa_noutdev].a_devno = audiooutdev[iodev];
snd_pcm_nonblock(alsa_outdev[alsa_noutdev].a_handle, 1);
alsa_noutdev++;
}
if (!alsa_nindev && !alsa_noutdev)
goto blewit;

/* If all the open devices support mmap_noninterleaved, let's call
Wini's code in s_audio_alsamm.c */
alsa_usemmap = 1;
for (iodev = 0; iodev < alsa_nindev; iodev++)
if (!alsaio_canmmap(&alsa_indev[iodev]))
alsa_usemmap = 0;
for (iodev = 0; iodev < alsa_noutdev; iodev++)
if (!alsaio_canmmap(&alsa_outdev[iodev]))
alsa_usemmap = 0;
if (alsa_usemmap)
{
post("using mmap audio interface");
if (alsamm_open_audio(rate, blocksize))
goto blewit;
else return (0);
}
for (iodev = 0; iodev < alsa_nindev; iodev++)
{
int channels = chindev[iodev];
if (alsaio_setup(&alsa_indev[iodev], 0, &channels, &rate,
nfrags, frag_size) < 0)
goto blewit;
inchans += channels;
}
for (iodev = 0; iodev < alsa_noutdev; iodev++)
{
int channels = choutdev[iodev];
if (alsaio_setup(&alsa_outdev[iodev], 1, &channels, &rate,
nfrags, frag_size) < 0)
goto blewit;
outchans += channels;
}
if (!inchans && !outchans)
goto blewit;

for (iodev = 0; iodev < alsa_nindev; iodev++)
snd_pcm_prepare(alsa_indev[iodev].a_handle);
for (iodev = 0; iodev < alsa_noutdev; iodev++)
snd_pcm_prepare(alsa_outdev[iodev].a_handle);

/* if duplex we can link the channels so they start together */
for (iodev = 0; iodev < alsa_nindev; iodev++)
for (dev2 = 0; dev2 < alsa_noutdev; dev2++)
{
if (alsa_indev[iodev].a_devno == alsa_outdev[iodev].a_devno)
{
snd_pcm_link(alsa_indev[iodev].a_handle,
alsa_outdev[iodev].a_handle);
}
}

/* allocate the status variables */
if (!alsa_status)
{
err = snd_pcm_status_malloc(&alsa_status);
check_error(err, -1, "snd_pcm_status_malloc");
}

/* fill the buffer with silence and prime the output FIFOs. This
should automatically start the output devices. */
memset(alsa_snd_buf, 0, alsa_snd_bufsize);

if (outchans)
{
i = (frag_size * nfrags)/DEFDACBLKSIZE + 1;
while (i--)
{
for (iodev = 0; iodev < alsa_noutdev; iodev++)
snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
DEFDACBLKSIZE);
}
}
if (inchans)
{
/* some of the ADC devices might already have been started by
starting the outputs above, but others might still need it. */
for (iodev = 0; iodev < alsa_nindev; iodev++)
if (snd_pcm_state(alsa_indev[iodev].a_handle)
!= SND_PCM_STATE_RUNNING)
if ((err = snd_pcm_start(alsa_indev[iodev].a_handle)) < 0)
check_error(err, -1, "input start failed");
}
return (0);
blewit:
STUFF->st_inchannels = 0;
STUFF->st_outchannels = 0;
alsa_close_audio();
return (1);
}

void alsa_close_audio(void)
{
int err, iodev;
if (alsa_usemmap)
{
alsamm_close_audio();
return;
}
for (iodev = 0; iodev < alsa_nindev; iodev++)
{
err = snd_pcm_close(alsa_indev[iodev].a_handle);
check_error(err, 0, "snd_pcm_close");
}
for (iodev = 0; iodev < alsa_noutdev; iodev++)
{
err = snd_pcm_close(alsa_outdev[iodev].a_handle);
check_error(err, 1, "snd_pcm_close");
}
alsa_nindev = alsa_noutdev = 0;
}

int alsa_send_dacs(void)
{
static double timenow;
double timelast;
t_sample *fp, *fp1, *fp2;
int i, j, k, err, iodev, result, ch, resync = 0;;
int chansintogo, chansouttogo;
unsigned int transfersize;

if (alsa_usemmap)
return (alsamm_send_dacs());

if (!alsa_nindev && !alsa_noutdev)
return (SENDDACS_NO);

chansintogo = STUFF->st_inchannels;
chansouttogo = STUFF->st_outchannels;
transfersize = DEFDACBLKSIZE;

timelast = timenow;
timenow = sys_getrealtime();

#ifdef DEBUG_ALSA_XFER
if (timenow - timelast > 0.050)
post("long wait between calls: %d",
(int)(1000 * (timenow - timelast))), fflush(stderr);
callno++;
#endif


for (iodev = 0; iodev < alsa_nindev; iodev++)
{
result = snd_pcm_state(alsa_indev[iodev].a_handle);
if (result == SND_PCM_STATE_XRUN)
{
int res2 = snd_pcm_start(alsa_indev[iodev].a_handle);
fprintf(stderr, "restart alsa input\n");
if (res2 < 0)
fprintf(stderr, "alsa xrun recovery apparently failed\n");
}
snd_pcm_status(alsa_indev[iodev].a_handle, alsa_status);
if (snd_pcm_status_get_avail(alsa_status) < transfersize)
return (SENDDACS_NO);
}
for (iodev = 0; iodev < alsa_noutdev; iodev++)
{
result = snd_pcm_state(alsa_outdev[iodev].a_handle);
if (result == SND_PCM_STATE_XRUN)
{
int res2 = snd_pcm_start(alsa_outdev[iodev].a_handle);
fprintf(stderr, "restart alsa output\n");
if (res2 < 0)
fprintf(stderr, "alsa xrun recovery apparently failed\n");
}
snd_pcm_status(alsa_outdev[iodev].a_handle, alsa_status);
if (snd_pcm_status_get_avail(alsa_status) < transfersize)
return (SENDDACS_NO);
}

#ifdef DEBUG_ALSA_XFER
post("xfer %d", transfersize);
#endif
/* do output */
for (iodev = 0, fp1 = STUFF->st_soundout, ch = 0;
iodev < alsa_noutdev; iodev++)
{
int thisdevchans = alsa_outdev[iodev].a_channels;
int chans = (chansouttogo < thisdevchans ? chansouttogo : thisdevchans);
chansouttogo -= chans;

if (alsa_outdev[iodev].a_sampwidth == 4)
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
{
float s1 = *fp2 * INT32_MAX;
((t_alsa_sample32 *)alsa_snd_buf)[j] = CLIP32(s1);
}
for (; i < thisdevchans; i++, ch++)
for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
((t_alsa_sample32 *)alsa_snd_buf)[j] = 0;
}
else if (alsa_outdev[iodev].a_sampwidth == 3)
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
{
int s = *fp2 * 8388352.;
if (s > 8388351)
s = 8388351;
else if (s < -8388351)
s = -8388351;
#if BYTE_ORDER == LITTLE_ENDIAN
((char *)(alsa_snd_buf))[3*j] = (s & 255);
((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
fprintf(stderr, "big endian 24-bit not supported");
#endif
}
for (; i < thisdevchans; i++, ch++)
for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
((char *)(alsa_snd_buf))[3*j] =
((char *)(alsa_snd_buf))[3*j+1] =
((char *)(alsa_snd_buf))[3*j+2] = 0;
}
else /* 16 bit samples */
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
{
int s = *fp2 * 32767.;
if (s > 32767)
s = 32767;
else if (s < -32767)
s = -32767;
((t_alsa_sample16 *)alsa_snd_buf)[j] = s;
}
for (; i < thisdevchans; i++, ch++)
for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans)
((t_alsa_sample16 *)alsa_snd_buf)[j] = 0;
}
result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
transfersize);

if (result != (int)transfersize)
{
#ifdef DEBUG_ALSA_XFER
if (result >= 0 || errno == EAGAIN)
post("ALSA: write returned %d of %d\n",
result, transfersize);
else post("ALSA: write: %s\n",
snd_strerror(errno));
#endif
sys_log_error(ERR_DATALATE);
if (result == -EPIPE)
{
result = snd_pcm_prepare(alsa_indev[iodev].a_handle);
if (result < 0)
fprintf(stderr, "read reset error %d\n", result);
}
else fprintf(stderr, "read other error %d\n", result);
resync = 1;
}

/* zero out the output buffer */
memset(STUFF->st_soundout, 0, DEFDACBLKSIZE * sizeof(*STUFF->st_soundout) *
STUFF->st_outchannels);
if (sys_getrealtime() - timenow > 0.002)
{
#ifdef DEBUG_ALSA_XFER
post("output %d took %d msec\n",
callno, (int)(1000 * (timenow - timelast))), fflush(stderr);
#endif
timenow = sys_getrealtime();
sys_log_error(ERR_DACSLEPT);
}
}

/* do input */
for (iodev = 0, fp1 = STUFF->st_soundin, ch = 0; iodev < alsa_nindev; iodev++)
{
int thisdevchans = alsa_indev[iodev].a_channels;
int chans = (chansintogo < thisdevchans ? chansintogo : thisdevchans);
chansouttogo -= chans;
result = snd_pcm_readi(alsa_indev[iodev].a_handle, alsa_snd_buf,
transfersize);
if (result < (int)transfersize)
{
#ifdef DEBUG_ALSA_XFER
if (result < 0)
post("snd_pcm_read %d %d: %s\n",
callno, xferno, snd_strerror(errno));
else post("snd_pcm_read %d %d returned only %d\n",
callno, xferno, result);
#endif
sys_log_error(ERR_DATALATE);
if (result == -EPIPE)
{
result = snd_pcm_prepare(alsa_indev[iodev].a_handle);
if (result < 0)
fprintf(stderr, "read reset error %d\n", result);
}
else fprintf(stderr, "read other error %d\n", result);
resync = 1;
}
if (alsa_indev[iodev].a_sampwidth == 4)
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
{
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
*fp2 = (float) ((t_alsa_sample32 *)alsa_snd_buf)[j]
* (1./ INT32_MAX);
}
}
else if (alsa_indev[iodev].a_sampwidth == 3)
{
#if BYTE_ORDER == LITTLE_ENDIAN
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
{
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
*fp2 = ((float) (
(((unsigned char *)alsa_snd_buf)[3*j] << 8)
| (((unsigned char *)alsa_snd_buf)[3*j+1] << 16)
| (((unsigned char *)alsa_snd_buf)[3*j+2] << 24)))
* (1./ INT32_MAX);
}
#else
fprintf(stderr, "big endian 24-bit not supported");
#endif
}
else
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
{
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
*fp2 = (float) ((t_alsa_sample16 *)alsa_snd_buf)[j]
* 3.051850e-05;
}
}
}
#ifdef DEBUG_ALSA_XFER
xferno++;
#endif
if (sys_getrealtime() - timenow > 0.002)
{
#ifdef DEBUG_ALSA_XFER
post("alsa_send_dacs took %d msec\n",
(int)(1000 * (sys_getrealtime() - timenow)));
#endif
sys_log_error(ERR_ADCSLEPT);
}
{
static int checkcountdown = 0;
if (!checkcountdown--)
{
checkcountdown = 10;
if (alsa_nindev + alsa_noutdev > 1)
alsa_checkiosync(); /* check I/O are in sync */
}
}
return SENDDACS_YES;
}

void alsa_printstate( void)
{
int i, result, iodev = 0;
snd_pcm_sframes_t indelay = 0, outdelay = 0;
if (sys_audioapi != API_ALSA)
{
error("restart-audio: implemented for ALSA only.");
return;
}
if (STUFF->st_inchannels)
{
result = snd_pcm_delay(alsa_indev[iodev].a_handle, &indelay);
if (result < 0)
post("snd_pcm_delay 1 failed");
else post("in delay %d", indelay);
}
if (STUFF->st_outchannels)
{
result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay);
if (result < 0)
post("snd_pcm_delay 2 failed");
else post("out delay %d", outdelay);
}
post("sum %d (%d mod 64)\n", indelay + outdelay, (indelay+outdelay)%64);

post("buf samples %d", alsa_buf_samps);
}

void alsa_putzeros(int iodev, int n)
{
int i, result;
memset(alsa_snd_buf, 0,
alsa_outdev[iodev].a_sampwidth * DEFDACBLKSIZE *
alsa_outdev[iodev].a_channels);
for (i = 0; i < n; i++)
{
result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
DEFDACBLKSIZE);
#if 0
if (result != DEFDACBLKSIZE)
post("result %d", result);
#endif
}
/* post ("putzeros %d", n); */
}

void alsa_getzeros(int iodev, int n)
{
int i, result;
for (i = 0; i < n; i++)
{
result = snd_pcm_readi(alsa_indev[iodev].a_handle, alsa_snd_buf,
DEFDACBLKSIZE);
#if 0
if (result != DEFDACBLKSIZE)
post("result %d", result);
#endif
}
/* post ("getzeros %d", n); */
}

/* call this only if both input and output are open */
static void alsa_checkiosync( void)
{
int i, result, giveup = 50, alreadylogged = 0, iodev = 0, err;
snd_pcm_sframes_t minphase, maxphase, thisphase, outdelay;

while (1)
{
if (giveup-- <= 0)
{
post("tried but couldn't sync A/D/A");
alsa_jittermax += 1;
return;
}
minphase = 0x7fffffff;
maxphase = -0x7fffffff;
for (iodev = 0; iodev < alsa_noutdev; iodev++)
{
if ((result = snd_pcm_state(alsa_outdev[iodev].a_handle))
!= SND_PCM_STATE_RUNNING && result != SND_PCM_STATE_XRUN)
{
if (sys_verbose)
post("restarting output device from state %d",
snd_pcm_state(alsa_outdev[iodev].a_handle));
if ((err = snd_pcm_start(alsa_outdev[iodev].a_handle)) < 0)
check_error(err, 0, "restart failed");
}
result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay);
if (result < 0)
{
snd_pcm_prepare(alsa_outdev[iodev].a_handle);
result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay);
}
#ifdef DEBUG_ALSA_XFER
post("outfifo %d %d %d",
callno, xferno, outdelay);
#endif
if (result < 0)
{
post("output snd_pcm_delay failed: %s", snd_strerror(result));
if (snd_pcm_status(alsa_outdev[iodev].a_handle,
alsa_status) < 0)
post("output snd_pcm_status failed");
else post("astate %d",
snd_pcm_status_get_state(alsa_status));
return;
}
thisphase = alsa_buf_samps - outdelay;
if (thisphase < minphase)
minphase = thisphase;
if (thisphase > maxphase)
maxphase = thisphase;
if (outdelay < 0)
sys_log_error(ERR_DATALATE), alreadylogged = 1;
}
for (iodev = 0; iodev < alsa_nindev; iodev++)
{
if ((result = snd_pcm_state(alsa_indev[iodev].a_handle))
!= SND_PCM_STATE_RUNNING && result != SND_PCM_STATE_XRUN)
{
if (sys_verbose)
post("restarting input device from state %d",
snd_pcm_state(alsa_indev[iodev].a_handle));
if ((err = snd_pcm_start(alsa_indev[iodev].a_handle)) < 0)
check_error(err, 1, "restart failed");
}
result = snd_pcm_delay(alsa_indev[iodev].a_handle, &thisphase);
if (result < 0)
{
snd_pcm_prepare(alsa_indev[iodev].a_handle);
result = snd_pcm_delay(alsa_indev[iodev].a_handle, &thisphase);
}
#ifdef DEBUG_ALSA_XFER
post("infifo %d %d %d",
callno, xferno, thisphase);
#endif
if (result < 0)
{
post("output snd_pcm_delay failed: %s", snd_strerror(result));
if (snd_pcm_status(alsa_outdev[iodev].a_handle,
alsa_status) < 0)
post("output snd_pcm_status failed");
else post("astate %d",
snd_pcm_status_get_state(alsa_status));
return;
}
if (thisphase < minphase)
minphase = thisphase;
if (thisphase > maxphase)
maxphase = thisphase;
}
/* the "correct" position is for all the phases to be exactly
equal; but since we only make corrections DEFDACBLKSIZE samples
at a time, we just ask that the spread be not more than 3/4
of a block. */
if (maxphase <= minphase + (alsa_jittermax * (DEFDACBLKSIZE / 4)))
break;

#ifdef DEBUG_ALSA_XFER
post("resync audio %d %d %d", xferno, minphase, maxphase);
#endif

for (iodev = 0; iodev < alsa_noutdev; iodev++)
{
result = snd_pcm_delay(alsa_outdev[iodev].a_handle, &outdelay);
if (result < 0)
break;
thisphase = alsa_buf_samps - outdelay;
if (thisphase > minphase + DEFDACBLKSIZE)
{
alsa_putzeros(iodev, 1);
if (!alreadylogged)
sys_log_error(ERR_RESYNC), alreadylogged = 1;
#ifdef DEBUG_ALSA_XFER
post("putz %d %d %d %d",
callno, xferno, (int)thisphase, (int)minphase);
#endif
}
}
for (iodev = 0; iodev < alsa_nindev; iodev++)
{
result = snd_pcm_delay(alsa_indev[iodev].a_handle, &thisphase);
if (result < 0)
break;
if (thisphase > minphase + DEFDACBLKSIZE)
{
alsa_getzeros(iodev, 1);
if (!alreadylogged)
sys_log_error(ERR_RESYNC), alreadylogged = 1;
#ifdef DEBUG_ALSA_XFER
post("getz %d %d %d %d",
callno, xferno, (int)thisphase, (int)minphase);
#endif
}
}
/* it's possible we didn't do anything; if so don't repeat */
if (!alreadylogged)
break;
}
#ifdef DEBUG_ALSA_XFER
if (alreadylogged)
post("done resync");
#endif
}

static int alsa_nnames = 0;
static char **alsa_names = 0;

void alsa_adddev(char *name)
{
if (alsa_nnames)
alsa_names = (char **)t_resizebytes(alsa_names,
alsa_nnames * sizeof(char *),
(alsa_nnames+1) * sizeof(char *));
else alsa_names = (char **)t_getbytes(sizeof(char *));
alsa_names[alsa_nnames] = gensym(name)->s_name;
alsa_nnames++;
}

static void alsa_numbertoname(int devno, char *devname, int nchar)
{
int ndev = 0, cardno = -1;
while (!snd_card_next(&cardno) && cardno >= 0)
ndev++;
if (devno < 2*ndev)
{
if (devno & 1)
snprintf(devname, nchar, "plughw:%d", devno/2);
else snprintf(devname, nchar, "hw:%d", devno/2);
}
else if (devno <2*ndev + alsa_nnames)
snprintf(devname, nchar, "%s", alsa_names[devno - 2*ndev]);
else snprintf(devname, nchar, "???");
}

/* For each hardware card found, we list two devices, the "hard" and
"plug" one. The card scan is derived from portaudio code. */
void alsa_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int ndev = 0, cardno = -1, i, j;
*canmulti = 2; /* supports multiple devices */
while (!snd_card_next(&cardno) && cardno >= 0)
{
snd_ctl_t *ctl;
snd_ctl_card_info_t *info;
char devname[80];
const char *desc;
if (2 * ndev + 2 > maxndev)
break;
sprintf(devname, "hw:%d", cardno );
/* fprintf(stderr, "\ntry %s...\n", devname); */
if (snd_ctl_open(&ctl, devname, 0) >= 0)
{
snd_ctl_card_info_malloc(&info);
snd_ctl_card_info(ctl, info);
desc = snd_ctl_card_info_get_name(info);
snprintf(indevlist + 2*ndev * devdescsize, devdescsize,
"%s (hardware)", desc);
snprintf(indevlist + (2*ndev + 1) * devdescsize, devdescsize,
"%s (plug-in)", desc);
snprintf(outdevlist + 2*ndev * devdescsize, devdescsize,
"%s (hardware)", desc);
snprintf(outdevlist + (2*ndev + 1) * devdescsize, devdescsize,
"%s (plug-in)", desc);
indevlist[(2*ndev+1) * devdescsize - 1] =
indevlist[(2*ndev+2) * devdescsize - 1] =
outdevlist[(2*ndev+1) * devdescsize - 1] =
outdevlist[(2*ndev+2) * devdescsize - 1] = 0;
snd_ctl_card_info_free(info);
}
else
{
fprintf(stderr, "ALSA card scan error\n");
sprintf(indevlist + 2*ndev * devdescsize, "???");
sprintf(indevlist + (2*ndev + 1) * devdescsize, "???");
sprintf(outdevlist + 2*ndev * devdescsize, "???");
sprintf(outdevlist + (2*ndev + 1) * devdescsize, "???");
}
/* fprintf(stderr, "name: %s\n", snd_ctl_card_info_get_name(info)); */
ndev++;
}
for (i = 0, j = 2*ndev; i < alsa_nnames; i++, j++)
{
if (j >= maxndev)
break;
snprintf(indevlist + j * devdescsize, devdescsize, "%s",
alsa_names[i]);
snprintf(outdevlist + j * devdescsize, devdescsize, "%s",
alsa_names[i]);
indevlist[(i+1) * devdescsize - 1] =
outdevlist[(i+1) * devdescsize - 1] = 0;
}
*nindevs = *noutdevs = j;
}

+ 40
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_alsa.h View File

@@ -0,0 +1,40 @@
/* Copyright (c) 1997- Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */


typedef int16_t t_alsa_sample16;
typedef int32_t t_alsa_sample32;
#define ALSA_SAMPLEWIDTH_16 sizeof(t_alsa_sample16)
#define ALSA_SAMPLEWIDTH_32 sizeof(t_alsa_sample32)
#define ALSA_XFERSIZE16 (signed int)(sizeof(t_alsa_sample16) * DEFDACBLKSIZE)
#define ALSA_XFERSIZE32 (signed int)(sizeof(t_alsa_sample32) * DEFDACBLKSIZE)
#define ALSA_MAXDEV 4
#define ALSA_JITTER 1024
#define ALSA_EXTRABUFFER 2048
#define ALSA_DEFFRAGSIZE 64
#define ALSA_DEFNFRAG 12

#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif

typedef struct _alsa_dev
{
snd_pcm_t *a_handle;
int a_devno;
int a_sampwidth;
int a_channels;
char **a_addr;
int a_synced;
} t_alsa_dev;

extern t_alsa_dev alsa_indev[ALSA_MAXDEV];
extern t_alsa_dev alsa_outdev[ALSA_MAXDEV];
extern int alsa_nindev;
extern int alsa_noutdev;

int alsamm_open_audio(int rate, int blocksize);
void alsamm_close_audio(void);
int alsamm_send_dacs(void);

+ 1365
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_alsamm.c
File diff suppressed because it is too large
View File


+ 43
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_audiounit.c View File

@@ -0,0 +1,43 @@

/* ------------- routines for Apple AudioUnit in AudioToolbox -------------- */
#ifdef USEAPI_AUDIOUNIT

/* this is currently a placeholder file while we decide which one of three implementations of this API we use */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "m_pd.h"
#include "s_stuff.h"
#include <AudioToolbox/AudioToolbox.h>

pthread_mutex_t audiounit_mutex;
pthread_cond_t audiounit_sem;

int audiounit_open_audio(int inchans, int outchans, int rate)
{
return 0;
}

void audiounit_close_audio(void)
{
}

int audiounit_send_dacs(void)
{
return 0;
}

void audiounit_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
post("device getting not implemented for AudioUnit yet\n");
}

void audiounit_listdevs( void)
{
post("device listing not implemented for AudioUnit yet\n");
}

#endif /* AUDIOUNIT */

+ 37
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_dummy.c View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#ifdef USEAPI_DUMMY

#include <stdio.h>

int dummy_open_audio(int nin, int nout, int sr) {
return 0;
}

int dummy_close_audio( void) {
return 0;
}

int dummy_send_dacs( void) {
return 0;
}

void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist,
int *noutdevs, int *canmulti, int maxndev, int devdescsize) {
sprintf(indevlist, "NONE");
sprintf(outdevlist, "NONE");
*nindevs = *noutdevs = 1;
*canmulti = 0;
}

void dummy_listdevs( void) {
// do nothing
}

#endif


+ 132
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_esd.c View File

@@ -0,0 +1,132 @@
/* Copyright (c) 2006 Guenter Geiger,
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

#ifdef USEAPI_ESD

#include <stdio.h>
#include <string.h> /* memset */
#include <esd.h>
#include "m_pd.h"
#include "s_stuff.h"
#include "m_fixed.h"

/* exported variables */

/* private data */

static int esd_socket_out;
static int esd_channels_out;

static int esd_socket_in;
static int esd_channels_in;


int esd_open_audio(int nindev, int *indev, int nchin, int *chin,
int noutdev, int *outdev, int nchout, int *chout, int rate)
{

esd_format_t format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_PLAY;

indev[0] = 0;
nindev = 1;

outdev[0] = 0;
noutdev = 1;

rate = sys_dacsr = ESD_DEFAULT_RATE;

if (*chout == 2) {
esd_socket_out = esd_play_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd");
if (esd_socket_out <= 0) {
fprintf (stderr, "Error at esd open: %d\n", esd_socket_out);
esd_channels_out = *chout = 0;
return 0;
}
esd_channels_out = *chout = 2;
}

if (*chin == 2) {
esd_socket_in = esd_record_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd-in");
if (esd_socket_in <= 0) {
fprintf (stderr, "Error at esd open: %d\n", esd_socket_in);
esd_channels_in = *chin = 0;
return 0;
}
esd_channels_in = *chin = 2;
}
return (0);
}

void esd_close_audio( void)
{
close(esd_socket_out);
close(esd_socket_in);
}


#define DEFDACBLKSIZE 64
#define MAXCHANS 2

static short buf[DEFDACBLKSIZE*MAXCHANS];

int esd_send_dacs(void)
{
t_sample* fp1,*fp2;
short* sp;
int i,j;

/* Do input */

if (esd_channels_in) {
read(esd_socket_in,buf,DEFDACBLKSIZE*esd_channels_out*2);
for (i = DEFDACBLKSIZE, fp1 = sys_soundin,
sp = (short *)buf; i--; fp1++, sp += esd_channels_in) {
for (j=0, fp2 = fp1; j<esd_channels_in; j++, fp2 += DEFDACBLKSIZE)
{
int s = INVSCALE16(sp[j]);
*fp2 = s;
}
}
}

/* Do output */

if (esd_channels_out) {
for (i = DEFDACBLKSIZE, fp1 = sys_soundout,
sp = (short *)buf; i--; fp1++, sp += esd_channels_out) {
for (j=0, fp2 = fp1; j<esd_channels_out; j++, fp2 += DEFDACBLKSIZE)
{
int s = SCALE16(*fp2);
if (s > 32767) s = 32767;
else if (s < -32767) s = -32767;
sp[j] = s;
}
}

write(esd_socket_out,buf,DEFDACBLKSIZE*esd_channels_out*2);
}

memset(sys_soundin,0,DEFDACBLKSIZE*esd_channels_out*2);
memset(sys_soundout,0,DEFDACBLKSIZE*esd_channels_out*4);

return (SENDDACS_YES);
}

void esd_listdevs( void)
{
post("device listing not implemented for ESD yet\n");
}

void esd_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int i, ndev;
*canmulti = 1; /* supports multiple devices */
sprintf(indevlist, "ESD device");
sprintf(outdevlist, "ESD device");
*nindevs = *noutdevs = 1;
}

#endif

+ 572
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_jack.c View File

@@ -0,0 +1,572 @@
/* Copyright (c) 2003, Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* Audio back-end for connecting with the JACK audio interconnect system.
*/

#ifdef USEAPI_JACK

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "m_pd.h"
#include "s_stuff.h"
#ifdef __APPLE__
#include <jack/weakjack.h>
#endif
#include <jack/jack.h>
#include <regex.h>

#define MAX_CLIENTS 100
#define MAX_JACK_PORTS 128 /* higher values seem to give bad xrun problems */
#define BUF_JACK 4096
#define JACK_OUT_MAX 64

static jack_nframes_t jack_out_max;
static jack_nframes_t jack_filled = 0;
static t_sample *jack_outbuf;
static t_sample *jack_inbuf;
static int jack_started = 0;
static jack_port_t *input_port[MAX_JACK_PORTS];
static jack_port_t *output_port[MAX_JACK_PORTS];
static int outport_count = 0;
static jack_client_t *jack_client = NULL;
static char * desired_client_name = NULL;
char *jack_client_names[MAX_CLIENTS];
static int jack_dio_error;
static t_audiocallback jack_callback;
static int jack_should_autoconnect = 1;
pthread_mutex_t jack_mutex;
pthread_cond_t jack_sem;

static int pollprocess(jack_nframes_t nframes, void *arg)
{
int j;
jack_default_audio_sample_t *out, *in;

pthread_mutex_lock(&jack_mutex);
if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
else jack_out_max = JACK_OUT_MAX;
if (jack_filled >= nframes)
{
if (jack_filled != nframes)
fprintf(stderr,"Partial read\n");
/* hmm, how to find out whether 't_sample' and
'jack_default_audio_sample_t' are actually the same type??? */
if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t))
{
for (j = 0; j < STUFF->st_outchannels; j++)
{
if (out = jack_port_get_buffer(output_port[j], nframes))
memcpy(out, jack_outbuf + (j * BUF_JACK),
sizeof (jack_default_audio_sample_t) * nframes);
}
for (j = 0; j < STUFF->st_inchannels; j++)
{
if (in = jack_port_get_buffer(input_port[j], nframes))
memcpy(jack_inbuf + (j * BUF_JACK), in,
sizeof (jack_default_audio_sample_t) * nframes);
}
}
else
{
unsigned int frame=0;
t_sample*data;
for (j = 0; j < STUFF->st_outchannels; j++)
{
if (out = jack_port_get_buffer (output_port[j], nframes))
{
data = jack_outbuf + (j * BUF_JACK);
for (frame=0; frame<nframes; frame++)
*out++ = *data++;
}
}
for (j = 0; j < STUFF->st_inchannels; j++)
{
if (in = jack_port_get_buffer( input_port[j], nframes))
{
data = jack_inbuf + (j * BUF_JACK);
for (frame=0; frame<nframes; frame++)
*data++ = *in++;
}
}
}
jack_filled -= nframes;
}
else
{ /* PD could not keep up ! */
if (jack_started) jack_dio_error = 1;
for (j = 0; j < outport_count; j++)
{
if (out = jack_port_get_buffer (output_port[j], nframes))
memset(out, 0, sizeof (float) * nframes);
memset(jack_outbuf + j * BUF_JACK, 0, BUF_JACK * sizeof(t_sample));
}
jack_filled = 0;
}
pthread_cond_broadcast(&jack_sem);
pthread_mutex_unlock(&jack_mutex);
return 0;
}

static int callbackprocess(jack_nframes_t nframes, void *arg)
{
int chan, j, k;
unsigned int n;
jack_default_audio_sample_t *out[MAX_JACK_PORTS], *in[MAX_JACK_PORTS], *jp;

if (nframes % DEFDACBLKSIZE)
{
fprintf(stderr, "jack: nframes %d not a multiple of blocksize %d\n",
nframes, DEFDACBLKSIZE);
nframes -= (nframes % DEFDACBLKSIZE);
}
for (chan = 0; chan < STUFF->st_inchannels; chan++)
in[chan] = jack_port_get_buffer(input_port[chan], nframes);
for (chan = 0; chan < STUFF->st_outchannels; chan++)
out[chan] = jack_port_get_buffer(output_port[chan], nframes);
for (n = 0; n < nframes; n += DEFDACBLKSIZE)
{
t_sample *fp;
for (chan = 0; chan < STUFF->st_inchannels; chan++)
if (in[chan])
{
for (fp = STUFF->st_soundin + chan*DEFDACBLKSIZE,
jp = in[chan] + n, j=0; j < DEFDACBLKSIZE; j++)
*fp++ = *jp++;
}
for (chan = 0; chan < STUFF->st_outchannels; chan++)
{
for (fp = STUFF->st_soundout + chan*DEFDACBLKSIZE,
j = 0; j < DEFDACBLKSIZE; j++)
*fp++ = 0;
}
(*jack_callback)();
for (chan = 0; chan < STUFF->st_outchannels; chan++)
if (out[chan])
{
for (fp = STUFF->st_soundout + chan*DEFDACBLKSIZE, jp = out[chan] + n,
j=0; j < DEFDACBLKSIZE; j++)
*jp++ = *fp++;
}
}
return 0;
}

static int
jack_srate (jack_nframes_t srate, void *arg)
{
STUFF->st_dacsr = srate;
return 0;
}


void glob_audio_setapi(void *dummy, t_floatarg f);

static void
jack_shutdown (void *arg)
{
error("JACK: server shut down");

jack_deactivate (jack_client);
//jack_client_close(jack_client); /* likely to hang if the server shut down */
jack_client = NULL;

glob_audio_setapi(NULL, API_NONE); // set pd_whichapi 0
}

static int jack_xrun(void* arg) {
jack_dio_error = 1;
return 0;
}


static char** jack_get_clients(void)
{
const char **jack_ports;
int i,j;
int num_clients = 0;
regex_t port_regex;
jack_ports = jack_get_ports( jack_client, "", "", 0 );
regcomp( &port_regex, "^[^:]*", REG_EXTENDED );

jack_client_names[0] = NULL;

/* Build a list of clients from the list of ports */
for( i = 0; jack_ports[i] != NULL; i++ )
{
int client_seen;
regmatch_t match_info;
char tmp_client_name[100];

if(num_clients>=MAX_CLIENTS)break;


/* extract the client name from the port name, using a regex
* that parses the clientname:portname syntax */
regexec( &port_regex, jack_ports[i], 1, &match_info, 0 );
memcpy( tmp_client_name, &jack_ports[i][match_info.rm_so],
match_info.rm_eo - match_info.rm_so );
tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0';

/* do we know about this port's client yet? */
client_seen = 0;

for( j = 0; j < num_clients; j++ )
if( strcmp( tmp_client_name, jack_client_names[j] ) == 0 )
client_seen = 1;

if( client_seen == 0 )
{
jack_client_names[num_clients] = (char*)getbytes(strlen(tmp_client_name) + 1);

/* The alsa_pcm client should go in spot 0. If this
* is the alsa_pcm client AND we are NOT about to put
* it in spot 0 put it in spot 0 and move whatever
* was already in spot 0 to the end. */

if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 )
{
char* tmp;
/* alsa_pcm goes in spot 0 */
tmp = jack_client_names[ num_clients ];
jack_client_names[ num_clients ] = jack_client_names[0];
jack_client_names[0] = tmp;
strcpy( jack_client_names[0], tmp_client_name);
}
else
{
/* put the new client at the end of the client list */
strcpy( jack_client_names[ num_clients ], tmp_client_name );
}
num_clients++;
}
}

/* for (i=0;i<num_clients;i++) post("client: %s",jack_client_names[i]); */

free( jack_ports );
return jack_client_names;
}

/*
* Wire up all the ports of one client.
*
*/

static int jack_connect_ports(char* client)
{
char regex_pattern[100]; /* its always the same, ... */
int i;
const char **jack_ports;

if (strlen(client) > 96) return -1;

sprintf( regex_pattern, "%s:.*", client );

jack_ports = jack_get_ports( jack_client, regex_pattern,
NULL, JackPortIsOutput);
if (jack_ports)
{
for (i=0;jack_ports[i] != NULL && i < STUFF->st_inchannels;i++)
if (jack_connect (jack_client, jack_ports[i],
jack_port_name (input_port[i])))
error ("JACK: cannot connect input ports %s -> %s",
jack_ports[i],jack_port_name (input_port[i]));
free(jack_ports);
}
jack_ports = jack_get_ports( jack_client, regex_pattern,
NULL, JackPortIsInput);
if (jack_ports)
{
for (i=0;jack_ports[i] != NULL && i < STUFF->st_outchannels;i++)
if (jack_connect (jack_client, jack_port_name (output_port[i]),
jack_ports[i]))
error( "JACK: cannot connect output ports %s -> %s",
jack_port_name (output_port[i]),jack_ports[i]);

free(jack_ports);
}
return 0;
}


static void pd_jack_error_callback(const char *desc) {
error("JACKerror: %s", desc);
return;
}

int
jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback)
{
int j;
char port_name[80] = "";
char client_name[80] = "";

int client_iterator = 0;
int new_jack = 0;
int srate;
jack_status_t status;

if (!jack_client_open)
{
error("Can't open Jack (it seems not to be installed)");
return 1;
}

jack_dio_error = 0;

if ((inchans == 0) && (outchans == 0)) return 0;

if (outchans > MAX_JACK_PORTS) {
error("JACK: %d output ports not supported, setting to %d",
outchans, MAX_JACK_PORTS);
outchans = MAX_JACK_PORTS;
}

if (inchans > MAX_JACK_PORTS) {
error("JACK: %d input ports not supported, setting to %d",
inchans, MAX_JACK_PORTS);
inchans = MAX_JACK_PORTS;
}

/* try to become a client of the JACK server. (If no JACK server exists,
jack_client_open() will start uone up by default. It's not clear
whether or not this is desirable; see long Pd list thread started by
yvan volochine, June 2013) */
if (!jack_client) {
if (!desired_client_name || !strlen(desired_client_name))
jack_client_name("pure_data");
jack_client = jack_client_open (desired_client_name, JackNoStartServer,
&status, NULL);
if (status & JackFailure) {
error("JACK: Failure. Is JACK running?");
verbose(1, "JACK: Returned status is: %d", status);
jack_client=NULL;
/* jack spits out enough messages already, do not warn */
STUFF->st_inchannels = STUFF->st_outchannels = 0;
return 1;
}
if (status & JackNameNotUnique)
jack_client_name(jack_get_client_name(jack_client));
verbose(1, "JACK: registered as '%s'", desired_client_name);

STUFF->st_inchannels = inchans;
STUFF->st_outchannels = outchans;
if (jack_inbuf)
free(jack_inbuf);
if (STUFF->st_inchannels)
jack_inbuf = calloc(sizeof(t_sample), STUFF->st_inchannels * BUF_JACK);
if (jack_outbuf)
free(jack_outbuf);
if (STUFF->st_outchannels)
jack_outbuf = calloc(sizeof(t_sample), STUFF->st_outchannels * BUF_JACK);

jack_get_clients();

/* set JACK callback functions */

jack_callback = callback;
jack_set_process_callback(jack_client,
(callback? callbackprocess : pollprocess), 0);

jack_set_error_function (pd_jack_error_callback);

#ifdef JACK_XRUN
jack_set_xrun_callback (jack_client, jack_xrun, NULL);
#endif

/* tell the JACK server to call `srate()' whenever
the sample rate of the system changes.
*/

jack_set_sample_rate_callback (jack_client, jack_srate, 0);


/* tell the JACK server to call `jack_shutdown()' if
it ever shuts down, either entirely, or if it
just decides to stop calling us.
*/

jack_on_shutdown (jack_client, jack_shutdown, 0);

for (j=0; j<STUFF->st_inchannels; j++)
input_port[j]=NULL;
for (j=0; j<STUFF->st_outchannels; j++)
output_port[j] = NULL;

new_jack = 1;
}

/* display the current sample rate. once the client is activated
(see below), you should rely on your own sample rate
callback (see above) for this value.
*/

srate = jack_get_sample_rate (jack_client);
STUFF->st_dacsr = srate;

/* create the ports */

for (j = 0; j < inchans; j++)
{
sprintf(port_name, "input%d", j);
if (!input_port[j]) input_port[j] = jack_port_register (jack_client,
port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
if (!input_port[j])
{
error("JACK: can only register %d input ports (of %d requested)",
j, inchans);
STUFF->st_inchannels = inchans = j;
break;
}
}

for (j = 0; j < outchans; j++)
{
sprintf(port_name, "output%d", j);
if (!output_port[j]) output_port[j] = jack_port_register (jack_client,
port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
if (!output_port[j])
{
error("JACK: can only register %d output ports (of %d requested)",
j, outchans);
STUFF->st_outchannels = outchans = j;
break;
}
}
outport_count = outchans;

/* tell the JACK server that we are ready to roll */

if (new_jack)
{
if (jack_activate (jack_client)) {
error("cannot activate client");
STUFF->st_inchannels = STUFF->st_outchannels = 0;
return 1;
}

for (j = 0; j < outchans; j++)
memset(jack_outbuf + j * BUF_JACK, 0,
BUF_JACK * sizeof(t_sample));

if (jack_client_names[0] && jack_should_autoconnect)
jack_connect_ports(jack_client_names[0]);

pthread_mutex_init(&jack_mutex, NULL);
pthread_cond_init(&jack_sem, NULL);
}
return 0;
}

void jack_close_audio(void)
{
if (jack_client){
jack_deactivate (jack_client);
jack_client_close(jack_client);
}

jack_client=NULL;
jack_started = 0;

pthread_cond_broadcast(&jack_sem);

pthread_cond_destroy(&jack_sem);
pthread_mutex_destroy(&jack_mutex);
if (jack_inbuf)
free(jack_inbuf), jack_inbuf = 0;
if (jack_outbuf)
free(jack_outbuf), jack_outbuf = 0;

}

int jack_send_dacs(void)
{
t_sample * fp;
int j;
int rtnval = SENDDACS_YES;
int timenow;
int timeref = sys_getrealtime();
if (!jack_client) return SENDDACS_NO;
if (!STUFF->st_inchannels && !STUFF->st_outchannels) return (SENDDACS_NO);
if (jack_dio_error)
{
sys_log_error(ERR_RESYNC);
jack_dio_error = 0;
}
pthread_mutex_lock(&jack_mutex);
if (jack_filled >= jack_out_max)
pthread_cond_wait(&jack_sem,&jack_mutex);

if (!jack_client)
{
pthread_mutex_unlock(&jack_mutex);
return SENDDACS_NO;
}
jack_started = 1;

fp = STUFF->st_soundout;
for (j = 0; j < STUFF->st_outchannels; j++)
{
memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp,
DEFDACBLKSIZE*sizeof(t_sample));
fp += DEFDACBLKSIZE;
}
fp = STUFF->st_soundin;
for (j = 0; j < STUFF->st_inchannels; j++)
{
memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled,
DEFDACBLKSIZE*sizeof(t_sample));
fp += DEFDACBLKSIZE;
}
jack_filled += DEFDACBLKSIZE;
pthread_mutex_unlock(&jack_mutex);

if ((timenow = sys_getrealtime()) - timeref > 0.002)
{
rtnval = SENDDACS_SLEPT;
}
memset(STUFF->st_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*STUFF->st_outchannels);
return rtnval;
}

void jack_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int i, ndev;
*canmulti = 0; /* supports multiple devices */
ndev = 1;
for (i = 0; i < ndev; i++)
{
sprintf(indevlist + i * devdescsize, "JACK");
sprintf(outdevlist + i * devdescsize, "JACK");
}
*nindevs = *noutdevs = ndev;
}

void jack_listdevs( void)
{
post("device listing not implemented for jack yet\n");
}

void jack_autoconnect(int v)
{
jack_should_autoconnect = v;
}

void jack_client_name(char *name)
{
if (desired_client_name) {
free(desired_client_name);
desired_client_name = NULL;
}
if (name) {
desired_client_name = (char*)getbytes(strlen(name) + 1);
strcpy(desired_client_name, name);
}
}

#endif /* JACK */

+ 794
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_mmio.c View File

@@ -0,0 +1,794 @@
/* 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. */

/* modified 2/98 by Winfried Ritsch to deal with up to 4 synchronized
"wave" devices, which is how ADAT boards appear to the WAVE API. */

#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>

#include <windows.h>

#include <mmsystem.h>

/* ------------------------- audio -------------------------- */

static void nt_close_midiin(void);
static void nt_noresync( void);

static void postflags(void);

#define NAPORTS 16 /* wini hack for multiple ADDA devices */
#define CHANNELS_PER_DEVICE 2
#define DEFAULTCHANS 2
#define DEFAULTSRATE 44100
#define SAMPSIZE 2

int nt_realdacblksize;
#define DEFREALDACBLKSIZE (4 * DEFDACBLKSIZE) /* larger underlying bufsize */

#define MAXBUFFER 100 /* number of buffers in use at maximum advance */
#define DEFBUFFER 30 /* default is about 30x6 = 180 msec! */
static int nt_naudiobuffer = DEFBUFFER;

static int nt_whichapi = API_MMIO;
static int nt_meters; /* true if we're metering */
static float nt_inmax; /* max input amplitude */
static float nt_outmax; /* max output amplitude */
static int nt_nwavein, nt_nwaveout; /* number of WAVE devices in and out */

typedef struct _sbuf
{
HANDLE hData;
HPSTR lpData; // pointer to waveform data memory
HANDLE hWaveHdr;
WAVEHDR *lpWaveHdr; // pointer to header structure
} t_sbuf;

t_sbuf ntsnd_outvec[NAPORTS][MAXBUFFER]; /* circular buffer array */
HWAVEOUT ntsnd_outdev[NAPORTS]; /* output device */
static int ntsnd_outphase[NAPORTS]; /* index of next buffer to send */

t_sbuf ntsnd_invec[NAPORTS][MAXBUFFER]; /* circular buffer array */
HWAVEIN ntsnd_indev[NAPORTS]; /* input device */
static int ntsnd_inphase[NAPORTS]; /* index of next buffer to read */

static void nt_waveinerror(char *s, int err)
{
char t[256];
waveInGetErrorText(err, t, 256);
fprintf(stderr, s, t);
}

static void nt_waveouterror(char *s, int err)
{
char t[256];
waveOutGetErrorText(err, t, 256);
fprintf(stderr, s, t);
}

static void wave_prep(t_sbuf *bp, int setdone)
{
WAVEHDR *wh;
short *sp;
int i;
/*
* Allocate and lock memory for the waveform data. The memory
* for waveform data must be globally allocated with
* GMEM_MOVEABLE and GMEM_SHARE flags.
*/

if (!(bp->hData =
GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
(DWORD) (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize))))
printf("alloc 1 failed\n");

if (!(bp->lpData =
(HPSTR) GlobalLock(bp->hData)))
printf("lock 1 failed\n");

/* Allocate and lock memory for the header. */

if (!(bp->hWaveHdr =
GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof(WAVEHDR))))
printf("alloc 2 failed\n");

if (!(wh = bp->lpWaveHdr =
(WAVEHDR *) GlobalLock(bp->hWaveHdr)))
printf("lock 2 failed\n");

for (i = CHANNELS_PER_DEVICE * nt_realdacblksize,
sp = (short *)bp->lpData; i--; )
*sp++ = 0;

wh->lpData = bp->lpData;
wh->dwBufferLength = (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize);
wh->dwFlags = 0;
wh->dwLoops = 0L;
wh->lpNext = 0;
wh->reserved = 0;
/* optionally (for writing) set DONE flag as if we had queued them */
if (setdone)
wh->dwFlags = WHDR_DONE;
}

static UINT nt_whichdac = WAVE_MAPPER, nt_whichadc = WAVE_MAPPER;

int mmio_do_open_audio(void)
{
PCMWAVEFORMAT form;
int i, j;
UINT mmresult;
int nad, nda;
static int naudioprepped = 0, nindevsprepped = 0, noutdevsprepped = 0;
if (sys_verbose)
post("%d devices in, %d devices out",
nt_nwavein, nt_nwaveout);

form.wf.wFormatTag = WAVE_FORMAT_PCM;
form.wf.nChannels = CHANNELS_PER_DEVICE;
form.wf.nSamplesPerSec = STUFF->st_dacsr;
form.wf.nAvgBytesPerSec = STUFF->st_dacsr * (CHANNELS_PER_DEVICE * SAMPSIZE);
form.wf.nBlockAlign = CHANNELS_PER_DEVICE * SAMPSIZE;
form.wBitsPerSample = 8 * SAMPSIZE;

if (nt_nwavein <= 1 && nt_nwaveout <= 1)
nt_noresync();

if (nindevsprepped < nt_nwavein)
{
for (i = nindevsprepped; i < nt_nwavein; i++)
for (j = 0; j < naudioprepped; j++)
wave_prep(&ntsnd_invec[i][j], 0);
nindevsprepped = nt_nwavein;
}
if (noutdevsprepped < nt_nwaveout)
{
for (i = noutdevsprepped; i < nt_nwaveout; i++)
for (j = 0; j < naudioprepped; j++)
wave_prep(&ntsnd_outvec[i][j], 1);
noutdevsprepped = nt_nwaveout;
}
if (naudioprepped < nt_naudiobuffer)
{
for (j = naudioprepped; j < nt_naudiobuffer; j++)
{
for (i = 0; i < nt_nwavein; i++)
wave_prep(&ntsnd_invec[i][j], 0);
for (i = 0; i < nt_nwaveout; i++)
wave_prep(&ntsnd_outvec[i][j], 1);
}
naudioprepped = nt_naudiobuffer;
}
for (nad=0; nad < nt_nwavein; nad++)
{
/* Open waveform device(s), sucessively numbered, for input */

mmresult = waveInOpen(&ntsnd_indev[nad], nt_whichadc+nad,
(WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL);

if (sys_verbose)
printf("opened adc device %d with return %d\n",
nt_whichadc+nad,mmresult);

if (mmresult != MMSYSERR_NOERROR)
{
nt_waveinerror("waveInOpen: %s\n", mmresult);
nt_nwavein = nad; /* nt_nwavein = 0 wini */
}
else
{
for (i = 0; i < nt_naudiobuffer; i++)
{
mmresult = waveInPrepareHeader(ntsnd_indev[nad],
ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveinprepareheader: %s\n", mmresult);
mmresult = waveInAddBuffer(ntsnd_indev[nad],
ntsnd_invec[nad][i].lpWaveHdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
}
}
}
/* quickly start them all together */
for (nad = 0; nad < nt_nwavein; nad++)
waveInStart(ntsnd_indev[nad]);

for (nda = 0; nda < nt_nwaveout; nda++)
{
/* Open a waveform device for output in sucessiv device numbering*/
mmresult = waveOutOpen(&ntsnd_outdev[nda], nt_whichdac + nda,
(WAVEFORMATEX *)(&form), 0L, 0L, CALLBACK_NULL);

if (sys_verbose)
fprintf(stderr,"opened dac device %d, with return %d\n",
nt_whichdac +nda, mmresult);

if (mmresult != MMSYSERR_NOERROR)
{
fprintf(stderr,"Wave out open device %d + %d\n",nt_whichdac,nda);
nt_waveouterror("waveOutOpen device: %s\n", mmresult);
nt_nwaveout = nda;
}
}

return (0);
}

void mmio_close_audio( void)
{
int errcode;
int nda, nad;
if (sys_verbose)
post("closing audio...");

for (nda=0; nda < nt_nwaveout; nda++) /*if (nt_nwaveout) wini */
{
errcode = waveOutReset(ntsnd_outdev[nda]);
if (errcode != MMSYSERR_NOERROR)
printf("error resetting output %d: %d\n", nda, errcode);
errcode = waveOutClose(ntsnd_outdev[nda]);
if (errcode != MMSYSERR_NOERROR)
printf("error closing output %d: %d\n",nda , errcode);
}
nt_nwaveout = 0;

for(nad=0; nad < nt_nwavein;nad++) /* if (nt_nwavein) wini */
{
errcode = waveInReset(ntsnd_indev[nad]);
if (errcode != MMSYSERR_NOERROR)
printf("error resetting input: %d\n", errcode);
errcode = waveInClose(ntsnd_indev[nad]);
if (errcode != MMSYSERR_NOERROR)
printf("error closing input: %d\n", errcode);
}
nt_nwavein = 0;
}


#define ADCJITTER 10 /* We tolerate X buffers of jitter by default */
#define DACJITTER 10

static int nt_adcjitterbufsallowed = ADCJITTER;
static int nt_dacjitterbufsallowed = DACJITTER;

/* ------------- MIDI time stamping from audio clock ------------ */

#ifdef MIDI_TIMESTAMP

static double nt_hibuftime;
static double initsystime = -1;

/* call this whenever we reset audio */
static void nt_resetmidisync(void)
{
initsystime = clock_getsystime();
nt_hibuftime = sys_getrealtime();
}

/* call this whenever we're idled waiting for audio to be ready.
The routine maintains a high and low water point for the difference
between real and DAC time. */

static void nt_midisync(void)
{
double jittersec, diff;

if (initsystime == -1) nt_resetmidisync();
jittersec = (nt_dacjitterbufsallowed > nt_adcjitterbufsallowed ?
nt_dacjitterbufsallowed : nt_adcjitterbufsallowed)
* nt_realdacblksize / STUFF->st_getsr();
diff = sys_getrealtime() - 0.001 * clock_gettimesince(initsystime);
if (diff > nt_hibuftime) nt_hibuftime = diff;
if (diff < nt_hibuftime - jittersec)
{
post("jitter excess %d %f", dac, diff);
nt_resetmidisync();
}
}

static double nt_midigettimefor(LARGE_INTEGER timestamp)
{
/* this is broken now... used to work when "timestamp" was derived from
QueryPerformanceCounter() instead of the gates approved
timeGetSystemTime() call in the MIDI callback routine below. */
return (nt_tixtotime(timestamp) - nt_hibuftime);
}
#endif /* MIDI_TIMESTAMP */


static int nt_fill = 0;
#define WRAPFWD(x) ((x) >= nt_naudiobuffer ? (x) - nt_naudiobuffer: (x))
#define WRAPBACK(x) ((x) < 0 ? (x) + nt_naudiobuffer: (x))
#define MAXRESYNC 500

#if 0 /* this is used for debugging */
static void nt_printaudiostatus(void)
{
int nad, nda;
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0;
int firstphasedone = -1, firstphasebusy = -1;
for (count = 0; count < nt_naudiobuffer; count++)
{
int donethis =
(ntsnd_invec[nad][phase2].lpWaveHdr->dwFlags & WHDR_DONE);
int donenext =
(ntsnd_invec[nad][phase3].lpWaveHdr->dwFlags & WHDR_DONE);
if (donethis && !donenext)
{
if (firstphasebusy >= 0) goto multipleadc;
firstphasebusy = count;
}
if (!donethis && donenext)
{
if (firstphasedone >= 0) goto multipleadc;
firstphasedone = count;
}
phase2 = phase3;
phase3 = WRAPFWD(phase2 + 1);
}
post("nad %d phase %d busy %d done %d", nad, phase, firstphasebusy,
firstphasedone);
continue;
multipleadc:
startpost("nad %d phase %d: oops:", nad, phase);
for (count = 0; count < nt_naudiobuffer; count++)
{
char buf[80];
sprintf(buf, " %d",
(ntsnd_invec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE));
poststring(buf);
}
endpost();
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nad];
int phase2 = phase, phase3 = WRAPFWD(phase2), count, ntrans = 0;
int firstphasedone = -1, firstphasebusy = -1;
for (count = 0; count < nt_naudiobuffer; count++)
{
int donethis =
(ntsnd_outvec[nda][phase2].lpWaveHdr->dwFlags & WHDR_DONE);
int donenext =
(ntsnd_outvec[nda][phase3].lpWaveHdr->dwFlags & WHDR_DONE);
if (donethis && !donenext)
{
if (firstphasebusy >= 0) goto multipledac;
firstphasebusy = count;
}
if (!donethis && donenext)
{
if (firstphasedone >= 0) goto multipledac;
firstphasedone = count;
}
phase2 = phase3;
phase3 = WRAPFWD(phase2 + 1);
}
if (firstphasebusy < 0) post("nda %d phase %d all %d",
nda, phase, (ntsnd_outvec[nad][0].lpWaveHdr->dwFlags & WHDR_DONE));
else post("nda %d phase %d busy %d done %d", nda, phase, firstphasebusy,
firstphasedone);
continue;
multipledac:
startpost("nda %d phase %d: oops:", nda, phase);
for (count = 0; count < nt_naudiobuffer; count++)
{
char buf[80];
sprintf(buf, " %d",
(ntsnd_outvec[nad][count].lpWaveHdr->dwFlags & WHDR_DONE));
poststring(buf);
}
endpost();
}
}
#endif /* 0 */

/* this is a hack to avoid ever resyncing audio pointers in case for whatever
reason the sync testing below gives false positives. */

static int nt_resync_cancelled;

static void nt_noresync( void)
{
nt_resync_cancelled = 1;
}

static void nt_resyncaudio(void)
{
UINT mmresult;
int nad, nda, count;
if (nt_resync_cancelled)
return;
/* for each open input device, eat all buffers which are marked
ready. The next one will thus be "busy". */
post("resyncing audio");
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
for (count = 0; count < MAXRESYNC; count++)
{
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
if (!(inwavehdr->dwFlags & WHDR_DONE)) break;
if (inwavehdr->dwFlags & WHDR_PREPARED)
waveInUnprepareHeader(ntsnd_indev[nad],
inwavehdr, sizeof(WAVEHDR));
inwavehdr->dwFlags = 0L;
waveInPrepareHeader(ntsnd_indev[nad], inwavehdr, sizeof(WAVEHDR));
mmresult = waveInAddBuffer(ntsnd_indev[nad], inwavehdr,
sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
ntsnd_inphase[nad] = phase = WRAPFWD(phase + 1);
}
if (count == MAXRESYNC) post("resync error 1");
}
/* Each output buffer which is "ready" is filled with zeros and
queued. */
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
for (count = 0; count < MAXRESYNC; count++)
{
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
if (!(outwavehdr->dwFlags & WHDR_DONE)) break;
if (outwavehdr->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(ntsnd_outdev[nda],
outwavehdr, sizeof(WAVEHDR));
outwavehdr->dwFlags = 0L;
memset((char *)(ntsnd_outvec[nda][phase].lpData),
0, (CHANNELS_PER_DEVICE * SAMPSIZE * nt_realdacblksize));
waveOutPrepareHeader(ntsnd_outdev[nda], outwavehdr,
sizeof(WAVEHDR));
mmresult = waveOutWrite(ntsnd_outdev[nda], outwavehdr,
sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveouterror("waveOutAddBuffer: %s\n", mmresult);
ntsnd_outphase[nda] = phase = WRAPFWD(phase + 1);
}
if (count == MAXRESYNC) post("resync error 2");
}

#ifdef MIDI_TIMESTAMP
nt_resetmidisync();
#endif

}

#define LATE 0
#define RESYNC 1
#define NOTHING 2
static int nt_errorcount;
static int nt_resynccount;
static double nt_nextreporttime = -1;

void nt_logerror(int which)
{
#if 0
post("error %d %d", count, which);
if (which < NOTHING) nt_errorcount++;
if (which == RESYNC) nt_resynccount++;
if (sys_getrealtime() > nt_nextreporttime)
{
post("%d audio I/O error%s", nt_errorcount,
(nt_errorcount > 1 ? "s" : ""));
if (nt_resynccount) post("DAC/ADC sync error");
nt_errorcount = nt_resynccount = 0;
nt_nextreporttime = sys_getrealtime() - 5;
}
#endif
}

/* system buffer with t_sample types for one tick */

int mmio_send_dacs(void)
{
HMMIO hmmio;
UINT mmresult;
HANDLE hFormat;
int i, j;
short *sp1, *sp2;
float *fp1, *fp2;
int nextfill, doxfer = 0;
int nda, nad;
if (!nt_nwavein && !nt_nwaveout) return (0);


if (nt_meters)
{
int i, n;
float maxsamp;
for (i = 0, n = 2 * nt_nwavein * DEFDACBLKSIZE, maxsamp = nt_inmax;
i < n; i++)
{
float f = STUFF->st_soundin[i];
if (f > maxsamp) maxsamp = f;
else if (-f > maxsamp) maxsamp = -f;
}
nt_inmax = maxsamp;
for (i = 0, n = 2 * nt_nwaveout * DEFDACBLKSIZE, maxsamp = nt_outmax;
i < n; i++)
{
float f = STUFF->st_soundout[i];
if (f > maxsamp) maxsamp = f;
else if (-f > maxsamp) maxsamp = -f;
}
nt_outmax = maxsamp;
}

/* the "fill pointer" nt_fill controls where in the next
I/O buffers we will write and/or read. If it's zero, we
first check whether the buffers are marked "done". */

if (!nt_fill)
{
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
if (!(inwavehdr->dwFlags & WHDR_DONE)) goto idle;
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
WAVEHDR *outwavehdr =
ntsnd_outvec[nda][phase].lpWaveHdr;
if (!(outwavehdr->dwFlags & WHDR_DONE)) goto idle;
}
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
WAVEHDR *inwavehdr =
ntsnd_invec[nad][phase].lpWaveHdr;
if (inwavehdr->dwFlags & WHDR_PREPARED)
waveInUnprepareHeader(ntsnd_indev[nad],
inwavehdr, sizeof(WAVEHDR));
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
if (outwavehdr->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(ntsnd_outdev[nda],
outwavehdr, sizeof(WAVEHDR));
}
}

/* Convert audio output to fixed-point and put it in the output
buffer. */
for (nda = 0, fp1 = STUFF->st_soundout; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];

for (i = 0, sp1 = (short *)(ntsnd_outvec[nda][phase].lpData) +
CHANNELS_PER_DEVICE * nt_fill;
i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
{
for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
{
int x1 = 32767.f * *fp2;
if (x1 > 32767) x1 = 32767;
else if (x1 < -32767) x1 = -32767;
*sp2 = x1;
}
}
}
memset(STUFF->st_soundout, 0,
(DEFDACBLKSIZE *sizeof(t_sample)*CHANNELS_PER_DEVICE)*nt_nwaveout);

/* vice versa for the input buffer */

for (nad = 0, fp1 = STUFF->st_soundin; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];

for (i = 0, sp1 = (short *)(ntsnd_invec[nad][phase].lpData) +
CHANNELS_PER_DEVICE * nt_fill;
i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
{
for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
{
*fp2 = ((float)(1./32767.)) * (float)(*sp2);
}
}
}

nt_fill = nt_fill + DEFDACBLKSIZE;
if (nt_fill == nt_realdacblksize)
{
nt_fill = 0;

for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
HWAVEIN device = ntsnd_indev[nad];
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
waveInPrepareHeader(device, inwavehdr, sizeof(WAVEHDR));
mmresult = waveInAddBuffer(device, inwavehdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
ntsnd_inphase[nad] = WRAPFWD(phase + 1);
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
HWAVEOUT device = ntsnd_outdev[nda];
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
waveOutPrepareHeader(device, outwavehdr, sizeof(WAVEHDR));
mmresult = waveOutWrite(device, outwavehdr, sizeof(WAVEHDR));
if (mmresult != MMSYSERR_NOERROR)
nt_waveouterror("waveOutWrite: %s\n", mmresult);
ntsnd_outphase[nda] = WRAPFWD(phase + 1);
}

/* check for DAC underflow or ADC overflow. */
for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = WRAPBACK(ntsnd_inphase[nad] - 2);
WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
if (inwavehdr->dwFlags & WHDR_DONE) goto late;
}
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = WRAPBACK(ntsnd_outphase[nda] - 2);
WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
if (outwavehdr->dwFlags & WHDR_DONE) goto late;
}
}
return (1);

late:

nt_logerror(LATE);
nt_resyncaudio();
return (1);

idle:

/* If more than nt_adcjitterbufsallowed ADC buffers are ready
on any input device, resynchronize */

for (nad = 0; nad < nt_nwavein; nad++)
{
int phase = ntsnd_inphase[nad];
WAVEHDR *inwavehdr =
ntsnd_invec[nad]
[WRAPFWD(phase + nt_adcjitterbufsallowed)].lpWaveHdr;
if (inwavehdr->dwFlags & WHDR_DONE)
{
nt_resyncaudio();
return (0);
}
}

/* test dac sync the same way */
for (nda = 0; nda < nt_nwaveout; nda++)
{
int phase = ntsnd_outphase[nda];
WAVEHDR *outwavehdr =
ntsnd_outvec[nda]
[WRAPFWD(phase + nt_dacjitterbufsallowed)].lpWaveHdr;
if (outwavehdr->dwFlags & WHDR_DONE)
{
nt_resyncaudio();
return (0);
}
}
#ifdef MIDI_TIMESTAMP
nt_midisync();
#endif
return (0);
}

/* ------------------- public routines -------------------------- */

int mmio_open_audio(int naudioindev, int *audioindev,
int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
int nchoutdev, int *choutdev, int rate, int blocksize)
{
int nbuf;

nt_realdacblksize = (blocksize ? blocksize : DEFREALDACBLKSIZE);
nbuf = sys_advance_samples/nt_realdacblksize;
if (nbuf >= MAXBUFFER)
{
fprintf(stderr, "pd: audio buffering maxed out to %d\n",
(int)(MAXBUFFER * ((nt_realdacblksize * 1000.)/44100.)));
nbuf = MAXBUFFER;
}
else if (nbuf < 4) nbuf = 4;
/* fprintf(stderr, "%d audio buffers\n", nbuf); */
nt_naudiobuffer = nbuf;
if (nt_adcjitterbufsallowed > nbuf - 2)
nt_adcjitterbufsallowed = nbuf - 2;
if (nt_dacjitterbufsallowed > nbuf - 2)
nt_dacjitterbufsallowed = nbuf - 2;

nt_nwavein = STUFF->st_inchannels / 2;
nt_nwaveout = STUFF->st_outchannels / 2;
nt_whichadc = (naudioindev < 1 ?
(nt_nwavein > 1 ? WAVE_MAPPER : -1) : audioindev[0]);
nt_whichdac = (naudiooutdev < 1 ?
(nt_nwaveout > 1 ? WAVE_MAPPER : -1) : audiooutdev[0]);
if (naudiooutdev > 1 || naudioindev > 1)
post("separate audio device choice not supported; using sequential devices.");
return (mmio_do_open_audio());
}


void mmio_reportidle(void)
{
}

#if 0
/* list the audio and MIDI device names */
void mmio_listdevs(void)
{
UINT wRtn, ndevices;
unsigned int i;

ndevices = waveInGetNumDevs();
for (i = 0; i < ndevices; i++)
{
WAVEINCAPS wicap;
wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap,
sizeof(wicap));
if (wRtn) nt_waveinerror("waveInGetDevCaps: %s\n", wRtn);
else fprintf(stderr,
"audio input device #%d: %s\n", i+1, wicap.szPname);
}

ndevices = waveOutGetNumDevs();
for (i = 0; i < ndevices; i++)
{
WAVEOUTCAPS wocap;
wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap,
sizeof(wocap));
if (wRtn) nt_waveouterror("waveOutGetDevCaps: %s\n", wRtn);
else fprintf(stderr,
"audio output device #%d: %s\n", i+1, wocap.szPname);
}
}
#endif

void mmio_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int wRtn, ndev, i;

*canmulti = 2; /* supports multiple devices */
ndev = waveInGetNumDevs();
if (ndev > maxndev)
ndev = maxndev;
*nindevs = ndev;
for (i = 0; i < ndev; i++)
{
WAVEINCAPS wicap;
wRtn = waveInGetDevCaps(i, (LPWAVEINCAPS) &wicap, sizeof(wicap));
_snprintf(indevlist + i * devdescsize, devdescsize, "%s",
(wRtn ? "???" : wicap.szPname));
outdevlist[(i+1) * devdescsize - 1] = 0;
}

ndev = waveOutGetNumDevs();
if (ndev > maxndev)
ndev = maxndev;
*noutdevs = ndev;
for (i = 0; i < ndev; i++)
{
WAVEOUTCAPS wocap;
wRtn = waveOutGetDevCaps(i, (LPWAVEOUTCAPS) &wocap, sizeof(wocap));
_snprintf(outdevlist + i * devdescsize, devdescsize, "%s",
(wRtn ? "???" : wocap.szPname));
outdevlist[(i+1) * devdescsize - 1] = 0;
}
}

+ 795
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_oss.c View File

@@ -0,0 +1,795 @@
/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
* Winfried Ritsch, Karl MacMillan, and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* this file inputs and outputs audio using the OSS API available on linux. */

#include <sys/soundcard.h>

#ifndef SNDCTL_DSP_GETISPACE
#define SNDCTL_DSP_GETISPACE SOUND_PCM_GETISPACE
#endif
#ifndef SNDCTL_DSP_GETOSPACE
#define SNDCTL_DSP_GETOSPACE SOUND_PCM_GETOSPACE
#endif

#include "m_pd.h"
#include "s_stuff.h"
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mman.h>


/* Defines */
#define DEBUG(x) x
#define DEBUG2(x) {x;}

#define OSS_MAXCHPERDEV 32 /* max channels per OSS device */
#define OSS_MAXDEV 4 /* maximum number of input or output devices */
#define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */
#define OSS_DEFAUDIOBUF 40000 /* default audiobuffer, microseconds */
#define OSS_DEFAULTCH 2
#define RME_DEFAULTCH 8 /* need this even if RME undefined */
typedef int16_t t_oss_int16;
typedef int32_t t_oss_int32;
#define OSS_MAXSAMPLEWIDTH sizeof(t_oss_int32)
#define OSS_BYTESPERCHAN(width) (DEFDACBLKSIZE * (width))
#define OSS_XFERSAMPS(chans) (DEFDACBLKSIZE* (chans))
#define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))

/* GLOBALS */
static int linux_meters; /* true if we're metering */
static t_sample linux_inmax; /* max input amplitude */
static t_sample linux_outmax; /* max output amplitude */
static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
extern int audio_blocksize; /* stolen from s_audio.c */
/* our device handles */

typedef struct _oss_dev
{
int d_fd;
unsigned int d_space; /* bytes available for writing/reading */
int d_bufsize; /* total buffer size in blocks for this device */
int d_dropcount; /* # of buffers to drop for resync (output only) */
unsigned int d_nchannels; /* number of channels for this device */
unsigned int d_bytespersamp; /* bytes per sample (2 for 16 bit, 4 for 32) */
} t_oss_dev;

static t_oss_dev linux_dacs[OSS_MAXDEV];
static t_oss_dev linux_adcs[OSS_MAXDEV];
static int linux_noutdevs = 0;
static int linux_nindevs = 0;

/* OSS-specific private variables */
static int oss_blockmode = 1; /* flag to use "blockmode" */
static char ossdsp[] = "/dev/dsp%d";

/* don't assume we can turn all 31 bits when doing float-to-fix;
otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
#define FMAX 0x7ffff000
#define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))

/* ---------------- public routines ----------------------- */

static int oss_ndev = 0;

/* find out how many OSS devices we have. Since this has to
open the devices to find out if they're there, we have
to be called before audio is actually started up. So we
cache the results, which in effect are the number of available
devices. */
void oss_init(void)
{
int fd, i;
static int countedthem = 0;
if (countedthem)
return;
for (i = 0; i < 10; i++)
{
char devname[100];
if (i == 0)
strcpy(devname, "/dev/dsp");
else sprintf(devname, "/dev/dsp%d", i);
if ( (fd = open(devname, O_WRONLY|O_NONBLOCK)) != -1)
{
oss_ndev++;
close(fd);
}
else break;
}
countedthem = 1;
}

typedef struct _multidev {
int fd;
int channels;
int format;
} t_multidev;

int oss_reset(int fd) {
int err;
if ((err = ioctl(fd,SNDCTL_DSP_RESET)) < 0)
error("OSS: Could not reset");
return err;
}

void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize,
int suggestedblocksize)
{
int orig, param, nblk, fd = dev->d_fd, wantformat;
int nchannels = dev->d_nchannels;
int advwas = sys_schedadvance;

audio_buf_info ainfo;

/* we only know how to do 2 byte samples */
wantformat = AFMT_S16_NE;
dev->d_bytespersamp = 2;

param = wantformat;

if (ioctl(fd, SNDCTL_DSP_SETFMT, &param) == -1)
fprintf(stderr,"OSS: Could not set DSP format\n");
else if (wantformat != param)
fprintf(stderr,"OSS: DSP format: wanted %d, got %d\n",
wantformat, param);

/* sample rate */
orig = param = srate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &param) == -1)
fprintf(stderr,"OSS: Could not set sampling rate for device\n");
else if( orig != param )
fprintf(stderr,"OSS: sampling rate: wanted %d, got %d\n",
orig, param );

if (oss_blockmode && !skipblocksize)
{
int fragbytes, logfragsize, nfragment;
/* setting fragment count and size. */
linux_fragsize = suggestedblocksize;
if (!linux_fragsize)
{
linux_fragsize = OSS_DEFFRAGSIZE;
while (linux_fragsize > DEFDACBLKSIZE
&& linux_fragsize * 6 > sys_advance_samples)
linux_fragsize = linux_fragsize/2;
}
/* post("adv_samples %d", sys_advance_samples); */
nfragment = (sys_schedadvance * (44100. * 1.e-6)) / linux_fragsize;

fragbytes = linux_fragsize * (dev->d_bytespersamp * nchannels);
logfragsize = ilog2(fragbytes);

if (fragbytes != (1 << logfragsize))
post("warning: OSS takes only power of 2 blocksize; using %d",
(1 << logfragsize)/(dev->d_bytespersamp * nchannels));
if (sys_verbose)
post("setting nfrags = %d, fragsize %d\n", nfragment, fragbytes);

param = orig = (nfragment<<16) + logfragsize;
if (ioctl(fd,SNDCTL_DSP_SETFRAGMENT, &param) == -1)
error("OSS: Could not set or read fragment size\n");
if (param != orig)
{
nfragment = ((param >> 16) & 0xffff);
logfragsize = (param & 0xffff);
post("warning: actual fragments %d, blocksize %d",
nfragment, (1 << logfragsize));
}
if (sys_verbose)
post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance));
}

if (dac)
{
/* use "free space" to learn the buffer size. Normally you
should set this to your own desired value; but this seems not
to be implemented uniformly across different sound cards. LATER
we should figure out what to do if the requested scheduler advance
is greater than this buffer size; for now, we just print something
out. */

int defect;
if (ioctl(fd, SNDCTL_DSP_GETOSPACE,&ainfo) < 0)
fprintf(stderr,"OSS: ioctl on output device failed");
dev->d_bufsize = ainfo.bytes;

defect = sys_advance_samples * (dev->d_bytespersamp * nchannels)
- dev->d_bufsize - OSS_XFERSIZE(nchannels, dev->d_bytespersamp);
if (defect > 0)
{
if (sys_verbose || defect > (dev->d_bufsize >> 2))
fprintf(stderr,
"OSS: requested audio buffer size %d limited to %d\n",
sys_advance_samples * (dev->d_bytespersamp * nchannels),
dev->d_bufsize);
sys_advance_samples =
(dev->d_bufsize - OSS_XFERSAMPS(nchannels)) /
(dev->d_bytespersamp *nchannels);
}
}
}

static int oss_setchannels(int fd, int wantchannels, char *devname)
{
int param;
if (sys_verbose)
post("setchan %d", wantchannels);
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &param) == -1)
{
if (sys_verbose)
error("OSS: SOUND_DSP_READ_CHANNELS failed %s", devname);
}
else
{
if (sys_verbose)
post("channels originally %d for %s", param, devname);
if (param == wantchannels)
{
if (sys_verbose)
post("number of channels doesn't need setting\n");
return (wantchannels);
}
}
param = wantchannels;
whynot:
while (param > 1)
{
int save = param;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &param) == -1)
error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname);
else if (param == save)
return (param);
param = save - 1;
}

return (0);
}

int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
int noutdev, int *outdev, int nchout, int *chout, int rate,
int blocksize)
{
int capabilities = 0;
int inchannels = 0, outchannels = 0;
char devname[20];
int n, i, fd, flags;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
int num_devs = 0;
int wantmore=0;
int spread = 0;
audio_buf_info ainfo;

linux_nindevs = linux_noutdevs = 0;
/* mark devices unopened */
for (i = 0; i < OSS_MAXDEV; i++)
linux_adcs[i].d_fd = linux_dacs[i].d_fd = -1;

/* open output devices */
wantmore=0;
if (noutdev < 0 || nindev < 0)
bug("linux_open_audio");

for (n = 0; n < noutdev; n++)
{
int gotchans, j, inindex = -1;
int thisdevice = (outdev[n] >= 0 ? outdev[n] : 0);
int wantchannels = (nchout>n) ? chout[n] : wantmore;
fd = -1;
if (!wantchannels)
goto end_out_loop;

if (thisdevice > 0)
sprintf(devname, "/dev/dsp%d", thisdevice);
else sprintf(devname, "/dev/dsp");
/* search for input request for same device. Succeed only
if the number of channels matches. */
for (j = 0; j < nindev; j++)
if (indev[j] == thisdevice && chin[j] == wantchannels)
inindex = j;

/* if the same device is requested for input and output,
try to open it read/write */
if (inindex >= 0)
{
sys_setalarm(1000000);
if ((fd = open(devname, O_RDWR | O_NDELAY)) == -1)
{
post("%s (read/write): %s", devname, strerror(errno));
post("(now will try write-only...)");
}
else
{
if (fcntl(fd, F_SETFD, 1) < 0)
post("couldn't set close-on-exec flag on audio");
if ((flags = fcntl(fd, F_GETFL)) < 0)
post("couldn't get audio device flags");
else if (fcntl(fd, F_SETFL, flags & (~O_NDELAY)) < 0)
post("couldn't set audio device flags");
if (sys_verbose)
post("opened %s for reading and writing\n", devname);
linux_adcs[inindex].d_fd = fd;
}
}
/* if that didn't happen or if it failed, try write-only */
if (fd == -1)
{
sys_setalarm(1000000);
if ((fd = open(devname, O_WRONLY | O_NDELAY)) == -1)
{
post("%s (writeonly): %s",
devname, strerror(errno));
break;
}
if (fcntl(fd, F_SETFD, 1) < 0)
post("couldn't set close-on-exec flag on audio");
if ((flags = fcntl(fd, F_GETFL)) < 0)
post("couldn't get audio device flags");
else if (fcntl(fd, F_SETFL, flags & (~O_NDELAY)) < 0)
post("couldn't set audio device flags");
if (sys_verbose)
post("opened %s for writing only\n", devname);
}
if (ioctl(fd, SNDCTL_DSP_GETCAPS, &capabilities) == -1)
error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname);

gotchans = oss_setchannels(fd,
(wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
devname);

if (sys_verbose)
post("opened audio output on %s; got %d channels",
devname, gotchans);

if (gotchans < 2)
{
/* can't even do stereo? just give up. */
close(fd);
}
else
{
linux_dacs[linux_noutdevs].d_nchannels = gotchans;
linux_dacs[linux_noutdevs].d_fd = fd;
oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize);

linux_noutdevs++;
outchannels += gotchans;
if (inindex >= 0)
{
linux_adcs[inindex].d_nchannels = gotchans;
chin[inindex] = gotchans;
}
}
/* LATER think about spreading large numbers of channels over
various dsp's and vice-versa */
wantmore = wantchannels - gotchans;
end_out_loop: ;
}

/* open input devices */
wantmore = 0;
for (n = 0; n < nindev; n++)
{
int gotchans=0;
int thisdevice = (indev[n] >= 0 ? indev[n] : 0);
int wantchannels = (nchin>n)?chin[n]:wantmore;
int alreadyopened = 0;
if (!wantchannels)
goto end_in_loop;

if (thisdevice > 0)
sprintf(devname, "/dev/dsp%d", thisdevice);
else sprintf(devname, "/dev/dsp");

sys_setalarm(1000000);

/* perhaps it's already open from the above? */
if (linux_adcs[n].d_fd >= 0)
{
fd = linux_adcs[n].d_fd;
alreadyopened = 1;
if (sys_verbose)
post("already opened it");
}
else
{
/* otherwise try to open it here. */
if ((fd = open(devname, O_RDONLY | O_NDELAY)) == -1)
{
post("%s (readonly): %s", devname, strerror(errno));
goto end_in_loop;
}
if (fcntl(fd, F_SETFD, 1) < 0)
post("couldn't set close-on-exec flag on audio");
if ((flags = fcntl(fd, F_GETFL)) < 0)
post("couldn't get audio device flags");
else if (fcntl(fd, F_SETFL, flags & (~O_NDELAY)) < 0)
post("couldn't set audio device flags");
if (sys_verbose)
post("opened %s for reading only\n", devname);
}
linux_adcs[linux_nindevs].d_fd = fd;

gotchans = oss_setchannels(fd,
(wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
devname);
if (sys_verbose)
post("opened audio input device %s; got %d channels",
devname, gotchans);

if (gotchans < 1)
{
close(fd);
goto end_in_loop;
}

linux_adcs[linux_nindevs].d_nchannels = gotchans;

oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened,
blocksize);

inchannels += gotchans;
linux_nindevs++;

wantmore = wantchannels-gotchans;
/* LATER think about spreading large numbers of channels over
various dsp's and vice-versa */
end_in_loop: ;
}

/* We have to do a read to start the engine. This is
necessary because sys_send_dacs waits until the input
buffer is filled and only reads on a filled buffer.
This is good, because it's a way to make sure that we
will not block. But I wonder why we only have to read
from one of the devices and not all of them??? */

if (linux_nindevs)
{
if (sys_verbose)
fprintf(stderr,("OSS: issuing first ADC 'read' ... "));
read(linux_adcs[0].d_fd, buf,
linux_adcs[0].d_bytespersamp *
linux_adcs[0].d_nchannels * DEFDACBLKSIZE);
if (sys_verbose)
fprintf(stderr, "...done.\n");
}
/* now go and fill all the output buffers. */
for (i = 0; i < linux_noutdevs; i++)
{
int j;
memset(buf, 0, linux_dacs[i].d_bytespersamp *
linux_dacs[i].d_nchannels * DEFDACBLKSIZE);
for (j = 0; j < sys_advance_samples/DEFDACBLKSIZE; j++)
write(linux_dacs[i].d_fd, buf,
linux_dacs[i].d_bytespersamp *
linux_dacs[i].d_nchannels * DEFDACBLKSIZE);
}
sys_setalarm(0);
STUFF->st_inchannels = inchannels;
STUFF->st_outchannels = outchannels;
return (0);
}

void oss_close_audio( void)
{
int i;
for (i=0;i<linux_nindevs;i++)
close(linux_adcs[i].d_fd);

for (i=0;i<linux_noutdevs;i++)
close(linux_dacs[i].d_fd);

linux_nindevs = linux_noutdevs = 0;
}

static int linux_dacs_write(int fd,void* buf,long bytes)
{
return write(fd, buf, bytes);
}

static int linux_adcs_read(int fd,void* buf,long bytes)
{
return read(fd, buf, bytes);
}

/* query audio devices for "available" data size. */
static void oss_calcspace(void)
{
int dev;
audio_buf_info ainfo;
for (dev=0; dev < linux_noutdevs; dev++)
{
if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0)
fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
linux_dacs[dev].d_space = ainfo.bytes;
}

for (dev = 0; dev < linux_nindevs; dev++)
{
if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE,&ainfo) < 0)
fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
dev, linux_adcs[dev].d_fd);
linux_adcs[dev].d_space = ainfo.bytes;
}
}

void linux_audiostatus(void)
{
int dev;
if (!oss_blockmode)
{
oss_calcspace();
for (dev=0; dev < linux_noutdevs; dev++)
fprintf(stderr, "dac %d space %d\n", dev, linux_dacs[dev].d_space);

for (dev = 0; dev < linux_nindevs; dev++)
fprintf(stderr, "adc %d space %d\n", dev, linux_adcs[dev].d_space);

}
}

/* this call resyncs audio output and input which will cause discontinuities
in audio output and/or input. */

static void oss_doresync( void)
{
int dev, zeroed = 0, wantsize;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
audio_buf_info ainfo;

/* 1. if any input devices are ahead (have more than 1 buffer stored),
drop one or more buffers worth */
for (dev = 0; dev < linux_nindevs; dev++)
{
if (linux_adcs[dev].d_space == 0)
{
linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp));
}
else while (linux_adcs[dev].d_space >
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp))
{
linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp));
if (ioctl(linux_adcs[dev].d_fd, SNDCTL_DSP_GETISPACE, &ainfo) < 0)
{
fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
dev, linux_adcs[dev].d_fd);
break;
}
linux_adcs[dev].d_space = ainfo.bytes;
}
}

/* 2. if any output devices are behind, feed them zeros to catch them
up */
for (dev = 0; dev < linux_noutdevs; dev++)
{
while (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
sys_advance_samples * (linux_dacs[dev].d_nchannels *
linux_dacs[dev].d_bytespersamp))
{
if (!zeroed)
{
unsigned int i;
for (i = 0; i < OSS_XFERSAMPS(linux_dacs[dev].d_nchannels);
i++)
buf[i] = 0;
zeroed = 1;
}
linux_dacs_write(linux_dacs[dev].d_fd, buf,
OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
linux_dacs[dev].d_bytespersamp));
if (ioctl(linux_dacs[dev].d_fd, SNDCTL_DSP_GETOSPACE, &ainfo) < 0)
{
fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
dev, linux_dacs[dev].d_fd);
break;
}
linux_dacs[dev].d_space = ainfo.bytes;
}
}
/* 3. if any DAC devices are too far ahead, plan to drop the
number of frames which will let the others catch up. */
for (dev = 0; dev < linux_noutdevs; dev++)
{
if (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
(sys_advance_samples - 1) * linux_dacs[dev].d_nchannels *
linux_dacs[dev].d_bytespersamp)
{
linux_dacs[dev].d_dropcount = sys_advance_samples - 1 -
(linux_dacs[dev].d_space - linux_dacs[dev].d_bufsize) /
(linux_dacs[dev].d_nchannels *
linux_dacs[dev].d_bytespersamp) ;
}
else linux_dacs[dev].d_dropcount = 0;
}
}

int oss_send_dacs(void)
{
t_sample *fp1, *fp2;
long fill;
int i, j, dev, rtnval = SENDDACS_YES;
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
t_oss_int16 *sp;
t_oss_int32 *lp;
/* the maximum number of samples we should have in the ADC buffer */
int idle = 0;
int thischan;
double timeref, timenow;

if (!linux_nindevs && !linux_noutdevs)
return (SENDDACS_NO);

if (!oss_blockmode)
{
/* determine whether we're idle. This is true if either (1)
some input device has less than one buffer to read or (2) some
output device has fewer than (sys_advance_samples) blocks buffered
already. */
oss_calcspace();

for (dev=0; dev < linux_noutdevs; dev++)
if (linux_dacs[dev].d_dropcount ||
(linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space >
sys_advance_samples * linux_dacs[dev].d_bytespersamp *
linux_dacs[dev].d_nchannels))
idle = 1;
for (dev=0; dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space <
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp))
idle = 1;
}

if (idle && !oss_blockmode)
{
/* sometimes---rarely---when the ADC available-byte-count is
zero, it's genuine, but usually it's because we're so
late that the ADC has overrun its entire kernel buffer. We
distinguish between the two by waiting 2 msec and asking again.
There should be an error flag we could check instead; look for this
someday... */
for (dev = 0;dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space == 0)
{
audio_buf_info ainfo;
sys_microsleep(2000);
oss_calcspace();
if (linux_adcs[dev].d_space != 0) continue;

/* here's the bad case. Give up and resync. */
sys_log_error(ERR_DATALATE);
oss_doresync();
return (SENDDACS_NO);
}
/* check for slippage between devices, either because
data got lost in the driver from a previous late condition, or
because the devices aren't synced. When we're idle, no
input device should have more than one buffer readable and
no output device should have less than sys_advance_samples-1
*/

for (dev=0; dev < linux_noutdevs; dev++)
if (!linux_dacs[dev].d_dropcount &&
(linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space <
(sys_advance_samples - 2) *
(linux_dacs[dev].d_bytespersamp *
linux_dacs[dev].d_nchannels)))
goto badsync;
for (dev=0; dev < linux_nindevs; dev++)
if (linux_adcs[dev].d_space > 3 *
OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
linux_adcs[dev].d_bytespersamp))
goto badsync;

/* return zero to tell the scheduler we're idle. */
return (SENDDACS_NO);
badsync:
sys_log_error(ERR_RESYNC);
oss_doresync();
return (SENDDACS_NO);

}

/* do output */

timeref = sys_getrealtime();
for (dev=0, thischan = 0; dev < linux_noutdevs; dev++)
{
int nchannels = linux_dacs[dev].d_nchannels;
if (linux_dacs[dev].d_dropcount)
linux_dacs[dev].d_dropcount--;
else
{
if (linux_dacs[dev].d_bytespersamp == 2)
{
for (i = DEFDACBLKSIZE, fp1 = STUFF->st_soundout +
DEFDACBLKSIZE*thischan,
sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
{
for (j=0, fp2 = fp1; j<nchannels; j++, fp2 += DEFDACBLKSIZE)
{
int s = *fp2 * 32767.;
if (s > 32767) s = 32767;
else if (s < -32767) s = -32767;
sp[j] = s;
}
}
}
linux_dacs_write(linux_dacs[dev].d_fd, buf,
OSS_XFERSIZE(nchannels, linux_dacs[dev].d_bytespersamp));
if ((timenow = sys_getrealtime()) - timeref > 0.002)
{
if (!oss_blockmode)
sys_log_error(ERR_DACSLEPT);
else rtnval = SENDDACS_SLEPT;
}
timeref = timenow;
}
thischan += nchannels;
}
memset(STUFF->st_soundout, 0,
STUFF->st_outchannels * (sizeof(t_sample) * DEFDACBLKSIZE));

/* do input */

for (dev = 0, thischan = 0; dev < linux_nindevs; dev++)
{
int nchannels = linux_adcs[dev].d_nchannels;
linux_adcs_read(linux_adcs[dev].d_fd, buf,
OSS_XFERSIZE(nchannels, linux_adcs[dev].d_bytespersamp));

if ((timenow = sys_getrealtime()) - timeref > 0.002)
{
if (!oss_blockmode)
sys_log_error(ERR_ADCSLEPT);
else
rtnval = SENDDACS_SLEPT;
}
timeref = timenow;

if (linux_adcs[dev].d_bytespersamp == 2)
{
for (i = DEFDACBLKSIZE,fp1 = STUFF->st_soundin + thischan*DEFDACBLKSIZE,
sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
{
for (j=0;j<nchannels;j++)
fp1[j*DEFDACBLKSIZE] = (float)sp[j]*(float)3.051850e-05;
}
}
thischan += nchannels;
}
return (rtnval);
}

void oss_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int i, ndev;
*canmulti = 2; /* supports multiple devices */
if ((ndev = oss_ndev) > maxndev)
ndev = maxndev;
for (i = 0; i < ndev; i++)
{
sprintf(indevlist + i * devdescsize, "OSS device #%d", i+1);
sprintf(outdevlist + i * devdescsize, "OSS device #%d", i+1);
}
*nindevs = *noutdevs = ndev;
}

+ 642
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_pa.c View File

@@ -0,0 +1,642 @@
/* Copyright (c) 2001 Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* this file calls Ross Bencina's and Phil Burk's Portaudio package. It's
the main way in for Mac OS and, with Michael Casey's help, also into
ASIO in Windows.

Both blocking and non-blocking call styles are supported. If non-blocking
is requested, either we call portaudio in non-blocking mode, or else we
call portaudio in callback mode and manage our own FIFO se we can offer
Pd "blocking" I/O calls. To do the latter we define FAKEBLOCKING; this
works better in MAXOSX (gets 40 msec lower latency!) and might also in
Windows. If FAKEBLOCKING is defined we can choose between two methods
for waiting on the (presumebly other-thread) I/O to complete, either
correct thread synchronization (by defining THREADSIGNAL) or just sleeping
and polling; the latter seems to work better so far.
*/

/* dolist...
switch to usleep in s_inter.c
*/

#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <portaudio.h>

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

#ifndef _WIN32 /* for the "dup2" workaround -- do we still need it? */
#include <unistd.h>
#endif

#ifdef _WIN32
# include <malloc.h> /* MSVC or mingw on windows */
#elif defined(__linux__) || defined(__APPLE__)
# include <alloca.h> /* linux, mac, mingw, cygwin */
#else
# include <stdlib.h> /* BSDs for example */
#endif

#if 1
#define FAKEBLOCKING
#endif

#if defined (FAKEBLOCKING) && defined(_WIN32)
#include <windows.h> /* for Sleep() */
#endif

/* define this to enable thread signaling instead of polling */
/* #define THREADSIGNAL */

/* LATER try to figure out how to handle default devices in portaudio;
the way s_audio.c handles them isn't going to work here. */

/* public interface declared in m_imp.h */

/* implementation */
static PaStream *pa_stream;
static int pa_inchans, pa_outchans;
static float *pa_soundin, *pa_soundout;
static t_audiocallback pa_callback;

static int pa_started;
static int pa_nbuffers;
static int pa_dio_error;

#ifdef FAKEBLOCKING
#include "s_audio_paring.h"
static PA_VOLATILE char *pa_outbuf;
static PA_VOLATILE sys_ringbuf pa_outring;
static PA_VOLATILE char *pa_inbuf;
static PA_VOLATILE sys_ringbuf pa_inring;
#ifdef THREADSIGNAL
#include <pthread.h>
pthread_mutex_t pa_mutex;
pthread_cond_t pa_sem;
#endif /* THREADSIGNAL */
#endif /* FAKEBLOCKING */

static void pa_init(void) /* Initialize PortAudio */
{
static int initialized;
if (!initialized)
{
#ifdef __APPLE__
/* for some reason, on the Mac Pa_Initialize() closes file descriptor
1 (standard output) As a workaround, dup it to another number and dup2
it back afterward. */
int newfd = dup(1);
int another = open("/dev/null", 0);
dup2(another, 1);
int err = Pa_Initialize();
close(1);
close(another);
if (newfd >= 0)
{
fflush(stdout);
dup2(newfd, 1);
close(newfd);
}
#else
int err = Pa_Initialize();
#endif


if ( err != paNoError )
{
post("Error opening audio: %s", err, Pa_GetErrorText(err));
return;
}
initialized = 1;
}
}

static int pa_lowlevel_callback(const void *inputBuffer,
void *outputBuffer, unsigned long nframes,
const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
void *userData)
{
int i;
unsigned int n, j;
float *fbuf, *fp2, *fp3, *soundiop;
if (nframes % DEFDACBLKSIZE)
{
post("warning: audio nframes %ld not a multiple of blocksize %d",
nframes, (int)DEFDACBLKSIZE);
nframes -= (nframes % DEFDACBLKSIZE);
}
for (n = 0; n < nframes; n += DEFDACBLKSIZE)
{
if (inputBuffer != NULL)
{
fbuf = ((float *)inputBuffer) + n*pa_inchans;
soundiop = pa_soundin;
for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
j++, fp3 += pa_inchans)
*soundiop++ = *fp3;
}
else memset((void *)pa_soundin, 0,
DEFDACBLKSIZE * pa_inchans * sizeof(float));
memset((void *)pa_soundout, 0,
DEFDACBLKSIZE * pa_outchans * sizeof(float));
(*pa_callback)();
if (outputBuffer != NULL)
{
fbuf = ((float *)outputBuffer) + n*pa_outchans;
soundiop = pa_soundout;
for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
j++, fp3 += pa_outchans)
*fp3 = *soundiop++;
}
}
return 0;
}

#ifdef FAKEBLOCKING
/* callback for "non-callback" case in which we actualy open portaudio
in callback mode but fake "blocking mode". We communicate with the
main thread via FIFO. First read the audio output FIFO (which
we sync on, not waiting for it but supplying zeros to the audio output if
there aren't enough samples in the FIFO when we are called), then write
to the audio input FIFO. The main thread will wait for the input fifo.
We can either throw it a pthreads condition or just allow the main thread
to poll for us; so far polling seems to work better. */
static int pa_fifo_callback(const void *inputBuffer,
void *outputBuffer, unsigned long nframes,
const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
void *userData)
{
/* callback routine for non-callback client... throw samples into
and read them out of a FIFO */
int ch;
long fiforoom;
float *fbuf;

#if CHECKFIFOS
if (pa_inchans * sys_ringbuf_getreadavailable(&pa_outring) !=
pa_outchans * sys_ringbuf_getwriteavailable(&pa_inring))
post("warning: in and out rings unequal (%d, %d)",
sys_ringbuf_getreadavailable(&pa_outring),
sys_ringbuf_getwriteavailable(&pa_inring));
#endif
fiforoom = sys_ringbuf_getreadavailable(&pa_outring);
if ((unsigned)fiforoom >= nframes*pa_outchans*sizeof(float))
{
if (outputBuffer)
sys_ringbuf_read(&pa_outring, outputBuffer,
nframes*pa_outchans*sizeof(float), pa_outbuf);
else if (pa_outchans)
post("audio error: no outputBuffer but output channels");
if (inputBuffer)
sys_ringbuf_write(&pa_inring, inputBuffer,
nframes*pa_inchans*sizeof(float), pa_inbuf);
else if (pa_inchans)
post("audio error: no inputBuffer but input channels");
}
else
{ /* PD could not keep up; generate zeros */
if (pa_started)
pa_dio_error = 1;
if (outputBuffer)
{
for (ch = 0; ch < pa_outchans; ch++)
{
unsigned long frame;
fbuf = ((float *)outputBuffer) + ch;
for (frame = 0; frame < nframes; frame++, fbuf += pa_outchans)
*fbuf = 0;
}
}
}
#ifdef THREADSIGNAL
pthread_mutex_lock(&pa_mutex);
pthread_cond_signal(&pa_sem);
pthread_mutex_unlock(&pa_mutex);
#endif
return 0;
}
#endif /* FAKEBLOCKING */

PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
int framesperbuf, int nbuffers, int indeviceno, int outdeviceno, PaStreamCallback *callbackfn)
{
long bytesPerSample;
PaError err;
PaStreamParameters instreamparams, outstreamparams;
PaStreamParameters*p_instreamparams=0, *p_outstreamparams=0;

/* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
nchannels, flags, nbuffers, framesperbuf); */

instreamparams.device = indeviceno;
instreamparams.channelCount = inchannels;
instreamparams.sampleFormat = paFloat32;
instreamparams.hostApiSpecificStreamInfo = 0;

outstreamparams.device = outdeviceno;
outstreamparams.channelCount = outchannels;
outstreamparams.sampleFormat = paFloat32;
outstreamparams.hostApiSpecificStreamInfo = 0;

#ifdef FAKEBLOCKING
instreamparams.suggestedLatency = outstreamparams.suggestedLatency = 0;
#else
instreamparams.suggestedLatency = outstreamparams.suggestedLatency =
nbuffers*framesperbuf/sampleRate;
#endif /* FAKEBLOCKING */

if( inchannels>0 && indeviceno >= 0)
p_instreamparams=&instreamparams;
if( outchannels>0 && outdeviceno >= 0)
p_outstreamparams=&outstreamparams;

err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams, sampleRate);

if (paFormatIsSupported != err)
{
/* check whether we have to change the numbers of channel and/or samplerate */
const PaDeviceInfo* info = 0;
double inRate=0, outRate=0;

if (inchannels>0)
{
if (NULL != (info = Pa_GetDeviceInfo( instreamparams.device )))
{
inRate=info->defaultSampleRate;

if(info->maxInputChannels<inchannels)
instreamparams.channelCount=info->maxInputChannels;
}
}

if (outchannels>0)
{
if (NULL != (info = Pa_GetDeviceInfo( outstreamparams.device )))
{
outRate=info->defaultSampleRate;

if(info->maxOutputChannels<outchannels)
outstreamparams.channelCount=info->maxOutputChannels;
}
}

if (err == paInvalidSampleRate)
{
sampleRate=outRate;
}

err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams,
sampleRate);
if (paFormatIsSupported != err)
goto error;
}
err = Pa_OpenStream(
&pa_stream,
p_instreamparams,
p_outstreamparams,
sampleRate,
framesperbuf,
paNoFlag, /* portaudio will clip for us */
callbackfn,
0);
if (err != paNoError)
goto error;

err = Pa_StartStream(pa_stream);
if (err != paNoError)
{
post("error opening failed; closing audio stream: %s",
Pa_GetErrorText(err));
pa_close_audio();
goto error;
}
STUFF->st_dacsr=sampleRate;
return paNoError;
error:
pa_stream = NULL;
return err;
}

int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
t_sample *soundout, int framesperbuf, int nbuffers,
int indeviceno, int outdeviceno, t_audiocallback callbackfn)
{
PaError err;
int j, devno, pa_indev = -1, pa_outdev = -1;

pa_callback = callbackfn;
/* fprintf(stderr, "open callback %d\n", (callbackfn != 0)); */
pa_init();
/* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */

if (pa_stream)
pa_close_audio();

if (inchans > 0)
{
for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++)
{
const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
if (info->maxInputChannels > 0)
{
if (devno == indeviceno)
{
if (inchans > info->maxInputChannels)
inchans = info->maxInputChannels;

pa_indev = j;
break;
}
devno++;
}
}
}

if (outchans > 0)
{
for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++)
{
const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
if (info->maxOutputChannels > 0)
{
if (devno == outdeviceno)
{
if (outchans > info->maxOutputChannels)
outchans = info->maxOutputChannels;

pa_outdev = j;
break;
}
devno++;
}
}
}

if (inchans > 0 && pa_indev == -1)
inchans = 0;
if (outchans > 0 && pa_outdev == -1)
outchans = 0;

if (sys_verbose)
{
post("input device %d, channels %d", pa_indev, inchans);
post("output device %d, channels %d", pa_outdev, outchans);
post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
post("rate %d", rate);
}
pa_inchans = STUFF->st_inchannels = inchans;
pa_outchans = STUFF->st_outchannels = outchans;
pa_soundin = soundin;
pa_soundout = soundout;

#ifdef FAKEBLOCKING
if (pa_inbuf)
free((char *)pa_inbuf), pa_inbuf = 0;
if (pa_outbuf)
free((char *)pa_outbuf), pa_outbuf = 0;
#endif

if (! inchans && !outchans)
return (0);

if (callbackfn)
{
pa_callback = callbackfn;
err = pa_open_callback(rate, inchans, outchans,
framesperbuf, nbuffers, pa_indev, pa_outdev, pa_lowlevel_callback);
}
else
{
#ifdef FAKEBLOCKING
if (pa_inchans)
{
pa_inbuf = malloc(nbuffers*framesperbuf*pa_inchans*sizeof(float));
sys_ringbuf_init(&pa_inring,
nbuffers*framesperbuf*pa_inchans*sizeof(float), pa_inbuf,
nbuffers*framesperbuf*pa_inchans*sizeof(float));
}
if (pa_outchans)
{
pa_outbuf = malloc(nbuffers*framesperbuf*pa_outchans*sizeof(float));
sys_ringbuf_init(&pa_outring,
nbuffers*framesperbuf*pa_outchans*sizeof(float), pa_outbuf, 0);
}
err = pa_open_callback(rate, inchans, outchans,
framesperbuf, nbuffers, pa_indev, pa_outdev, pa_fifo_callback);
#else
err = pa_open_callback(rate, inchans, outchans,
framesperbuf, nbuffers, pa_indev, pa_outdev, 0);
#endif
}
pa_started = 0;
pa_nbuffers = nbuffers;
if ( err != paNoError )
{
post("Error opening audio: %s", Pa_GetErrorText(err));
/* Pa_Terminate(); */
return (1);
}
else if (sys_verbose)
post("... opened OK.");
return (0);
}

void pa_close_audio( void)
{
if (pa_stream)
{
Pa_AbortStream(pa_stream);
Pa_CloseStream(pa_stream);
}
pa_stream = 0;
#ifdef FAKEBLOCKING
if (pa_inbuf)
free((char *)pa_inbuf), pa_inbuf = 0;
if (pa_outbuf)
free((char *)pa_outbuf), pa_outbuf = 0;
#endif
}

int pa_send_dacs(void)
{
t_sample *fp;
float *fp2, *fp3;
float *conversionbuf;
int j, k;
int rtnval = SENDDACS_YES;
#ifndef FAKEBLOCKING
double timebefore;
#endif /* FAKEBLOCKING */
if ((!STUFF->st_inchannels && !STUFF->st_outchannels) || !pa_stream)
return (SENDDACS_NO);
conversionbuf = (float *)alloca((STUFF->st_inchannels > STUFF->st_outchannels?
STUFF->st_inchannels:STUFF->st_outchannels) * DEFDACBLKSIZE * sizeof(float));

#ifdef FAKEBLOCKING
if (!STUFF->st_inchannels) /* if no input channels sync on output */
{
#ifdef THREADSIGNAL
pthread_mutex_lock(&pa_mutex);
#endif
while (sys_ringbuf_getwriteavailable(&pa_outring) <
(long)(STUFF->st_outchannels * DEFDACBLKSIZE * sizeof(float)))
{
rtnval = SENDDACS_SLEPT;
#ifdef THREADSIGNAL
pthread_cond_wait(&pa_sem, &pa_mutex);
#else
#ifdef _WIN32
Sleep(1);
#else
usleep(1000);
#endif /* _WIN32 */
#endif /* THREADSIGNAL */
}
#ifdef THREADSIGNAL
pthread_mutex_unlock(&pa_mutex);
#endif
}
/* write output */
if (STUFF->st_outchannels)
{
for (j = 0, fp = STUFF->st_soundout, fp2 = conversionbuf;
j < STUFF->st_outchannels; j++, fp2++)
for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
k++, fp++, fp3 += STUFF->st_outchannels)
*fp3 = *fp;
sys_ringbuf_write(&pa_outring, conversionbuf,
STUFF->st_outchannels*(DEFDACBLKSIZE*sizeof(float)), pa_outbuf);
}
if (STUFF->st_inchannels) /* if there is input sync on it */
{
#ifdef THREADSIGNAL
pthread_mutex_lock(&pa_mutex);
#endif
while (sys_ringbuf_getreadavailable(&pa_inring) <
(long)(STUFF->st_inchannels * DEFDACBLKSIZE * sizeof(float)))
{
rtnval = SENDDACS_SLEPT;
#ifdef THREADSIGNAL
pthread_cond_wait(&pa_sem, &pa_mutex);
#else
#ifdef _WIN32
Sleep(1);
#else
usleep(1000);
#endif /* _WIN32 */
#endif /* THREADSIGNAL */
}
#ifdef THREADSIGNAL
pthread_mutex_unlock(&pa_mutex);
#endif
}
if (STUFF->st_inchannels)
{
sys_ringbuf_read(&pa_inring, conversionbuf,
STUFF->st_inchannels*(DEFDACBLKSIZE*sizeof(float)), pa_inbuf);
for (j = 0, fp = STUFF->st_soundin, fp2 = conversionbuf;
j < STUFF->st_inchannels; j++, fp2++)
for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
k++, fp++, fp3 += STUFF->st_inchannels)
*fp = *fp3;
}

#else /* FAKEBLOCKING */
timebefore = sys_getrealtime();
/* write output */
if (STUFF->st_outchannels)
{
if (!pa_started)
{
memset(conversionbuf, 0,
STUFF->st_outchannels * DEFDACBLKSIZE * sizeof(float));
for (j = 0; j < pa_nbuffers-1; j++)
Pa_WriteStream(pa_stream, conversionbuf, DEFDACBLKSIZE);
}
for (j = 0, fp = STUFF->st_soundout, fp2 = conversionbuf;
j < STUFF->st_outchannels; j++, fp2++)
for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
k++, fp++, fp3 += STUFF->st_outchannels)
*fp3 = *fp;
Pa_WriteStream(pa_stream, conversionbuf, DEFDACBLKSIZE);
}

if (STUFF->st_inchannels)
{
Pa_ReadStream(pa_stream, conversionbuf, DEFDACBLKSIZE);
for (j = 0, fp = STUFF->st_soundin, fp2 = conversionbuf;
j < STUFF->st_inchannels; j++, fp2++)
for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
k++, fp++, fp3 += STUFF->st_inchannels)
*fp = *fp3;
}
if (sys_getrealtime() - timebefore > 0.002)
{
rtnval = SENDDACS_SLEPT;
}
#endif /* FAKEBLOCKING */
pa_started = 1;

memset(STUFF->st_soundout, 0,
DEFDACBLKSIZE*sizeof(t_sample)*STUFF->st_outchannels);
return (rtnval);
}

/* scanning for devices */
void pa_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize)
{
int i, nin = 0, nout = 0, ndev;
*canmulti = 1; /* one dev each for input and output */

pa_init();
ndev = Pa_GetDeviceCount();
for (i = 0; i < ndev; i++)
{
const PaDeviceInfo *pdi = Pa_GetDeviceInfo(i);
if (pdi->maxInputChannels > 0 && nin < maxndev)
{
/* LATER figure out how to get API name correctly */
snprintf(indevlist + nin * devdescsize, devdescsize,
#ifdef _WIN32
"%s:%s", (pdi->hostApi == 0 ? "MMIO" : (pdi->hostApi == 1 ? "ASIO" : "?")),
#else
#ifdef __APPLE__
"%s",
#else
"(%d) %s", pdi->hostApi,
#endif
#endif
pdi->name);
nin++;
}
if (pdi->maxOutputChannels > 0 && nout < maxndev)
{
snprintf(outdevlist + nout * devdescsize, devdescsize,
#ifdef _WIN32
"%s:%s", (pdi->hostApi == 0 ? "MMIO" : (pdi->hostApi == 1 ? "ASIO" : "?")),
#else
#ifdef __APPLE__
"%s",
#else
"(%d) %s", pdi->hostApi,
#endif
#endif
pdi->name);
nout++;
}
}
*nindevs = nin;
*noutdevs = nout;
}

+ 255
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_paring.c View File

@@ -0,0 +1,255 @@
/*
* ringbuffer.c
* Ring Buffer utility..
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* modified 2002/07/13 by olaf.matthes@gmx.de to allow any number if channels
*
* extensively hacked by msp@ucsd.edu for various reasons
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "s_audio_paring.h"
#include <string.h>

/* Clear buffer. Should only be called when buffer is NOT being read. */
static void sys_ringbuf_Flush(PA_VOLATILE sys_ringbuf *rbuf,
PA_VOLATILE void *dataPtr, long nfill);

/* Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
static long sys_ringbuf_GetWriteRegions(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer);
static long sys_ringbuf_AdvanceWriteIndex(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes);

/* Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be read or numBytes, whichever is smaller.
*/
static long sys_ringbuf_GetReadRegions(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer);

static long sys_ringbuf_AdvanceReadIndex(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes );

/***************************************************************************
* Initialize FIFO.
*/
long sys_ringbuf_init(PA_VOLATILE sys_ringbuf *rbuf, long numBytes,
PA_VOLATILE char *dataPtr, long nfill)
{
rbuf->bufferSize = numBytes;
sys_ringbuf_Flush(rbuf, dataPtr, nfill);
return 0;
}
/***************************************************************************
** Return number of bytes available for reading. */
long sys_ringbuf_getreadavailable(PA_VOLATILE sys_ringbuf *rbuf)
{
long ret = rbuf->writeIndex - rbuf->readIndex;
if (ret < 0)
ret += 2 * rbuf->bufferSize;
if (ret < 0 || ret > rbuf->bufferSize)
fprintf(stderr,
"consistency check failed: sys_ringbuf_getreadavailable\n");
return ( ret );
}
/***************************************************************************
** Return number of bytes available for writing. */
long sys_ringbuf_getwriteavailable(PA_VOLATILE sys_ringbuf *rbuf)
{
return ( rbuf->bufferSize - sys_ringbuf_getreadavailable(rbuf));
}

/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
static void sys_ringbuf_Flush(PA_VOLATILE sys_ringbuf *rbuf,
PA_VOLATILE void *dataPtr, long nfill)
{
PA_VOLATILE char *s;
long n;
rbuf->readIndex = 0;
rbuf->writeIndex = nfill;
for (n = nfill, s = dataPtr; n--; s++)
*s = 0;
}

/***************************************************************************
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
static long sys_ringbuf_GetWriteRegions(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer)
{
long index;
long available = sys_ringbuf_getwriteavailable( rbuf );
if( numBytes > available ) numBytes = available;
/* Check to see if write is not contiguous. */
index = rbuf->writeIndex;
while (index >= rbuf->bufferSize)
index -= rbuf->bufferSize;
if( (index + numBytes) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index;
*dataPtr1 = &buffer[index];
*sizePtr1 = firstHalf;
*dataPtr2 = &buffer[0];
*sizePtr2 = numBytes - firstHalf;
}
else
{
*dataPtr1 = &buffer[index];
*sizePtr1 = numBytes;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
return numBytes;
}


/***************************************************************************
*/
static long sys_ringbuf_AdvanceWriteIndex(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes)
{
long ret = (rbuf->writeIndex + numBytes);
if ( ret >= 2 * rbuf->bufferSize)
ret -= 2 * rbuf->bufferSize; /* check for end of buffer */
return rbuf->writeIndex = ret;
}

/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
static long sys_ringbuf_GetReadRegions(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes, PA_VOLATILE void **dataPtr1, long *sizePtr1,
PA_VOLATILE void **dataPtr2, long *sizePtr2, PA_VOLATILE char *buffer)
{
long index;
long available = sys_ringbuf_getreadavailable( rbuf );
if( numBytes > available ) numBytes = available;
/* Check to see if read is not contiguous. */
index = rbuf->readIndex;
while (index >= rbuf->bufferSize)
index -= rbuf->bufferSize;

if( (index + numBytes) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index;
*dataPtr1 = &buffer[index];
*sizePtr1 = firstHalf;
*dataPtr2 = &buffer[0];
*sizePtr2 = numBytes - firstHalf;
}
else
{
*dataPtr1 = &buffer[index];
*sizePtr1 = numBytes;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
return numBytes;
}
/***************************************************************************
*/
static long sys_ringbuf_AdvanceReadIndex(PA_VOLATILE sys_ringbuf *rbuf,
long numBytes)
{
long ret = (rbuf->readIndex + numBytes);
if( ret >= 2 * rbuf->bufferSize)
ret -= 2 * rbuf->bufferSize;
return rbuf->readIndex = ret;
}

/***************************************************************************
** Return bytes written. */
long sys_ringbuf_write(PA_VOLATILE sys_ringbuf *rbuf, const void *data,
long numBytes, PA_VOLATILE char *buffer)
{
long size1, size2, numWritten;
PA_VOLATILE void *data1, *data2;
numWritten = sys_ringbuf_GetWriteRegions( rbuf, numBytes, &data1, &size1,
&data2, &size2, buffer);
if( size2 > 0 )
{

memcpy((void *)data1, data, size1 );
data = ((char *)data) + size1;
memcpy((void *)data2, data, size2 );
}
else
{
memcpy((void *)data1, data, size1 );
}
sys_ringbuf_AdvanceWriteIndex( rbuf, numWritten );
return numWritten;
}

/***************************************************************************
** Return bytes read. */
long sys_ringbuf_read(PA_VOLATILE sys_ringbuf *rbuf, void *data, long numBytes,
PA_VOLATILE char *buffer)
{
long size1, size2, numRead;
PA_VOLATILE void *data1, *data2;
numRead = sys_ringbuf_GetReadRegions( rbuf, numBytes, &data1, &size1,
&data2, &size2, buffer);
if( size2 > 0 )
{
memcpy(data, (void *)data1, size1 );
data = ((char *)data) + size1;
memcpy(data, (void *)data2, size2 );
}
else
{
memcpy( data, (void *)data1, size1 );
}
sys_ringbuf_AdvanceReadIndex( rbuf, numRead );
return numRead;
}

+ 75
- 0
ports/camomile/source/LibPd/pure-data/src/s_audio_paring.h View File

@@ -0,0 +1,75 @@
#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

/*
* ringbuffer.h
* Ring Buffer utility..
*
* Author: Phil Burk, http://www.softsynth.com
*
* This program is distributed with the PortAudio Portable Audio Library.
* For more information see: http://www.audiomulch.com/portaudio/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/

/* If it's ever desired to use shared memory so that one process reads and
another one writes to the same ring buffer, define this as 'volatile' : */
#define PA_VOLATILE

typedef struct
{
long bufferSize; /* Number of bytes in FIFO.
Set by sys_ringbuf_init */
PA_VOLATILE long writeIndex; /* Index of next writable byte.
Set by sys_ringbuf_AdvanceWriteIndex */
PA_VOLATILE long readIndex; /* Index of next readable byte.
Set by sys_ringbuf_AdvanceReadIndex */
} sys_ringbuf;

/* Initialize Ring Buffer. */
long sys_ringbuf_init(PA_VOLATILE sys_ringbuf *rbuf, long numBytes,
PA_VOLATILE char *dataPtr, long nfill);

/* Return number of bytes available for writing. */
long sys_ringbuf_getwriteavailable(PA_VOLATILE sys_ringbuf *rbuf);
/* Return number of bytes available for read. */
long sys_ringbuf_getreadavailable(PA_VOLATILE sys_ringbuf *rbuf);
/* Return bytes written. */
long sys_ringbuf_write(PA_VOLATILE sys_ringbuf *rbuf, const void *data,
long numBytes, PA_VOLATILE char *buffer);
/* Return bytes read. */
long sys_ringbuf_read(PA_VOLATILE sys_ringbuf *rbuf, void *data, long numBytes,
PA_VOLATILE char *buffer);

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _RINGBUFFER_H */

+ 36
- 0
ports/camomile/source/LibPd/pure-data/src/s_entry.c View File

@@ -0,0 +1,36 @@
/* In MSW, this is all there is to pd; the rest sits in a "pdlib" dll so
that externs can link back to functions defined in pd. */

int sys_main(int argc, char **argv);

/*
* gcc does not support the __try stuff, only MSVC. Also, MinGW allows you to
* use main() instead of WinMain(). <hans@at.or.at>
*/
#if defined(_MSC_VER) && !defined(COMMANDVERSION)
#include <windows.h>
#include <stdio.h>

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
__try {
sys_main(__argc,__argv);
}
__finally
{
printf("caught an exception; stopping\n");
}
return (0);
}

#else /* not _MSC_VER ... */
int main(int argc, char **argv)
{
return (sys_main(argc, argv));
}
#endif /* _MSC_VER */



+ 697
- 0
ports/camomile/source/LibPd/pure-data/src/s_file.c View File

@@ -0,0 +1,697 @@
/* Copyright (c) 1997-2004 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 implements a mechanism for storing and retrieving preferences.
* Should later be renamed "preferences.c" or something.
*
* In unix this is handled by the "~/.pdsettings" file, in windows by
* the registry, and in MacOS by the Preferences system.
*/

#include "m_pd.h"
#include "s_stuff.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#include <io.h>
#endif
#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
#define snprintf _snprintf
#endif

void sys_doflags( void);

static PERTHREAD char *sys_prefbuf;
static PERTHREAD int sys_prefbufsize;
static PERTHREAD FILE *sys_prefsavefp;

static void sys_initloadpreferences_file(const char *filename)
{
int fd;
long length;
if ((fd = open(filename, 0)) < 0)
{
if (sys_verbose)
perror(filename);
return;
}
length = lseek(fd, 0, 2);
if (length < 0)
{
if (sys_verbose)
perror(filename);
close(fd);
return;
}
lseek(fd, 0, 0);
if (!(sys_prefbuf = malloc(length + 2)))
{
error("couldn't allocate memory for preferences buffer");
close(fd);
return;
}
sys_prefbuf[0] = '\n';
if (read(fd, sys_prefbuf+1, length) < length)
{
perror(filename);
sys_prefbuf[0] = 0;
close(fd);
return;
}
sys_prefbuf[length+1] = 0;
close(fd);
if (sys_verbose)
post("success reading preferences from: %s", filename);
}

static int sys_getpreference_file(const char *key, char *value, int size)
{
char searchfor[80], *where, *whereend;
if (!sys_prefbuf)
return (0);
sprintf(searchfor, "\n%s:", key);
where = strstr(sys_prefbuf, searchfor);
if (!where)
return (0);
where += strlen(searchfor);
while (*where == ' ' || *where == '\t')
where++;
for (whereend = where; *whereend && *whereend != '\n'; whereend++)
;
if (*whereend == '\n')
whereend--;
if (whereend > where + size - 1)
whereend = where + size - 1;
strncpy(value, where, whereend+1-where);
value[whereend+1-where] = 0;
return (1);
}

static void sys_doneloadpreferences_file( void)
{
if (sys_prefbuf)
free(sys_prefbuf);
}

static void sys_initsavepreferences_file(const char *filename)
{
if ((sys_prefsavefp = fopen(filename, "w")) == NULL)
pd_error(0, "%s: %s", filename, strerror(errno));
}

static void sys_putpreference_file(const char *key, const char *value)
{
if (sys_prefsavefp)
fprintf(sys_prefsavefp, "%s: %s\n",
key, value);
}

static void sys_donesavepreferences_file( void)
{
if (sys_prefsavefp)
{
fclose(sys_prefsavefp);
sys_prefsavefp = 0;
}
}


/***** linux/android/BSD etc: read and write to ~/.pdsettings file ******/
#if !defined(_WIN32) && !defined(__APPLE__)

static void sys_initloadpreferences( void)
{
char filenamebuf[MAXPDSTRING], *homedir = getenv("HOME");
int fd, length;
char user_prefs_file[MAXPDSTRING]; /* user prefs file */
/* default prefs embedded in the package */
char default_prefs_file[MAXPDSTRING];
struct stat statbuf;

snprintf(default_prefs_file, MAXPDSTRING, "%s/default.pdsettings",
sys_libdir->s_name);
snprintf(user_prefs_file, MAXPDSTRING, "%s/.pdsettings",
(homedir ? homedir : "."));
if (stat(user_prefs_file, &statbuf) == 0)
strncpy(filenamebuf, user_prefs_file, MAXPDSTRING);
else if (stat(default_prefs_file, &statbuf) == 0)
strncpy(filenamebuf, default_prefs_file, MAXPDSTRING);
else return;
filenamebuf[MAXPDSTRING-1] = 0;
sys_initloadpreferences_file(filenamebuf);
}

static int sys_getpreference(const char *key, char *value, int size)
{
return (sys_getpreference_file(key, value, size));
}

static void sys_doneloadpreferences( void)
{
sys_doneloadpreferences_file();
}

static void sys_initsavepreferences( void)
{
char filenamebuf[MAXPDSTRING],
*homedir = getenv("HOME");
FILE *fp;

if (!homedir)
return;
snprintf(filenamebuf, MAXPDSTRING, "%s/.pdsettings", homedir);
filenamebuf[MAXPDSTRING-1] = 0;
sys_initsavepreferences_file(filenamebuf);
}

static void sys_putpreference(const char *key, const char *value)
{
sys_putpreference_file(key, value);
}

static void sys_donesavepreferences( void)
{
sys_donesavepreferences_file();
}

#else /* !defined(_WIN32) && !defined(__APPLE__) */

static void sys_initloadpreferences( void)
{
if (sys_prefbuf)
bug("sys_initloadpreferences");
}
static void sys_doneloadpreferences( void)
{
if (sys_prefbuf)
sys_doneloadpreferences_file();
}
static void sys_initsavepreferences( void)
{
if (sys_prefsavefp)
bug("sys_initsavepreferences");
}
static void sys_donesavepreferences( void)
{
if (sys_prefsavefp)
sys_donesavepreferences_file();
}

static int sys_getpreference(const char *key, char *value, int size)
{
if (sys_prefbuf)
return (sys_getpreference_file(key, value, size));
else
{
#ifdef _WIN32
HKEY hkey;
DWORD bigsize = size;
LONG err = RegOpenKeyEx(HKEY_CURRENT_USER,
"Software\\Pure-Data", 0, KEY_QUERY_VALUE, &hkey);
if (err != ERROR_SUCCESS)
return (0);
err = RegQueryValueEx(hkey, key, 0, 0, value, &bigsize);
if (err != ERROR_SUCCESS)
{
RegCloseKey(hkey);
return (0);
}
RegCloseKey(hkey);
return (1);
#endif /* _WIN32 */
#ifdef __APPLE__
char cmdbuf[256];
int nread = 0, nleft = size;
char embedded_prefs[MAXPDSTRING];
char user_prefs[MAXPDSTRING];
char *homedir = getenv("HOME");
struct stat statbuf;
/* the 'defaults' command expects the filename without .plist at the
end */
snprintf(embedded_prefs, MAXPDSTRING, "%s/../org.puredata.pd",
sys_libdir->s_name);
snprintf(user_prefs, MAXPDSTRING,
"%s/Library/Preferences/org.puredata.pd.plist", homedir);
if (stat(user_prefs, &statbuf) == 0)
snprintf(cmdbuf, 256, "defaults read org.puredata.pd %s 2> /dev/null\n",
key);
else snprintf(cmdbuf, 256, "defaults read %s %s 2> /dev/null\n",
embedded_prefs, key);
FILE *fp = popen(cmdbuf, "r");
while (nread < size)
{
int newread = fread(value+nread, 1, size-nread, fp);
if (newread <= 0)
break;
nread += newread;
}
pclose(fp);
if (nread < 1)
return (0);
if (nread >= size)
nread = size-1;
value[nread] = 0;
if (value[nread-1] == '\n') /* remove newline character at end */
value[nread-1] = 0;
return(1);
#endif /* __APPLE__ */
}
}

static void sys_putpreference(const char *key, const char *value)
{
if (sys_prefsavefp)
sys_putpreference_file(key, value);
else
{
#ifdef _WIN32
HKEY hkey;
LONG err = RegCreateKeyEx(HKEY_CURRENT_USER,
"Software\\Pure-Data", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
NULL, &hkey, NULL);
if (err != ERROR_SUCCESS)
{
error("unable to create registry entry: %s\n", key);
return;
}
err = RegSetValueEx(hkey, key, 0, REG_EXPAND_SZ, value, strlen(value)+1);
if (err != ERROR_SUCCESS)
error("unable to set registry entry: %s\n", key);
RegCloseKey(hkey);
#endif /* _WIN32 */
#ifdef __APPLE__
char cmdbuf[MAXPDSTRING];
snprintf(cmdbuf, MAXPDSTRING,
"defaults write org.puredata.pd %s \"%s\" 2> /dev/null\n", key, value);
system(cmdbuf);
#endif /* __APPLE__ */
}
}
#endif /* !defined(_WIN32) && !defined(__APPLE__) */

void sys_loadpreferences(const char *filename, int startingup)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
int i, rate = 0, advance = -1, callback = 0, blocksize = 0,
api, midiapi, nolib, maxi;
char prefbuf[MAXPDSTRING], keybuf[80];

if (*filename)
sys_initloadpreferences_file(filename);
else sys_initloadpreferences();
/* load audio preferences */
if (sys_getpreference("audioapi", prefbuf, MAXPDSTRING)
&& sscanf(prefbuf, "%d", &api) > 0)
sys_set_audio_api(api);
/* JMZ/MB: brackets for initializing */
if (sys_getpreference("noaudioin", prefbuf, MAXPDSTRING) &&
(!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True")))
naudioindev = 0;
else
{
for (i = 0, naudioindev = 0; i < MAXAUDIOINDEV; i++)
{
/* first try to find a name - if that matches an existing
device use it. Otherwise fall back to device number. */
int devn;
/* read in device number and channel count */
sprintf(keybuf, "audioindev%d", i+1);
if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING))
break;
if (sscanf(prefbuf, "%d %d", &audioindev[i], &chindev[i]) < 2)
break;
/* possibly override device number if the device name was
also saved and if it matches one we have now */
sprintf(keybuf, "audioindevname%d", i+1);
if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING)
&& (devn = sys_audiodevnametonumber(0, prefbuf)) >= 0)
audioindev[i] = devn;
naudioindev++;
}
/* if no preferences at all, set -1 for default behavior */
if (naudioindev == 0)
naudioindev = -1;
}
/* JMZ/MB: brackets for initializing */
if (sys_getpreference("noaudioout", prefbuf, MAXPDSTRING) &&
(!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True")))
naudiooutdev = 0;
else
{
for (i = 0, naudiooutdev = 0; i < MAXAUDIOOUTDEV; i++)
{
int devn;
sprintf(keybuf, "audiooutdev%d", i+1);
if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING))
break;
if (sscanf(prefbuf, "%d %d", &audiooutdev[i], &choutdev[i]) < 2)
break;
sprintf(keybuf, "audiooutdevname%d", i+1);
if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING)
&& (devn = sys_audiodevnametonumber(1, prefbuf)) >= 0)
audiooutdev[i] = devn;
naudiooutdev++;
}
if (naudiooutdev == 0)
naudiooutdev = -1;
}
if (sys_getpreference("rate", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &rate);
if (sys_getpreference("audiobuf", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &advance);
if (sys_getpreference("callback", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &callback);
if (sys_getpreference("blocksize", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &blocksize);
sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev,
naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
callback, blocksize);

/* load MIDI preferences */
if (sys_getpreference("midiapi", prefbuf, MAXPDSTRING)
&& sscanf(prefbuf, "%d", &midiapi) > 0)
sys_set_midi_api(midiapi);
/* JMZ/MB: brackets for initializing */
if (sys_getpreference("nomidiin", prefbuf, MAXPDSTRING) &&
(!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True")))
nmidiindev = 0;
else for (i = 0, nmidiindev = 0; i < MAXMIDIINDEV; i++)
{
/* first try to find a name - if that matches an existing device
use it. Otherwise fall back to device number. */
int devn;
sprintf(keybuf, "midiindevname%d", i+1);
if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING)
&& (devn = sys_mididevnametonumber(0, prefbuf)) >= 0)
midiindev[i] = devn;
else
{
sprintf(keybuf, "midiindev%d", i+1);
if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING))
break;
if (sscanf(prefbuf, "%d", &midiindev[i]) < 1)
break;
}
nmidiindev++;
}
/* JMZ/MB: brackets for initializing */
if (sys_getpreference("nomidiout", prefbuf, MAXPDSTRING) &&
(!strcmp(prefbuf, ".") || !strcmp(prefbuf, "True")))
nmidioutdev = 0;
else for (i = 0, nmidioutdev = 0; i < MAXMIDIOUTDEV; i++)
{
int devn;
sprintf(keybuf, "midioutdevname%d", i+1);
if (sys_getpreference(keybuf, prefbuf, MAXPDSTRING)
&& (devn = sys_mididevnametonumber(1, prefbuf)) >= 0)
midioutdev[i] = devn;
else
{
sprintf(keybuf, "midioutdev%d", i+1);
if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING))
break;
if (sscanf(prefbuf, "%d", &midioutdev[i]) < 1)
break;
}
nmidioutdev++;
}
sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0);

/* search path */
if (sys_getpreference("npath", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &maxi);
else maxi = 0x7fffffff;
for (i = 0; i<maxi; i++)
{
sprintf(keybuf, "path%d", i+1);
if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING))
break;
STUFF->st_searchpath =
namelist_append_files(STUFF->st_searchpath, prefbuf);
}
if (sys_getpreference("standardpath", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_usestdpath);
if (sys_getpreference("verbose", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_verbose);

/* startup settings */
if (sys_getpreference("nloadlib", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &maxi);
else maxi = 0x7fffffff;
for (i = 0; i<maxi; i++)
{
sprintf(keybuf, "loadlib%d", i+1);
if (!sys_getpreference(keybuf, prefbuf, MAXPDSTRING))
break;
STUFF->st_externlist = namelist_append_files(STUFF->st_externlist, prefbuf);
}
if (sys_getpreference("defeatrt", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_defeatrt);
if (sys_getpreference("flags", prefbuf, MAXPDSTRING) &&
strcmp(prefbuf, "."))
{
sys_flags = gensym(prefbuf);
if (startingup)
sys_doflags();
}
if (sys_defeatrt)
sys_hipriority = 0;
else
#if defined(__linux__) || defined(__CYGWIN__)
sys_hipriority = 1;
#else
#if defined(_WIN32) || defined(ANDROID)
sys_hipriority = 0;
#else
sys_hipriority = 1;
#endif
#endif
if (sys_getpreference("zoom", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &sys_zoom_open);

sys_doneloadpreferences();
}

void sys_savepreferences(const char *filename)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int i, rate, advance, callback, blocksize;
char buf1[MAXPDSTRING], buf2[MAXPDSTRING];
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];

if (filename && *filename)
sys_initsavepreferences_file(filename);
else sys_initsavepreferences();
/* audio settings */
sprintf(buf1, "%d", sys_audioapi);
sys_putpreference("audioapi", buf1);

sys_get_audio_params(&naudioindev, audioindev, chindev,
&naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
&blocksize);

sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False"));
for (i = 0; i < naudioindev; i++)
{
sprintf(buf1, "audioindev%d", i+1);
sprintf(buf2, "%d %d", audioindev[i], chindev[i]);
sys_putpreference(buf1, buf2);
sprintf(buf1, "audioindevname%d", i+1);
sys_audiodevnumbertoname(0, audioindev[i], buf2, MAXPDSTRING);
if (! *buf2)
strcat(buf2, "?");
sys_putpreference(buf1, buf2);
}
sys_putpreference("noaudioout", (naudiooutdev <= 0 ? "True" : "False"));
for (i = 0; i < naudiooutdev; i++)
{
sprintf(buf1, "audiooutdev%d", i+1);
sprintf(buf2, "%d %d", audiooutdev[i], choutdev[i]);
sys_putpreference(buf1, buf2);
sprintf(buf1, "audiooutdevname%d", i+1);
sys_audiodevnumbertoname(1, audiooutdev[i], buf2, MAXPDSTRING);
if (! *buf2)
strcat(buf2, "?");
sys_putpreference(buf1, buf2);
}

sprintf(buf1, "%d", advance);
sys_putpreference("audiobuf", buf1);

sprintf(buf1, "%d", rate);
sys_putpreference("rate", buf1);

sprintf(buf1, "%d", callback);
sys_putpreference("callback", buf1);

sprintf(buf1, "%d", blocksize);
sys_putpreference("blocksize", buf1);

/* MIDI settings */
sprintf(buf1, "%d", sys_midiapi);
sys_putpreference("midiapi", buf1);

sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev);
sys_putpreference("nomidiin", (nmidiindev <= 0 ? "True" : "False"));
for (i = 0; i < nmidiindev; i++)
{
sprintf(buf1, "midiindev%d", i+1);
sprintf(buf2, "%d", midiindev[i]);
sys_putpreference(buf1, buf2);
sprintf(buf1, "midiindevname%d", i+1);
sys_mididevnumbertoname(0, midiindev[i], buf2, MAXPDSTRING);
if (! *buf2)
strcat(buf2, "?");
sys_putpreference(buf1, buf2);
}
sys_putpreference("nomidiout", (nmidioutdev <= 0 ? "True" : "False"));
for (i = 0; i < nmidioutdev; i++)
{
sprintf(buf1, "midioutdev%d", i+1);
sprintf(buf2, "%d", midioutdev[i]);
sys_putpreference(buf1, buf2);
sprintf(buf1, "midioutdevname%d", i+1);
sys_mididevnumbertoname(1, midioutdev[i], buf2, MAXPDSTRING);
if (! *buf2)
strcat(buf2, "?");
sys_putpreference(buf1, buf2);
}
/* file search path */

for (i = 0; 1; i++)
{
char *pathelem = namelist_get(STUFF->st_searchpath, i);
if (!pathelem)
break;
sprintf(buf1, "path%d", i+1);
sys_putpreference(buf1, pathelem);
}
sprintf(buf1, "%d", i);
sys_putpreference("npath", buf1);
sprintf(buf1, "%d", sys_usestdpath);
sys_putpreference("standardpath", buf1);
sprintf(buf1, "%d", sys_verbose);
sys_putpreference("verbose", buf1);

/* startup */
for (i = 0; 1; i++)
{
char *pathelem = namelist_get(STUFF->st_externlist, i);
if (!pathelem)
break;
sprintf(buf1, "loadlib%d", i+1);
sys_putpreference(buf1, pathelem);
}
sprintf(buf1, "%d", i);
sys_putpreference("nloadlib", buf1);
sprintf(buf1, "%d", sys_defeatrt);
sys_putpreference("defeatrt", buf1);
sys_putpreference("flags",
(sys_flags ? sys_flags->s_name : ""));
/* misc */
sprintf(buf1, "%d", sys_zoom_open);
sys_putpreference("zoom", buf1);
sys_putpreference("loading", "no");

sys_donesavepreferences();
}

/* calls from GUI to load/save from/to a file */
void glob_loadpreferences(t_pd *dummy, t_symbol *filesym)
{
sys_loadpreferences(filesym->s_name, 0);
sys_close_audio();
sys_reopen_audio();
sys_close_midi();
sys_reopen_midi();
}

void glob_savepreferences(t_pd *dummy, t_symbol *filesym)
{
sys_savepreferences(filesym->s_name);
}

void glob_forgetpreferences(t_pd *dummy)
{
#if !defined(_WIN32) && !defined(__APPLE__)
if (system("cat ~/.pdsettings >& /dev/null\n"))
post("no Pd settings to clear");
else if (!system("rm ~/.pdsettings\n"))
post("removed .pdsettings file");
else post("couldn't delete .pdsettings file");
#endif /* !defined(_WIN32) && !defined(__APPLE__) */
#ifdef __APPLE__
char cmdbuf[MAXPDSTRING];
int warn = 1;
if (!sys_getpreference("audioapi", cmdbuf, MAXPDSTRING))
post("no Pd settings to clear"), warn = 0;
/* do it anyhow, why not... */
snprintf(cmdbuf, MAXPDSTRING,
"defaults delete org.puredata.pd 2> /dev/null\n");
if (system(cmdbuf) && warn)
post("failed to erase Pd settings");
else if(warn) post("erased Pd settings");
#endif /* __APPLE__ */
#ifdef _WIN32
HKEY hkey;
if (RegOpenKeyEx(HKEY_CURRENT_USER,
"Software", 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
post("no Pd settings to erase");
else
{
if (RegDeleteKey(hkey, "Pure-Data") != ERROR_SUCCESS)
post("no Pd settings to erase");
else post("erased Pd settings");
RegCloseKey(hkey);
}
#endif /* _WIN32 */
}

int sys_oktoloadfiles(int done)
{
#if defined(_WIN32) || defined(__APPLE__)
if (done)
{
sys_putpreference("loading", "no");
return (1);
}
else
{
char prefbuf[MAXPDSTRING];
if (sys_getpreference("loading", prefbuf, MAXPDSTRING) &&
strcmp(prefbuf, "no"))
{
post(
"skipping loading preferences... Pd seems to have crashed on startup.");
post("(re-save preferences to reinstate them)");
return (0);
}
else
{
sys_putpreference("loading", "yes");
return (1);
}
}
#else
return (1);
#endif
}

+ 1607
- 0
ports/camomile/source/LibPd/pure-data/src/s_inter.c
File diff suppressed because it is too large
View File


+ 492
- 0
ports/camomile/source/LibPd/pure-data/src/s_loader.c View File

@@ -0,0 +1,492 @@
/* 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. */

#if defined(HAVE_LIBDL) || defined(__FreeBSD__)
#include <dlfcn.h>
#endif
#ifdef HAVE_UNISTD_H
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#endif
#ifdef _WIN32
#include <io.h>
#include <windows.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
#include <string.h>
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#include <sys/stat.h>
#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
#define snprintf _snprintf
#define stat _stat
#endif

typedef void (*t_xxx)(void);

/* naming convention for externs. The names are kept distinct for those
who wish to make "fat" externs compiled for many platforms. Less specific
fallbacks are provided, primarily for back-compatibility; these suffice if
you are building a package which will run with a single set of compiled
objects. The specific name is the letter b, l, d, or m for BSD, linux,
darwin, or microsoft, followed by a more specific string, either "fat" for
a fat binary or an indication of the instruction set. */

#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) || defined(__FreeBSD__)
static char sys_dllextent2[] = ".pd_linux";
# ifdef __x86_64__
static char sys_dllextent[] = ".l_ia64"; // this should be .l_x86_64 or .l_amd64
# elif defined(__i386__) || defined(_M_IX86)
static char sys_dllextent[] = ".l_i386";
# elif defined(__arm__)
static char sys_dllextent[] = ".l_arm";
# else
static char sys_dllextent[] = ".so";
# endif
#elif defined(__APPLE__)
# ifndef MACOSX3
static char sys_dllextent[] = ".d_fat", sys_dllextent2[] = ".pd_darwin";
# else
static char sys_dllextent[] = ".d_ppc", sys_dllextent2[] = ".pd_darwin";
# endif
#elif defined(_WIN32) || defined(__CYGWIN__)
static char sys_dllextent[] = ".m_i386", sys_dllextent2[] = ".dll";
#else
static char sys_dllextent[] = ".so", sys_dllextent2[] = ".so";
#endif

/* maintain list of loaded modules to avoid repeating loads */
typedef struct _loadedlist
{
struct _loadedlist *ll_next;
t_symbol *ll_name;
} t_loadlist;

static t_loadlist *sys_loaded;
int sys_onloadlist(const char *classname) /* return true if already loaded */
{
t_symbol *s = gensym(classname);
t_loadlist *ll;
for (ll = sys_loaded; ll; ll = ll->ll_next)
if (ll->ll_name == s)
return (1);
return (0);
}

/* add to list of loaded modules */
void sys_putonloadlist(const char *classname)
{
t_loadlist *ll = (t_loadlist *)getbytes(sizeof(*ll));
ll->ll_name = gensym(classname);
ll->ll_next = sys_loaded;
sys_loaded = ll;
/* post("put on list %s", classname); */
}

void class_set_extern_dir(t_symbol *s);

static int sys_do_load_abs(t_canvas *canvas, const char *objectname,
const char *path);
static int sys_do_load_lib(t_canvas *canvas, const char *objectname,
const char *path)
{
char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING],
*nameptr, altsymname[MAXPDSTRING];
const char *classname, *cnameptr;
void *dlobj;
t_xxx makeout = NULL;
int i, hexmunge = 0, fd;
#ifdef _WIN32
HINSTANCE ntdll;
#endif
/* NULL-path is only used as a last resort,
but we have already tried all paths */
if(!path)return (0);

if ((classname = strrchr(objectname, '/')))
classname++;
else classname = objectname;
for (i = 0, cnameptr = classname; i < MAXPDSTRING-7 && *cnameptr;
cnameptr++)
{
char c = *cnameptr;
if ((c>='0' && c<='9') || (c>='A' && c<='Z')||
(c>='a' && c<='z' )|| c == '_')
{
symname[i] = c;
i++;
}
/* trailing tilde becomes "_tilde" */
else if (c == '~' && cnameptr[1] == 0)
{
strcpy(symname+i, "_tilde");
i += strlen(symname+i);
}
else /* anything you can't put in a C symbol is sprintf'ed in hex */
{
sprintf(symname+i, "0x%02x", c);
i += strlen(symname+i);
hexmunge = 1;
}
}
symname[i] = 0;
if (hexmunge)
{
memmove(symname+6, symname, strlen(symname)+1);
strncpy(symname, "setup_", 6);
}
else strcat(symname, "_setup");

#if 0
fprintf(stderr, "lib: %s\n", classname);
#endif
/* try looking in the path for (objectname).(sys_dllextent) ... */
if ((fd = sys_trytoopenone(path, objectname, sys_dllextent,
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0)
goto gotone;
/* same, with the more generic sys_dllextent2 */
if ((fd = sys_trytoopenone(path, objectname, sys_dllextent2,
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0)
goto gotone;
/* next try (objectname)/(classname).(sys_dllextent) ... */
strncpy(filename, objectname, MAXPDSTRING);
filename[MAXPDSTRING-2] = 0;
strcat(filename, "/");
strncat(filename, classname, MAXPDSTRING-strlen(filename));
filename[MAXPDSTRING-1] = 0;
if ((fd = sys_trytoopenone(path, filename, sys_dllextent,
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0)
goto gotone;
if ((fd = sys_trytoopenone(path, filename, sys_dllextent2,
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0)
goto gotone;
#ifdef ANDROID
/* Android libs have a 'lib' prefix, '.so' suffix and don't allow ~ */
char libname[MAXPDSTRING] = "lib";
strncat(libname, objectname, MAXPDSTRING - 4);
int len = strlen(libname);
if (libname[len-1] == '~' && len < MAXPDSTRING - 6) {
strcpy(libname+len-1, "_tilde");
}
if ((fd = sys_trytoopenone(path, libname, ".so",
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0)
goto gotone;
#endif
return (0);
gotone:
close(fd);
class_set_extern_dir(gensym(dirbuf));

/* rebuild the absolute pathname */
strncpy(filename, dirbuf, MAXPDSTRING);
filename[MAXPDSTRING-2] = 0;
strcat(filename, "/");
strncat(filename, nameptr, MAXPDSTRING-strlen(filename));
filename[MAXPDSTRING-1] = 0;

#ifdef _WIN32
{
char dirname[MAXPDSTRING], *s, *basename;
sys_bashfilename(filename, filename);
/* set the dirname as DllDirectory, meaning in the path for
loading other DLLs so that dependent libraries can be included
in the same folder as the external. SetDllDirectory() needs a
minimum supported version of Windows XP SP1 for
SetDllDirectory, so WINVER must be 0x0502 */
strncpy(dirname, filename, MAXPDSTRING);
s = strrchr(dirname, '\\');
basename = s;
if (s && *s)
*s = '\0';
if (!SetDllDirectory(dirname))
error("Could not set '%s' as DllDirectory(), '%s' might not load.",
dirname, basename);
/* now load the DLL for the external */
ntdll = LoadLibrary(filename);
if (!ntdll)
{
error("%s: couldn't load", filename);
class_set_extern_dir(&s_);
return (0);
}
makeout = (t_xxx)GetProcAddress(ntdll, symname);
if (!makeout)
makeout = (t_xxx)GetProcAddress(ntdll, "setup");
SetDllDirectory(NULL); /* reset DLL dir to nothing */
}
#elif defined(HAVE_LIBDL) || defined(__FreeBSD__)
dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
if (!dlobj)
{
error("%s: %s", filename, dlerror());
class_set_extern_dir(&s_);
return (0);
}
makeout = (t_xxx)dlsym(dlobj, symname);
if(!makeout)
makeout = (t_xxx)dlsym(dlobj, "setup");
#else
#warning "No dynamic loading mechanism specified, \
libdl or WIN32 required for loading externals!"
#endif

if (!makeout)
{
error("load_object: Symbol \"%s\" not found", symname);
class_set_extern_dir(&s_);
return 0;
}
(*makeout)();
class_set_extern_dir(&s_);
return (1);
}


/* linked list of loaders */
typedef struct loader_queue {
loader_t loader;
struct loader_queue *next;
} loader_queue_t;

static loader_queue_t loaders = {sys_do_load_lib, NULL};

/* register class loader function */
void sys_register_loader(loader_t loader)
{
loader_queue_t *q = &loaders;
while (1)
{
if (q->loader == loader) /* already loaded - nothing to do */
return;
else if (q->next)
q = q->next;
else
{
q->next = (loader_queue_t *)getbytes(sizeof(loader_queue_t));
q->next->loader = loader;
q->next->next = NULL;
break;
}
}
}

#include "g_canvas.h"

/* the data passed to the iter-function */
struct _loadlib_data
{
t_canvas *canvas;
const char *classname;
int ok;
};

int sys_loadlib_iter(const char *path, struct _loadlib_data *data)
{
int ok = 0;
loader_queue_t *q;
for(q = &loaders; q; q = q->next)
if ((ok = q->loader(data->canvas, data->classname, path)))
break;
/* if all loaders failed, try to load as abstraction */
if (!ok)
ok = sys_do_load_abs(data->canvas, data->classname, path);
data->ok = ok;
return (ok == 0);
}

int sys_load_lib(t_canvas *canvas, const char *classname)
{
int dspstate = canvas_suspend_dsp();
struct _loadlib_data data;
data.canvas = canvas;
data.ok = 0;

if (sys_onloadlist(classname))
{
error("%s: already loaded", classname);
return (1);
}
/* if classname is absolute, try this first */
if (sys_isabsolutepath(classname))
{
/* this is just copied from sys_open_absolute()
LATER avoid code duplication */
char dirbuf[MAXPDSTRING], *z = strrchr(classname, '/');
int dirlen;
if (!z)
return (0);
dirlen = (int)(z - classname);
if (dirlen > MAXPDSTRING-1)
dirlen = MAXPDSTRING-1;
strncpy(dirbuf, classname, dirlen);
dirbuf[dirlen] = 0;
data.classname=classname+(dirlen+1);
sys_loadlib_iter(dirbuf, &data);
}
data.classname = classname;
if(!data.ok)
canvas_path_iterate(canvas, (t_canvas_path_iterator)sys_loadlib_iter,
&data);

/* if loaders failed so far, we try a last time without a PATH
* let the loaders search wherever they want */
if (!data.ok)
sys_loadlib_iter(0, &data);

if(data.ok)
sys_putonloadlist(classname);


canvas_resume_dsp(dspstate);
return data.ok;
}

int sys_run_scheduler(const char *externalschedlibname,
const char *sys_extraflagsstring)
{
typedef int (*t_externalschedlibmain)(const char *);
t_externalschedlibmain externalmainfunc;
char filename[MAXPDSTRING];
struct stat statbuf;
snprintf(filename, sizeof(filename), "%s%s", externalschedlibname,
sys_dllextent);
sys_bashfilename(filename, filename);
/* if first-choice file extent can't 'stat', go for second */
if (stat(filename, &statbuf) < 0)
{
snprintf(filename, sizeof(filename), "%s%s", externalschedlibname,
sys_dllextent2);
sys_bashfilename(filename, filename);
}
#ifdef _WIN32
{
HINSTANCE ntdll = LoadLibrary(filename);
if (!ntdll)
{
fprintf(stderr, "%s: couldn't load external scheduler\n", filename);
error("%s: couldn't load external scheduler", filename);
return (1);
}
externalmainfunc =
(t_externalschedlibmain)GetProcAddress(ntdll, "pd_extern_sched");
if (!externalmainfunc)
externalmainfunc =
(t_externalschedlibmain)GetProcAddress(ntdll, "main");
}
#elif defined HAVE_LIBDL
{
void *dlobj;
dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
if (!dlobj)
{
error("%s: %s", filename, dlerror());
fprintf(stderr, "dlopen failed for %s: %s\n", filename, dlerror());
return (1);
}
externalmainfunc = (t_externalschedlibmain)dlsym(dlobj,
"pd_extern_sched");
}
#else
return (0);
#endif
if (externalmainfunc)
return((*externalmainfunc)(sys_extraflagsstring));
else
{
fprintf(stderr, "%s: couldn't find pd_extern_sched() or main()\n",
filename);
return (0);
}
}


/* abstraction loading */
void canvas_popabstraction(t_canvas *x);
int pd_setloadingabstraction(t_symbol *sym);

static t_pd *do_create_abstraction(t_symbol*s, int argc, t_atom *argv)
{
/*
* TODO: check if the there is a binbuf cached for <canvas::symbol>
and use that instead. We'll have to invalidate the cache once we
are done (either with a clock_delay(0) or something else)
*/
if (!pd_setloadingabstraction(s))
{
const char *objectname = s->s_name;
char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr;
t_glist *glist = (t_glist *)canvas_getcurrent();
t_canvas *canvas = (t_canvas*)glist_getcanvas(glist);
int fd = -1;

t_pd *was = s__X.s_thing;
snprintf(classslashclass, MAXPDSTRING, "%s/%s", objectname, objectname);
if ((fd = canvas_open(canvas, objectname, ".pd",
dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
(fd = canvas_open(canvas, objectname, ".pat",
dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
(fd = canvas_open(canvas, classslashclass, ".pd",
dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0)
{
close(fd);
canvas_setargs(argc, argv);

binbuf_evalfile(gensym(nameptr), gensym(dirbuf));
if (s__X.s_thing && was != s__X.s_thing)
canvas_popabstraction((t_canvas *)(s__X.s_thing));
else s__X.s_thing = was;
canvas_setargs(0, 0);
return (pd_this->pd_newest);
}
/* otherwise we couldn't do it; just return 0 */
}
else error("%s: can't load abstraction within itself\n", s->s_name);
pd_this->pd_newest = 0;
return (0);
}

/* search for abstraction; register a creator if found */
static int sys_do_load_abs(t_canvas *canvas, const char *objectname,
const char *path)
{
int fd;
static t_gobj*abstraction_classes = 0;
char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr;
/* NULL-path is only used as a last resort,
but we have already tried all paths */
if (!path) return (0);

snprintf(classslashclass, MAXPDSTRING, "%s/%s", objectname, objectname);
if ((fd = sys_trytoopenone(path, objectname, ".pd",
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0 ||
(fd = sys_trytoopenone(path, objectname, ".pat",
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0 ||
(fd = sys_trytoopenone(path, classslashclass, ".pd",
dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0)
{
t_class*c=0;
close(fd);
/* found an abstraction, now register it as a new pseudo-class */
class_set_extern_dir(gensym(dirbuf));
if((c=class_new(gensym(objectname),
(t_newmethod)do_create_abstraction, 0,
0, 0, A_GIMME, 0)))
{
/* store away the newly created class, maybe we will need it one day */
t_gobj*absclass=0;
absclass=t_getbytes(sizeof(*absclass));
absclass->g_pd=c;
absclass->g_next=abstraction_classes;
abstraction_classes=absclass;
}
class_set_extern_dir(&s_);

return (1);
}
return (0);
}

+ 1469
- 0
ports/camomile/source/LibPd/pure-data/src/s_main.c
File diff suppressed because it is too large
View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save