Browse Source

Import PdPulp code

master
falkTX 9 years ago
parent
commit
9f10632fe6
100 changed files with 52838 additions and 0 deletions
  1. +33
    -0
      ports/PdPulp/JuceLibraryCode/JuceHeader.h
  2. +135
    -0
      ports/PdPulp/JuceLibraryCode/JucePluginCharacteristics.h
  3. +109
    -0
      ports/PdPulp/LV2-fx/premake.lua
  4. +109
    -0
      ports/PdPulp/LV2-ins/premake.lua
  5. +68
    -0
      ports/PdPulp/Source/FloatParameter.h
  6. +322
    -0
      ports/PdPulp/Source/MainComponent.cpp
  7. +91
    -0
      ports/PdPulp/Source/MainComponent.h
  8. +1118
    -0
      ports/PdPulp/Source/PdBase.cpp
  9. +522
    -0
      ports/PdPulp/Source/PdBase.hpp
  10. +35
    -0
      ports/PdPulp/Source/PdMidiReceiver.hpp
  11. +36
    -0
      ports/PdPulp/Source/PdReceiver.hpp
  12. +196
    -0
      ports/PdPulp/Source/PdTypes.cpp
  13. +306
    -0
      ports/PdPulp/Source/PdTypes.hpp
  14. +108
    -0
      ports/PdPulp/Source/PluginEditor.cpp
  15. +68
    -0
      ports/PdPulp/Source/PluginEditor.h
  16. +375
    -0
      ports/PdPulp/Source/PluginProcessor.cpp
  17. +96
    -0
      ports/PdPulp/Source/PluginProcessor.h
  18. +187
    -0
      ports/PdPulp/Source/SendSlider.cpp
  19. +77
    -0
      ports/PdPulp/Source/SendSlider.h
  20. +1308
    -0
      ports/PdPulp/Source/mono-tape-echo.pd
  21. +101
    -0
      ports/PdPulp/Source/ringbuffer.c
  22. +46
    -0
      ports/PdPulp/Source/ringbuffer.h
  23. +92
    -0
      ports/PdPulp/Source/sawsynth.pd
  24. +34
    -0
      ports/PdPulp/Source/test2.pd
  25. +16
    -0
      ports/PdPulp/Source/test3.pd
  26. +57
    -0
      ports/PdPulp/Source/test4.pd
  27. +48
    -0
      ports/PdPulp/Source/z_print_util.c
  28. +45
    -0
      ports/PdPulp/Source/z_print_util.h
  29. +410
    -0
      ports/PdPulp/Source/z_queued.c
  30. +42
    -0
      ports/PdPulp/Source/z_queued.h
  31. +109
    -0
      ports/PdPulp/VST-fx/premake.lua
  32. +109
    -0
      ports/PdPulp/VST-ins/premake.lua
  33. +71
    -0
      ports/PdPulp/libpd/libpd_wrapper/s_libpdmidi.c
  34. +101
    -0
      ports/PdPulp/libpd/libpd_wrapper/util/ringbuffer.c
  35. +46
    -0
      ports/PdPulp/libpd/libpd_wrapper/util/ringbuffer.h
  36. +48
    -0
      ports/PdPulp/libpd/libpd_wrapper/util/z_print_util.c
  37. +45
    -0
      ports/PdPulp/libpd/libpd_wrapper/util/z_print_util.h
  38. +410
    -0
      ports/PdPulp/libpd/libpd_wrapper/util/z_queued.c
  39. +42
    -0
      ports/PdPulp/libpd/libpd_wrapper/util/z_queued.h
  40. +68
    -0
      ports/PdPulp/libpd/libpd_wrapper/x_libpdreceive.c
  41. +16
    -0
      ports/PdPulp/libpd/libpd_wrapper/x_libpdreceive.h
  42. +26
    -0
      ports/PdPulp/libpd/libpd_wrapper/z_hooks.c
  43. +35
    -0
      ports/PdPulp/libpd/libpd_wrapper/z_hooks.h
  44. +456
    -0
      ports/PdPulp/libpd/libpd_wrapper/z_libpd.c
  45. +115
    -0
      ports/PdPulp/libpd/libpd_wrapper/z_libpd.h
  46. +261
    -0
      ports/PdPulp/libpd/pure-data/src/CHANGELOG.txt
  47. +162
    -0
      ports/PdPulp/libpd/pure-data/src/Makefile.am
  48. +843
    -0
      ports/PdPulp/libpd/pure-data/src/d_arithmetic.c
  49. +1050
    -0
      ports/PdPulp/libpd/pure-data/src/d_array.c
  50. +850
    -0
      ports/PdPulp/libpd/pure-data/src/d_ctl.c
  51. +184
    -0
      ports/PdPulp/libpd/pure-data/src/d_dac.c
  52. +334
    -0
      ports/PdPulp/libpd/pure-data/src/d_delay.c
  53. +355
    -0
      ports/PdPulp/libpd/pure-data/src/d_fft.c
  54. +3482
    -0
      ports/PdPulp/libpd/pure-data/src/d_fft_fftsg.c
  55. +177
    -0
      ports/PdPulp/libpd/pure-data/src/d_fft_fftw.c
  56. +1082
    -0
      ports/PdPulp/libpd/pure-data/src/d_filter.c
  57. +361
    -0
      ports/PdPulp/libpd/pure-data/src/d_global.c
  58. +778
    -0
      ports/PdPulp/libpd/pure-data/src/d_math.c
  59. +136
    -0
      ports/PdPulp/libpd/pure-data/src/d_misc.c
  60. +513
    -0
      ports/PdPulp/libpd/pure-data/src/d_osc.c
  61. +216
    -0
      ports/PdPulp/libpd/pure-data/src/d_resample.c
  62. +2652
    -0
      ports/PdPulp/libpd/pure-data/src/d_soundfile.c
  63. +1203
    -0
      ports/PdPulp/libpd/pure-data/src/d_ugen.c
  64. +672
    -0
      ports/PdPulp/libpd/pure-data/src/g_all_guis.c
  65. +323
    -0
      ports/PdPulp/libpd/pure-data/src/g_all_guis.h
  66. +1245
    -0
      ports/PdPulp/libpd/pure-data/src/g_array.c
  67. +555
    -0
      ports/PdPulp/libpd/pure-data/src/g_bang.c
  68. +1664
    -0
      ports/PdPulp/libpd/pure-data/src/g_canvas.c
  69. +622
    -0
      ports/PdPulp/libpd/pure-data/src/g_canvas.h
  70. +2869
    -0
      ports/PdPulp/libpd/pure-data/src/g_editor.c
  71. +1103
    -0
      ports/PdPulp/libpd/pure-data/src/g_graph.c
  72. +97
    -0
      ports/PdPulp/libpd/pure-data/src/g_guiconnect.c
  73. +745
    -0
      ports/PdPulp/libpd/pure-data/src/g_hdial.c
  74. +638
    -0
      ports/PdPulp/libpd/pure-data/src/g_hslider.c
  75. +622
    -0
      ports/PdPulp/libpd/pure-data/src/g_io.c
  76. +387
    -0
      ports/PdPulp/libpd/pure-data/src/g_mycanvas.c
  77. +907
    -0
      ports/PdPulp/libpd/pure-data/src/g_numbox.c
  78. +787
    -0
      ports/PdPulp/libpd/pure-data/src/g_readwrite.c
  79. +643
    -0
      ports/PdPulp/libpd/pure-data/src/g_rtext.c
  80. +448
    -0
      ports/PdPulp/libpd/pure-data/src/g_scalar.c
  81. +2717
    -0
      ports/PdPulp/libpd/pure-data/src/g_template.c
  82. +1462
    -0
      ports/PdPulp/libpd/pure-data/src/g_text.c
  83. +477
    -0
      ports/PdPulp/libpd/pure-data/src/g_toggle.c
  84. +1276
    -0
      ports/PdPulp/libpd/pure-data/src/g_traversal.c
  85. +728
    -0
      ports/PdPulp/libpd/pure-data/src/g_vdial.c
  86. +640
    -0
      ports/PdPulp/libpd/pure-data/src/g_vslider.c
  87. +741
    -0
      ports/PdPulp/libpd/pure-data/src/g_vumeter.c
  88. +129
    -0
      ports/PdPulp/libpd/pure-data/src/m_atom.c
  89. +1530
    -0
      ports/PdPulp/libpd/pure-data/src/m_binbuf.c
  90. +871
    -0
      ports/PdPulp/libpd/pure-data/src/m_class.c
  91. +106
    -0
      ports/PdPulp/libpd/pure-data/src/m_conf.c
  92. +198
    -0
      ports/PdPulp/libpd/pure-data/src/m_glob.c
  93. +110
    -0
      ports/PdPulp/libpd/pure-data/src/m_imp.h
  94. +89
    -0
      ports/PdPulp/libpd/pure-data/src/m_memory.c
  95. +743
    -0
      ports/PdPulp/libpd/pure-data/src/m_obj.c
  96. +367
    -0
      ports/PdPulp/libpd/pure-data/src/m_pd.c
  97. +770
    -0
      ports/PdPulp/libpd/pure-data/src/m_pd.h
  98. +668
    -0
      ports/PdPulp/libpd/pure-data/src/m_sched.c
  99. +2139
    -0
      ports/PdPulp/libpd/pure-data/src/makefile.dependencies
  100. +224
    -0
      ports/PdPulp/libpd/pure-data/src/makefile.gnu

+ 33
- 0
ports/PdPulp/JuceLibraryCode/JuceHeader.h View File

@@ -0,0 +1,33 @@
/*
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.
*/
#ifndef __APPHEADERFILE_EDFSFF__
#define __APPHEADERFILE_EDFSFF__
#include "JucePluginMain.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 = "Pd Pulp";
const char* const versionString = "1.0.0";
const int versionNumber = 0x10000;
}
#endif
#endif // __APPHEADERFILE_EDFSFF__

+ 135
- 0
ports/PdPulp/JuceLibraryCode/JucePluginCharacteristics.h View File

@@ -0,0 +1,135 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
There's a section below where you can add your own custom code safely, and the
Introjucer will preserve the contents of that block, but the best way to change
any of these definitions is by using the Introjucer's project settings.
Any commented-out settings will assume their default values.
*/
#ifndef __JUCE_APPCONFIG_LIBPDPL__
#define __JUCE_APPCONFIG_LIBPDPL__
//==============================================================================
// Audio plugin settings..
#if PULP_SYNTH
#define JucePlugin_Name "Pd Pulp"
#define JucePlugin_MaxNumInputChannels 2
#define JucePlugin_MaxNumOutputChannels 2
#define JucePlugin_PreferredChannelConfigurations {0, 1}, {0, 2}
#define JucePlugin_IsSynth 1
#define JucePlugin_WantsMidiInput 1
#define JucePlugin_VSTCategory kPlugCategSynth
#define JucePlugin_PluginCode 'PDLP'
#else
#define JucePlugin_Name "Pd Pulp FX"
#define JucePlugin_MaxNumInputChannels 2
#define JucePlugin_MaxNumOutputChannels 2
#define JucePlugin_PreferredChannelConfigurations {1, 1}, {2, 2}
#define JucePlugin_IsSynth 0
#define JucePlugin_WantsMidiInput 0
#define JucePlugin_VSTCategory kPlugCategEffect
#define JucePlugin_PluginCode 'PDLF'
#endif
#ifndef JucePlugin_Desc
#define JucePlugin_Desc "a pure data audio plugin runtime environment"
#endif
#ifndef JucePlugin_Manufacturer
#define JucePlugin_Manufacturer "Audiosalt"
#endif
#ifndef JucePlugin_ManufacturerWebsite
#define JucePlugin_ManufacturerWebsite "audiosalt.com"
#endif
#ifndef JucePlugin_ManufacturerEmail
#define JucePlugin_ManufacturerEmail ""
#endif
#ifndef JucePlugin_ManufacturerCode
#define JucePlugin_ManufacturerCode 'ASLT'
#endif
#ifndef JucePlugin_ProducesMidiOutput
#define JucePlugin_ProducesMidiOutput 0
#endif
#ifndef JucePlugin_SilenceInProducesSilenceOut
#define JucePlugin_SilenceInProducesSilenceOut 0
#endif
#ifndef JucePlugin_EditorRequiresKeyboardFocus
#define JucePlugin_EditorRequiresKeyboardFocus 1
#endif
#ifndef JucePlugin_Version
#define JucePlugin_Version 1.0.0
#endif
#ifndef JucePlugin_VersionCode
#define JucePlugin_VersionCode 0x10000
#endif
#ifndef JucePlugin_VersionString
#define JucePlugin_VersionString "1.0.0"
#endif
#ifndef JucePlugin_VSTUniqueID
#define JucePlugin_VSTUniqueID JucePlugin_PluginCode
#endif
#ifndef JucePlugin_AUMainType
#define JucePlugin_AUMainType kAudioUnitType_MusicDevice
#endif
#ifndef JucePlugin_AUSubType
#define JucePlugin_AUSubType JucePlugin_PluginCode
#endif
#ifndef JucePlugin_AUExportPrefix
#define JucePlugin_AUExportPrefix PdPulpAU
#endif
#ifndef JucePlugin_AUExportPrefixQuoted
#define JucePlugin_AUExportPrefixQuoted "PdPulpAU"
#endif
#ifndef JucePlugin_AUManufacturerCode
#define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_CFBundleIdentifier
#define JucePlugin_CFBundleIdentifier com.audiosalt.pdpulp
#endif
#ifndef JucePlugin_RTASCategory
#define JucePlugin_RTASCategory ePlugInCategory_SWGenerators
#endif
#ifndef JucePlugin_RTASManufacturerCode
#define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_RTASProductId
#define JucePlugin_RTASProductId JucePlugin_PluginCode
#endif
#ifndef JucePlugin_RTASDisableBypass
#define JucePlugin_RTASDisableBypass 0
#endif
#ifndef JucePlugin_RTASDisableMultiMono
#define JucePlugin_RTASDisableMultiMono 0
#endif
#ifndef JucePlugin_AAXIdentifier
#define JucePlugin_AAXIdentifier com.audiosalt.pdpulp
#endif
#ifndef JucePlugin_AAXManufacturerCode
#define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_AAXProductId
#define JucePlugin_AAXProductId JucePlugin_PluginCode
#endif
#ifndef JucePlugin_AAXCategory
#define JucePlugin_AAXCategory AAX_ePlugInCategory_Dynamics
#endif
#ifndef JucePlugin_AAXDisableBypass
#define JucePlugin_AAXDisableBypass 0
#endif
#ifndef JucePlugin_AAXDisableMultiMono
#define JucePlugin_AAXDisableMultiMono 0
#endif
#define JucePlugin_LV2URI "http://pdpulp.audiosalt.com"
#define JucePlugin_WantsLV2Presets 0
#define JucePlugin_WantsLV2State 1
#define JucePlugin_WantsLV2TimePos 0
#define JucePlugin_WantsLV2FixedBlockSize 1
#endif // __JUCE_APPCONFIG_LIBPDPL__

+ 109
- 0
ports/PdPulp/LV2-fx/premake.lua View File

@@ -0,0 +1,109 @@
dofile("../../../scripts/make-project.lua")
package = make_juce_lv2_project("PdPulpFX")
package.buildoptions = {
package.buildoptions,
"-Wno-unused",
"-Wno-unused-parameter",
"-Wno-parentheses",
"-Wno-switch"
}
package.defines = {
package.defines,
"PULP_SYNTH=0",
"USEAPI_DUMMY",
"PD",
"HAVE_LIBDL",
"HAVE_UNISTD_H",
"HAVE_ALLOCA_H",
"_LARGEFILE64_SOURCE"
}
package.includepaths = {
package.includepaths,
"../Source",
"../JuceLibraryCode",
"../libpd/libpd_wrapper",
"../libpd/pure-data/src"
}
package.files = {
matchfiles (
"../Source/*.c",
"../Source/*.cpp",
"../libpd/pure-data/src/g_canvas.c",
"../libpd/pure-data/src/g_graph.c",
"../libpd/pure-data/src/g_text.c",
"../libpd/pure-data/src/g_rtext.c",
"../libpd/pure-data/src/g_array.c",
"../libpd/pure-data/src/g_template.c",
"../libpd/pure-data/src/g_io.c",
"../libpd/pure-data/src/g_scalar.c",
"../libpd/pure-data/src/g_traversal.c",
"../libpd/pure-data/src/g_guiconnect.c",
"../libpd/pure-data/src/g_readwrite.c",
"../libpd/pure-data/src/g_editor.c",
"../libpd/pure-data/src/g_all_guis.c",
"../libpd/pure-data/src/g_bang.c",
"../libpd/pure-data/src/g_hdial.c",
"../libpd/pure-data/src/g_hslider.c",
"../libpd/pure-data/src/g_mycanvas.c",
"../libpd/pure-data/src/g_numbox.c",
"../libpd/pure-data/src/g_toggle.c",
"../libpd/pure-data/src/g_vdial.c",
"../libpd/pure-data/src/g_vslider.c",
"../libpd/pure-data/src/g_vumeter.c",
"../libpd/pure-data/src/m_pd.c",
"../libpd/pure-data/src/m_class.c",
"../libpd/pure-data/src/m_obj.c",
"../libpd/pure-data/src/m_atom.c",
"../libpd/pure-data/src/m_memory.c",
"../libpd/pure-data/src/m_binbuf.c",
"../libpd/pure-data/src/m_conf.c",
"../libpd/pure-data/src/m_glob.c",
"../libpd/pure-data/src/m_sched.c",
"../libpd/pure-data/src/s_main.c",
"../libpd/pure-data/src/s_inter.c",
"../libpd/pure-data/src/s_file.c",
"../libpd/pure-data/src/s_print.c",
"../libpd/pure-data/src/s_loader.c",
"../libpd/pure-data/src/s_path.c",
"../libpd/pure-data/src/s_audio.c",
"../libpd/pure-data/src/s_audio_dummy.c",
"../libpd/pure-data/src/s_utf8.c",
"../libpd/pure-data/src/s_audio_paring.c",
"../libpd/pure-data/src/d_ugen.c",
"../libpd/pure-data/src/d_ctl.c",
"../libpd/pure-data/src/d_arithmetic.c",
"../libpd/pure-data/src/d_osc.c",
"../libpd/pure-data/src/d_filter.c",
"../libpd/pure-data/src/d_dac.c",
"../libpd/pure-data/src/d_misc.c",
"../libpd/pure-data/src/d_math.c",
"../libpd/pure-data/src/d_fft.c",
"../libpd/pure-data/src/d_fft_fftsg.c",
"../libpd/pure-data/src/d_array.c",
"../libpd/pure-data/src/d_global.c",
"../libpd/pure-data/src/d_delay.c",
"../libpd/pure-data/src/d_resample.c",
"../libpd/pure-data/src/d_soundfile.c",
"../libpd/pure-data/src/x_arithmetic.c",
"../libpd/pure-data/src/x_connective.c",
"../libpd/pure-data/src/x_interface.c",
"../libpd/pure-data/src/x_midi.c",
"../libpd/pure-data/src/x_misc.c",
"../libpd/pure-data/src/x_time.c",
"../libpd/pure-data/src/x_acoustics.c",
"../libpd/pure-data/src/x_net.c",
"../libpd/pure-data/src/x_text.c",
"../libpd/pure-data/src/x_gui.c",
"../libpd/pure-data/src/x_list.c",
"../libpd/pure-data/src/x_array.c",
"../libpd/pure-data/src/x_scalar.c",
"../libpd/libpd_wrapper/*.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}

+ 109
- 0
ports/PdPulp/LV2-ins/premake.lua View File

@@ -0,0 +1,109 @@
dofile("../../../scripts/make-project.lua")
package = make_juce_lv2_project("PdPulp")
package.buildoptions = {
package.buildoptions,
"-Wno-unused",
"-Wno-unused-parameter",
"-Wno-parentheses",
"-Wno-switch"
}
package.defines = {
package.defines,
"PULP_SYNTH=1",
"USEAPI_DUMMY",
"PD",
"HAVE_LIBDL",
"HAVE_UNISTD_H",
"HAVE_ALLOCA_H",
"_LARGEFILE64_SOURCE"
}
package.includepaths = {
package.includepaths,
"../Source",
"../JuceLibraryCode",
"../libpd/libpd_wrapper",
"../libpd/pure-data/src"
}
package.files = {
matchfiles (
"../Source/*.c",
"../Source/*.cpp",
"../libpd/pure-data/src/g_canvas.c",
"../libpd/pure-data/src/g_graph.c",
"../libpd/pure-data/src/g_text.c",
"../libpd/pure-data/src/g_rtext.c",
"../libpd/pure-data/src/g_array.c",
"../libpd/pure-data/src/g_template.c",
"../libpd/pure-data/src/g_io.c",
"../libpd/pure-data/src/g_scalar.c",
"../libpd/pure-data/src/g_traversal.c",
"../libpd/pure-data/src/g_guiconnect.c",
"../libpd/pure-data/src/g_readwrite.c",
"../libpd/pure-data/src/g_editor.c",
"../libpd/pure-data/src/g_all_guis.c",
"../libpd/pure-data/src/g_bang.c",
"../libpd/pure-data/src/g_hdial.c",
"../libpd/pure-data/src/g_hslider.c",
"../libpd/pure-data/src/g_mycanvas.c",
"../libpd/pure-data/src/g_numbox.c",
"../libpd/pure-data/src/g_toggle.c",
"../libpd/pure-data/src/g_vdial.c",
"../libpd/pure-data/src/g_vslider.c",
"../libpd/pure-data/src/g_vumeter.c",
"../libpd/pure-data/src/m_pd.c",
"../libpd/pure-data/src/m_class.c",
"../libpd/pure-data/src/m_obj.c",
"../libpd/pure-data/src/m_atom.c",
"../libpd/pure-data/src/m_memory.c",
"../libpd/pure-data/src/m_binbuf.c",
"../libpd/pure-data/src/m_conf.c",
"../libpd/pure-data/src/m_glob.c",
"../libpd/pure-data/src/m_sched.c",
"../libpd/pure-data/src/s_main.c",
"../libpd/pure-data/src/s_inter.c",
"../libpd/pure-data/src/s_file.c",
"../libpd/pure-data/src/s_print.c",
"../libpd/pure-data/src/s_loader.c",
"../libpd/pure-data/src/s_path.c",
"../libpd/pure-data/src/s_audio.c",
"../libpd/pure-data/src/s_audio_dummy.c",
"../libpd/pure-data/src/s_utf8.c",
"../libpd/pure-data/src/s_audio_paring.c",
"../libpd/pure-data/src/d_ugen.c",
"../libpd/pure-data/src/d_ctl.c",
"../libpd/pure-data/src/d_arithmetic.c",
"../libpd/pure-data/src/d_osc.c",
"../libpd/pure-data/src/d_filter.c",
"../libpd/pure-data/src/d_dac.c",
"../libpd/pure-data/src/d_misc.c",
"../libpd/pure-data/src/d_math.c",
"../libpd/pure-data/src/d_fft.c",
"../libpd/pure-data/src/d_fft_fftsg.c",
"../libpd/pure-data/src/d_array.c",
"../libpd/pure-data/src/d_global.c",
"../libpd/pure-data/src/d_delay.c",
"../libpd/pure-data/src/d_resample.c",
"../libpd/pure-data/src/d_soundfile.c",
"../libpd/pure-data/src/x_arithmetic.c",
"../libpd/pure-data/src/x_connective.c",
"../libpd/pure-data/src/x_interface.c",
"../libpd/pure-data/src/x_midi.c",
"../libpd/pure-data/src/x_misc.c",
"../libpd/pure-data/src/x_time.c",
"../libpd/pure-data/src/x_acoustics.c",
"../libpd/pure-data/src/x_net.c",
"../libpd/pure-data/src/x_text.c",
"../libpd/pure-data/src/x_gui.c",
"../libpd/pure-data/src/x_list.c",
"../libpd/pure-data/src/x_array.c",
"../libpd/pure-data/src/x_scalar.c",
"../libpd/libpd_wrapper/*.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}

+ 68
- 0
ports/PdPulp/Source/FloatParameter.h View File

@@ -0,0 +1,68 @@
/*
==============================================================================
FloatParameter.h
Created: 3 Jul 2015 3:53:57pm
Author: Karl
==============================================================================
*/
#ifndef FLOATPARAMETER_H_INCLUDED
#define FLOATPARAMETER_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class FloatParameter : public AudioProcessorParameter
{
public:
FloatParameter (float defaultParameterValue, const String& paramName)
: defaultValue (defaultParameterValue),
value (defaultParameterValue),
name (paramName)
{
}
float getValue() const override
{
return value;
}
void setValue (float newValue) override
{
value = newValue;
}
float getDefaultValue() const override
{
return defaultValue;
}
String getName (int maximumStringLength) const override
{
return name;
}
void setName (String n)
{
name = n;
}
String getLabel() const override
{
return String();
}
float getValueForText (const String& text) const override
{
return text.getFloatValue();
}
private:
float defaultValue, value;
String name;
};
#endif // FLOATPARAMETER_H_INCLUDED

+ 322
- 0
ports/PdPulp/Source/MainComponent.cpp View File

@@ -0,0 +1,322 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.1.1
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
//[/Headers]
#include "MainComponent.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
MainComponent::MainComponent (PureDataAudioProcessor& processor)
: PureDataAudioProcessorEditor(processor)
{
//[Constructor_pre] You can add your own custom stuff here..
//[/Constructor_pre]
addAndMakeVisible (sendSlider1 = new SendSlider (1, processor));
addAndMakeVisible (sendSlider2 = new SendSlider (2, processor));
addAndMakeVisible (sendSlider5 = new SendSlider (3, processor));
addAndMakeVisible (sendSlider6 = new SendSlider (4, processor));
addAndMakeVisible (sendSlider7 = new SendSlider (5, processor));
addAndMakeVisible (sendSlider3 = new SendSlider (6, processor));
addAndMakeVisible (sendSlider4 = new SendSlider (7, processor));
addAndMakeVisible (sendSlider8 = new SendSlider (8, processor));
addAndMakeVisible (sendSlider9 = new SendSlider (9, processor));
addAndMakeVisible (sendSlider10 = new SendSlider (10, processor));
addAndMakeVisible (findButton = new TextButton ("new button"));
findButton->setButtonText (TRANS("Find patch..."));
findButton->addListener (this);
findButton->setColour (TextButton::buttonColourId, Colour (0xffadadad));
findButton->setColour (TextButton::buttonOnColourId, Colour (0xff727272));
addAndMakeVisible (pathField = new Label ("new label",
String::empty));
pathField->setFont (Font (15.00f, Font::plain));
pathField->setJustificationType (Justification::centred);
pathField->setEditable (false, false, false);
pathField->setColour (Label::backgroundColourId, Colour (0x21000000));
pathField->setColour (Label::textColourId, Colour (0xffbcbcbc));
pathField->setColour (TextEditor::textColourId, Colours::black);
pathField->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (reloadButton = new TextButton ("new button"));
reloadButton->setTooltip (TRANS("Reload the pd patch file."));
reloadButton->setButtonText (TRANS("Reload"));
reloadButton->addListener (this);
reloadButton->setColour (TextButton::buttonColourId, Colour (0xffadadad));
reloadButton->setColour (TextButton::buttonOnColourId, Colour (0xff727272));
addAndMakeVisible (editButton = new TextButton ("new button"));
editButton->setTooltip (TRANS("Opens PD editor if existent."));
editButton->setButtonText (TRANS("Edit"));
editButton->addListener (this);
editButton->setColour (TextButton::buttonColourId, Colour (0xffadadad));
editButton->setColour (TextButton::buttonOnColourId, Colour (0xff727272));
addAndMakeVisible (statusField = new Label ("new label",
String::empty));
statusField->setFont (Font (11.00f, Font::plain));
statusField->setJustificationType (Justification::centred);
statusField->setEditable (false, false, false);
statusField->setColour (Label::backgroundColourId, Colour (0x00000000));
statusField->setColour (Label::textColourId, Colour (0xbcbcbcbc));
statusField->setColour (TextEditor::textColourId, Colours::black);
statusField->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (label = new Label ("new label",
TRANS("PD Pulp")));
label->setFont (Font ("DIN Alternate", 29.20f, Font::bold));
label->setJustificationType (Justification::topLeft);
label->setEditable (false, false, false);
label->setColour (Label::textColourId, Colours::white);
label->setColour (TextEditor::textColourId, Colours::black);
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (label2 = new Label ("new label",
TRANS("a pure data audio plugin runtime environment")));
label2->setFont (Font (14.00f, Font::italic));
label2->setJustificationType (Justification::bottomRight);
label2->setEditable (false, false, false);
label2->setColour (Label::textColourId, Colour (0x94ffffff));
label2->setColour (TextEditor::textColourId, Colours::black);
label2->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
//[UserPreSize]
//[/UserPreSize]
setSize (500, 385);
//[Constructor] You can add your own custom stuff here..
PureDataAudioProcessor& p = (PureDataAudioProcessor&) processor;
pathField->setText(p.getPatchFile().getFileName(), dontSendNotification);
startTimer(25);
//[/Constructor]
}
MainComponent::~MainComponent()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
sendSlider1 = nullptr;
sendSlider2 = nullptr;
sendSlider5 = nullptr;
sendSlider6 = nullptr;
sendSlider7 = nullptr;
sendSlider3 = nullptr;
sendSlider4 = nullptr;
sendSlider8 = nullptr;
sendSlider9 = nullptr;
sendSlider10 = nullptr;
findButton = nullptr;
pathField = nullptr;
reloadButton = nullptr;
editButton = nullptr;
statusField = nullptr;
label = nullptr;
label2 = nullptr;
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void MainComponent::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint]
g.fillAll (Colour (0xff303030));
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
}
void MainComponent::resized()
{
//[UserPreResize] Add your own custom resize code here..
//[/UserPreResize]
sendSlider1->setBounds (9, 122, 98, 120);
sendSlider2->setBounds (101, 122, 98, 120);
sendSlider5->setBounds (197, 122, 98, 120);
sendSlider6->setBounds (293, 122, 98, 120);
sendSlider7->setBounds (389, 122, 98, 120);
sendSlider3->setBounds (9, 246, 98, 120);
sendSlider4->setBounds (101, 246, 98, 120);
sendSlider8->setBounds (197, 246, 98, 120);
sendSlider9->setBounds (293, 246, 98, 120);
sendSlider10->setBounds (389, 246, 98, 120);
findButton->setBounds (368, 56, 104, 24);
pathField->setBounds (24, 56, 328, 24);
reloadButton->setBounds (352, 90, 64, 20);
editButton->setBounds (424, 90, 48, 20);
statusField->setBounds (25, 91, 311, 17);
label->setBounds (22, 16, 170, 32);
label2->setBounds (168, 24, 304, 16);
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
void MainComponent::buttonClicked (Button* buttonThatWasClicked)
{
//[UserbuttonClicked_Pre]
PureDataAudioProcessor& p = (PureDataAudioProcessor&) processor;
//[/UserbuttonClicked_Pre]
if (buttonThatWasClicked == findButton)
{
//[UserButtonCode_findButton] -- add your button handler code here..
FileChooser fc ("Choose a pd file to open...",
File::getCurrentWorkingDirectory(),
"*",
true);
if (fc.browseForFileToOpen())
{
pathField->setText(fc.getResult().getFileName(), dontSendNotification);
p.setPatchFile(fc.getResult());
p.reloadPatch(NULL);
}
//[/UserButtonCode_findButton]
}
else if (buttonThatWasClicked == reloadButton)
{
//[UserButtonCode_reloadButton] -- add your button handler code here..
p.reloadPatch(NULL);
//[/UserButtonCode_reloadButton]
}
else if (buttonThatWasClicked == editButton)
{
//[UserButtonCode_editButton] -- add your button handler code here..
p.getPatchFile().startAsProcess();
//[/UserButtonCode_editButton]
}
//[UserbuttonClicked_Post]
//[/UserbuttonClicked_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void MainComponent::timerCallback()
{
PureDataAudioProcessor& p = (PureDataAudioProcessor&) processor;
statusField->setText(p.status, dontSendNotification);
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Introjucer information section --
This is where the Introjucer stores the metadata that describe this GUI layout, so
make changes in here at your peril!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="MainComponent" componentName=""
parentClasses="public PureDataAudioProcessorEditor, public Timer"
constructorParams="PureDataAudioProcessor&amp; processor" variableInitialisers="PureDataAudioProcessorEditor(processor)"
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="500" initialHeight="385">
<BACKGROUND backgroundColour="ff303030"/>
<JUCERCOMP name="" id="bc71a9946298412f" memberName="sendSlider1" virtualName=""
explicitFocusOrder="0" pos="9 122 98 120" sourceFile="SendSlider.cpp"
constructorParams="1, processor"/>
<JUCERCOMP name="" id="2cbea2ce044e5daa" memberName="sendSlider2" virtualName=""
explicitFocusOrder="0" pos="101 122 98 120" sourceFile="SendSlider.cpp"
constructorParams="2, processor"/>
<JUCERCOMP name="" id="e8e479a7b178aed7" memberName="sendSlider5" virtualName=""
explicitFocusOrder="0" pos="197 122 98 120" sourceFile="SendSlider.cpp"
constructorParams="3, processor"/>
<JUCERCOMP name="" id="8371429f476dadb8" memberName="sendSlider6" virtualName=""
explicitFocusOrder="0" pos="293 122 98 120" sourceFile="SendSlider.cpp"
constructorParams="4, processor"/>
<JUCERCOMP name="" id="6a6f5c3c175c8eea" memberName="sendSlider7" virtualName=""
explicitFocusOrder="0" pos="389 122 98 120" sourceFile="SendSlider.cpp"
constructorParams="5, processor"/>
<JUCERCOMP name="" id="b743230df56fafcb" memberName="sendSlider3" virtualName=""
explicitFocusOrder="0" pos="9 246 98 120" sourceFile="SendSlider.cpp"
constructorParams="6, processor"/>
<JUCERCOMP name="" id="488c56ced9555a30" memberName="sendSlider4" virtualName=""
explicitFocusOrder="0" pos="101 246 98 120" sourceFile="SendSlider.cpp"
constructorParams="7, processor"/>
<JUCERCOMP name="" id="9f9f04d1bb5763fc" memberName="sendSlider8" virtualName=""
explicitFocusOrder="0" pos="197 246 98 120" sourceFile="SendSlider.cpp"
constructorParams="8, processor"/>
<JUCERCOMP name="" id="c4f70e09d260381f" memberName="sendSlider9" virtualName=""
explicitFocusOrder="0" pos="293 246 98 120" sourceFile="SendSlider.cpp"
constructorParams="9, processor"/>
<JUCERCOMP name="" id="4fe4af228a7dcf41" memberName="sendSlider10" virtualName=""
explicitFocusOrder="0" pos="389 246 98 120" sourceFile="SendSlider.cpp"
constructorParams="10, processor"/>
<TEXTBUTTON name="new button" id="1e5168d1e5fff12c" memberName="findButton"
virtualName="" explicitFocusOrder="0" pos="368 56 104 24" bgColOff="ffadadad"
bgColOn="ff727272" buttonText="Find patch..." connectedEdges="0"
needsCallback="1" radioGroupId="0"/>
<LABEL name="new label" id="90c1e98cfe7db5e9" memberName="pathField"
virtualName="" explicitFocusOrder="0" pos="24 56 328 24" bkgCol="21000000"
textCol="ffbcbcbc" edTextCol="ff000000" edBkgCol="0" labelText=""
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="36"/>
<TEXTBUTTON name="new button" id="46837e8b39cdf5ab" memberName="reloadButton"
virtualName="" explicitFocusOrder="0" pos="352 90 64 20" tooltip="Reload the pd patch file."
bgColOff="ffadadad" bgColOn="ff727272" buttonText="Reload" connectedEdges="0"
needsCallback="1" radioGroupId="0"/>
<TEXTBUTTON name="new button" id="fe82abb32a3951b0" memberName="editButton"
virtualName="" explicitFocusOrder="0" pos="424 90 48 20" tooltip="Opens PD editor if existent."
bgColOff="ffadadad" bgColOn="ff727272" buttonText="Edit" connectedEdges="0"
needsCallback="1" radioGroupId="0"/>
<LABEL name="new label" id="90ee85fe76c3c3e8" memberName="statusField"
virtualName="" explicitFocusOrder="0" pos="25 91 311 17" bkgCol="0"
textCol="bcbcbcbc" edTextCol="ff000000" edBkgCol="0" labelText=""
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="11" bold="0" italic="0" justification="36"/>
<LABEL name="new label" id="4f92306c17723f92" memberName="label" virtualName=""
explicitFocusOrder="0" pos="22 16 170 32" textCol="ffffffff"
edTextCol="ff000000" edBkgCol="0" labelText="PD Pulp" editableSingleClick="0"
editableDoubleClick="0" focusDiscardsChanges="0" fontname="DIN Alternate"
fontsize="29.199999999999999289" bold="1" italic="0" justification="9"/>
<LABEL name="new label" id="eb75ff4acec7a7ab" memberName="label2" virtualName=""
explicitFocusOrder="0" pos="168 24 304 16" textCol="94ffffff"
edTextCol="ff000000" edBkgCol="0" labelText="a pure data audio plugin runtime environment"
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="14" bold="0" italic="1" justification="18"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

+ 91
- 0
ports/PdPulp/Source/MainComponent.h View File

@@ -0,0 +1,91 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.1.1
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
#ifndef __JUCE_HEADER_9002020A4DD09B20__
#define __JUCE_HEADER_9002020A4DD09B20__
//[Headers] -- You can add your own extra header files here --
#include "JuceHeader.h"
#include "PluginProcessor.h"
#include "PluginEditor.h"
//[/Headers]
#include "SendSlider.h"
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Introjucer.
Describe your class and how it works here!
//[/Comments]
*/
class MainComponent : public PureDataAudioProcessorEditor,
public Timer,
public ButtonListener
{
public:
//==============================================================================
MainComponent (PureDataAudioProcessor& processor);
~MainComponent();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
//[/UserMethods]
void paint (Graphics& g);
void resized();
void buttonClicked (Button* buttonThatWasClicked);
private:
//[UserVariables] -- You can add your own custom variables in this section.
void timerCallback();
//[/UserVariables]
//==============================================================================
ScopedPointer<SendSlider> sendSlider1;
ScopedPointer<SendSlider> sendSlider2;
ScopedPointer<SendSlider> sendSlider5;
ScopedPointer<SendSlider> sendSlider6;
ScopedPointer<SendSlider> sendSlider7;
ScopedPointer<SendSlider> sendSlider3;
ScopedPointer<SendSlider> sendSlider4;
ScopedPointer<SendSlider> sendSlider8;
ScopedPointer<SendSlider> sendSlider9;
ScopedPointer<SendSlider> sendSlider10;
ScopedPointer<TextButton> findButton;
ScopedPointer<Label> pathField;
ScopedPointer<TextButton> reloadButton;
ScopedPointer<TextButton> editButton;
ScopedPointer<Label> statusField;
ScopedPointer<Label> label;
ScopedPointer<Label> label2;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_9002020A4DD09B20__

+ 1118
- 0
ports/PdPulp/Source/PdBase.cpp
File diff suppressed because it is too large
View File


+ 522
- 0
ports/PdPulp/Source/PdBase.hpp View File

@@ -0,0 +1,522 @@
/*
* Copyright (c) 2012 Dan Wilcox <danomatika@gmail.com>
*
* BSD Simplified License.
* 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 for documentation
*
* This file was originally written for the ofxPd openFrameworks addon:
* https://github.com/danomatika/ofxPd
*
*/
#pragma once

#include <map>

#include "PdReceiver.hpp"
#include "PdMidiReceiver.hpp"

#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H
#endif

// define this to use C++11 std::mutex for locking
#ifdef LIBPD_USE_STD_MUTEX
#if __cplusplus < 201103L
#warning std::mutex requires C++11
#else
#include <mutex>
#endif
#endif

typedef struct _atom t_atom;

namespace pd {

/// a Pure Data instance
///
/// use this class directly or extend it and any of its virtual functions
///
///
/// note: this object is not thread safe by default, use the ring
///
/// see https://github.com/danomatika/ofxPd/tree/master/src for an example
///
/// note: if you need to grab events in your main thread (aka working with a gui),
/// you should either use
///
/// note: libpd currently does not support multiple states and it is
/// suggested that you use only one PdBase-derived object at a time
///
/// calls from multiple PdBase instances currently use a global context
/// kept in a singleton object, thus only one Receiver & one MidiReceiver
/// can be used within a single program
///
/// multiple context support will be added if/when it is included within
/// libpd
///
class PdBase {

public :

PdBase();
virtual ~PdBase();

/// \section Initializing Pd

/// initialize resources and set up the audio processing
///
/// set the audio latency by setting the libpd ticks per buffer:
/// ticks per buffer * lib pd block size (always 64)
///
/// ie 4 ticks per buffer * 64 = buffer len of 512
///
/// the lower the number of ticks, the faster the audio processing
/// if you experience audio dropouts (audible clicks), increase the
/// ticks per buffer
///
/// set queued = true to use the built in ringbuffers for message and
/// midi event passing, you will then need to call receiveMessages() and
/// receiveMidi() in order to pass messages from the ringbuffers to your
/// PdReceiver and PdMidiReceiver implementations
///
/// the queued ringbuffers are useful when you need to receieve events
/// on a gui thread and don't want to use locking (aka the mutex)
///
/// return true if setup successfully
///
/// note: must be called before processing
///
virtual bool init(const int numInChannels, const int numOutChannels,
const int sampleRate, bool queued=false);

/// clear resources
virtual void clear();

/// \section Adding Search Paths

/// add to the pd search path
/// takes an absolute or relative path (in data folder)
///
/// note: fails silently if path not found
///
virtual void addToSearchPath(const std::string& path);

/// clear the current pd search path
virtual void clearSearchPath();

/// \section Opening Patches

/// open a patch file (aka somefile.pd) in a specified path
/// returns a Patch object
///
/// use Patch::isValid() to check if a patch was opened successfully:
///
/// Patch p1 = pd.openPatch("somefile.pd", "/some/path/");
/// if(!p1.isValid()) {
/// cout << "aww ... p1 couldn't be opened" << endl;
/// }
virtual pd::Patch openPatch(const std::string& patch, const std::string& path);

/// open a patch file using the filename and path of an existing patch
///
/// set the filename within the patch object or use a previously opened
/// object
///
/// // open an instance of "somefile.pd"
/// Patch p2("somefile.pd", "/some/path"); // set file and path
/// pd.openPatch(p2);
///
/// // open a new instance of "somefile.pd"
/// Patch p3 = pd.openPatch(p2);
///
/// // p2 and p3 refer to 2 different instances of "somefile.pd"
///
virtual pd::Patch openPatch(pd::Patch& patch);

/// close a patch file
/// takes only the patch's basename (filename without extension)
virtual void closePatch(const std::string& patch);

/// close a patch file, takes a patch object
/// note: clears the given Patch object
virtual void closePatch(pd::Patch& patch);

/// \section Audio Processing

/// main process callbacks
///
/// one of these must be called for audio dsp and message computation to occur
///
/// processes one pd tick, writes raw data to buffers
///
/// inBuffer must be an array of the right size, never null
/// use inBuffer = new type[0] if no input is desired
///
/// outBuffer must be an array of size outBufferSize from openAudio call
/// returns false on error
///
/// note: raw does not interlace the buffers
///
bool processRaw(const float* inBuffer, float* outBuffer);
bool processShort(int ticks, const short* inBuffer, short* outBuffer);
bool processFloat(int ticks, const float* inBuffer, float* outBuffer);
bool processDouble(int ticks, const double* inBuffer, double* outBuffer);

/// \section Audio Processing Control

/// start/stop audio processing
///
/// note: in general, once started, you won't need to turn off audio processing
///
/// shortcut for [; pd dsp 1( & [; pd dsp 0(
///
virtual void computeAudio(bool state);

//// \section Message Receiving

/// subscribe/unsubscribe to source names from libpd
///
/// aka the pd receive name
///
/// [r source]
/// |
///
virtual void subscribe(const std::string& source);
virtual void unsubscribe(const std::string& source);
virtual bool exists(const std::string& source); ///< is a receiver subscribed?
virtual void unsubscribeAll(); ///< receivers will be unsubscribed from *all* sources

/// process the interal message queue if using the ringbuffer
///
/// internally, libpd will use a ringbuffer to pass messages & midi without
/// needing to require locking (mutexes) if you call init() with queued = true
///
/// call these in a loop somewhere in order to receive waiting messages
/// or midi data which are then sent to your PdReceiver & PdMidiReceiver
///
virtual void receiveMessages();
virtual void receiveMidi();

/// \section Event Receiving via Callbacks

/// set the incoming event receiver, disables the event queue
///
/// automatically receives from all currently subscribed sources
///
/// set this to NULL to disable callback receiving and reenable the
/// event queue
///
void setReceiver(pd::PdReceiver* receiver);

/// \section Midi Receiving via Callbacks

/// set the incoming midi event receiver, disables the midi queue
///
/// automatically receives from all midi channels
///
/// set this to NULL to disable midi events and reenable the midi queue
///
void setMidiReceiver(pd::PdMidiReceiver* midiReceiver);

/// \section Sending Functions

/// messages
virtual void sendBang(const std::string& dest);
virtual void sendFloat(const std::string& dest, float num);
virtual void sendSymbol(const std::string& dest, const std::string& symbol);

/// compound messages
///
/// pd.startMessage();
/// pd.addSymbol("hello");
/// pd.addFloat(1.23);
/// pd.finishList("test"); // "test" is the reciever name in pd
///
/// sends [list hello 1.23( -> [r test],
/// you will need to use the [list trim] object on the reciving end
///
/// finishMsg sends a typed message -> [; test msg1 hello 1.23(
///
/// pd.startMessage();
/// pd.addSymbol("hello");
/// pd.addFloat(1.23);
/// pd.finishMessage("test", "msg1");
///
virtual void startMessage();
virtual void addFloat(const float num);
virtual void addSymbol(const std::string& symbol);
virtual void finishList(const std::string& dest);
virtual void finishMessage(const std::string& dest, const std::string& msg);

/// compound messages using the PdBase List type
///
/// List list;
/// list.addSymbol("hello");
/// list.addFloat(1.23);
/// pd.sendList("test", list);
///
/// sends [list hello 1.23( -> [r test]
///
/// clear the list:
///
/// list.clear();
///
/// stream operators work as well:
///
/// list << "hello" << 1.23;
/// pd.sendMessage("test", "msg1", list);
///
/// sends a typed message -> [; test msg1 hello 1.23(
///
virtual void sendList(const std::string& dest, const pd::List& list);
virtual void sendMessage(const std::string& dest, const std::string& msg,
const pd::List& list = pd::List());

/// midi
///
/// send midi messages, any out of range messages will be silently ignored
///
/// number ranges:
/// channel 0 - 15 * dev# (dev #0: 0-15, dev #1: 16-31, etc)
/// pitch 0 - 127
/// velocity 0 - 127
/// controller value 0 - 127
/// program value 1 - 128
/// bend value -8192 - 8191
/// touch value 0 - 127
///
/// note, in pd:
/// [bendin] takes 0 - 16383 while [bendout] returns -8192 - 8192
/// [pgmin] and [pgmout] are 0 - 127
///
virtual void sendNoteOn(const int channel, const int pitch, const int velocity=64);
virtual void sendControlChange(const int channel, const int controller, const int value);
virtual void sendProgramChange(const int channel, const int value);
virtual void sendPitchBend(const int channel, const int value);
virtual void sendAftertouch(const int channel, const int value);
virtual void sendPolyAftertouch(const int channel, const int pitch, const int value);

/// raw midi bytes
///
/// value is a raw midi byte value 0 - 255
/// port is the raw portmidi port #, similar to a channel
///
/// for some reason, [midiin], [sysexin] & [realtimein] add 2 to the port num,
/// so sending to port 1 in PdBase returns port 3 in pd
///
/// however, [midiout], [sysexout], & [realtimeout] do not add to the port num,
/// so sending port 1 to [midiout] returns port 1 in PdBase
///
virtual void sendMidiByte(const int port, const int value);
virtual void sendSysex(const int port, const int value);
virtual void sendSysRealTime(const int port, const int value);

/// \section Sending Stream Interface

/// single messages
///
/// pd << Bang("test"); /// "test" is the reciever name in pd
/// pd << Float("test", 100);
/// pd << Symbol("test", "a symbol");
///
PdBase& operator<<(const pd::Bang& var);
PdBase& operator<<(const pd::Float& var);
PdBase& operator<<(const pd::Symbol& var);

/// compound messages
///
/// pd << StartMessage() << 100 << 1.2 << "a symbol" << FinishList("test");
///
PdBase& operator<<(const pd::StartMessage& var);
PdBase& operator<<(const pd::FinishList& var);
PdBase& operator<<(const pd::FinishMessage& var);

/// add a float to the message
PdBase& operator<<(const bool var);
PdBase& operator<<(const int var);
PdBase& operator<<(const float var);
PdBase& operator<<(const double var);

/// add a symbol to the message
PdBase& operator<<(const char var);
PdBase& operator<<(const char* var);
PdBase& operator<<(const std::string& var);

/// midi
///
/// pd << NoteOn(64) << NoteOn(64, 60) << NoteOn(64, 60, 1);
/// pd << ControlChange(100, 64) << ProgramChange(100, 1) << PitchBend(2000, 1);
/// pd << Aftertouch(127, 1) << PolyAftertouch(64, 127, 1);
///
PdBase& operator<<(const pd::NoteOn& var);
PdBase& operator<<(const pd::ControlChange& var);
PdBase& operator<<(const pd::ProgramChange& var);
PdBase& operator<<(const pd::PitchBend& var);
PdBase& operator<<(const pd::Aftertouch& var);
PdBase& operator<<(const pd::PolyAftertouch& var);

/// compound raw midi byte stream
///
/// pd << StartMidi() << 0xEF << 0x45 << Finish();
/// pd << StartSysex() << 0xE7 << 0x45 << 0x56 << 0x17 << Finish();
///
PdBase& operator<<(const pd::StartMidi& var);
PdBase& operator<<(const pd::StartSysex& var);
PdBase& operator<<(const pd::StartSysRealTime& var);
PdBase& operator<<(const pd::Finish& var);

/// is a message or byte stream currently in progress?
bool isMessageInProgress();

/// \section Array Access

/// get the size of a pd array
/// returns 0 if array not found
int arraySize(const std::string& arrayName);

/// read from a pd array
///
/// resizes given vector to readLen, checks readLen and offset
///
/// returns true on success, false on failure
///
/// calling without setting readLen and offset reads the whole array:
///
/// vector<float> array1;
/// readArray("array1", array1);
///
virtual bool readArray(const std::string& arrayName, std::vector<float>& dest,
int readLen=-1, int offset=0);

/// write to a pd array
///
/// calling without setting writeLen and offset writes the whole array:
///
/// writeArray("array1", array1);
///
virtual bool writeArray(const std::string& arrayName, std::vector<float>& source,
int writeLen=-1, int offset=0);

/// clear array and set to a specific value
virtual void clearArray(const std::string& arrayName, int value=0);

/// \section Utils

/// has the global pd instance been initialized?
bool isInited();

/// is the global pd instance using the ringerbuffer queue for message padding?
bool isQueued();

/// get the blocksize of pd (sample length per channel)
static int blockSize();

/// get/set the max length of messages and lists, default: 32
void setMaxMessageLen(unsigned int len);
unsigned int maxMessageLen();

protected:

#ifdef LIBPD_USE_STD_MUTEX
/// locks libpd C function calls, enable by defining LIBPD_USE_STD_MUTEX
std::mutex mutex;
#endif

private:

/// compound message status
enum MsgType {
MSG,
MIDI,
SYSEX,
SYSRT
};

/// a singleton libpd instance wrapper
class PdContext {

public:

/// singleton data access
/// returns a reference to itself
/// note: only creates a new object on the first call
static PdContext& instance();

/// increments the num of pd base objects
void addBase();

/// decrements the num of pd base objects
/// clears if removing last base
void removeBase();

/// init the pd instance
bool init(const int numInChannels, const int numOutChannels,
const int sampleRate, bool queued);

/// clear the pd instance
void clear();

/// turn dsp on/off
void computeAudio(bool state);

/// is the instance inited?
inline bool isInited() {return bInited;}

/// is this instance queued?
inline bool isQueued() {return bQueued;}

/// \section Variables

bool bMsgInProgress; //< is a compound message being constructed?
int maxMsgLen; //< maximum allowed message length
int curMsgLen; //< the length of the current message

/// compound message status
PdBase::MsgType msgType;

int midiPort; //< target midi port

std::map<std::string,void*> sources; //< subscribed sources

pd::PdReceiver* receiver; //< the message receiver
pd::PdMidiReceiver* midiReceiver; //< the midi receiver

private:

bool bLibPdInited; //< has libpd_init be called?
bool bInited; //< is this pd context inited?
bool bQueued; //< is this context using the libpd_queued ringbuffer?

unsigned int numBases; //< number of pd base objects

// hide all the constructors, copy functions here
PdContext(); // cannot create
virtual ~PdContext(); // cannot destroy
void operator =(PdContext& from) {} // not copyable

/// libpd static callback functions
static void _print(const char* s);

static void _bang(const char* source);
static void _float(const char* source, float value);
static void _symbol(const char* source, const char* symbol);

static void _list(const char* source, int argc, t_atom* argv);
static void _message(const char* source, const char *symbol,
int argc, t_atom *argv);

static void _noteon(int channel, int pitch, int velocity);
static void _controlchange(int channel, int controller, int value);
static void _programchange(int channel, int value);
static void _pitchbend(int channel, int value);
static void _aftertouch(int channel, int value);
static void _polyaftertouch(int channel, int pitch, int value);

static void _midibyte(int port, int byte);
};
};

} // namespace

+ 35
- 0
ports/PdPulp/Source/PdMidiReceiver.hpp View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2012 Dan Wilcox <danomatika@gmail.com>
*
* BSD Simplified License.
* 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 for documentation
*
* This file was originally written for the ofxPd openFrameworks addon:
* https://github.com/danomatika/ofxPd
*
*/
#pragma once

namespace pd {

/// a pd midi receiver base class
class PdMidiReceiver {

public:

/// midi
virtual void receiveNoteOn(const int channel, const int pitch, const int velocity) {}
virtual void receiveControlChange(const int channel, const int controller, const int value) {}
virtual void receiveProgramChange(const int channel, const int value) {} // note: pgm value is 1-128
virtual void receivePitchBend(const int channel, const int value) {}
virtual void receiveAftertouch(const int channel, const int value) {}
virtual void receivePolyAftertouch(const int channel, const int pitch, const int value) {}

/// raw midi byte
virtual void receiveMidiByte(const int port, const int byte) {}
};

} // namespace

+ 36
- 0
ports/PdPulp/Source/PdReceiver.hpp View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2012 Dan Wilcox <danomatika@gmail.com>
*
* BSD Simplified License.
* 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 for documentation
*
* This file was originally written for the ofxPd openFrameworks addon:
* https://github.com/danomatika/ofxPd
*
*/
#pragma once

#include "PdTypes.hpp"

namespace pd {

/// a pd message receiver base class
class PdReceiver {

public:

/// print
virtual void print(const std::string& message) {};

/// messages
virtual void receiveBang(const std::string& dest) {}
virtual void receiveFloat(const std::string& dest, float num) {}
virtual void receiveSymbol(const std::string& dest, const std::string& symbol) {}
virtual void receiveList(const std::string& dest, const List& list) {}
virtual void receiveMessage(const std::string& dest, const std::string& msg, const List& list) {}
};

} // namespace

+ 196
- 0
ports/PdPulp/Source/PdTypes.cpp View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2012 Dan Wilcox <danomatika@gmail.com>
*
* BSD Simplified License.
* 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 for documentation
*
* This file was originally written for the ofxPd openFrameworks addon:
* https://github.com/danomatika/ofxPd
*
*/
#include "PdTypes.hpp"

#include <iostream>
#include <sstream>

namespace pd {

/// PATCH
//----------------------------------------------------------
Patch::Patch() : _handle(NULL), _dollarZero(0), _dollarZeroStr("0"),
_filename(""), _path("") {}

Patch::Patch(const std::string& filename, const std::string& path) :
_handle(NULL), _dollarZero(0), _dollarZeroStr("0"),
_filename(filename), _path(path) {}

Patch::Patch(void* handle, int dollarZero, const std::string& filename, const std::string& path) :
_handle(handle), _dollarZero(dollarZero), _filename(filename), _path(path) {
std::stringstream itoa;
itoa << dollarZero;
_dollarZeroStr = itoa.str();
}

bool Patch::isValid() const {
if(_handle == NULL)
return false;
return true;
}

void Patch::clear() {
_handle = NULL;
_dollarZero = 0;
_dollarZeroStr = "0";
}

Patch::Patch(const Patch& from) {
_handle = from._handle;
_dollarZero = from._dollarZero;
_dollarZeroStr = from._dollarZeroStr;
_filename = from._filename;
_path = from._path;
}

void Patch::operator=(const Patch& from) {
_handle = from._handle;
_dollarZero = from._dollarZero;
_dollarZeroStr = from._dollarZeroStr;
_filename = from._filename;
_path = from._path;
}

std::ostream& operator<<(std::ostream& os, const Patch& from) {
return os << "Patch: \"" << from.filename() << "\" $0: " << from.dollarZeroStr()
<< " valid: " << from.isValid();
}

/// LIST
//----------------------------------------------------------
List::List() {}

bool List::isFloat(const unsigned int index) const {
if(index < objects.size())
if(objects[index].type == List::FLOAT)
return true;
return false;
}

bool List::isSymbol(const unsigned int index) const {
if(index < objects.size())
if(objects[index].type == List::SYMBOL)
return true;
return false;
}

//----------------------------------------------------------
float List::getFloat(const unsigned int index) const {
if(!isFloat(index)) {
std::cerr << "Pd: List: object " << index << " is not a float" << std::endl;
return 0;
}
return objects[index].value;
}

std::string List::getSymbol(const unsigned int index) const {
if(!isSymbol(index)) {
std::cerr << "Pd: List: object " << index << " is not a symbol" << std::endl;
return "";
}
return objects[index].symbol;
}

//----------------------------------------------------------
void List::addFloat(const float num) {
MsgObject o;
o.type = List::FLOAT;
o.value = num;
objects.push_back(o);
typeString += 'f';
}

void List::addSymbol(const std::string& symbol) {
MsgObject o;
o.type = List::SYMBOL;
o.symbol = symbol;
objects.push_back(o);
typeString += 's';
}

List& List::operator<<(const bool var) {
addFloat((float) var);
return *this;
}

List& List::operator<<(const int var) {
addFloat((float) var);
return *this;
}

List& List::operator<<(const float var) {
addFloat((float) var);
return *this;
}

List& List::operator<<(const double var) {
addFloat((float) var);
return *this;
}

List& List::operator<<(const char var) {
std::string s;
s = var;
addSymbol(s);
return *this;
}

List& List::operator<<(const char* var) {
addSymbol((std::string) var);
return *this;
}

List& List::operator<<(const std::string& var) {
addSymbol((std::string) var);
return *this;
}

//----------------------------------------------------------
const unsigned int List::len() const {
return (unsigned int) objects.size();
}

const std::string& List::types() const {
return typeString;
}

void List::clear() {
typeString = "";
objects.clear();
}

std::string List::toString() const {

std::string line;
std::stringstream itoa;

for(int i = 0; i < objects.size(); ++i) {
if(isFloat(i)) {
itoa << getFloat(i);
line += itoa.str();
itoa.str("");
}
else
line += getSymbol(i);
line += " ";
}

return line;
}

std::ostream& operator<<(std::ostream& os, const List& from) {
return os << from.toString();
}

} // namespace

+ 306
- 0
ports/PdPulp/Source/PdTypes.hpp View File

@@ -0,0 +1,306 @@
/*
* Copyright (c) 2012 Dan Wilcox <danomatika@gmail.com>
*
* BSD Simplified License.
* 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 for documentation
*
* This file was originally written for the ofxPd openFrameworks addon:
* https://github.com/danomatika/ofxPd
*
*/
#pragma once

#include <string>
#include <vector>

namespace pd {

/// \section Pd Patch

/// a pd patch
///
/// if you use the copy constructor/operator, keep in mind the libpd void* pointer
/// patch handle is copied and problems can arise if one object is used to close
/// a patch that other copies may be referring to
class Patch {

public:

Patch();
Patch(const std::string& filename, const std::string& path);
Patch(void* handle, int dollarZero, const std::string& filename, const std::string& path);

/// data access
void* handle() const {return _handle;}
int dollarZero() const {return _dollarZero;}
std::string filename() const {return _filename;}
std::string path() const {return _path;}

/// get dollarZero as a string
std::string dollarZeroStr() const {return _dollarZeroStr;}

/// is the patch pointer valid?
bool isValid() const;

/// clear patch pointer and dollar zero (does not close patch!)
///
/// note: does not clear filename and path so the object can be reused
// for opening multiple instances
void clear();

/// copy constructor
Patch(const Patch& from);

/// copy operator
void operator=(const Patch& from);

/// print to ostream
friend std::ostream& operator<<(std::ostream& os, const Patch& from);

private:

void* _handle; //< patch handle pointer
int _dollarZero; //< the unique patch id, ie $0
std::string _dollarZeroStr; //< $0 as a string

std::string _filename; //< filename
std::string _path; //< full path
};

/// \section Pd stream interface message objects

/// bang event
struct Bang {

const std::string dest; //< dest receiver name

explicit Bang(const std::string& dest) : dest(dest) {}
};

/// float value
struct Float {

const std::string dest; //< dest receiver name
const float num; //< the float value

Float(const std::string& dest, const float num) :
dest(dest), num(num) {}
};

/// symbol value
struct Symbol {

const std::string dest; //< dest receiver name
const std::string symbol; //< the symbol value

Symbol(const std::string& dest, const std::string& symbol) :
dest(dest), symbol(symbol) {}
};

/// a compound message containing floats and symbols
class List {

public:

List();

/// \section Read

/// check type
bool isFloat(const unsigned int index) const;
bool isSymbol(const unsigned int index) const;

/// get item as type
float getFloat(const unsigned int index) const;
std::string getSymbol(const unsigned int index) const;

/// \section Write

/// add elements to the list
///
/// List list;
/// list.addSymbol("hello");
/// list.addFloat(1.23);
///
void addFloat(const float num);
void addSymbol(const std::string& symbol);

/// \section Write Stream Interface

/// list << "hello" << 1.23;

/// add a float to the message
List& operator<<(const bool var);
List& operator<<(const int var);
List& operator<<(const float var);
List& operator<<(const double var);

/// add a symbol to the message
List& operator<<(const char var);
List& operator<<(const char* var);
List& operator<<(const std::string& var);

/// \section Util

const unsigned int len() const; //< number of items
const std::string& types() const; //< OSC style type string ie "fsfs"
void clear(); //< clear all objects

/// get list as a string
std::string toString() const;

/// print to ostream
friend std::ostream& operator<<(std::ostream& os, const List& from);

private:

std::string typeString; //< OSC style type string

// object type
enum MsgType {
FLOAT,
SYMBOL
};

// object wrapper
struct MsgObject {
MsgType type;
float value;
std::string symbol;
};

std::vector<MsgObject> objects; //< list objects
};

/// start a compound message
struct StartMessage {
explicit StartMessage() {}
};

/// finish a compound message as a list
struct FinishList {

const std::string dest; //< dest receiver name

explicit FinishList(const std::string& dest) : dest(dest) {}
};

/// finish a compound message as a typed message
struct FinishMessage {

const std::string dest; //< dest receiver name
const std::string msg; //< target msg at the dest

FinishMessage(const std::string& dest, const std::string& msg) :
dest(dest), msg(msg) {}
};

/// /section Pd stream interface midi objects
/// ref: http://www.gweep.net/~prefect/eng/reference/protocol/midispec.html

/// send a note on event (set vel = 0 for noteoff)
struct NoteOn {

const int channel; //< channel (0 - 15 * dev#)
const int pitch; //< pitch (0 - 127)
const int velocity; //< velocity (0 - 127)

NoteOn(const int channel, const int pitch, const int velocity=64) :
channel(channel), pitch(pitch), velocity(velocity) {}
};

/// change a control value aka send a CC message
struct ControlChange {

const int channel; //< channel (0 - 15 * dev#)
const int controller; //< controller (0 - 127)
const int value; //< value (0 - 127)

ControlChange(const int channel, const int controller, const int value) :
channel(channel), controller(controller), value(value) {}
};

/// change a program value (ie an instrument)
struct ProgramChange {

const int channel; //< channel (0 - 15 * dev#)
const int value; //< value (0 - 127)

ProgramChange(const int channel, const int value) :
channel(channel), value(value) {}
};

/// change the pitch bend value
struct PitchBend {

const int channel; //< channel (0 - 15 * dev#)
const int value; //< value (-8192 - 8192)

PitchBend(const int channel, const int value) :
channel(channel), value(value) {}
};

/// change an aftertouch value
struct Aftertouch {

const int channel; //< channel (0 - 15 * dev#)
const int value; //< value (0 - 127)

Aftertouch(const int channel, const int value) :
channel(channel), value(value) {}
};

/// change a poly aftertouch value
struct PolyAftertouch {

const int channel; //< channel (0 - 15 * dev#)
const int pitch; //< pitch (0 - 127)
const int value; //< value (0 - 127)

PolyAftertouch(const int channel, const int pitch, const int value) :
channel(channel), pitch(pitch), value(value) {}
};

/// a raw midi byte
struct MidiByte {

const int port; //< raw portmidi port
//< see http://en.wikipedia.org/wiki/PortMidi
const unsigned char byte; //< the raw midi byte value

MidiByte(const int port, unsigned char byte) : port(port), byte(byte) {}
};

/// start a raw midi byte stream
struct StartMidi {

const int port; //< raw portmidi port

explicit StartMidi(const int port=0) : port(port) {}
};

/// start a raw sysex byte stream
struct StartSysex {

const int port; //< raw portmidi port

explicit StartSysex(const int port=0) : port(port) {}
};

/// start a sys realtime byte stream
struct StartSysRealTime {

const int port; //< raw portmidi port

explicit StartSysRealTime(const int port=0) : port(port) {}
};

/// finish a midi byte stream
struct Finish {
explicit Finish() {}
};

} // namespace

+ 108
- 0
ports/PdPulp/Source/PluginEditor.cpp View File

@@ -0,0 +1,108 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.1.1
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
//[/Headers]
#include "PluginEditor.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
PureDataAudioProcessorEditor::PureDataAudioProcessorEditor (PureDataAudioProcessor& p)
: AudioProcessorEditor (p)
{
//[Constructor_pre] You can add your own custom stuff here..
//[/Constructor_pre]
//[UserPreSize]
//[/UserPreSize]
setSize (600, 400);
//[Constructor] You can add your own custom stuff here..
//[/Constructor]
}
PureDataAudioProcessorEditor::~PureDataAudioProcessorEditor()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void PureDataAudioProcessorEditor::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint]
g.fillAll (Colours::white);
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
}
void PureDataAudioProcessorEditor::resized()
{
//[UserPreResize] Add your own custom resize code here..
//[/UserPreResize]
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Introjucer information section --
This is where the Introjucer stores the metadata that describe this GUI layout, so
make changes in here at your peril!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="PureDataAudioProcessorEditor"
componentName="" parentClasses="public AudioProcessorEditor"
constructorParams="PureDataAudioProcessor&amp; p" variableInitialisers="AudioProcessorEditor (p)"
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="0" initialWidth="600" initialHeight="400">
<BACKGROUND backgroundColour="ffffffff"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

+ 68
- 0
ports/PdPulp/Source/PluginEditor.h View File

@@ -0,0 +1,68 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.1.1
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
#ifndef __JUCE_HEADER_DFA254F056F7859__
#define __JUCE_HEADER_DFA254F056F7859__
//[Headers] -- You can add your own extra header files here --
#include "JuceHeader.h"
#include "PluginProcessor.h"
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Introjucer.
Describe your class and how it works here!
//[/Comments]
*/
class PureDataAudioProcessorEditor : public AudioProcessorEditor
{
public:
//==============================================================================
PureDataAudioProcessorEditor (PureDataAudioProcessor& p);
~PureDataAudioProcessorEditor();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
//[/UserMethods]
void paint (Graphics& g);
void resized();
private:
//[UserVariables] -- You can add your own custom variables in this section.
//[/UserVariables]
//==============================================================================
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PureDataAudioProcessorEditor)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_DFA254F056F7859__

+ 375
- 0
ports/PdPulp/Source/PluginProcessor.cpp View File

@@ -0,0 +1,375 @@
/*
==============================================================================
This file was auto-generated by the Introjucer!
It contains the basic framework code for a JUCE plugin processor.
==============================================================================
*/
#include "PluginProcessor.h"
#include "MainComponent.h"
bool PureDataAudioProcessor::otherInstanceAlreadyRunning;
//==============================================================================
PureDataAudioProcessor::PureDataAudioProcessor()
{
for (int i=0; i<10; i++) {
FloatParameter* p = new FloatParameter (0.5, ("Param" + (String) (i+1)).toStdString());
parameterList.add(p);
addParameter(p);
}
if(PureDataAudioProcessor::otherInstanceAlreadyRunning) {
isInstanceLocked = true;
}
PureDataAudioProcessor::otherInstanceAlreadyRunning = true;
}
PureDataAudioProcessor::~PureDataAudioProcessor()
{
pd = nullptr;
if (!isInstanceLocked) {
PureDataAudioProcessor::otherInstanceAlreadyRunning = false;
}
}
//==============================================================================
void PureDataAudioProcessor::setParameterName(int index, String name)
{
FloatParameter* p = parameterList.getUnchecked(index);
p->setName(name);
}
const String PureDataAudioProcessor::getName() const
{
return JucePlugin_Name;
}
const String PureDataAudioProcessor::getInputChannelName (int channelIndex) const
{
return String (channelIndex + 1);
}
const String PureDataAudioProcessor::getOutputChannelName (int channelIndex) const
{
return String (channelIndex + 1);
}
bool PureDataAudioProcessor::isInputChannelStereoPair (int index) const
{
return true;
}
bool PureDataAudioProcessor::isOutputChannelStereoPair (int index) const
{
return true;
}
bool PureDataAudioProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}
bool PureDataAudioProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}
bool PureDataAudioProcessor::silenceInProducesSilenceOut() const
{
return false;
}
double PureDataAudioProcessor::getTailLengthSeconds() const
{
return 0.0;
}
int PureDataAudioProcessor::getNumPrograms()
{
return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
// so this should be at least 1, even if you're not really implementing programs.
}
int PureDataAudioProcessor::getCurrentProgram()
{
return 0;
}
void PureDataAudioProcessor::setCurrentProgram (int index)
{
}
const String PureDataAudioProcessor::getProgramName (int index)
{
return String();
}
void PureDataAudioProcessor::changeProgramName (int index, const String& newName)
{
}
//==============================================================================
void PureDataAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Use this method as the place to do any pre-playback
// initialisation that you need..
reloadPatch(sampleRate);
pos = 0;
}
void PureDataAudioProcessor::releaseResources()
{
// When playback stops, you can use this as an opportunity to free up any
// spare memory, etc.
if (pd != nullptr)
{
pd->computeAudio (false);
pd->closePatch (patch);
}
pd = nullptr;
pdInBuffer.free();
pdOutBuffer.free();
}
void PureDataAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
if (isInstanceLocked) {
return;
}
// In case we have more outputs than inputs, this code clears any output channels that didn't contain input data, (because these aren't guaranteed to be empty - they may contain garbage).
// I've added this to avoid people getting screaming feedback when they first compile the plugin, but obviously you don't need to this code if your algorithm already fills all the output channels.
for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
buffer.clear (i, 0, buffer.getNumSamples());
int numChannels = jmin (getNumInputChannels(), getNumOutputChannels());
int len = buffer.getNumSamples();
int idx = 0;
for (int i=0; i<parameterList.size(); i++) {
FloatParameter* parameter = parameterList[i];
pd->sendFloat(parameter->getName(300).toStdString(), parameter->getValue());
}
MidiMessage message;
MidiBuffer::Iterator it (midiMessages);
int samplePosition = buffer.getNumSamples();
while (it.getNextEvent (message, samplePosition))
{
if (message.isNoteOn (true)) {
pd->sendNoteOn (message.getChannel(), message.getNoteNumber(), message.getVelocity());
}
if (message.isNoteOff (true)) {
pd->sendNoteOn (message.getChannel(), message.getNoteNumber(), 0);
}
}
while (len > 0)
{
int max = jmin (len, pd->blockSize());
/* interleave audio */
{
float* dstBuffer = pdInBuffer.getData();
for (int i = 0; i < max; ++i)
{
for (int channelIndex = 0; channelIndex < numChannels; ++channelIndex)
*dstBuffer++ = buffer.getReadPointer(channelIndex) [idx + i];
}
}
pd->processFloat (1, pdInBuffer.getData(), pdOutBuffer.getData());
/* write-back */
{
const float* srcBuffer = pdOutBuffer.getData();
for (int i = 0; i < max; ++i)
{
for (int channelIndex = 0; channelIndex < numChannels; ++channelIndex)
buffer.getWritePointer (channelIndex) [idx + i] = *srcBuffer++;
}
}
idx += max;
len -= max;
}
}
//==============================================================================
bool PureDataAudioProcessor::hasEditor() const
{
return true; // (change this to false if you choose to not supply an editor)
}
AudioProcessorEditor* PureDataAudioProcessor::createEditor()
{
return new MainComponent(*this);
}
//==============================================================================
void PureDataAudioProcessor::getStateInformation (MemoryBlock& destData)
{
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
// STORE / SAVE
XmlElement xml(getName());
// patchfile
XmlElement* patchfileElement = new XmlElement("patchfile");
patchfileElement->setAttribute("path", patchfile.getParentDirectory().getFullPathName());
patchfileElement->setAttribute("fullpath", patchfile.getFullPathName());
patchfileElement->setAttribute("filename", patchfile.getFileName());
xml.addChildElement(patchfileElement);
// parameters
XmlElement* parameterListElement = new XmlElement("parameterList");
for(size_t i = 0; i < parameterList.size(); ++i) {
XmlElement* parameterElement = new XmlElement("parameter");
FloatParameter* parameter = parameterList[i];
parameterElement->setAttribute("index", (int) parameter->getParameterIndex());
parameterElement->setAttribute("name", parameter->getName(256));
parameterElement->setAttribute("value", (double) parameter->getValue());
parameterListElement->addChildElement(parameterElement);
}
xml.addChildElement(parameterListElement);
MemoryOutputStream stream;
xml.writeToStream(stream, "");
//std::cout << "save [" << stream.toString() << "] " << std::endl;
copyXmlToBinary(xml, destData);
}
void PureDataAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
// RESTORE / LOAD
ScopedPointer<XmlElement> xml(getXmlFromBinary(data, sizeInBytes));
if(xml != 0 && xml->hasTagName(getName())) {
MemoryOutputStream stream;
xml->writeToStream(stream, "<?xml version=\"1.0\"?>");
//std::cout << "load [" << stream.toString() << "] " << std::endl;
forEachXmlChildElement (*xml, child)
{
std::cout << " - load : " << child->getTagName() << std::endl;
if(child->hasTagName("patchfile")) {
File path(child->getStringAttribute ("fullpath"));
if (path.exists()) {
patchfile = path; // creates a copy
reloadPatch(NULL);
} else {
// Todo add exclamation mark or something
std::cout << "cant find " << child->getStringAttribute("fullpath") << std::endl;
}
}
if(child->hasTagName("parameterList")) {
forEachXmlChildElement (*child, parameterElement) {
//std::cout << "loading param " << parameterElement->getStringAttribute("name");
//std::cout << "[" << parameterElement->getIntAttribute("index") << "]: ";
//std::cout << parameterElement->getDoubleAttribute("value") << std::endl;
setParameter(parameterElement->getIntAttribute("index"), (float) parameterElement->getDoubleAttribute("value"));
setParameterName(parameterElement->getIntAttribute("index"), parameterElement->getStringAttribute("name"));
}
}
}
}
}
void PureDataAudioProcessor::reloadPatch (double sampleRate)
{
if (isInstanceLocked) {
status = "Currently only one simultaneous instance of this plugin is allowed";
return;
}
if (sampleRate) {
cachedSampleRate = sampleRate;
} else {
sampleRate = cachedSampleRate;
}
if (pd) {
pd->computeAudio(false);
pd->closePatch(patch);
}
pd = new pd::PdBase;
pd->init (getNumInputChannels(), getNumOutputChannels(), sampleRate);
int numChannels = jmin (getNumInputChannels(), getNumOutputChannels());
pdInBuffer.calloc (pd->blockSize() * numChannels);
pdOutBuffer.calloc (pd->blockSize() * numChannels);
if (!patchfile.exists()) {
if (patchfile.getFullPathName().toStdString() != "") {
status = "File does not exist";
}
return;
}
if (patchfile.isDirectory()) {
status = "You selected a directory";
return;
}
patch = pd->openPatch (patchfile.getFileName().toStdString(), patchfile.getParentDirectory().getFullPathName().toStdString());
if (patch.isValid()) {
pd->computeAudio (true);
status = "Patch loaded successfully";
} else {
status = "Selected patch is not valid, sorry";
}
}
void PureDataAudioProcessor::setPatchFile(File file)
{
patchfile = file;
}
File PureDataAudioProcessor::getPatchFile()
{
return patchfile;
}
//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new PureDataAudioProcessor();
}

+ 96
- 0
ports/PdPulp/Source/PluginProcessor.h View File

@@ -0,0 +1,96 @@
/*
==============================================================================
This file was auto-generated by the Introjucer!
It contains the basic framework code for a JUCE plugin processor.
==============================================================================
*/
#ifndef PLUGINPROCESSOR_H_INCLUDED
#define PLUGINPROCESSOR_H_INCLUDED
#include "PdBase.hpp"
#include "../JuceLibraryCode/JuceHeader.h"
#include "FloatParameter.h"
//==============================================================================
/**
*/
class PureDataAudioProcessor : public AudioProcessor
{
public:
//==============================================================================
PureDataAudioProcessor();
~PureDataAudioProcessor();
void setParameterName(int index, String name);
//==============================================================================
void prepareToPlay (double sampleRate, int samplesPerBlock) override;
void releaseResources() override;
void processBlock (AudioSampleBuffer&, MidiBuffer&) override;
//==============================================================================
AudioProcessorEditor* createEditor() override;
bool hasEditor() const override;
//==============================================================================
const String getName() const override;
const String getInputChannelName (int channelIndex) const override;
const String getOutputChannelName (int channelIndex) const override;
bool isInputChannelStereoPair (int index) const override;
bool isOutputChannelStereoPair (int index) const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
bool silenceInProducesSilenceOut() const override;
double getTailLengthSeconds() const override;
//==============================================================================
int getNumPrograms() override;
int getCurrentProgram() override;
void setCurrentProgram (int index) override;
const String getProgramName (int index) override;
void changeProgramName (int index, const String& newName) override;
//==============================================================================
void getStateInformation (MemoryBlock& destData) override;
void setStateInformation (const void* data, int sizeInBytes) override;
void reloadPatch(double sampleRate);
void setPatchFile(File file);
File getPatchFile();
String status = "Select a pure data patch file...";
static bool otherInstanceAlreadyRunning;
bool isInstanceLocked = false;
private:
ScopedPointer<pd::PdBase> pd;
int pos;
Array<FloatParameter*> parameterList;
AudioProcessorParameter* freq;
AudioProcessorParameter* volume;
AudioProcessorParameter* del_delay;
AudioProcessorParameter* del_feedback;
AudioProcessorParameter* del_mode_rate;
AudioProcessorParameter* del_mode_depth;
File patchfile;
pd::Patch patch;
HeapBlock<float> pdInBuffer, pdOutBuffer;
double cachedSampleRate;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PureDataAudioProcessor)
};
#endif // PLUGINPROCESSOR_H_INCLUDED

+ 187
- 0
ports/PdPulp/Source/SendSlider.cpp View File

@@ -0,0 +1,187 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.1.1
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
#include "PluginProcessor.h"
//[/Headers]
#include "SendSlider.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
SendSlider::SendSlider (int index, AudioProcessor& processor)
: index(index),
processor(processor)
{
//[Constructor_pre] You can add your own custom stuff here..
//[/Constructor_pre]
addAndMakeVisible (slider = new Slider ("slider"));
slider->setRange (0, 1, 0);
slider->setSliderStyle (Slider::RotaryVerticalDrag);
slider->setTextBoxStyle (Slider::TextBoxBelow, false, 80, 20);
slider->setColour (Slider::thumbColourId, Colour (0xff5c5c5c));
slider->setColour (Slider::rotarySliderFillColourId, Colour (0x7fdddddd));
slider->setColour (Slider::rotarySliderOutlineColourId, Colour (0x66e6e6e6));
slider->setColour (Slider::textBoxHighlightColourId, Colour (0x40a6a6a6));
slider->addListener (this);
addAndMakeVisible (label = new Label ("label",
TRANS("Label")));
label->setTooltip (TRANS("Click to set the name of the corresponding Pure Data receive port."));
label->setFont (Font (15.00f, Font::plain));
label->setJustificationType (Justification::centred);
label->setEditable (true, true, false);
label->setColour (Label::backgroundColourId, Colour (0x00404040));
label->setColour (Label::textColourId, Colour (0xffc4c4c4));
label->setColour (TextEditor::textColourId, Colour (0xffe9e9e9));
label->setColour (TextEditor::backgroundColourId, Colour (0x00343434));
label->addListener (this);
//[UserPreSize]
//[/UserPreSize]
setSize (100, 130);
//[Constructor] You can add your own custom stuff here..
PureDataAudioProcessor& p = (PureDataAudioProcessor&) processor;
String labelText(p.getParameterName(index-1));
label->setText(labelText, dontSendNotification);
startTimer(25);
//[/Constructor]
}
SendSlider::~SendSlider()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
slider = nullptr;
label = nullptr;
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void SendSlider::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint]
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
}
void SendSlider::resized()
{
//[UserPreResize] Add your own custom resize code here..
//[/UserPreResize]
slider->setBounds (14, 35, 71, 80);
label->setBounds (-4, 5, 104, 24);
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
void SendSlider::sliderValueChanged (Slider* sliderThatWasMoved)
{
//[UsersliderValueChanged_Pre]
//[/UsersliderValueChanged_Pre]
if (sliderThatWasMoved == slider)
{
//[UserSliderCode_slider] -- add your slider handling code here..
processor.setParameterNotifyingHost(index-1, sliderThatWasMoved->getValue());
//[/UserSliderCode_slider]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
}
void SendSlider::labelTextChanged (Label* labelThatHasChanged)
{
//[UserlabelTextChanged_Pre]
//[/UserlabelTextChanged_Pre]
if (labelThatHasChanged == label)
{
//[UserLabelCode_label] -- add your label text handling code here..
PureDataAudioProcessor& p = (PureDataAudioProcessor&) processor;
p.setParameterName(index-1, labelThatHasChanged->getTextValue().toString());
//[/UserLabelCode_label]
}
//[UserlabelTextChanged_Post]
//[/UserlabelTextChanged_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void SendSlider::timerCallback()
{
slider->setValue(processor.getParameter(index-1), NotificationType::dontSendNotification);
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Introjucer information section --
This is where the Introjucer stores the metadata that describe this GUI layout, so
make changes in here at your peril!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="SendSlider" componentName=""
parentClasses="public Component, public Timer" constructorParams="int index, AudioProcessor&amp; processor"
variableInitialisers="index(index),&#10;processor(processor)"
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="100" initialHeight="130">
<BACKGROUND backgroundColour="ffffff"/>
<SLIDER name="slider" id="a814494a82a416fe" memberName="slider" virtualName=""
explicitFocusOrder="0" pos="14 35 71 80" thumbcol="ff5c5c5c"
rotarysliderfill="7fdddddd" rotaryslideroutline="66e6e6e6" textboxhighlight="40a6a6a6"
min="0" max="1" int="0" style="RotaryVerticalDrag" textBoxPos="TextBoxBelow"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<LABEL name="label" id="6f4900c890043ea2" memberName="label" virtualName=""
explicitFocusOrder="0" pos="-4 5 104 24" tooltip="Click to set the name of the corresponding Pure Data receive port."
bkgCol="404040" textCol="ffc4c4c4" edTextCol="ffe9e9e9" edBkgCol="343434"
labelText="Label" editableSingleClick="1" editableDoubleClick="1"
focusDiscardsChanges="0" fontname="Default font" fontsize="15"
bold="0" italic="0" justification="36"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

+ 77
- 0
ports/PdPulp/Source/SendSlider.h View File

@@ -0,0 +1,77 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.1.1
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
#ifndef __JUCE_HEADER_E639DC74856C943A__
#define __JUCE_HEADER_E639DC74856C943A__
//[Headers] -- You can add your own extra header files here --
#include "JuceHeader.h"
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Introjucer.
Describe your class and how it works here!
//[/Comments]
*/
class SendSlider : public Component,
public Timer,
public SliderListener,
public LabelListener
{
public:
//==============================================================================
SendSlider (int index, AudioProcessor& processor);
~SendSlider();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void timerCallback();
//[/UserMethods]
void paint (Graphics& g);
void resized();
void sliderValueChanged (Slider* sliderThatWasMoved);
void labelTextChanged (Label* labelThatHasChanged);
private:
//[UserVariables] -- You can add your own custom variables in this section.
int index;
AudioProcessor& processor;
//[/UserVariables]
//==============================================================================
ScopedPointer<Slider> slider;
ScopedPointer<Label> label;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SendSlider)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_E639DC74856C943A__

+ 1308
- 0
ports/PdPulp/Source/mono-tape-echo.pd
File diff suppressed because it is too large
View File


+ 101
- 0
ports/PdPulp/Source/ringbuffer.c View File

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

#include "ringbuffer.h"

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

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_and_or(&(buffer->read_idx), 0);
int write_idx = __sync_fetch_and_or(&(buffer->write_idx), 0);
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_and_or(&(buffer->read_idx), 0);
int write_idx = __sync_fetch_and_or(&(buffer->write_idx), 0);
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_val_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_val_compare_and_swap(&(buffer->read_idx), buffer->read_idx,
(read_idx + len) % buffer->size); // Includes memory barrier.
return 0;
}

+ 46
- 0
ports/PdPulp/Source/ringbuffer.h View File

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

#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

+ 92
- 0
ports/PdPulp/Source/sawsynth.pd View File

@@ -0,0 +1,92 @@
#N canvas 611 141 490 657 10;
#X floatatom 66 97 0 0 0 0 - - -;
#X obj 34 56 notein;
#X floatatom 307 83 0 0 0 0 - - -;
#X obj 34 245 mtof;
#X obj 34 271 phasor~;
#X obj 243 627 dac~;
#X obj 243 576 *~;
#X floatatom 92 100 5 0 0 0 - - -, f 5;
#X obj 184 106 vsl 15 128 0 10 0 0 empty empty Q 0 -9 0 10 -262144
-1 -1 0 1;
#X obj 138 106 vsl 15 128 0 127 0 0 empty empty F 0 -9 0 10 -262144
-1 -1 8000 1;
#X obj 138 245 mtof;
#X msg 44 306 clear;
#X msg 185 292 \$1 50;
#X floatatom 137 355 5 0 0 0 - - -, f 5;
#X obj 34 360 vcf~;
#X obj 137 313 line;
#X obj 185 313 line;
#X msg 137 291 \$1 50;
#X floatatom 185 355 5 0 0 0 - - -, f 5;
#X obj 346 320 pack;
#X obj 307 105 moses 1;
#X obj 307 346 line~;
#X obj 307 320 pack;
#X obj 270 105 vsl 15 128 0 1000 0 0 empty empty A 0 -9 0 10 -262144
-1 -1 254 1;
#X obj 228 104 vsl 15 128 0 1000 0 0 empty empty D 0 -9 0 10 -262144
-1 -1 254 1;
#X obj 346 291 / 127;
#X floatatom 305 152 5 0 0 0 - - -, f 5;
#X floatatom 345 151 5 0 0 0 - - -, f 5;
#X obj 34 220 clip 0 127;
#X floatatom 42 97 0 0 0 0 - - -;
#X obj 138 51 * 127;
#X obj 138 24 r Cutoff;
#X msg 202 263 4;
#X obj 188 241 loadbang;
#X msg 199 50 64, f 2;
#X obj 199 25 loadbang;
#X msg 228 50 40, f 2;
#X msg 270 50 40, f 2;
#X obj 49 125 r Pitch;
#X obj 49 147 * 24;
#X obj 49 167 - 12;
#X obj 34 191 +;
#X connect 1 0 29 0;
#X connect 1 0 41 0;
#X connect 1 1 0 0;
#X connect 1 1 2 0;
#X connect 1 2 7 0;
#X connect 2 0 20 0;
#X connect 3 0 4 0;
#X connect 4 0 14 0;
#X connect 6 0 5 0;
#X connect 6 0 5 1;
#X connect 9 0 10 0;
#X connect 10 0 17 0;
#X connect 11 0 14 0;
#X connect 12 0 16 0;
#X connect 14 0 6 0;
#X connect 15 0 13 0;
#X connect 15 0 14 1;
#X connect 16 0 14 2;
#X connect 16 0 18 0;
#X connect 17 0 15 0;
#X connect 19 0 21 0;
#X connect 20 0 26 0;
#X connect 20 1 27 0;
#X connect 21 0 6 1;
#X connect 22 0 21 0;
#X connect 23 0 19 1;
#X connect 24 0 22 1;
#X connect 25 0 19 0;
#X connect 26 0 22 0;
#X connect 27 0 25 0;
#X connect 28 0 3 0;
#X connect 30 0 9 0;
#X connect 31 0 30 0;
#X connect 32 0 12 0;
#X connect 33 0 32 0;
#X connect 34 0 9 0;
#X connect 35 0 34 0;
#X connect 35 0 36 0;
#X connect 35 0 37 0;
#X connect 36 0 24 0;
#X connect 37 0 23 0;
#X connect 38 0 39 0;
#X connect 39 0 40 0;
#X connect 40 0 41 1;
#X connect 41 0 28 0;

+ 34
- 0
ports/PdPulp/Source/test2.pd View File

@@ -0,0 +1,34 @@
#N canvas 691 58 428 399 10;
#X obj 78 125 dac~;
#X obj 10 111 *~ 1;
#X obj 15 20 osc~ 440;
#X obj 15 39 *~ 0.2;
#X obj 90 19 adc~ 1;
#X obj 89 65 *~ 1;
#X obj 30 74 r left;
#X obj 87 152 loadbang;
#X obj 87 174 metro 1000;
#X obj 87 195 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
1;
#X obj 87 239 realtime;
#X obj 86 294 print PD_RUNS;
#X obj 87 216 sel 0;
#X obj 132 217 sel 1;
#X floatatom 214 193 5 0 0 0 - - -, f 5;
#X obj 258 132 r pitch;
#X connect 1 0 0 0;
#X connect 2 0 3 0;
#X connect 3 0 1 0;
#X connect 3 0 0 1;
#X connect 4 0 5 0;
#X connect 5 0 0 0;
#X connect 5 0 0 1;
#X connect 6 0 1 1;
#X connect 7 0 8 0;
#X connect 8 0 9 0;
#X connect 9 0 12 0;
#X connect 9 0 13 0;
#X connect 12 0 10 0;
#X connect 13 0 10 1;
#X connect 14 0 2 0;
#X connect 15 0 14 0;

+ 16
- 0
ports/PdPulp/Source/test3.pd View File

@@ -0,0 +1,16 @@
#N canvas 294 144 684 574 10;
#X obj 172 306 dac~;
#X obj 109 139 osc~ 440;
#X floatatom 156 89 5 0 0 0 - - -, f 5;
#X obj 109 196 *~ 0.5;
#X floatatom 292 179 5 0 0 0 - - -, f 5;
#X obj 201 119 r volume;
#X obj 206 55 r freq;
#X obj 400 112 notein;
#X connect 1 0 3 0;
#X connect 2 0 1 0;
#X connect 3 0 0 1;
#X connect 3 0 0 0;
#X connect 4 0 3 1;
#X connect 5 0 4 0;
#X connect 6 0 2 0;

+ 57
- 0
ports/PdPulp/Source/test4.pd View File

@@ -0,0 +1,57 @@
#N canvas 4 23 470 456 10;
#X obj 84 409 dac~;
#X obj 94 36 osc~ 440;
#X floatatom 141 90 5 0 0 0 - - -;
#X obj 18 166 *~ 0.5;
#X floatatom 201 152 5 0 0 0 - - -;
#X obj 201 126 r volume;
#X obj 175 37 r freq;
#X obj 222 228 mono-tape-echo;
#X obj 483 32 notein;
#X text 531 33 MIDI note \, velocity \, MIDI channel;
#X obj 484 60 mtof;
#X text 563 163 off;
#X floatatom 519 216 0 0 0 0 - - -;
#X obj 519 321 noteout;
#X obj 519 295 makenote 64 250;
#X obj 519 242 metro 500;
#X msg 519 189 1;
#X msg 551 189 0;
#X text 519 166 on;
#X msg 519 269 60;
#X text 568 110 outputs work similarly. They all take an optional channel
as creation argument \, and ctlin takes a control number and a channel.
You get inlets to change them in any case. IF you specify no channel
\, it's channel 1;
#X obj 521 134 print freq;
#X obj 538 401 print note?;
#X obj 514 167 print note-IN;
#X obj 725 195 midiin;
#X floatatom 725 226 0 0 0 0 - - -;
#X floatatom 756 226 0 0 0 0 - - -;
#X obj 709 290 print in1;
#X obj 785 291 print in2;
#X connect 1 0 3 0;
#X connect 2 0 1 0;
#X connect 3 0 7 0;
#X connect 4 0 3 1;
#X connect 5 0 4 0;
#X connect 6 0 2 0;
#X connect 7 0 0 0;
#X connect 7 0 0 1;
#X connect 8 0 10 0;
#X connect 8 0 23 0;
#X connect 10 0 2 0;
#X connect 10 0 21 0;
#X connect 12 0 15 0;
#X connect 14 0 13 0;
#X connect 14 0 22 0;
#X connect 14 1 13 1;
#X connect 15 0 19 0;
#X connect 16 0 12 0;
#X connect 17 0 12 0;
#X connect 19 0 14 0;
#X connect 24 0 25 0;
#X connect 24 1 26 0;
#X connect 25 0 27 0;
#X connect 26 0 28 0;

+ 48
- 0
ports/PdPulp/Source/z_print_util.c 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.
*/

#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;
}
}

+ 45
- 0
ports/PdPulp/Source/z_print_util.h View File

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

#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

+ 410
- 0
ports/PdPulp/Source/z_queued.c View File

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

#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;
}
}
}

+ 42
- 0
ports/PdPulp/Source/z_queued.h View File

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

#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

+ 109
- 0
ports/PdPulp/VST-fx/premake.lua View File

@@ -0,0 +1,109 @@
dofile("../../../scripts/make-project.lua")
package = make_juce_vst_project("PdPulpFX")
package.buildoptions = {
package.buildoptions,
"-Wno-unused",
"-Wno-unused-parameter",
"-Wno-parentheses",
"-Wno-switch"
}
package.defines = {
package.defines,
"PULP_SYNTH=0",
"USEAPI_DUMMY",
"PD",
"HAVE_LIBDL",
"HAVE_UNISTD_H",
"HAVE_ALLOCA_H",
"_LARGEFILE64_SOURCE"
}
package.includepaths = {
package.includepaths,
"../Source",
"../JuceLibraryCode",
"../libpd/libpd_wrapper",
"../libpd/pure-data/src"
}
package.files = {
matchfiles (
"../Source/*.c",
"../Source/*.cpp",
"../libpd/pure-data/src/g_canvas.c",
"../libpd/pure-data/src/g_graph.c",
"../libpd/pure-data/src/g_text.c",
"../libpd/pure-data/src/g_rtext.c",
"../libpd/pure-data/src/g_array.c",
"../libpd/pure-data/src/g_template.c",
"../libpd/pure-data/src/g_io.c",
"../libpd/pure-data/src/g_scalar.c",
"../libpd/pure-data/src/g_traversal.c",
"../libpd/pure-data/src/g_guiconnect.c",
"../libpd/pure-data/src/g_readwrite.c",
"../libpd/pure-data/src/g_editor.c",
"../libpd/pure-data/src/g_all_guis.c",
"../libpd/pure-data/src/g_bang.c",
"../libpd/pure-data/src/g_hdial.c",
"../libpd/pure-data/src/g_hslider.c",
"../libpd/pure-data/src/g_mycanvas.c",
"../libpd/pure-data/src/g_numbox.c",
"../libpd/pure-data/src/g_toggle.c",
"../libpd/pure-data/src/g_vdial.c",
"../libpd/pure-data/src/g_vslider.c",
"../libpd/pure-data/src/g_vumeter.c",
"../libpd/pure-data/src/m_pd.c",
"../libpd/pure-data/src/m_class.c",
"../libpd/pure-data/src/m_obj.c",
"../libpd/pure-data/src/m_atom.c",
"../libpd/pure-data/src/m_memory.c",
"../libpd/pure-data/src/m_binbuf.c",
"../libpd/pure-data/src/m_conf.c",
"../libpd/pure-data/src/m_glob.c",
"../libpd/pure-data/src/m_sched.c",
"../libpd/pure-data/src/s_main.c",
"../libpd/pure-data/src/s_inter.c",
"../libpd/pure-data/src/s_file.c",
"../libpd/pure-data/src/s_print.c",
"../libpd/pure-data/src/s_loader.c",
"../libpd/pure-data/src/s_path.c",
"../libpd/pure-data/src/s_audio.c",
"../libpd/pure-data/src/s_audio_dummy.c",
"../libpd/pure-data/src/s_utf8.c",
"../libpd/pure-data/src/s_audio_paring.c",
"../libpd/pure-data/src/d_ugen.c",
"../libpd/pure-data/src/d_ctl.c",
"../libpd/pure-data/src/d_arithmetic.c",
"../libpd/pure-data/src/d_osc.c",
"../libpd/pure-data/src/d_filter.c",
"../libpd/pure-data/src/d_dac.c",
"../libpd/pure-data/src/d_misc.c",
"../libpd/pure-data/src/d_math.c",
"../libpd/pure-data/src/d_fft.c",
"../libpd/pure-data/src/d_fft_fftsg.c",
"../libpd/pure-data/src/d_array.c",
"../libpd/pure-data/src/d_global.c",
"../libpd/pure-data/src/d_delay.c",
"../libpd/pure-data/src/d_resample.c",
"../libpd/pure-data/src/d_soundfile.c",
"../libpd/pure-data/src/x_arithmetic.c",
"../libpd/pure-data/src/x_connective.c",
"../libpd/pure-data/src/x_interface.c",
"../libpd/pure-data/src/x_midi.c",
"../libpd/pure-data/src/x_misc.c",
"../libpd/pure-data/src/x_time.c",
"../libpd/pure-data/src/x_acoustics.c",
"../libpd/pure-data/src/x_net.c",
"../libpd/pure-data/src/x_text.c",
"../libpd/pure-data/src/x_gui.c",
"../libpd/pure-data/src/x_list.c",
"../libpd/pure-data/src/x_array.c",
"../libpd/pure-data/src/x_scalar.c",
"../libpd/libpd_wrapper/*.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}

+ 109
- 0
ports/PdPulp/VST-ins/premake.lua View File

@@ -0,0 +1,109 @@
dofile("../../../scripts/make-project.lua")
package = make_juce_vst_project("PdPulp")
package.buildoptions = {
package.buildoptions,
"-Wno-unused",
"-Wno-unused-parameter",
"-Wno-parentheses",
"-Wno-switch"
}
package.defines = {
package.defines,
"PULP_SYNTH=1",
"USEAPI_DUMMY",
"PD",
"HAVE_LIBDL",
"HAVE_UNISTD_H",
"HAVE_ALLOCA_H",
"_LARGEFILE64_SOURCE"
}
package.includepaths = {
package.includepaths,
"../Source",
"../JuceLibraryCode",
"../libpd/libpd_wrapper",
"../libpd/pure-data/src"
}
package.files = {
matchfiles (
"../Source/*.c",
"../Source/*.cpp",
"../libpd/pure-data/src/g_canvas.c",
"../libpd/pure-data/src/g_graph.c",
"../libpd/pure-data/src/g_text.c",
"../libpd/pure-data/src/g_rtext.c",
"../libpd/pure-data/src/g_array.c",
"../libpd/pure-data/src/g_template.c",
"../libpd/pure-data/src/g_io.c",
"../libpd/pure-data/src/g_scalar.c",
"../libpd/pure-data/src/g_traversal.c",
"../libpd/pure-data/src/g_guiconnect.c",
"../libpd/pure-data/src/g_readwrite.c",
"../libpd/pure-data/src/g_editor.c",
"../libpd/pure-data/src/g_all_guis.c",
"../libpd/pure-data/src/g_bang.c",
"../libpd/pure-data/src/g_hdial.c",
"../libpd/pure-data/src/g_hslider.c",
"../libpd/pure-data/src/g_mycanvas.c",
"../libpd/pure-data/src/g_numbox.c",
"../libpd/pure-data/src/g_toggle.c",
"../libpd/pure-data/src/g_vdial.c",
"../libpd/pure-data/src/g_vslider.c",
"../libpd/pure-data/src/g_vumeter.c",
"../libpd/pure-data/src/m_pd.c",
"../libpd/pure-data/src/m_class.c",
"../libpd/pure-data/src/m_obj.c",
"../libpd/pure-data/src/m_atom.c",
"../libpd/pure-data/src/m_memory.c",
"../libpd/pure-data/src/m_binbuf.c",
"../libpd/pure-data/src/m_conf.c",
"../libpd/pure-data/src/m_glob.c",
"../libpd/pure-data/src/m_sched.c",
"../libpd/pure-data/src/s_main.c",
"../libpd/pure-data/src/s_inter.c",
"../libpd/pure-data/src/s_file.c",
"../libpd/pure-data/src/s_print.c",
"../libpd/pure-data/src/s_loader.c",
"../libpd/pure-data/src/s_path.c",
"../libpd/pure-data/src/s_audio.c",
"../libpd/pure-data/src/s_audio_dummy.c",
"../libpd/pure-data/src/s_utf8.c",
"../libpd/pure-data/src/s_audio_paring.c",
"../libpd/pure-data/src/d_ugen.c",
"../libpd/pure-data/src/d_ctl.c",
"../libpd/pure-data/src/d_arithmetic.c",
"../libpd/pure-data/src/d_osc.c",
"../libpd/pure-data/src/d_filter.c",
"../libpd/pure-data/src/d_dac.c",
"../libpd/pure-data/src/d_misc.c",
"../libpd/pure-data/src/d_math.c",
"../libpd/pure-data/src/d_fft.c",
"../libpd/pure-data/src/d_fft_fftsg.c",
"../libpd/pure-data/src/d_array.c",
"../libpd/pure-data/src/d_global.c",
"../libpd/pure-data/src/d_delay.c",
"../libpd/pure-data/src/d_resample.c",
"../libpd/pure-data/src/d_soundfile.c",
"../libpd/pure-data/src/x_arithmetic.c",
"../libpd/pure-data/src/x_connective.c",
"../libpd/pure-data/src/x_interface.c",
"../libpd/pure-data/src/x_midi.c",
"../libpd/pure-data/src/x_misc.c",
"../libpd/pure-data/src/x_time.c",
"../libpd/pure-data/src/x_acoustics.c",
"../libpd/pure-data/src/x_net.c",
"../libpd/pure-data/src/x_text.c",
"../libpd/pure-data/src/x_gui.c",
"../libpd/pure-data/src/x_list.c",
"../libpd/pure-data/src/x_array.c",
"../libpd/pure-data/src/x_scalar.c",
"../libpd/libpd_wrapper/*.c",
"../../../libs/juce-plugin/JucePluginMain.cpp"
)
}

+ 71
- 0
ports/PdPulp/libpd/libpd_wrapper/s_libpdmidi.c View File

@@ -0,0 +1,71 @@
/* 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));
}

// The rest is not relevant to libpd.
void sys_get_midi_apis(char *buf) {}
void sys_listmididevs(void) {}
void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
int *pnmidioutdev, int *pmidioutdev) {}
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) {}


+ 101
- 0
ports/PdPulp/libpd/libpd_wrapper/util/ringbuffer.c View File

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

#include "ringbuffer.h"

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

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_and_or(&(buffer->read_idx), 0);
int write_idx = __sync_fetch_and_or(&(buffer->write_idx), 0);
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_and_or(&(buffer->read_idx), 0);
int write_idx = __sync_fetch_and_or(&(buffer->write_idx), 0);
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_val_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_val_compare_and_swap(&(buffer->read_idx), buffer->read_idx,
(read_idx + len) % buffer->size); // Includes memory barrier.
return 0;
}

+ 46
- 0
ports/PdPulp/libpd/libpd_wrapper/util/ringbuffer.h View File

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

#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

+ 48
- 0
ports/PdPulp/libpd/libpd_wrapper/util/z_print_util.c 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.
*/

#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;
}
}

+ 45
- 0
ports/PdPulp/libpd/libpd_wrapper/util/z_print_util.h View File

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

#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

+ 410
- 0
ports/PdPulp/libpd/libpd_wrapper/util/z_queued.c View File

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

#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;
}
}
}

+ 42
- 0
ports/PdPulp/libpd/libpd_wrapper/util/z_queued.h View File

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

#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

+ 68
- 0
ports/PdPulp/libpd/libpd_wrapper/x_libpdreceive.c View File

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

#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);
}

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

void libpdreceive_setup(void) {
libpdrec_class = class_new(gensym("libpd_receive"),
(t_newmethod)libpdreceive_new, (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);
}

+ 16
- 0
ports/PdPulp/libpd/libpd_wrapper/x_libpdreceive.h View File

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

#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/PdPulp/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/PdPulp/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

+ 456
- 0
ports/PdPulp/libpd/libpd_wrapper/z_libpd.c View File

@@ -0,0 +1,456 @@
/*
* 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 http://gitorious.org/pdlib/pages/Libpd for documentation
*
*/

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#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
void pd_init(void);

// (optional) built in pd externals setup functions
#ifdef LIBPD_EXTRA
void bob_tilde_setup();
void bonk_tilde_setup();
void choice_setup();
void expr_setup(); // also loads expr~ & fexpr~
void fiddle_tilde_setup();
void loop_tilde_setup();
void lrshift_tilde_setup();
void pique_setup();
void sigmund_tilde_setup();
void stdout_setup();
#endif

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

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;
sys_soundin = NULL;
sys_soundout = NULL;
// are all these settings necessary?
sys_schedblocksize = DEFDACBLKSIZE;
sys_externalschedlib = 0;
sys_printtostderr = 0;
sys_usestdpath = 0; // don't use pd_extrapath, only sys_searchpath
sys_debuglevel = 0;
sys_verbose = 0;
sys_noloadbang = 0;
sys_nogui = 1;
sys_hipriority = 0;
sys_nmidiin = 0;
sys_nmidiout = 0;
sys_init_fdpoll();
#ifdef HAVE_SCHED_TICK_ARG
sys_time = 0;
#endif
pd_init();
libpdreceive_setup();
sys_set_audio_api(API_DUMMY);
sys_searchpath = NULL;

#ifdef LIBPD_EXTRA
bob_tilde_setup();
bonk_tilde_setup();
choice_setup();
expr_setup();
fiddle_tilde_setup();
loop_tilde_setup();
lrshift_tilde_setup();
pique_setup();
sigmund_tilde_setup();
stdout_setup();
#endif

return 0;
}

void libpd_clear_search_path(void) {
namelist_free(sys_searchpath);
sys_searchpath = NULL;
}

void libpd_add_to_search_path(const char *s) {
sys_searchpath = namelist_append(sys_searchpath, s, 0);
}

void *libpd_openfile(const char *basename, const char *dirname) {
return (void *)glob_evalfile(NULL, gensym(basename), gensym(dirname));
}

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

int libpd_getdollarzero(void *x) {
pd_pushsym((t_pd *)x);
int dzero = canvas_getdollarzero();
pd_popsym((t_pd *)x);
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_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();
return 0;
}

int libpd_process_raw(const float *inBuffer, float *outBuffer) {
size_t n_in = sys_inchannels * DEFDACBLKSIZE;
size_t n_out = sys_outchannels * DEFDACBLKSIZE;
t_sample *p;
size_t i;
sys_microsleep(0);
for (p = sys_soundin, i = 0; i < n_in; i++) {
*p++ = *inBuffer++;
}
memset(sys_soundout, 0, n_out * sizeof(t_sample));
SCHED_TICK(sys_time + sys_time_per_dsp_tick);
for (p = sys_soundout, i = 0; i < n_out; i++) {
*outBuffer++ = *p++;
}
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_microsleep(0); \
for (i = 0; i < ticks; i++) { \
for (j = 0, p0 = sys_soundin; j < DEFDACBLKSIZE; j++, p0++) { \
for (k = 0, p1 = p0; k < sys_inchannels; k++, p1 += DEFDACBLKSIZE) { \
*p1 = *inBuffer++ _x; \
} \
} \
memset(sys_soundout, 0, sys_outchannels*DEFDACBLKSIZE*sizeof(t_sample)); \
SCHED_TICK(sys_time + sys_time_per_dsp_tick); \
for (j = 0, p0 = sys_soundout; j < DEFDACBLKSIZE; j++, p0++) { \
for (k = 0, p1 = p0; k < sys_outchannels; k++, p1 += DEFDACBLKSIZE) { \
*outBuffer++ = *p1 _y; \
} \
} \
} \
return 0;

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

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

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

int libpd_arraysize(const char *name) {
GETARRAY
return garray_npoints(garray);
}

#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) {
MEMCPY(*dest++, (vec++)->w_float)
return 0;
}

int libpd_write_array(const char *name, int offset, float *src, int n) {
MEMCPY((vec++)->w_float, *src++)
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 = get_object(recv);
if (dest == NULL) return -1;
pd_list(dest, &s_list, n, v);
return 0;
}

int libpd_message(const char *recv, const char *msg, int n, t_atom *v) {
t_pd *dest = get_object(recv);
if (dest == NULL) return -1;
pd_typedmess(dest, gensym(msg), n, v);
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 = gensym(s);
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) {
return libpdreceive_new(gensym(sym));
}

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

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 = get_object(recv);
if (obj == NULL) return -1;
pd_symbol(obj, gensym(sym));
return 0;
}

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

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

int libpd_blocksize(void) {
return DEFDACBLKSIZE;
}

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

#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)
inmidi_noteon(PORT, CHANNEL, pitch, velocity);
return 0;
}

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

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

int libpd_pitchbend(int channel, int value) {
CHECK_CHANNEL
if (value < -8192 || value > 8191) return -1;
inmidi_pitchbend(PORT, CHANNEL, value + 8192);
// 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)
inmidi_aftertouch(PORT, CHANNEL, value);
return 0;
}

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

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

int libpd_sysex(int port, int byte) {
CHECK_PORT
CHECK_RANGE_7BIT(byte)
inmidi_sysex(port, byte);
return 0;
}

int libpd_sysrealtime(int port, int byte) {
CHECK_PORT
CHECK_RANGE_8BIT(byte)
inmidi_realtimein(port, byte);
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;
}

+ 115
- 0
ports/PdPulp/libpd/libpd_wrapper/z_libpd.h View File

@@ -0,0 +1,115 @@
/*
* 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 http://gitorious.org/pdlib/pages/Libpd 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(int ticks,
const float *inBuffer, float *outBuffer);
EXTERN int libpd_process_double(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, 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);

#ifdef __cplusplus
}
#endif

#endif

+ 261
- 0
ports/PdPulp/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




+ 162
- 0
ports/PdPulp/libpd/pure-data/src/Makefile.am View File

@@ -0,0 +1,162 @@
AUTOMAKE_OPTIONS = foreign

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

pdsend_CFLAGS =
pdreceive_CFLAGS =
pd_watchdog_CFLAGS =
LIBS = @LIBS@
INCLUDES = @INCLUDES@

SUFFIXES = .@EXTENSION@ .@SHARED_LIB@

bin_PROGRAMS = pd pdsend pdreceive
pdsend_SOURCES = u_pdsend.c
pdreceive_SOURCES = u_pdreceive.c
pd_watchdog_SOURCES = s_watchdog.c
pd_LDADD =
pd_SOURCES = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c \
g_io.c g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_array.c d_global.c \
d_delay.c d_resample.c 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

pd_includedir = ${includedir}/pd
pd_include_HEADERS = m_pd.h m_imp.h g_canvas.h s_stuff.h g_all_guis.h
# compatibility: m_pd.h also goes into ${includedir}/
include_HEADERS = m_pd.h
noinst_HEADERS = g_all_guis.h s_audio_alsa.h s_audio_paring.h s_utf8.h

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


# configurations per library
if ALSA
pd_CFLAGS += -DUSEAPI_ALSA
pd_LDADD += @ALSA_LIBS@
pd_SOURCES += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c
endif

if COREAUDIO
LIBS += -framework CoreAudio -framework CoreMIDI \
-framework AudioUnit -framework AudioToolbox
endif

if FFTW
pd_SOURCES += d_fft_fftw.c
else
pd_SOURCES += d_fft_fftsg.c
endif

# TODO support Jack xrun
if JACK
pd_CFLAGS += -DUSEAPI_JACK -DJACK_XRUN
pd_SOURCES += s_audio_jack.c
if MACOSX
pd_LDFLAGS += -weak_framework Jackmp
else
pd_LDADD += @JACK_LIBS@
endif
endif

# Cygwin has a function OSS /dev/dsp, but not MIDI, and Pd is only set up to
# handle a single MIDI API
if OSS
if !WINDOWS
pd_CFLAGS += -DUSEAPI_OSS
pd_SOURCES += s_audio_oss.c s_midi_oss.c
endif
endif

if PORTAUDIO
pd_CFLAGS += -DUSEAPI_PORTAUDIO -I$(top_srcdir)/portaudio/include
pd_LDADD += $(top_builddir)/portaudio/lib/libportaudio.la
pd_SOURCES += s_audio_pa.c s_audio_paring.c
endif

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

if PORTMIDI
INCLUDES += -I$(top_srcdir)/portmidi/pm_common -I$(top_srcdir)/portmidi/porttime
pd_LDADD += $(top_builddir)/portmidi/libportmidi.la
pd_SOURCES += s_midi_pm.c
endif


# FIXXXME
# GNU/HURD, IPHONEOS, ... have no MIDI (not even OSS)
# i think it would be better to add s_midi_dummy.c only if no other midi API can be found
# (without OS-specific checks)
# even better would be, to allow Pd to have simply have no MIDI (nor AUDIO)
if IPHONEOS
pd_SOURCES += s_midi_dummy.c
endif

if HURD
libpdbindir = $(pkglibdir)/bin
libpdbin_DATA =
libpdbin_PROGRAMS = pd-watchdog pd
# this flag has to have a single leading "-" for libtool, even though ld uses
# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld...
pd_LDFLAGS += -export-dynamic
# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it
pd_LDFLAGS += $(LIBM)
# force linking to pthread, which should really be done with some autotools way
pd_LDFLAGS += -lpthread
# force linking to dl, which should really be done with some autotools way
pd_LDFLAGS += -ldl
endif

if LINUX
libpdbindir = $(pkglibdir)/bin
libpdbin_DATA =
libpdbin_PROGRAMS = pd-watchdog pd
# this flag has to have a single leading "-" for libtool, even though ld uses
# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld...
pd_LDFLAGS += -export-dynamic
# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it
pd_LDFLAGS += $(LIBM)
endif

if MACOSX
LIBS += -framework Carbon
pd_CFLAGS += -DMACOSX #kludge, should use auto macro __APPLE__
bin_SCRIPTS =
bin_PROGRAMS += pd-watchdog
endif

if WINDOWS
LIBS += -lwsock32 -lwinmm -lole32
pd_CFLAGS += -DUSEAPI_MMIO -DPD_INTERNAL
pd_SOURCES += s_audio_mmio.c s_midi_mmio.c
bin_SCRIPTS =
endif

if MINGW
# To use SetDllDirectory() in 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. That gives us -DWINVER=0x0502
pd_CFLAGS += -DWISHAPP='"wish85.exe"' -DWINVER=0x0502
bin_PROGRAMS += pd-watchdog
endif

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

+ 843
- 0
ports/PdPulp/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 g = *in2++;
*out++ = (g ? *in1++ / 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();
}


+ 1050
- 0
ports/PdPulp/libpd/pure-data/src/d_array.c
File diff suppressed because it is too large
View File


+ 850
- 0
ports/PdPulp/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 = (t_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();
}


+ 184
- 0
ports/PdPulp/libpd/pure-data/src/d_dac.c View File

@@ -0,0 +1,184 @@
/* 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_getintarg(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 = *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, sys_soundout + DEFDACBLKSIZE*ch,
(*sp2)->s_vec, sys_soundout + DEFDACBLKSIZE*ch, DEFDACBLKSIZE);
}
}

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_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_getintarg(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);
}

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 = *ip - 1;
if ((*sp2)->s_n != DEFDACBLKSIZE)
error("adc~: bad vector size");
else if (ch >= 0 && ch < sys_get_inchannels())
dsp_add_copy(sys_soundin + DEFDACBLKSIZE*ch,
(*sp2)->s_vec, DEFDACBLKSIZE);
else dsp_add_zero((*sp2)->s_vec, DEFDACBLKSIZE);
}
}

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_sethelpsymbol(adc_class, gensym("adc~_dac~"));
}

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


+ 334
- 0
ports/PdPulp/libpd/pure-data/src/d_delay.c View File

@@ -0,0 +1,334 @@
/* 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"
extern int ugen_getsortno(void);

#define DEFDELVS 64 /* LATER get this from canvas at DSP time */
static 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;
}
}

/* 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);
}

/* ----------------------------- 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 - DEFDELVS)
x->x_delsamps = delwriter->x_cspace.c_n - DEFDELVS;
}
}

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 - 1;
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("vd~"), (t_newmethod)sigvd_new, 0,
sizeof(t_sigvd), 0, 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/PdPulp/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 = 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 = 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 = 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 = 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 = 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 = 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 = 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();
}

+ 3482
- 0
ports/PdPulp/libpd/pure-data/src/d_fft_fftsg.c
File diff suppressed because it is too large
View File


+ 177
- 0
ports/PdPulp/libpd/pure-data/src/d_fft_fftw.c View File

@@ -0,0 +1,177 @@
/* 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)
{
info->in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
info->out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
info->plan = fftwf_plan_dft_1d(n, info->in, info->out, fwd?FFTW_FORWARD:FFTW_BACKWARD, FFTW_MEASURE);
}
return info;
}


/* 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/PdPulp/libpd/pure-data/src/d_filter.c
File diff suppressed because it is too large
View File


+ 361
- 0
ports/PdPulp/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();
}


+ 778
- 0
ports/PdPulp/libpd/pure-data/src/d_math.c View File

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

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;
long l = *(long *)(in++);
if (f < 0) *out++ = 0;
else
{
t_sample g = rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(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;
long l = *(long *)(in++);
if (f < 0) *out++ = 0;
else
{
t_sample g = rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(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 (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(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_symbol *s, int argc, t_atom *argv)
{
t_pow_tilde *x = (t_pow_tilde *)pd_new(pow_tilde_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 *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(t_symbol *s, int argc, t_atom *argv)
{
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_symbol *s, int argc, t_atom *argv)
{
t_log_tilde *x = (t_log_tilde *)pd_new(log_tilde_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 *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(t_symbol *s, int argc, t_atom *argv)
{
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/PdPulp/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"), 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();
}





+ 513
- 0
ports/PdPulp/libpd/pure-data/src/d_osc.c View File

@@ -0,0 +1,513 @@
/* 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, *scalarphasor_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 = (t_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);
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_setup(void)
{
noise_class = class_new(gensym("noise~"), (t_newmethod)noise_new, 0,
sizeof(t_noise), 0, 0);
class_addmethod(noise_class, (t_method)noise_dsp, gensym("dsp"), A_CANT, 0);
}


/* ----------------------- global setup routine ---------------- */
void d_osc_setup(void)
{
phasor_setup();
cos_setup();
osc_setup();
sigvcf_setup();
noise_setup();
}


+ 216
- 0
ports/PdPulp/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;
}

+ 2652
- 0
ports/PdPulp/libpd/pure-data/src/d_soundfile.c
File diff suppressed because it is too large
View File


+ 1203
- 0
ports/PdPulp/libpd/pure-data/src/d_ugen.c
File diff suppressed because it is too large
View File


+ 672
- 0
ports/PdPulp/libpd/pure-data/src/g_all_guis.c View File

@@ -0,0 +1,672 @@
/* 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 GGEE_HSLIDER_COMPATIBLE */

/*------------------ global varaibles -------------------------*/

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_getintarg(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;
}

void iemgui_all_col2save(t_iemgui *iemgui, int *bflcol)
{
bflcol[0] = -1 - (((0xfc0000 & iemgui->x_bcol) >> 6)|
((0xfc00 & iemgui->x_bcol) >> 4)|((0xfc & iemgui->x_bcol) >> 2));
bflcol[1] = -1 - (((0xfc0000 & iemgui->x_fcol) >> 6)|
((0xfc00 & iemgui->x_fcol) >> 4)|((0xfc & iemgui->x_fcol) >> 2));
bflcol[2] = -1 - (((0xfc0000 & iemgui->x_lcol) >> 6)|
((0xfc00 & iemgui->x_lcol) >> 4)|((0xfc & iemgui->x_lcol) >> 2));
}

void iemgui_all_colfromload(t_iemgui *iemgui, int *bflcol)
{
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]];
}
}

int iemgui_compatible_col(int i)
{
int j;

if(i >= 0)
{
j = iemgui_modulo_color(i);
return(iemgui_color_hex[(j)]);
}
else
return((-1 -i)&0xffffff);
}

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)
{
iemgui->x_ldx = (int)atom_getintarg(0, ac, av);
iemgui->x_ldy = (int)atom_getintarg(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,
text_ypix((t_object *)x,iemgui->x_glist)+iemgui->x_ldy);
}

void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
{
int f = (int)atom_getintarg(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_getintarg(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, 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)
{
iemgui->x_obj.te_xpix += (int)atom_getintarg(0, ac, av);
iemgui->x_obj.te_ypix += (int)atom_getintarg(1, ac, av);
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)
{
iemgui->x_obj.te_xpix = (int)atom_getintarg(0, ac, av);
iemgui->x_obj.te_ypix = (int)atom_getintarg(1, ac, av);
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)
{
iemgui->x_bcol = iemgui_compatible_col(atom_getintarg(0, ac, av));
if(ac > 2)
{
iemgui->x_fcol = iemgui_compatible_col(atom_getintarg(1, ac, av));
iemgui->x_lcol = iemgui_compatible_col(atom_getintarg(2, ac, av));
}
else
iemgui->x_lcol = iemgui_compatible_col(atom_getintarg(1, 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, int *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);
}

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_getintarg(5, argc, argv);
int ldx = (int)atom_getintarg(10, argc, argv);
int ldy = (int)atom_getintarg(11, argc, argv);
int f = (int)atom_getintarg(12, argc, argv);
int fs = (int)atom_getintarg(13, argc, argv);
int bcol = (int)atom_getintarg(14, argc, argv);
int fcol = (int)atom_getintarg(15, argc, argv);
int lcol = (int)atom_getintarg(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_getintarg(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_getintarg(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_getintarg(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);
}

+ 323
- 0
ports/PdPulp/libpd/pure-data/src/g_all_guis.h View File

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

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;
} 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 sys_noloadbang;
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 int iemgui_modulo_color(int col);
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_col2save(t_iemgui *iemgui, int *bflcol);
EXTERN void iemgui_all_colfromload(t_iemgui *iemgui, int *bflcol);
EXTERN int iemgui_compatible_col(int i);
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, int *bflcol);
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);

+ 1245
- 0
ports/PdPulp/libpd/pure-data/src/g_array.c
File diff suppressed because it is too large
View File


+ 555
- 0
ports/PdPulp/libpd/pure-data/src/g_bang.c View File

@@ -0,0 +1,555 @@
/* 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);
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -tags %lxBASE\n",
canvas, xpos, ypos,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create oval %d %d %d %d -fill #%6.6x -tags %lxBUT\n",
canvas, xpos+1, ypos+1,
xpos + x->x_gui.x_w-1, ypos + x->x_gui.x_h-1,
x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xpos,
ypos + x->x_gui.x_h-1, xpos + IOWIDTH,
ypos + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xpos, ypos,
xpos + IOWIDTH, ypos+1, x, 0);
}

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);
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);
sys_vgui(".x%lx.c coords %lxBUT %d %d %d %d\n",
canvas, x, xpos+1,ypos+1,
xpos + x->x_gui.x_w-1, ypos + x->x_gui.x_h-1);
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, ypos+x->x_gui.x_ldy);
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-1, xpos + IOWIDTH,
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 + IOWIDTH, ypos+1);
}

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, 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);
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 -tags %lxOUT%d\n",
canvas, xpos,
ypos + x->x_gui.x_h-1, xpos + IOWIDTH,
ypos + x->x_gui.x_h, 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 -tags %lxIN%d\n",
canvas, xpos, ypos,
xpos + IOWIDTH, ypos+1, 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;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiiisssiiiiiii", 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,
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 \
%d %d %d\n",
x->x_gui.x_w, 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)
{
if(x->x_flashed)
{
x->x_flashed = 0;
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
clock_delay(x->x_clock_brk, x->x_flashtime_break);
x->x_flashed = 1;
}
else
{
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, x->x_flashtime_hold);
}

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_getintarg(0, argc, argv);
int fthold = (int)atom_getintarg(2, argc, argv);
int ftbreak = (int)atom_getintarg(3, argc, argv);
int sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);

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_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)
{
if(!sys_noloadbang && 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_getintarg(0, ac, av));
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_getintarg(0, ac, av),
(int)atom_getintarg(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_brk(t_bng *x)
{
(*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 bflcol[]={-262144, -1, -1};
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);

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)&&IS_A_FLOAT(argv,11)
&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13))
{

a = (int)atom_getintarg(0, argc, argv);
fthold = (int)atom_getintarg(1, argc, argv);
ftbreak = (int)atom_getintarg(2, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(3, argc, argv));
iemgui_new_getnames(&x->x_gui, 4, argv);
ldx = (int)atom_getintarg(7, argc, argv);
ldy = (int)atom_getintarg(8, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(9, argc, argv));
fs = (int)atom_getintarg(10, argc, argv);
bflcol[0] = (int)atom_getintarg(11, argc, argv);
bflcol[1] = (int)atom_getintarg(12, argc, argv);
bflcol[2] = (int)atom_getintarg(13, argc, argv);
}
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);
iemgui_all_colfromload(&x->x_gui, bflcol);
x->x_gui.x_isa.x_locked = 0;
iemgui_verify_snd_ne_rcv(&x->x_gui);
x->x_clock_hld = clock_new(x, (t_method)bng_tick_hld);
x->x_clock_brk = clock_new(x, (t_method)bng_tick_brk);
x->x_clock_lck = clock_new(x, (t_method)bng_tick_lck);
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_brk);
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"), 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);
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);
}

+ 1664
- 0
ports/PdPulp/libpd/pure-data/src/g_canvas.c
File diff suppressed because it is too large
View File


+ 622
- 0
ports/PdPulp/libpd/pure-data/src/g_canvas.h View File

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

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
extern "C" {
#endif

/* --------------------- geometry ---------------------------- */
#define IOWIDTH 7 /* width of an inlet/outlet in pixels */
#define IOMIDDLE ((IOWIDTH-1)/2)
#define GLIST_DEFGRAPHWIDTH 200
#define GLIST_DEFGRAPHHEIGHT 140
/* ----------------------- data ------------------------------- */

typedef struct _updateheader
{
struct _updateheader *upd_next;
unsigned int upd_array:1; /* true if array, false if glist */
unsigned int upd_queued:1; /* true if we're queued */
} t_updateheader;

/* types to support glists grabbing mouse motion or keys from parent */
typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy);
typedef void (*t_glistkeyfn)(void *z, t_floatarg key);

EXTERN_STRUCT _rtext;
#define t_rtext struct _rtext

EXTERN_STRUCT _gtemplate;
#define t_gtemplate struct _gtemplate

EXTERN_STRUCT _guiconnect;
#define t_guiconnect struct _guiconnect

EXTERN_STRUCT _tscalar;
#define t_tscalar struct _tscalar

EXTERN_STRUCT _canvasenvironment;
#define t_canvasenvironment struct _canvasenvironment

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 */
};

#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;

/* 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 void gobj_save(t_gobj *x, t_binbuf *b);
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 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_xcoord(t_text *x, t_glist *glist);
EXTERN int text_ycoord(t_text *x, t_glist *glist);
EXTERN int text_xpix(t_text *x, t_glist *glist);
EXTERN int text_ypix(t_text *x, t_glist *glist);

/* -------------------- functions on rtexts ------------------------- */
#define RTEXT_DOWN 1
#define RTEXT_DRAG 2
#define RTEXT_DBL 3
#define RTEXT_SHIFT 4

EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who);
EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who);
EXTERN void rtext_draw(t_rtext *x);
EXTERN void rtext_erase(t_rtext *x);
EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x);
EXTERN int rtext_height(t_rtext *x);
EXTERN void rtext_displace(t_rtext *x, int dx, int dy);
EXTERN void rtext_select(t_rtext *x, int state);
EXTERN void rtext_activate(t_rtext *x, int state);
EXTERN void rtext_free(t_rtext *x);
EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s);
EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag);
EXTERN void rtext_retext(t_rtext *x);
EXTERN int rtext_width(t_rtext *x);
EXTERN int rtext_height(t_rtext *x);
EXTERN char *rtext_gettag(t_rtext *x);
EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
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 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 t_canvas *canvas_getcurrent(void);
EXTERN void canvas_setcurrent(t_canvas *x);
EXTERN void canvas_unsetcurrent(t_canvas *x);
EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
EXTERN void canvas_dirty(t_canvas *x, t_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);

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);


/* ---- 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 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_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);

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif

+ 2869
- 0
ports/PdPulp/libpd/pure-data/src/g_editor.c
File diff suppressed because it is too large
View File


+ 1103
- 0
ports/PdPulp/libpd/pure-data/src/g_graph.c
File diff suppressed because it is too large
View File


+ 97
- 0
ports/PdPulp/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);
}

+ 745
- 0
ports/PdPulp/libpd/pure-data/src/g_hdial.c View File

@@ -0,0 +1,745 @@
/* 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-horicontal 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 #%6.6x -outline #%6.6x\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 #%6.6x -outline #%6.6x\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)
{
t_canvas *canvas=glist_getcanvas(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;


for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -tags %lxBASE%d\n",
canvas, xx11, yy11, xx11+dx, yy12,
x->x_gui.x_bcol, x, i);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -outline #%6.6x -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;
}
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, xx11b+x->x_gui.x_ldx, yy11+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx11b, yy12-1, xx11b + IOWIDTH, yy12, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx11b, yy11, xx11b + IOWIDTH, yy11+1, x, 0);

}

void hradio_draw_move(t_hradio *x, t_glist *glist)
{
t_canvas *canvas=glist_getcanvas(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;

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, yy11+x->x_gui.x_ldy);
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-1, xx11b + IOWIDTH, 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 + IOWIDTH, yy11+1);
}

void hradio_draw_erase(t_hradio* x, t_glist* glist)
{
t_canvas *canvas=glist_getcanvas(glist);
int n=x->x_number, i;

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)
{
t_canvas *canvas=glist_getcanvas(glist);
int n=x->x_number, i;

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, 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 #%6.6x\n", canvas, x, i,
x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%6.6x -outline #%6.6x\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)
{
t_canvas *canvas=glist_getcanvas(glist);
int xpos=text_xpix(&x->x_gui.x_obj, glist);
int ypos=text_ypix(&x->x_gui.x_obj, 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 -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_w-1,
xpos + IOWIDTH, ypos + x->x_gui.x_w,
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 -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos + IOWIDTH, ypos+1, 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 hradio_draw_select(t_hradio* x, t_glist* glist)
{
t_canvas *canvas=glist_getcanvas(glist);
int n=x->x_number, i;

if(x->x_gui.x_fsf.x_selected)
{
for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%6.6x\n", canvas, x, i,
IEM_GUI_COLOR_SELECTED);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%6.6x\n", canvas, x, i,
IEM_GUI_COLOR_NORMAL);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\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;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiiisssiiiiiiif", 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,
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 \
%d %d %d\n",
x->x_gui.x_w, 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_getintarg(0, argc, argv);
int chg = (int)atom_getintarg(4, argc, argv);
int num = (int)atom_getintarg(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);
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 "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 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)
{
if(!sys_noloadbang && 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);
}
}

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_getintarg(0, ac, av));
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 bflcol[]={-262144, -1, -1};
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);

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,11)
&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13)&&IS_A_FLOAT(argv,14))
{
a = (int)atom_getintarg(0, argc, argv);
chg = (int)atom_getintarg(1, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(2, argc, argv));
num = (int)atom_getintarg(3, argc, argv);
iemgui_new_getnames(&x->x_gui, 4, argv);
ldx = (int)atom_getintarg(7, argc, argv);
ldy = (int)atom_getintarg(8, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(9, argc, argv));
fs = (int)atom_getintarg(10, argc, argv);
bflcol[0] = (int)atom_getintarg(11, argc, argv);
bflcol[1] = (int)atom_getintarg(12, argc, argv);
bflcol[2] = (int)atom_getintarg(13, argc, argv);
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_all_colfromload(&x->x_gui, bflcol);
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"), 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);
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_setwidget(hradio_old_class, &hradio_widgetbehavior);
class_sethelpsymbol(hradio_old_class, gensym("hradio"));
}

+ 638
- 0
ports/PdPulp/libpd/pure-data/src/g_hslider.c View File

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


/* ------------ hsl gui-horicontal 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+1,
r, ypos + x->x_gui.x_h);
}
}

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 r = xpos + (x->x_val + 50)/100;
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -tags %lxBASE\n",
canvas, xpos-3, ypos,
xpos + x->x_gui.x_w+2, ypos + x->x_gui.x_h,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d -width 3 -fill #%6.6x -tags %lxKNOB\n",
canvas, r, ypos+1, r,
ypos + x->x_gui.x_h, x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xpos-3, ypos + x->x_gui.x_h-1,
xpos+4, ypos + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xpos-3, ypos,
xpos+4, ypos+1, x, 0);
}

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 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-3, ypos,
xpos + x->x_gui.x_w+2, ypos + x->x_gui.x_h);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, r, ypos+1,
r, ypos + x->x_gui.x_h);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy);
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-3, ypos + x->x_gui.x_h-1,
xpos+4, 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-3, ypos,
xpos+4, ypos+1);
}

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 #%6.6x -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:"");
sys_vgui(".x%lx.c itemconfigure %lxKNOB -fill #%6.6x\n", canvas, x, x->x_gui.x_fcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\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);
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 -tags %lxOUT%d\n",
canvas, xpos-3, ypos + x->x_gui.x_h-1,
xpos+4, ypos + x->x_gui.x_h, 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 -tags %lxIN%d\n",
canvas, xpos-3, ypos,
xpos+4, ypos+1, 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);
}

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 #%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 %lxLABEL -fill #%6.6x\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) - 3;
*yp1 = text_ypix(&x->x_gui.x_obj, glist);
*xp2 = *xp1 + x->x_gui.x_w + 5;
*yp2 = *yp1 + x->x_gui.x_h;
}

static void hslider_save(t_gobj *z, t_binbuf *b)
{
t_hslider *x = (t_hslider *)z;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", 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, x->x_gui.x_h,
(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)
w = IEM_SL_MINSIZE;
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 - 1);
else
x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 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 - 1);
else
x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 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 \
%d %d %d\n",
x->x_gui.x_w, IEM_SL_MINSIZE, x->x_gui.x_h, 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 = (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;
if (x->x_lin0_log1)
fval = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01);
else fval = (double)(x->x_val)*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_getintarg(0, argc, argv);
int h = (int)atom_getintarg(1, argc, argv);
double min = (double)atom_getfloatarg(2, argc, argv);
double max = (double)atom_getfloatarg(3, argc, argv);
int lilo = (int)atom_getintarg(4, argc, argv);
int steady = (int)atom_getintarg(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);
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_getintarg(0, ac, av));
if(ac > 1)
x->x_gui.x_h = iemgui_clip_size((int)atom_getintarg(1, ac, av));
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 - 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_float(t_hslider *x, t_floatarg f)
{
double out;

hslider_set(x, f);
if(x->x_gui.x_fsf.x_put_in2out)
hslider_bang(x);
}

static void hslider_loadbang(t_hslider *x)
{
if(!sys_noloadbang && 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 bflcol[]={-262144, -1, -1};
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);

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,13)
&&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16))
{
w = (int)atom_getintarg(0, argc, argv);
h = (int)atom_getintarg(1, argc, argv);
min = (double)atom_getfloatarg(2, argc, argv);
max = (double)atom_getfloatarg(3, argc, argv);
lilo = (int)atom_getintarg(4, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv));
iemgui_new_getnames(&x->x_gui, 6, argv);
ldx = (int)atom_getintarg(9, argc, argv);
ldy = (int)atom_getintarg(10, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv));
fs = (int)atom_getintarg(12, argc, argv);
bflcol[0] = (int)atom_getintarg(13, argc, argv);
bflcol[1] = (int)atom_getintarg(14, argc, argv);
bflcol[2] = (int)atom_getintarg(15, argc, argv);
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_getintarg(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);
hslider_check_minmax(x, min, max);
iemgui_all_colfromload(&x->x_gui, bflcol);
iemgui_verify_snd_ne_rcv(&x->x_gui);
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"), 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);
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);
}

+ 622
- 0
ports/PdPulp/libpd/pure-data/src/g_io.c View File

@@ -0,0 +1,622 @@
/* 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);
}

static int tot;

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;
#if 0
if (tot < 5) post("-in %lx out %lx n %d", in, out, n);
if (tot < 5) post("-buf %lx endbuf %lx", x->x_buf, x->x_endbuf);
if (tot < 5) post("in[0] %f in[1] %f in[2] %f", in[0], in[1], in[2]);
#endif
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++;
}
#if 0
if (tot < 5) post("in %lx out %lx n %lx", in, out, n), tot++;
if (tot < 5) post("in[0] %f in[1] %f in[2] %f", in[0], in[1], in[2]);
#endif

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 indeces 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;
#if 0
if (tot < 5) post("-in %lx out %lx n %d", in, out, n);
if (tot < 5) post("-buf %lx endbuf %lx", x->x_buf, x->x_endbuf);
#endif
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;

#if 0
if (tot < 5) post("outlet in %lx out %lx n %lx", in, out, n), tot++;
#endif
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;

#if 0
if (tot < 5) post("outlet in %lx out %lx n %lx", in, out, n), tot++;
#endif
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 indeces 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();
}

+ 387
- 0
ports/PdPulp/libpd/pure-data/src/g_mycanvas.c View File

@@ -0,0 +1,387 @@
/* 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);
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -outline #%6.6x -tags %lxRECT\n",
canvas, xpos, ypos,
xpos + x->x_vis_w, ypos + x->x_vis_h,
x->x_gui.x_bcol, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -outline #%6.6x -tags %lxBASE\n",
canvas, xpos, ypos,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
}

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);
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,
ypos + x->x_vis_h);
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 coords %lxLABEL %d %d\n",
canvas, x, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy);
}

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 #%6.6x -outline #%6.6x\n", canvas, x,
x->x_gui.x_bcol, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%6.6x\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 #%6.6x -text {%s} \n",
canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize, 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 #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE -outline #%6.6x\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;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiisssiiiiiii", 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, 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 \
%d %d %d\n",
x->x_gui.x_w, 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, -1/*no frontcolor*/, 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);
x->x_at[1].a_w.w_float = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist);
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 = (int)atom_getintarg(0, argc, argv);
int w = (int)atom_getintarg(2, argc, argv);
int h = (int)atom_getintarg(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;
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 = (int)atom_getintarg(0, ac, av);

if(i < 1)
i = 1;
x->x_gui.x_w = i;
x->x_gui.x_h = i;
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 = (int)atom_getintarg(0, ac, av);
if(i < 1)
i = 1;
x->x_vis_w = i;
if(ac > 1)
{
i = (int)atom_getintarg(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 bflcol[]={-233017, -1, -66577};
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);

if(((argc >= 10)&&(argc <= 13))
&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,2))
{
a = (int)atom_getintarg(0, argc, argv);
w = (int)atom_getintarg(1, argc, argv);
h = (int)atom_getintarg(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)&&IS_A_FLOAT(argv,i+8)
&&IS_A_FLOAT(argv,i+9))
{
/* 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 = (int)atom_getintarg(i+4, argc, argv);
ldy = (int)atom_getintarg(i+5, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(i+6, argc, argv));
fs = (int)atom_getintarg(i+7, argc, argv);
bflcol[0] = (int)atom_getintarg(i+8, argc, argv);
bflcol[2] = (int)atom_getintarg(i+9, argc, argv);
}
if((argc == 13)&&IS_A_FLOAT(argv,i+10))
{
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(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;
iemgui_all_colfromload(&x->x_gui, bflcol);
x->x_at[0].a_type = A_FLOAT;
x->x_at[1].a_type = A_FLOAT;
iemgui_verify_snd_ne_rcv(&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);

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);
}

+ 907
- 0
ports/PdPulp/libpd/pure-data/src/g_numbox.c View File

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

/*------------------ global varaibles -------------------------*/


/*------------------ global functions -------------------------*/

static void my_numbox_key(void *z, t_floatarg fkey);
static void my_numbox_draw_update(t_gobj *client, t_glist *glist);

/* ------------ nmx 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_gui.x_w;
w /= 36;
x->x_numwidth = w + (x->x_gui.x_h / 2) + 4;
}

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 = 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_gui.x_w)/* if to reduce */
{
if(is_exp)
{
if(x->x_gui.x_w <= 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_gui.x_w - 4))
{
x->x_buf[0] = (f < 0.0 ? '-' : '+');
x->x_buf[1] = 0;
}
else
{
int new_exp_index=x->x_gui.x_w-4, 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_gui.x_w] = 0;
}

}
else
{
for(idecimal=0; idecimal < bufsize; idecimal++)
if(x->x_buf[idecimal] == '.')
break;
if(idecimal > x->x_gui.x_w)
{
x->x_buf[0] = (f < 0.0 ? '-' : '+');
x->x_buf[1] = 0;
}
else
x->x_buf[x->x_gui.x_w] = 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 = strlen(x->x_buf);

x->x_buf[sl] = '>';
x->x_buf[sl+1] = 0;
if(sl >= x->x_gui.x_w)
cp += sl - x->x_gui.x_w + 1;
sys_vgui(
".x%lx.c itemconfigure %lxNUMBER -fill #%6.6x -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 #%6.6x -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 #%6.6x -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 half=x->x_gui.x_h/2, d=1+x->x_gui.x_h/34;
int xpos=text_xpix(&x->x_gui.x_obj, glist);
int ypos=text_ypix(&x->x_gui.x_obj, glist);
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(
".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d -outline #%6.6x \
-fill #%6.6x -tags %lxBASE1\n",
canvas, xpos, ypos,
xpos + x->x_numwidth-4, ypos,
xpos + x->x_numwidth, ypos+4,
xpos + x->x_numwidth, ypos + x->x_gui.x_h,
xpos, ypos + x->x_gui.x_h,
IEM_GUI_COLOR_NORMAL, x->x_gui.x_bcol, x);
sys_vgui(
".x%lx.c create line %d %d %d %d %d %d -fill #%6.6x -tags %lxBASE2\n",
canvas, xpos, ypos,
xpos + half, ypos + half,
xpos, ypos + x->x_gui.x_h,
x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
my_numbox_ftoa(x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags %lxNUMBER\n",
canvas, xpos+half+2, ypos+half+d,
x->x_buf, x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_fcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h-1,
xpos+IOWIDTH, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos,
xpos+IOWIDTH, ypos+1,
x, 0);
}

static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist)
{
int half = x->x_gui.x_h/2, d=1+x->x_gui.x_h/34;
int xpos=text_xpix(&x->x_gui.x_obj, glist);
int ypos=text_ypix(&x->x_gui.x_obj, glist);
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(".x%lx.c coords %lxBASE1 %d %d %d %d %d %d %d %d %d %d\n",
canvas, x, xpos, ypos,
xpos + x->x_numwidth-4, ypos,
xpos + x->x_numwidth, ypos+4,
xpos + x->x_numwidth, ypos + x->x_gui.x_h,
xpos, ypos + x->x_gui.x_h);
sys_vgui(".x%lx.c coords %lxBASE2 %d %d %d %d %d %d\n",
canvas, x, xpos, ypos,
xpos + half, ypos + half,
xpos, ypos + x->x_gui.x_h);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy);
sys_vgui(".x%lx.c coords %lxNUMBER %d %d\n",
canvas, x, xpos+half+2, ypos+half+d);
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-1,
xpos+IOWIDTH, 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+IOWIDTH, ypos+1);
}

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 #%6.6x -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:"");
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -font {{%s} -%d %s} -fill #%6.6x \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_fcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE1 -fill #%6.6x\n", canvas,
x, x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%6.6x\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);
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 -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h-1,
xpos+IOWIDTH, ypos + x->x_gui.x_h,
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 -tags %lxIN%d\n",
canvas,
xpos, ypos,
xpos+IOWIDTH, ypos+1,
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);
}

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 #%6.6x\n",
canvas, x, IEM_GUI_COLOR_SELECTED);
sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%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);
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%6.6x\n",
canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
sys_vgui(".x%lx.c itemconfigure %lxBASE1 -outline #%6.6x\n",
canvas, x, IEM_GUI_COLOR_NORMAL);
sys_vgui(".x%lx.c itemconfigure %lxBASE2 -fill #%6.6x\n",
canvas, x, x->x_gui.x_fcol);
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n",
canvas, x, x->x_gui.x_lcol);
sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill #%6.6x\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_numwidth;
*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;
int 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, "ssiisiiffiisssiiiiiiifi", gensym("#X"),gensym("obj"),
(int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
gensym("nbx"), x->x_gui.x_w, x->x_gui.x_h,
(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 \
%d %d %d\n",
x->x_gui.x_w, 1, x->x_gui.x_h, 8,
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_getintarg(0, argc, argv);
int h = (int)atom_getintarg(1, argc, argv);
double min = (double)atom_getfloatarg(2, argc, argv);
double max = (double)atom_getfloatarg(3, argc, argv);
int lilo = (int)atom_getintarg(4, argc, argv);
int log_height = (int)atom_getintarg(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 < 1)
w = 1;
x->x_gui.x_w = w;
if(h < 8)
h = 8;
x->x_gui.x_h = h;
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_getintarg(0, ac, av);
if(w < 1)
w = 1;
x->x_gui.x_w = w;
if(ac > 1)
{
h = (int)atom_getintarg(1, ac, av);
if(h < 8)
h = 8;
x->x_gui.x_h = h;
}
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_getintarg(1, ac, av);

if(f < 4)
f = 4;
x->x_gui.x_fontsize = f;
f = (int)atom_getintarg(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)
{
if(!sys_noloadbang && 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=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 (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 bflcol[]={-262144, -1, -1};
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];

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,13)
&&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16))
{
w = (int)atom_getintarg(0, argc, argv);
h = (int)atom_getintarg(1, argc, argv);
min = (double)atom_getfloatarg(2, argc, argv);
max = (double)atom_getfloatarg(3, argc, argv);
lilo = (int)atom_getintarg(4, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv));
iemgui_new_getnames(&x->x_gui, 6, argv);
ldx = (int)atom_getintarg(9, argc, argv);
ldy = (int)atom_getintarg(10, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv));
fs = (int)atom_getintarg(12, argc, argv);
bflcol[0] = (int)atom_getintarg(13, argc, argv);
bflcol[1] = (int)atom_getintarg(14, argc, argv);
bflcol[2] = (int)atom_getintarg(15, argc, argv);
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_getintarg(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 < 4)
fs = 4;
x->x_gui.x_fontsize = fs;
if(w < 1)
w = 1;
x->x_gui.x_w = w;
if(h < 8)
h = 8;
x->x_gui.x_h = h;
x->x_buf[0] = 0;
my_numbox_calc_fontwidth(x);
my_numbox_check_minmax(x, min, max);
iemgui_all_colfromload(&x->x_gui, bflcol);
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;
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"), 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);
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);
}

+ 787
- 0
ports/PdPulp/libpd/pure-data/src/g_readwrite.c View File

@@ -0,0 +1,787 @@
/* 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);
binbuf_free(b);
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)
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);
template_free(newtemplate);
return;
}
template_free(newtemplate);
}
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;
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)))
{
/* copy new one to old one and deete new one */
memcpy(&((t_scalar *)oldone)->sc_vec, &((t_scalar *)newone)->sc_vec,
template->t_n * sizeof(t_word));
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->t_n, 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);
}
}
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_symbol **templatevec = getbytes(0);
int ntemplates = 0;
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. ----*/

/* 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;
/* 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);
}
}

/* 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 = template->t_n;
if (!template)
{
bug("canvas_savetemplatesto");
continue;
}
/* 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_gobj *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->gl_gobj);
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"), 0);
class_addmethod(c, (t_method)canvas_menusaveas,
gensym("menusaveas"), 0);
}

+ 643
- 0
ports/PdPulp/libpd/pure-data/src/g_rtext.c View File

@@ -0,0 +1,643 @@
/* 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
/* for some reason, it draws text 1 pixel lower on Mac OS X (& linux too?) */
#ifndef _WIN32
#define TMARGIN 2
#define BMARGIN 2
#else
#define TMARGIN 3
#define BMARGIN 1
#endif

#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);
}

static t_rtext *rtext_entered;

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;
}
}
if (rtext_entered == x) rtext_entered = 0;
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));
else font = glist_getfont(x->x_glist);
fontwidth = sys_fontwidth(font);
fontheight = sys_fontheight(font);
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 + (LMARGIN + RMARGIN);
pixhigh = nlines * fontheight + (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)
{
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_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);
for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next)
;
if (!x) bug("glist_findrtext");
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 accomodate unicode
codepoints for n (which we get since Tk is sending the "%A" substitution
for bind <Key>), effectively reducing the coverage of this clause to 7
bits. Case n>127 is covered by the next clause.
*/
if (n == '\n' || (n > 31 && n < 127))
{
newsize = x->x_bufsize+1;
x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
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);
}

+ 448
- 0
ports/PdPulp/libpd/pure-data/src/g_scalar.c View File

@@ -0,0 +1,448 @@
/* 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)
{
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)
{
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)
{
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)
{
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 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);
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);
}

+ 2717
- 0
ports/PdPulp/libpd/pure-data/src/g_template.c
File diff suppressed because it is too large
View File


+ 1462
- 0
ports/PdPulp/libpd/pure-data/src/g_text.c
File diff suppressed because it is too large
View File


+ 477
- 0
ports/PdPulp/libpd/pure-data/src/g_toggle.c View File

@@ -0,0 +1,477 @@
/* 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 #%6.6x\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 #%6.6x\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)
{
t_canvas *canvas=glist_getcanvas(glist);
int w=1, xx=text_xpix(&x->x_gui.x_obj, glist), yy=text_ypix(&x->x_gui.x_obj, glist);

if(x->x_gui.x_w >= 30)
w = 2;
if(x->x_gui.x_w >= 60)
w = 3;
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -tags %lxBASE\n",
canvas, xx, yy, xx + x->x_gui.x_w, yy + x->x_gui.x_h,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d -width %d -fill #%6.6x -tags %lxX1\n",
canvas, xx+w+1, yy+w+1, xx + x->x_gui.x_w-w, yy + x->x_gui.x_h-w, w,
(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 #%6.6x -tags %lxX2\n",
canvas, xx+w+1, yy + x->x_gui.x_h-w-1, xx + x->x_gui.x_w-w, yy+w, w,
(x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx+x->x_gui.x_ldx,
yy+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx, yy + x->x_gui.x_h-1, xx + IOWIDTH, yy + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx, yy, xx + IOWIDTH, yy+1, x, 0);
}

void toggle_draw_move(t_toggle *x, t_glist *glist)
{
t_canvas *canvas=glist_getcanvas(glist);
int w=1, xx=text_xpix(&x->x_gui.x_obj, glist), yy=text_ypix(&x->x_gui.x_obj, glist);

if(x->x_gui.x_w >= 30)
w = 2;

if(x->x_gui.x_w >= 60)
w = 3;
sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x, xx, yy, xx + x->x_gui.x_w, yy + x->x_gui.x_h);
sys_vgui(".x%lx.c itemconfigure %lxX1 -width %d\n", canvas, x, w);
sys_vgui(".x%lx.c coords %lxX1 %d %d %d %d\n",
canvas, x, xx+w+1, yy+w+1, xx + x->x_gui.x_w-w, yy + x->x_gui.x_h-w);
sys_vgui(".x%lx.c itemconfigure %lxX2 -width %d\n", canvas, x, w);
sys_vgui(".x%lx.c coords %lxX2 %d %d %d %d\n",
canvas, x, xx+w+1, yy + x->x_gui.x_h-w-1, xx + x->x_gui.x_w-w, yy+w);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xx+x->x_gui.x_ldx, yy+x->x_gui.x_ldy);
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, xx, yy + x->x_gui.x_h-1, xx + IOWIDTH, yy + 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, xx, yy, xx + IOWIDTH, yy+1);
}

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 #%6.6x -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:"");
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\n", canvas, x,
x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxX1 -fill #%6.6x\n", canvas, x,
x->x_on?x->x_gui.x_fcol:x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxX2 -fill #%6.6x\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);
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 -tags %lxOUT%d\n",
canvas, xpos,
ypos + x->x_gui.x_h-1, xpos + IOWIDTH,
ypos + x->x_gui.x_h, 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 -tags %lxIN%d\n",
canvas, xpos, ypos,
xpos + IOWIDTH, ypos+1, 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 #%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 %lxLABEL -fill #%6.6x\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;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiisssiiiiiiiff", 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,
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 \
%d %d %d\n",
x->x_gui.x_w, 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_getintarg(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);
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)
{
if(!sys_noloadbang && 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_getintarg(0, ac, av));
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 bflcol[]={-262144, -1, -1};
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);

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,9)
&&IS_A_FLOAT(argv,10)&&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12))
{
a = (int)atom_getintarg(0, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(1, argc, argv));
iemgui_new_getnames(&x->x_gui, 2, argv);
ldx = (int)atom_getintarg(5, argc, argv);
ldy = (int)atom_getintarg(6, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(7, argc, argv));
fs = (int)atom_getintarg(8, argc, argv);
bflcol[0] = (int)atom_getintarg(9, argc, argv);
bflcol[1] = (int)atom_getintarg(10, argc, argv);
bflcol[2] = (int)atom_getintarg(11, argc, argv);
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_all_colfromload(&x->x_gui, bflcol);
iemgui_verify_snd_ne_rcv(&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"), 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);
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);
}

+ 1276
- 0
ports/PdPulp/libpd/pure-data/src/g_traversal.c
File diff suppressed because it is too large
View File


+ 728
- 0
ports/PdPulp/libpd/pure-data/src/g_vdial.c View File

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

/*------------------ global variables -------------------------*/


/*------------------ global functions -------------------------*/




/* ------------- 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 #%6.6x -outline #%6.6x\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 #%6.6x -outline #%6.6x\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)
{
t_canvas *canvas=glist_getcanvas(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;

for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -tags %lxBASE%d\n",
canvas, xx11, yy11, xx12, yy12,
x->x_gui.x_bcol, x, i);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -outline #%6.6x -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;
}
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, xx11+x->x_gui.x_ldx, yy11b+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx11, yy11-1, xx11 + IOWIDTH, yy11, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx11, yy11b, xx11 + IOWIDTH, yy11b+1, x, 0);
}

void vradio_draw_move(t_vradio *x, t_glist *glist)
{
t_canvas *canvas=glist_getcanvas(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;

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;
}
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xx11+x->x_gui.x_ldx, yy11b+x->x_gui.x_ldy);
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-1, xx11 + IOWIDTH, 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 + IOWIDTH, yy11b+1);
}

void vradio_draw_erase(t_vradio* x, t_glist* glist)
{
t_canvas *canvas=glist_getcanvas(glist);
int n=x->x_number, i;

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)
{
t_canvas *canvas=glist_getcanvas(glist);
int n=x->x_number, i;

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, 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 #%6.6x\n", canvas, x, i,
x->x_gui.x_bcol);
sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%6.6x -outline #%6.6x\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)
{
t_canvas *canvas=glist_getcanvas(glist);
int xpos=text_xpix(&x->x_gui.x_obj, glist);
int ypos=text_ypix(&x->x_gui.x_obj, 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 -tags %lxOUT%d\n",
canvas, xpos,
ypos+(x->x_number*x->x_gui.x_h)-1,
xpos+ IOWIDTH,
ypos+(x->x_number*x->x_gui.x_h), 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 -tags %lxIN%d\n",
canvas, xpos, ypos,
xpos+ IOWIDTH, ypos+1,
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 vradio_draw_select(t_vradio* x, t_glist* glist)
{
t_canvas *canvas=glist_getcanvas(glist);
int n=x->x_number, i;

if(x->x_gui.x_fsf.x_selected)
{
for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%6.6x\n", canvas, x, i,
IEM_GUI_COLOR_SELECTED);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
}
else
{
for(i=0; i<n; i++)
{
sys_vgui(".x%lx.c itemconfigure %lxBASE%d -outline #%6.6x\n", canvas, x, i,
IEM_GUI_COLOR_NORMAL);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\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;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiiisssiiiiiiif", 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,
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 \
%d %d %d\n",
x->x_gui.x_w, 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_getintarg(0, argc, argv);
int chg = (int)atom_getintarg(4, argc, argv);
int num = (int)atom_getintarg(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);
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)
{
if(!sys_noloadbang && 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);
}
}

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_getintarg(0, ac, av));
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 bflcol[]={-262144, -1, -1};
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;

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,11)
&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13)&&IS_A_FLOAT(argv,14))
{
a = (int)atom_getintarg(0, argc, argv);
chg = (int)atom_getintarg(1, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(2, argc, argv));
num = (int)atom_getintarg(3, argc, argv);
iemgui_new_getnames(&x->x_gui, 4, argv);
ldx = (int)atom_getintarg(7, argc, argv);
ldy = (int)atom_getintarg(8, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(9, argc, argv));
fs = (int)atom_getintarg(10, argc, argv);
bflcol[0] = (int)atom_getintarg(11, argc, argv);
bflcol[1] = (int)atom_getintarg(12, argc, argv);
bflcol[2] = (int)atom_getintarg(13, argc, argv);
fval = atom_getintarg(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_all_colfromload(&x->x_gui, bflcol);
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"), 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);
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_setwidget(vradio_old_class, &vradio_widgetbehavior);
class_sethelpsymbol(vradio_old_class, gensym("vradio"));
}

+ 640
- 0
ports/PdPulp/libpd/pure-data/src/g_vslider.c View File

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


/* ------------ 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+1, r,
xpos + x->x_gui.x_w, 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 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 -fill #%6.6x -tags %lxBASE\n",
canvas, xpos, ypos-2,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h+3,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create line %d %d %d %d -width 3 -fill #%6.6x -tags %lxKNOB\n",
canvas, xpos+1, r,
xpos + x->x_gui.x_w, r, x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h+2,
xpos+7, ypos + x->x_gui.x_h+3,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos-2,
xpos+7, ypos-1,
x, 0);
}

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 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-2,
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h+3);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, xpos+1, r,
xpos + x->x_gui.x_w, r);
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy);
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+2,
xpos+7, ypos + x->x_gui.x_h+3);
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-2,
xpos+7, ypos-1);
}

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 #%6.6x -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:"");
sys_vgui(".x%lx.c itemconfigure %lxKNOB -fill #%6.6x\n", canvas,
x, x->x_gui.x_fcol);
sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\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);
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 -tags %lxOUT%d\n",
canvas,
xpos, ypos + x->x_gui.x_h+2,
xpos+7, ypos + x->x_gui.x_h+3,
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 -tags %lxIN%d\n",
canvas,
xpos, ypos-2,
xpos+7, ypos-1,
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);
}

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 #%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 %lxLABEL -fill #%6.6x\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) - 2;
*xp2 = *xp1 + x->x_gui.x_w;
*yp2 = *yp1 + x->x_gui.x_h + 5;
}

static void vslider_save(t_gobj *z, t_binbuf *b)
{
t_vslider *x = (t_vslider *)z;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", 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, x->x_gui.x_h,
(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)
h = IEM_SL_MINSIZE;
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 - 1);
else
x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_h - 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 - 1);
else
x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_h - 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 \
%d %d %d\n",
x->x_gui.x_w, IEM_GUI_MINSIZE, x->x_gui.x_h, 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;
if (x->x_lin0_log1)
fval = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01);
else fval = (double)(x->x_val)*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_getintarg(0, argc, argv);
int h = (int)atom_getintarg(1, argc, argv);
double min = (double)atom_getfloatarg(2, argc, argv);
double max = (double)atom_getfloatarg(3, argc, argv);
int lilo = (int)atom_getintarg(4, argc, argv);
int steady = (int)atom_getintarg(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);
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 = (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_getintarg(0, ac, av));
if(ac > 1)
vslider_check_height(x, (int)atom_getintarg(1, ac, av));
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 - 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_loadbang(t_vslider *x)
{
if(!sys_noloadbang && 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 bflcol[]={-262144, -1, -1};
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);

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,13)
&&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16))
{
w = (int)atom_getintarg(0, argc, argv);
h = (int)atom_getintarg(1, argc, argv);
min = (double)atom_getfloatarg(2, argc, argv);
max = (double)atom_getfloatarg(3, argc, argv);
lilo = (int)atom_getintarg(4, argc, argv);
iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv));
iemgui_new_getnames(&x->x_gui, 6, argv);
ldx = (int)atom_getintarg(9, argc, argv);
ldy = (int)atom_getintarg(10, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv));
fs = (int)atom_getintarg(12, argc, argv);
bflcol[0] = (int)atom_getintarg(13, argc, argv);
bflcol[1] = (int)atom_getintarg(14, argc, argv);
bflcol[2] = (int)atom_getintarg(15, argc, argv);
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_getintarg(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);
vslider_check_minmax(x, min, max);
iemgui_all_colfromload(&x->x_gui, bflcol);
iemgui_verify_snd_ne_rcv(&x->x_gui);
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"), 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);
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);
}

+ 741
- 0
ports/PdPulp/libpd/pure-data/src/g_vumeter.c View File

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

/* ----- 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)-1;
int xpos=text_xpix(&x->x_gui.x_obj, glist), quad1=xpos+w4+1, quad3=xpos+x->x_gui.x_w-w4-1;

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)*(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)*(IEM_VU_STEPS+1-x->x_peak)
- (x->x_led_size+1)/2;

sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n", canvas, x,
xpos, j,
xpos+x->x_gui.x_w+1, j);
sys_vgui(".x%lx.c itemconfigure %lxPLED -fill #%6.6x\n", canvas, x,
iemgui_color_hex[i]);
}
else
{
int mid=xpos+x->x_gui.x_w/2;

sys_vgui(".x%lx.c itemconfigure %lxPLED -fill #%6.6x\n",
canvas, x, x->x_gui.x_bcol);
sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n",
canvas, x, mid, ypos+20,
mid, ypos+20);
}
}
}

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)
{
t_canvas *canvas=glist_getcanvas(glist);

int xpos=text_xpix(&x->x_gui.x_obj, glist);
int ypos=text_ypix(&x->x_gui.x_obj, glist);
int w4=x->x_gui.x_w/4, mid=xpos+x->x_gui.x_w/2,
quad1=xpos+w4+1;
int quad3=xpos+x->x_gui.x_w-w4,
end=xpos+x->x_gui.x_w+4;
int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
int led_col, yyy, i, k4=ypos-k3;

sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -tags %lxBASE\n",
canvas, xpos-1, ypos-2,
xpos+x->x_gui.x_w+1,
ypos+x->x_gui.x_h+2, 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 #%6.6x -tags %lxRLED%d\n",
canvas, quad1, yyy, quad3, yyy, x->x_led_size, 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 #%6.6x -tags %lxSCALE%d\n",
canvas, end, yyy+k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, x->x_gui.x_fontsize,
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 #%6.6x -tags %lxSCALE%d\n",
canvas, end, yyy+k3, iemgui_vu_scale_str[i], x->x_gui.x_font,
x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x, i);
}
sys_vgui(".x%lx.c create rectangle %d %d %d %d -fill #%6.6x -outline #%6.6x -tags %lxRCOVER\n",
canvas, quad1, ypos-1, quad3-1,
ypos-1 + 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 #%6.6x -tags %lxPLED\n",
canvas, mid, ypos+10,
mid, ypos+10, x->x_led_size, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
-font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos-1, ypos + x->x_gui.x_h+1,
xpos + IOWIDTH-1, ypos + x->x_gui.x_h+2,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]x\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos + x->x_gui.x_h+1,
xpos+x->x_gui.x_w+1, ypos + x->x_gui.x_h+2,
x, 1);
}
if(!x->x_gui.x_fsf.x_rcv_able)
{
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos-1, ypos-2,
xpos + IOWIDTH-1, ypos-1,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos-2,
xpos+x->x_gui.x_w+1, ypos-1,
x, 1);
}
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)
{
t_canvas *canvas=glist_getcanvas(glist);

int xpos=text_xpix(&x->x_gui.x_obj, glist);
int ypos=text_ypix(&x->x_gui.x_obj, glist);
int w4=x->x_gui.x_w/4, quad1=xpos+w4+1;
int quad3=xpos+x->x_gui.x_w-w4,
end=xpos+x->x_gui.x_w+4;
int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
int yyy, i, k4=ypos-k3;

sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
canvas, x, xpos-1, ypos-2,
xpos+x->x_gui.x_w+1,ypos+x->x_gui.x_h+2);
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,
ypos+x->x_gui.x_ldy);
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-1, ypos + x->x_gui.x_h+1,
xpos + IOWIDTH-1, ypos + x->x_gui.x_h+2);
sys_vgui(".x%lx.c coords %lxOUT%d %d %d %d %d\n",
canvas, x, 1,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos + x->x_gui.x_h+1,
xpos+x->x_gui.x_w+1, ypos + x->x_gui.x_h+2);
}
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-1, ypos-2,
xpos + IOWIDTH-1, ypos-1);
sys_vgui(".x%lx.c coords %lxIN%d %d %d %d %d\n",
canvas, x, 1,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos-2,
xpos+x->x_gui.x_w+1, ypos-1);
}
}

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;
t_canvas *canvas=glist_getcanvas(glist);

sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\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,
x->x_led_size);
if(((i+2)&3) && (x->x_scale))
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} -font {{%s} -%d %s} -fill #%6.6x\n",
canvas, x, i, iemgui_vu_scale_str[i], 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);
}
if(x->x_scale)
{
i=IEM_VU_STEPS+1;
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} -font {{%s} -%d %s} -fill #%6.6x\n",
canvas, x, i, iemgui_vu_scale_str[i], 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);
}
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, 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 #%6.6x -outline #%6.6x\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,
x->x_led_size);
}

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);
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 -tags %lxOUT%d\n",
canvas,
xpos-1, ypos + x->x_gui.x_h+1,
xpos + IOWIDTH-1, ypos + x->x_gui.x_h+2,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos + x->x_gui.x_h+1,
xpos+x->x_gui.x_w+1, ypos + x->x_gui.x_h+2,
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 -tags %lxIN%d\n",
canvas,
xpos-1, ypos-2,
xpos + IOWIDTH-1, ypos-1,
x, 0);
sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos-2,
xpos+x->x_gui.x_w+1, ypos-1,
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 #%6.6x\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 #%6.6x\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 #%6.6x\n",
canvas, x, i, 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);
for(i=1; i<=IEM_VU_STEPS; i++)
{
if(((i+2)&3) && (x->x_scale))
sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -fill #%6.6x\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 #%6.6x\n",
canvas, x, i, x->x_gui.x_lcol);
}
sys_vgui(".x%lx.c itemconfigure %lxLABEL -fill #%6.6x\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;

*xp1 = text_xpix(&x->x_gui.x_obj, glist) - 1;
*yp1 = text_ypix(&x->x_gui.x_obj, glist) - 2;
*xp2 = *xp1 + x->x_gui.x_w + 2;
*yp2 = *yp1 + x->x_gui.x_h + 4;
}

static void vu_save(t_gobj *z, t_binbuf *b)
{
t_vu *x = (t_vu *)z;
int bflcol[3];
t_symbol *srl[3];

iemgui_save(&x->x_gui, srl, bflcol);
binbuf_addv(b, "ssiisiissiiiiiiii", 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, x->x_gui.x_h,
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;
}

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, end=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w+4;
int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
int yyy, k4=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)-k3;
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 #%6.6x -tags %lxSCALE%d\n",
canvas, end, yyy+k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, x->x_gui.x_fontsize,
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 #%6.6x -tags %lxSCALE%d\n",
canvas, end, yyy+k3, iemgui_vu_scale_str[i],
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
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 \
%d %d %d\n",
x->x_gui.x_w, IEM_GUI_MINSIZE, x->x_gui.x_h, 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, -1/*no front-color*/, 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_getintarg(0, argc, argv);
int h = (int)atom_getintarg(1, argc, argv);
int scale = (int)atom_getintarg(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);
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_getintarg(0, ac, av));
if(ac > 1)
vu_check_height(x, (int)atom_getintarg(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 bflcol[]={-66577, -1, -1};
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);

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,8)&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10))
{
w = (int)atom_getintarg(0, argc, argv);
h = (int)atom_getintarg(1, argc, argv);
iemgui_new_getnames(&x->x_gui, 1, argv);
ldx = (int)atom_getintarg(4, argc, argv);
ldy = (int)atom_getintarg(5, argc, argv);
iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(6, argc, argv));
fs = (int)atom_getintarg(7, argc, argv);
bflcol[0] = (int)atom_getintarg(8, argc, argv);
bflcol[2] = (int)atom_getintarg(9, argc, argv);
scale = (int)atom_getintarg(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_getintarg(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);
iemgui_all_colfromload(&x->x_gui, bflcol);
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);
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);
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);
}

+ 129
- 0
ports/PdPulp/libpd/pure-data/src/m_atom.c View File

@@ -0,0 +1,129 @@
/* 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 */
{
char buf[30];
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");
}
}

+ 1530
- 0
ports/PdPulp/libpd/pure-data/src/m_binbuf.c
File diff suppressed because it is too large
View File


+ 871
- 0
ports/PdPulp/libpd/pure-data/src/m_class.c View File

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

#define PD_CLASS_DEF
#include "m_pd.h"
#include "m_imp.h"
#include "s_stuff.h"
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _WIN32
#include <io.h>
#endif

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

#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
#define snprintf sprintf_s
#endif

static t_symbol *class_loadsym; /* name under which an extern is invoked */
static void pd_defaultfloat(t_pd *x, t_float f);
static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv);
t_pd pd_objectmaker; /* factory for creating "object" boxes */
t_pd pd_canvasmaker; /* factory for creating canvases */

static t_symbol *class_extern_dir = &s_;

static void pd_defaultanything(t_pd *x, t_symbol *s, int argc, t_atom *argv)
{
pd_error(x, "%s: no method for '%s'", (*x)->c_name->s_name, s->s_name);
}

static void pd_defaultbang(t_pd *x)
{
if (*(*x)->c_listmethod != pd_defaultlist)
(*(*x)->c_listmethod)(x, 0, 0, 0);
else (*(*x)->c_anymethod)(x, &s_bang, 0, 0);
}

/* am empty list calls the 'bang' method unless it's the default
bang method -- that might turn around and call our 'list' method
which could be an infinite recorsion. Fall through to calling our
'anything' method. That had better not turn around and call us with
an empty list. */
void pd_emptylist(t_pd *x)
{
if (*(*x)->c_bangmethod != pd_defaultbang)
(*(*x)->c_bangmethod)(x);
else (*(*x)->c_anymethod)(x, &s_bang, 0, 0);
}

static void pd_defaultpointer(t_pd *x, t_gpointer *gp)
{
if (*(*x)->c_listmethod != pd_defaultlist)
{
t_atom at;
SETPOINTER(&at, gp);
(*(*x)->c_listmethod)(x, 0, 1, &at);
}
else
{
t_atom at;
SETPOINTER(&at, gp);
(*(*x)->c_anymethod)(x, &s_pointer, 1, &at);
}
}

static void pd_defaultfloat(t_pd *x, t_float f)
{
if (*(*x)->c_listmethod != pd_defaultlist)
{
t_atom at;
SETFLOAT(&at, f);
(*(*x)->c_listmethod)(x, 0, 1, &at);
}
else
{
t_atom at;
SETFLOAT(&at, f);
(*(*x)->c_anymethod)(x, &s_float, 1, &at);
}
}

static void pd_defaultsymbol(t_pd *x, t_symbol *s)
{
if (*(*x)->c_listmethod != pd_defaultlist)
{
t_atom at;
SETSYMBOL(&at, s);
(*(*x)->c_listmethod)(x, 0, 1, &at);
}
else
{
t_atom at;
SETSYMBOL(&at, s);
(*(*x)->c_anymethod)(x, &s_symbol, 1, &at);
}
}

void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
static void class_nosavefn(t_gobj *z, t_binbuf *b);

/* handle "list" messages to Pds without explicit list methods defined. */
static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv)
{
/* a list with no elements is handled by the 'bang' method if
one exists. */
if (argc == 0 && *(*x)->c_bangmethod != pd_defaultbang)
{
(*(*x)->c_bangmethod)(x);
return;
}
/* a list with one element which is a number can be handled by a
"float" method if any is defined; same for "symbol", "pointer". */
if (argc == 1)
{
if (argv->a_type == A_FLOAT &&
*(*x)->c_floatmethod != pd_defaultfloat)
{
(*(*x)->c_floatmethod)(x, argv->a_w.w_float);
return;
}
else if (argv->a_type == A_SYMBOL &&
*(*x)->c_symbolmethod != pd_defaultsymbol)
{
(*(*x)->c_symbolmethod)(x, argv->a_w.w_symbol);
return;
}
else if (argv->a_type == A_POINTER &&
*(*x)->c_pointermethod != pd_defaultpointer)
{
(*(*x)->c_pointermethod)(x, argv->a_w.w_gpointer);
return;
}
}
/* Next try for an "anything" method */
if ((*x)->c_anymethod != pd_defaultanything)
(*(*x)->c_anymethod)(x, &s_list, argc, argv);

/* if the object is patchable (i.e., can have proper inlets)
send it on to obj_list which will unpack the list into the inlets */
else if ((*x)->c_patchable)
obj_list((t_object *)x, s, argc, argv);
/* otherwise gove up and complain. */
else pd_defaultanything(x, &s_list, argc, argv);
}

/* for now we assume that all "gobjs" are text unless explicitly
overridden later by calling class_setbehavior(). I'm not sure
how to deal with Pds that aren't gobjs; shouldn't there be a
way to check that at run time? Perhaps the presence of a "newmethod"
should be our cue, or perhaps the "tiny" flag. */

/* another matter. This routine does two unrelated things: it creates
a Pd class, but also adds a "new" method to create an instance of it.
These are combined for historical reasons and for brevity in writing
objects. To avoid adding a "new" method send a null function pointer.
To add additional ones, use class_addcreator below. Some "classes", like
"select", are actually two classes of the same name, one for the single-
argument form, one for the multiple one; see select_setup() to find out
how this is handled. */

extern void text_save(t_gobj *z, t_binbuf *b);

t_class *class_new(t_symbol *s, t_newmethod newmethod, t_method freemethod,
size_t size, int flags, t_atomtype type1, ...)
{
va_list ap;
t_atomtype vec[MAXPDARG+1], *vp = vec;
int count = 0;
t_class *c;
int typeflag = flags & CLASS_TYPEMASK;
if (!typeflag) typeflag = CLASS_PATCHABLE;
*vp = type1;

va_start(ap, type1);
while (*vp)
{
if (count == MAXPDARG)
{
error("class %s: sorry: only %d args typechecked; use A_GIMME",
s->s_name, MAXPDARG);
break;
}
vp++;
count++;
*vp = va_arg(ap, t_atomtype);
}
va_end(ap);
if (pd_objectmaker && newmethod)
{
/* add a "new" method by the name specified by the object */
class_addmethod(pd_objectmaker, (t_method)newmethod, s,
vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
if (class_loadsym)
{
/* if we're loading an extern it might have been invoked by a
longer file name; in this case, make this an admissible name
too. */
char *loadstring = class_loadsym->s_name,
l1 = strlen(s->s_name), l2 = strlen(loadstring);
if (l2 > l1 && !strcmp(s->s_name, loadstring + (l2 - l1)))
class_addmethod(pd_objectmaker, (t_method)newmethod,
class_loadsym,
vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
}
}
c = (t_class *)t_getbytes(sizeof(*c));
c->c_name = c->c_helpname = s;
c->c_size = size;
c->c_methods = t_getbytes(0);
c->c_nmethod = 0;
c->c_freemethod = (t_method)freemethod;
c->c_bangmethod = pd_defaultbang;
c->c_pointermethod = pd_defaultpointer;
c->c_floatmethod = pd_defaultfloat;
c->c_symbolmethod = pd_defaultsymbol;
c->c_listmethod = pd_defaultlist;
c->c_anymethod = pd_defaultanything;
c->c_wb = (typeflag == CLASS_PATCHABLE ? &text_widgetbehavior : 0);
c->c_pwb = 0;
c->c_firstin = ((flags & CLASS_NOINLET) == 0);
c->c_patchable = (typeflag == CLASS_PATCHABLE);
c->c_gobj = (typeflag >= CLASS_GOBJ);
c->c_drawcommand = 0;
c->c_floatsignalin = 0;
c->c_externdir = class_extern_dir;
c->c_savefn = (typeflag == CLASS_PATCHABLE ? text_save : class_nosavefn);
#if 0
post("class: %s", c->c_name->s_name);
#endif
return (c);
}

/* add a creation method, which is a function that returns a Pd object
suitable for putting in an object box. We presume you've got a class it
can belong to, but this won't be used until the newmethod is actually
called back (and the new method explicitly takes care of this.) */

void class_addcreator(t_newmethod newmethod, t_symbol *s,
t_atomtype type1, ...)
{
va_list ap;
t_atomtype vec[MAXPDARG+1], *vp = vec;
int count = 0;
*vp = type1;

va_start(ap, type1);
while (*vp)
{
if (count == MAXPDARG)
{
error("class %s: sorry: only %d creation args allowed",
s->s_name, MAXPDARG);
break;
}
vp++;
count++;
*vp = va_arg(ap, t_atomtype);
}
va_end(ap);
class_addmethod(pd_objectmaker, (t_method)newmethod, s,
vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
}

void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
t_atomtype arg1, ...)
{
va_list ap;
t_methodentry *m;
t_atomtype argtype = arg1;
int nargs;
va_start(ap, arg1);
/* "signal" method specifies that we take audio signals but
that we don't want automatic float to signal conversion. This
is obsolete; you should now use the CLASS_MAINSIGNALIN macro. */
if (sel == &s_signal)
{
if (c->c_floatsignalin)
post("warning: signal method overrides class_mainsignalin");
c->c_floatsignalin = -1;
}
/* check for special cases. "Pointer" is missing here so that
pd_objectmaker's pointer method can be typechecked differently. */
if (sel == &s_bang)
{
if (argtype) goto phooey;
class_addbang(c, fn);
}
else if (sel == &s_float)
{
if (argtype != A_FLOAT || va_arg(ap, t_atomtype)) goto phooey;
class_doaddfloat(c, fn);
}
else if (sel == &s_symbol)
{
if (argtype != A_SYMBOL || va_arg(ap, t_atomtype)) goto phooey;
class_addsymbol(c, fn);
}
else if (sel == &s_list)
{
if (argtype != A_GIMME) goto phooey;
class_addlist(c, fn);
}
else if (sel == &s_anything)
{
if (argtype != A_GIMME) goto phooey;
class_addanything(c, fn);
}
else
{
int i;
for (i = 0; i < c->c_nmethod; i++)
if (c->c_methods[i].me_name == sel)
{
char nbuf[80];
snprintf(nbuf, 80, "%s_aliased", sel->s_name);
c->c_methods[i].me_name = gensym(nbuf);
if (c == pd_objectmaker)
post("warning: class '%s' overwritten; old one renamed '%s'",
sel->s_name, nbuf);
else post("warning: old method '%s' for class '%s' renamed '%s'",
sel->s_name, c->c_name->s_name, nbuf);
}
c->c_methods = t_resizebytes(c->c_methods,
c->c_nmethod * sizeof(*c->c_methods),
(c->c_nmethod + 1) * sizeof(*c->c_methods));
m = c->c_methods + c->c_nmethod;
c->c_nmethod++;
m->me_name = sel;
m->me_fun = (t_gotfn)fn;
nargs = 0;
while (argtype != A_NULL && nargs < MAXPDARG)
{
m->me_arg[nargs++] = argtype;
argtype = va_arg(ap, t_atomtype);
}
if (argtype != A_NULL)
error("%s_%s: only 5 arguments are typecheckable; use A_GIMME",
c->c_name->s_name, sel->s_name);
va_end(ap);
m->me_arg[nargs] = A_NULL;
}
return;
phooey:
bug("class_addmethod: %s_%s: bad argument types\n",
c->c_name->s_name, sel->s_name);
}

/* Instead of these, see the "class_addfloat", etc., macros in m_pd.h */
void class_addbang(t_class *c, t_method fn)
{
c->c_bangmethod = (t_bangmethod)fn;
}

void class_addpointer(t_class *c, t_method fn)
{
c->c_pointermethod = (t_pointermethod)fn;
}

void class_doaddfloat(t_class *c, t_method fn)
{
c->c_floatmethod = (t_floatmethod)fn;
}

void class_addsymbol(t_class *c, t_method fn)
{
c->c_symbolmethod = (t_symbolmethod)fn;
}

void class_addlist(t_class *c, t_method fn)
{
c->c_listmethod = (t_listmethod)fn;
}

void class_addanything(t_class *c, t_method fn)
{
c->c_anymethod = (t_anymethod)fn;
}

void class_setwidget(t_class *c, t_widgetbehavior *w)
{
c->c_wb = w;
}

void class_setparentwidget(t_class *c, t_parentwidgetbehavior *pw)
{
c->c_pwb = pw;
}

char *class_getname(t_class *c)
{
return (c->c_name->s_name);
}

char *class_gethelpname(t_class *c)
{
return (c->c_helpname->s_name);
}

void class_sethelpsymbol(t_class *c, t_symbol *s)
{
c->c_helpname = s;
}

t_parentwidgetbehavior *pd_getparentwidget(t_pd *x)
{
return ((*x)->c_pwb);
}

void class_setdrawcommand(t_class *c)
{
c->c_drawcommand = 1;
}

int class_isdrawcommand(t_class *c)
{
return (c->c_drawcommand);
}

static void pd_floatforsignal(t_pd *x, t_float f)
{
int offset = (*x)->c_floatsignalin;
if (offset > 0)
*(t_float *)(((char *)x) + offset) = f;
else
pd_error(x, "%s: float unexpected for signal input",
(*x)->c_name->s_name);
}

void class_domainsignalin(t_class *c, int onset)
{
if (onset <= 0) onset = -1;
else
{
if (c->c_floatmethod != pd_defaultfloat)
post("warning: %s: float method overwritten", c->c_name->s_name);
c->c_floatmethod = (t_floatmethod)pd_floatforsignal;
}
c->c_floatsignalin = onset;
}

void class_set_extern_dir(t_symbol *s)
{
class_extern_dir = s;
}

char *class_gethelpdir(t_class *c)
{
return (c->c_externdir->s_name);
}

static void class_nosavefn(t_gobj *z, t_binbuf *b)
{
bug("save function called but not defined");
}

void class_setsavefn(t_class *c, t_savefn f)
{
c->c_savefn = f;
}

t_savefn class_getsavefn(t_class *c)
{
return (c->c_savefn);
}

void class_setpropertiesfn(t_class *c, t_propertiesfn f)
{
c->c_propertiesfn = f;
}

t_propertiesfn class_getpropertiesfn(t_class *c)
{
return (c->c_propertiesfn);
}

/* ---------------- the symbol table ------------------------ */

#define HASHSIZE 1024

static t_symbol *symhash[HASHSIZE];

t_symbol *dogensym(const char *s, t_symbol *oldsym)
{
t_symbol **sym1, *sym2;
unsigned int hash = 5381;
int length = 0;
const char *s2 = s;
while (*s2) /* djb2 hash algo */
{
hash = ((hash << 5) + hash) + *s2;
length++;
s2++;
}
sym1 = symhash + (hash & (HASHSIZE-1));
while (sym2 = *sym1)
{
if (!strcmp(sym2->s_name, s)) return(sym2);
sym1 = &sym2->s_next;
}
if (oldsym) sym2 = oldsym;
else
{
sym2 = (t_symbol *)t_getbytes(sizeof(*sym2));
sym2->s_name = t_getbytes(length+1);
sym2->s_next = 0;
sym2->s_thing = 0;
strcpy(sym2->s_name, s);
}
*sym1 = sym2;
return (sym2);
}

t_symbol *gensym(const char *s)
{
return(dogensym(s, 0));
}

static t_symbol *addfileextent(t_symbol *s)
{
char namebuf[MAXPDSTRING], *str = s->s_name;
int ln = strlen(str);
if (!strcmp(str + ln - 3, ".pd")) return (s);
strcpy(namebuf, str);
strcpy(namebuf+ln, ".pd");
return (gensym(namebuf));
}

#define MAXOBJDEPTH 1000
static int tryingalready;

void canvas_popabstraction(t_canvas *x);
extern t_pd *newest;

t_symbol* pathsearch(t_symbol *s,char* ext);
int pd_setloadingabstraction(t_symbol *sym);

/* this routine is called when a new "object" is requested whose class Pd
doesn't know. Pd tries to load it as an extern, then as an abstraction. */
void new_anything(void *dummy, t_symbol *s, int argc, t_atom *argv)
{
int fd;
char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr;
if (tryingalready>MAXOBJDEPTH){
error("maximum object loading depth %d reached", MAXOBJDEPTH);
return;
}
newest = 0;
class_loadsym = s;
if (sys_load_lib(canvas_getcurrent(), s->s_name))
{
tryingalready++;
typedmess(dummy, s, argc, argv);
tryingalready--;
return;
}
class_loadsym = 0;
/* for class/class.pd support, to match class/class.pd_linux */
snprintf(classslashclass, MAXPDSTRING, "%s/%s", s->s_name, s->s_name);
if ((fd = canvas_open(canvas_getcurrent(), s->s_name, ".pd",
dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
(fd = canvas_open(canvas_getcurrent(), s->s_name, ".pat",
dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
(fd = canvas_open(canvas_getcurrent(), classslashclass, ".pd",
dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0)
{
close (fd);
if (!pd_setloadingabstraction(s))
{
t_pd *was = s__X.s_thing;
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);
}
else error("%s: can't load abstraction within itself\n", s->s_name);
}
else newest = 0;
}

t_symbol s_pointer = {"pointer", 0, 0};
t_symbol s_float = {"float", 0, 0};
t_symbol s_symbol = {"symbol", 0, 0};
t_symbol s_bang = {"bang", 0, 0};
t_symbol s_list = {"list", 0, 0};
t_symbol s_anything = {"anything", 0, 0};
t_symbol s_signal = {"signal", 0, 0};
t_symbol s__N = {"#N", 0, 0};
t_symbol s__X = {"#X", 0, 0};
t_symbol s_x = {"x", 0, 0};
t_symbol s_y = {"y", 0, 0};
t_symbol s_ = {"", 0, 0};

static t_symbol *symlist[] = { &s_pointer, &s_float, &s_symbol, &s_bang,
&s_list, &s_anything, &s_signal, &s__N, &s__X, &s_x, &s_y, &s_};

void mess_init(void)
{
t_symbol **sp;
int i;

if (pd_objectmaker) return;
for (i = sizeof(symlist)/sizeof(*symlist), sp = symlist; i--; sp++)
(void) dogensym((*sp)->s_name, *sp);
pd_objectmaker = class_new(gensym("objectmaker"), 0, 0, sizeof(t_pd),
CLASS_DEFAULT, A_NULL);
pd_canvasmaker = class_new(gensym("classmaker"), 0, 0, sizeof(t_pd),
CLASS_DEFAULT, A_NULL);
class_addanything(pd_objectmaker, (t_method)new_anything);
}

t_pd *newest;

/* This is externally available, but note that it might later disappear; the
whole "newest" thing is a hack which needs to be redesigned. */
t_pd *pd_newest(void)
{
return (newest);
}

/* horribly, we need prototypes for each of the artificial function
calls in typedmess(), to keep the compiler quiet. */
typedef t_pd *(*t_newgimme)(t_symbol *s, int argc, t_atom *argv);
typedef void(*t_messgimme)(t_pd *x, t_symbol *s, int argc, t_atom *argv);

typedef t_pd *(*t_fun0)(
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
typedef t_pd *(*t_fun1)(t_int i1,
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
typedef t_pd *(*t_fun2)(t_int i1, t_int i2,
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
typedef t_pd *(*t_fun3)(t_int i1, t_int i2, t_int i3,
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
typedef t_pd *(*t_fun4)(t_int i1, t_int i2, t_int i3, t_int i4,
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
typedef t_pd *(*t_fun5)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5,
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
typedef t_pd *(*t_fun6)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, t_int i6,
t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);

void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
{
t_method *f;
t_class *c = *x;
t_methodentry *m;
t_atomtype *wp, wanttype;
int i;
t_int ai[MAXPDARG+1], *ap = ai;
t_floatarg ad[MAXPDARG+1], *dp = ad;
int narg = 0;
t_pd *bonzo;
/* check for messages that are handled by fixed slots in the class
structure. We don't catch "pointer" though so that sending "pointer"
to pd_objectmaker doesn't require that we supply a pointer value. */
if (s == &s_float)
{
if (!argc) (*c->c_floatmethod)(x, 0.);
else if (argv->a_type == A_FLOAT)
(*c->c_floatmethod)(x, argv->a_w.w_float);
else goto badarg;
return;
}
if (s == &s_bang)
{
(*c->c_bangmethod)(x);
return;
}
if (s == &s_list)
{
(*c->c_listmethod)(x, s, argc, argv);
return;
}
if (s == &s_symbol)
{
if (argc && argv->a_type == A_SYMBOL)
(*c->c_symbolmethod)(x, argv->a_w.w_symbol);
else
(*c->c_symbolmethod)(x, &s_);
return;
}
for (i = c->c_nmethod, m = c->c_methods; i--; m++)
if (m->me_name == s)
{
wp = m->me_arg;
if (*wp == A_GIMME)
{
if (x == &pd_objectmaker)
newest = (*((t_newgimme)(m->me_fun)))(s, argc, argv);
else (*((t_messgimme)(m->me_fun)))(x, s, argc, argv);
return;
}
if (argc > MAXPDARG) argc = MAXPDARG;
if (x != &pd_objectmaker) *(ap++) = (t_int)x, narg++;
while (wanttype = *wp++)
{
switch (wanttype)
{
case A_POINTER:
if (!argc) goto badarg;
else
{
if (argv->a_type == A_POINTER)
*ap = (t_int)(argv->a_w.w_gpointer);
else goto badarg;
argc--;
argv++;
}
narg++;
ap++;
break;
case A_FLOAT:
if (!argc) goto badarg;
case A_DEFFLOAT:
if (!argc) *dp = 0;
else
{
if (argv->a_type == A_FLOAT)
*dp = argv->a_w.w_float;
else goto badarg;
argc--;
argv++;
}
dp++;
break;
case A_SYMBOL:
if (!argc) goto badarg;
case A_DEFSYM:
if (!argc) *ap = (t_int)(&s_);
else
{
if (argv->a_type == A_SYMBOL)
*ap = (t_int)(argv->a_w.w_symbol);
/* if it's an unfilled "dollar" argument it appears
as zero here; cheat and bash it to the null
symbol. Unfortunately, this lets real zeros
pass as symbols too, which seems wrong... */
else if (x == &pd_objectmaker && argv->a_type == A_FLOAT
&& argv->a_w.w_float == 0)
*ap = (t_int)(&s_);
else goto badarg;
argc--;
argv++;
}
narg++;
ap++;
break;
default:
goto badarg;
}
}
switch (narg)
{
case 0 : bonzo = (*(t_fun0)(m->me_fun))
(ad[0], ad[1], ad[2], ad[3], ad[4]); break;
case 1 : bonzo = (*(t_fun1)(m->me_fun))
(ai[0], ad[0], ad[1], ad[2], ad[3], ad[4]); break;
case 2 : bonzo = (*(t_fun2)(m->me_fun))
(ai[0], ai[1], ad[0], ad[1], ad[2], ad[3], ad[4]); break;
case 3 : bonzo = (*(t_fun3)(m->me_fun))
(ai[0], ai[1], ai[2], ad[0], ad[1], ad[2], ad[3], ad[4]); break;
case 4 : bonzo = (*(t_fun4)(m->me_fun))
(ai[0], ai[1], ai[2], ai[3],
ad[0], ad[1], ad[2], ad[3], ad[4]); break;
case 5 : bonzo = (*(t_fun5)(m->me_fun))
(ai[0], ai[1], ai[2], ai[3], ai[4],
ad[0], ad[1], ad[2], ad[3], ad[4]); break;
case 6 : bonzo = (*(t_fun6)(m->me_fun))
(ai[0], ai[1], ai[2], ai[3], ai[4], ai[5],
ad[0], ad[1], ad[2], ad[3], ad[4]); break;
default: bonzo = 0;
}
if (x == &pd_objectmaker)
newest = bonzo;
return;
}
(*c->c_anymethod)(x, s, argc, argv);
return;
badarg:
pd_error(x, "Bad arguments for message '%s' to object '%s'",
s->s_name, c->c_name->s_name);
}

/* convenience routine giving a stdarg interface to typedmess(). Only
ten args supported; it seems unlikely anyone will need more since
longer messages are likely to be programmatically generated anyway. */
void pd_vmess(t_pd *x, t_symbol *sel, char *fmt, ...)
{
va_list ap;
t_atom arg[10], *at = arg;
int nargs = 0;
char *fp = fmt;

va_start(ap, fmt);
while (1)
{
if (nargs >= 10)
{
pd_error(x, "pd_vmess: only 10 allowed");
break;
}
switch(*fp++)
{
case 'f': SETFLOAT(at, va_arg(ap, double)); break;
case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
case 'p': SETPOINTER(at, va_arg(ap, t_gpointer *)); break;
default: goto done;
}
at++;
nargs++;
}
done:
va_end(ap);
typedmess(x, sel, nargs, arg);
}

void pd_forwardmess(t_pd *x, int argc, t_atom *argv)
{
if (argc)
{
t_atomtype t = argv->a_type;
if (t == A_SYMBOL) pd_typedmess(x, argv->a_w.w_symbol, argc-1, argv+1);
else if (t == A_POINTER)
{
if (argc == 1) pd_pointer(x, argv->a_w.w_gpointer);
else pd_list(x, &s_list, argc, argv);
}
else if (t == A_FLOAT)
{
if (argc == 1) pd_float(x, argv->a_w.w_float);
else pd_list(x, &s_list, argc, argv);
}
else bug("pd_forwardmess");
}

}

void nullfn(void) {}

t_gotfn getfn(t_pd *x, t_symbol *s)
{
t_class *c = *x;
t_methodentry *m;
int i;

for (i = c->c_nmethod, m = c->c_methods; i--; m++)
if (m->me_name == s) return(m->me_fun);
pd_error(x, "%s: no method for message '%s'", c->c_name->s_name, s->s_name);
return((t_gotfn)nullfn);
}

t_gotfn zgetfn(t_pd *x, t_symbol *s)
{
t_class *c = *x;
t_methodentry *m;
int i;

for (i = c->c_nmethod, m = c->c_methods; i--; m++)
if (m->me_name == s) return(m->me_fun);
return(0);
}

+ 106
- 0
ports/PdPulp/libpd/pure-data/src/m_conf.c View File

@@ -0,0 +1,106 @@
/* 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 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 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();
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();
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();
}


+ 198
- 0
ports/PdPulp/libpd/pure-data/src/m_glob.c View File

@@ -0,0 +1,198 @@
/* 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"

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_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_savepreferences(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 1
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");
}

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_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_savepreferences,
gensym("save-preferences"), 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;
}


+ 110
- 0
ports/PdPulp/libpd/pure-data/src/m_imp.h 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. */

/* 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 */
t_methodentry *c_methods; /* methods other than bang, etc below */
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;
struct _widgetbehavior *c_wb; /* "gobjs" only */
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 */
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 */
};

struct _pdinstance
{
double pd_systime; /* global time in Pd ticks */
t_clock *pd_clock_setlist; /* list of set clocks */
t_int *pd_dspchain; /* DSP chain */
int pd_dspchainsize; /* number of elements in DSP chain */
t_canvas *pd_canvaslist; /* list of all root canvases */
int pd_dspstate; /* whether DSP is on or off */
t_signal *pd_signals; /* list of signals used by DSP chain */
t_symbol *pd_midiin_sym; /* symbols bound to incoming MIDI... */
t_symbol *pd_sysexin_sym;
t_symbol *pd_notein_sym;
t_symbol *pd_ctlin_sym;
t_symbol *pd_pgmin_sym;
t_symbol *pd_bendin_sym;
t_symbol *pd_touchin_sym;
t_symbol *pd_polytouchin_sym;
t_symbol *pd_midiclkin_sym;
t_symbol *pd_midirealtimein_sym;
};

extern t_pdinstance *pd_this;

/* 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);

/* misc */
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/PdPulp/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

+ 743
- 0
ports/PdPulp/libpd/pure-data/src/m_obj.c View File

@@ -0,0 +1,743 @@
/* 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 int stackcount = 0; /* iteration counter */
#define STACKITER 1000 /* maximum iterations allowed */

static 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));
}

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 && x->ob_pd->c_floatsignalin)
{
if (!m--) return (0);
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)
{
int n = 0;
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);
n++;
}
for (i = x->ob_inlet; i; i = i->i_next, m--)
if (i->i_symfrom == &s_signal)
{
if (m == 0)
return (&i->i_un.iu_floatsignalvalue);
n++;
}
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);
}


+ 367
- 0
ports/PdPulp/libpd/pure-data/src/m_pd.c View File

@@ -0,0 +1,367 @@
/* 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"

/* 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"), "");
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);

t_pdinstance *pd_this;

static t_symbol *midi_gensym(const char *prefix, const char *name)
{
char buf[80];
strcpy(buf, prefix);
strncat(buf, name, 79 - strlen(buf));
return (gensym(buf));
}

static t_pdinstance *pdinstance_donew(int useprefix)
{
t_pdinstance *x = (t_pdinstance *)getbytes(sizeof(t_pdinstance));
char midiprefix[80];
if (useprefix)
sprintf(midiprefix, "%p", x);
else midiprefix[0] = 0;
x->pd_systime = 0;
x->pd_clock_setlist = 0;
x->pd_dspchain = 0;
x->pd_dspchainsize = 0;
x->pd_canvaslist = 0;
x->pd_dspstate = 0;
x->pd_midiin_sym = midi_gensym(midiprefix, "#midiin");
x->pd_sysexin_sym = midi_gensym(midiprefix, "#sysexin");
x->pd_notein_sym = midi_gensym(midiprefix, "#notein");
x->pd_ctlin_sym = midi_gensym(midiprefix, "#ctlin");
x->pd_pgmin_sym = midi_gensym(midiprefix, "#pgmin");
x->pd_bendin_sym = midi_gensym(midiprefix, "#bendin");
x->pd_touchin_sym = midi_gensym(midiprefix, "#touchin");
x->pd_polytouchin_sym = midi_gensym(midiprefix, "#polytouchin");
x->pd_midiclkin_sym = midi_gensym(midiprefix, "#midiclkin");
x->pd_midirealtimein_sym = midi_gensym(midiprefix, "#midirealtimein");
return (x);
}

EXTERN t_pdinstance *pdinstance_new(void)
{
return (pdinstance_donew(1));
}

void pd_init(void)
{
if (!pd_this)
pd_this = pdinstance_donew(0);
mess_init();
obj_init();
conf_init();
glob_init();
garray_init();
}

EXTERN void pd_setinstance(t_pdinstance *x)
{
pd_this = x;
}

EXTERN void pdinstance_free(t_pdinstance *x)
{
/* placeholder - LATER free symtab, dsp chain, classes and canvases */
}

EXTERN t_canvas *pd_getcanvaslist(void)
{
return (pd_this->pd_canvaslist);
}

EXTERN int pd_getdspstate(void)
{
return (pd_this->pd_dspstate);
}


+ 770
- 0
ports/PdPulp/libpd/pure-data/src/m_pd.h View File

@@ -0,0 +1,770 @@
/* 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 46
#define PD_BUGFIX_VERSION 6
#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 */

/* and depending on the compiler, hidden data structures are
declared differently: */
#if defined( __GNUC__) || defined( __BORLANDC__ ) || defined( __MWERKS__ )
#define EXTERN_STRUCT struct
#else
#define EXTERN_STRUCT extern struct
#endif

/* 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)
#define PD_LONGINTTYPE long
#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 stype message */
#define T_ATOM 3 /* a cell to display a number or symbol */

#define te_pd te_g.g_pd

/* t_object is synonym for t_text (LATER unify them) */

typedef struct _text t_object;

#define ob_outlet te_outlet
#define ob_inlet te_inlet
#define ob_binbuf te_binbuf
#define ob_pd te_g.g_pd
#define ob_g te_g

typedef void (*t_method)(void);
typedef void *(*t_newmethod)( void);

/* in ARM 64 a varargs prototype generates a different function call sequence
from a fixed one, so in that special case we maek 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.) */
#ifdef __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 */
EXTERN t_symbol s_pointer;
EXTERN t_symbol s_float;
EXTERN t_symbol s_symbol;
EXTERN t_symbol s_bang;
EXTERN t_symbol s_list;
EXTERN t_symbol s_anything;
EXTERN t_symbol s_signal;
EXTERN t_symbol s__N;
EXTERN t_symbol s__X;
EXTERN t_symbol s_x;
EXTERN t_symbol s_y;
EXTERN t_symbol s_;

/* --------- prototypes from the central message system ----------- */
EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv);
EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv);
EXTERN t_symbol *gensym(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 macrose are for sending non-type-checkable mesages, 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, 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_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 t_parentwidgetbehavior *pd_getparentwidget(t_pd *x);

/* -------------------- classes -------------- */

#define CLASS_DEFAULT 0 /* flags for new classes below */
#define CLASS_PD 1
#define CLASS_GOBJ 2
#define CLASS_PATCHABLE 3
#define CLASS_NOINLET 8

#define CLASS_TYPEMASK 3


EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod,
t_method freemethod, size_t size, int flags, t_atomtype arg1, ...);
EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s,
t_atomtype type1, ...);
EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
t_atomtype arg1, ...);
EXTERN void class_addbang(t_class *c, t_method fn);
EXTERN void class_addpointer(t_class *c, t_method fn);
EXTERN void class_doaddfloat(t_class *c, t_method fn);
EXTERN void class_addsymbol(t_class *c, t_method fn);
EXTERN void class_addlist(t_class *c, t_method fn);
EXTERN void class_addanything(t_class *c, t_method fn);
EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s);
EXTERN void class_setwidget(t_class *c, t_widgetbehavior *w);
EXTERN void class_setparentwidget(t_class *c, t_parentwidgetbehavior *w);
EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c);
EXTERN char *class_getname(t_class *c);
EXTERN char *class_gethelpname(t_class *c);
EXTERN 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
static inline int PD_BADFLOAT(t_sample f) {
t_sampleint_union u;
u.f=f;
return ((u.i & 0x7f800000)==0) || ((u.i&0x7f800000)==0x7f800000);
}
/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */
static inline int PD_BIGORSMALL(t_sample f) {
t_sampleint_union u;
u.f=f;
return ((u.i & 0x60000000)==0) || ((u.i & 0x60000000)==0x60000000);
}
# else
# warning 64bit mode: BIGORSMALL not implemented yet
# define PD_BADFLOAT(f) 0
# define PD_BIGORSMALL(f) 0
# endif
#else
# define PD_BADFLOAT(f) 0
# define PD_BIGORSMALL(f) 0
#endif
#else /* _MSC_VER */
#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))
#endif /* _MSC_VER */
/* get version number at run time */
EXTERN void sys_getversion(int *major, int *minor, int *bugfix);

EXTERN_STRUCT _pdinstance;
#define t_pdinstance struct _pdinstance /* m_imp.h */

/* m_pd.c */

EXTERN t_pdinstance *pdinstance_new( void);
EXTERN void pd_setinstance(t_pdinstance *x);
EXTERN void pdinstance_free(t_pdinstance *x);
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_ */

+ 668
- 0
ports/PdPulp/libpd/pure-data/src/m_sched.c View File

@@ -0,0 +1,668 @@
/* 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 THREAD_LOCKING 1
#if THREAD_LOCKING
#include "pthread.h"
#endif

#define SYS_QUIT_QUIT 1
#define SYS_QUIT_RESTART 2
static int sys_quit;

int sys_schedblocksize = DEFDACBLKSIZE;
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/sys_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/sys_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/sys_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)sys_schedblocksize) / sys_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)(sys_dacsr /(double)sys_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_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0))
{
glob_watchdog(0);
/* ping every 2 seconds */
sched_nextpingtime = sched_diddsp +
2 * (int)(sys_dacsr /(double)sys_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)(sys_dacsr /(double)sys_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;
double sys_time_per_dsp_tick;

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_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)sys_schedblocksize) / sys_dacsr;
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 + sys_time_per_dsp_tick;
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;
sys_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)sys_schedblocksize) / sys_dacsr;

#if THREAD_LOCKING
sys_lock();
#endif

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)
{
#if THREAD_LOCKING
/* T.Grill - send_dacs may sleep ->
unlock thread lock make that time available
- could messaging do any harm while sys_send_dacs is running?
*/
sys_unlock();
#endif
timeforward = sys_send_dacs();
#if THREAD_LOCKING
/* T.Grill - done */
sys_lock();
#endif
/* 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;
}
}
}
}
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();
#if THREAD_LOCKING
sys_unlock(); /* unlock while we idle */
#endif
/* 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);
}
#if THREAD_LOCKING
sys_lock();
#endif
sys_addhist(5);
sched_didnothing++;
}
}

#if THREAD_LOCKING
sys_unlock();
#endif
}

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)
{
sys_time_per_dsp_tick = (TIMEUNITPERSECOND) *
((double)sys_schedblocksize) / sys_dacsr;
while (sys_quit != SYS_QUIT_QUIT)
sched_tick();
return (0);
}

/* ------------ thread locking ------------------- */

#if THREAD_LOCKING
static pthread_mutex_t sys_mutex = PTHREAD_MUTEX_INITIALIZER;

void sys_lock(void)
{
pthread_mutex_lock(&sys_mutex);
}

void sys_unlock(void)
{
pthread_mutex_unlock(&sys_mutex);
}

int sys_trylock(void)
{
return pthread_mutex_trylock(&sys_mutex);
}

#else

void sys_lock(void) {}
void sys_unlock(void) {}
int sys_trylock(void) {return (1);}

#endif

void sys_exit(void)
{
sys_quit = SYS_QUIT_QUIT;
}

+ 2139
- 0
ports/PdPulp/libpd/pure-data/src/makefile.dependencies
File diff suppressed because it is too large
View File


+ 224
- 0
ports/PdPulp/libpd/pure-data/src/makefile.gnu View File

@@ -0,0 +1,224 @@
VPATH = ../obj:./
OBJ_DIR = ../obj
BIN_DIR = ../bin
PDEXEC = $(BIN_DIR)/pd
EXT= pd_linux

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

CPPFLAGS = -DPD -DHAVE_LIBDL -DHAVE_UNISTD_H -DHAVE_ALLOCA_H \
-DPDGUIDIR=\"tcl/\" \
-D_LARGEFILE64_SOURCE -DINSTALL_PREFIX=\"$(prefix)\" \
-Wall -W -Wstrict-prototypes \
-Wno-unused -Wno-unused-parameter -Wno-parentheses -Wno-switch

MORECFLAGS = -O3 -ffast-math -funroll-loops -fomit-frame-pointer

LDFLAGS = -Wl,-export-dynamic
LIB = -ldl -lm -lpthread

SYSSRC = s_midi_oss.c

# conditionally add code and flags for various audio APIs
ifdef ALSA
CPPFLAGS += -DUSEAPI_ALSA
SYSSRC += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c
LIB += -lasound
endif
ifdef JACK
CPPFLAGS += -DUSEAPI_JACK
SYSSRC += s_audio_jack.c
LIB += -ljack
endif
ifdef OSS
CPPFLAGS += -DUSEAPI_OSS
SYSSRC += s_audio_oss.c
endif
ifdef PA
CPPFLAGS += -DUSEAPI_PORTAUDIO
SYSSRC += s_audio_pa.c
LIB += -lportaudio
endif

CFLAGS = $(CPPFLAGS) $(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_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 \
$(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) $(GFLAGS) $(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) $(STRIPFLAG) -o $(BIN_DIR)/pd-watchdog s_watchdog.c

$(BIN_DIR)/pdsend: u_pdsend.c
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pdsend u_pdsend.c

$(BIN_DIR)/pdreceive: u_pdreceive.c
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) $(STRIPFLAG) -o $(BIN_DIR)/pdreceive u_pdreceive.c

$(PDEXEC): $(OBJ_DIR) $(OBJ)
test -d $(BIN_DIR) || mkdir -p $(BIN_DIR)
cd ../obj; $(CC) $(LDFLAGS) $(DBG_CFLAGS) -o $(PDEXEC) $(OBJ) $(LIB)

externs:
make -C ../extra/bonk~
make -C ../extra/choice
make -C ../extra/expr~
make -C ../extra/fiddle~
make -C ../extra/loop~
make -C ../extra/lrshift~
make -C ../extra/pique
make -C ../extra/sigmund~
make -C ../extra/pd~
make -C ../extra/stdout
make -C ../extra/bob~

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 -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








Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save