aboutsummaryrefslogtreecommitdiff
path: root/pd
diff options
context:
space:
mode:
authorHans-Christoph Steiner <eighthave@users.sourceforge.net>2011-10-09 16:36:37 +0000
committerHans-Christoph Steiner <eighthave@users.sourceforge.net>2011-10-09 16:36:37 +0000
commit21c068f1916330e90f814bed461fe0821d1665ec (patch)
tree949b73696fff09a44b8d3eb01b70bae7174cbd14 /pd
parentbf8ced1efe1a032342e864edc635fa4e2676670d (diff)
checked in pd-0.43-0.src.tar.gz
svn path=/trunk/; revision=15557
Diffstat (limited to 'pd')
-rw-r--r--pd/INSTALL.txt30
-rw-r--r--pd/Makefile.am464
-rw-r--r--pd/README.txt12
-rw-r--r--pd/asio/Makefile.am26
-rw-r--r--pd/asio/README.txt13
-rwxr-xr-xpd/autogen.sh24
-rw-r--r--pd/configure.ac272
-rw-r--r--pd/doc/1.manual/1.introduction.txt14
-rw-r--r--pd/doc/1.manual/index.htm2
-rw-r--r--pd/doc/1.manual/x1.htm82
-rw-r--r--pd/doc/1.manual/x2.htm8
-rw-r--r--pd/doc/1.manual/x3.htm56
-rw-r--r--pd/doc/1.manual/x5.htm64
-rw-r--r--pd/doc/3.audio.examples/E04.difference.tone.pd24
-rw-r--r--pd/doc/3.audio.examples/E06.exponential.pd10
-rw-r--r--pd/doc/3.audio.examples/E07.evenodd.pd14
-rw-r--r--pd/doc/3.audio.examples/I07.phase.vocoder.pd36
-rw-r--r--pd/doc/5.reference/bang-help.pd2
-rw-r--r--pd/doc/5.reference/block~-help.pd28
-rw-r--r--pd/doc/5.reference/delay-help.pd39
-rw-r--r--pd/doc/5.reference/drawpolygon-help.pd2
-rw-r--r--pd/doc/5.reference/line-help.pd51
-rw-r--r--pd/doc/5.reference/route-help.pd17
-rw-r--r--pd/doc/5.reference/spigot-help.pd1
-rw-r--r--pd/doc/5.reference/tabread-help.pd53
-rw-r--r--pd/doc/5.reference/tabread4-help.pd39
-rw-r--r--pd/doc/5.reference/tabread~-help.pd45
-rw-r--r--pd/doc/7.stuff/tools/latency.pd355
-rw-r--r--pd/doc/7.stuff/tools/testtone.pd4
-rw-r--r--pd/doc/7.stuff/tools/z.pd247
-rw-r--r--pd/extra/Makefile.am10
-rw-r--r--pd/extra/bonk~/GNUmakefile.am28
-rw-r--r--pd/extra/bonk~/bonk~-help.pd4
-rw-r--r--pd/extra/bonk~/bonk~.c29
-rw-r--r--pd/extra/bonk~/makefile2
-rw-r--r--pd/extra/choice/GNUmakefile.am28
-rw-r--r--pd/extra/choice/choice.c2
-rw-r--r--pd/extra/choice/makefile2
-rw-r--r--pd/extra/expr~/GNUmakefile.am50
-rw-r--r--pd/extra/expr~/makefile10
-rw-r--r--pd/extra/expr~/vexp_if.c4
-rw-r--r--pd/extra/fiddle~/GNUmakefile.am28
-rw-r--r--pd/extra/fiddle~/makefile2
-rw-r--r--pd/extra/loop~/GNUmakefile.am28
-rw-r--r--pd/extra/loop~/loop~-help.pd22
-rw-r--r--pd/extra/loop~/loop~.c26
-rw-r--r--pd/extra/loop~/makefile2
-rw-r--r--pd/extra/lrshift~/GNUmakefile.am28
-rw-r--r--pd/extra/lrshift~/lrshift~.c8
-rw-r--r--pd/extra/lrshift~/makefile2
-rw-r--r--pd/extra/makefile.subdir (renamed from pd/extra/makefile)22
-rw-r--r--pd/extra/pd~/GNUmakefile.am31
-rw-r--r--pd/extra/pd~/makefile3
-rw-r--r--pd/extra/pd~/pdsched.c25
-rw-r--r--pd/extra/pd~/pd~.c9
-rw-r--r--pd/extra/pique/GNUmakefile.am28
-rw-r--r--pd/extra/pique/makefile2
-rw-r--r--pd/extra/pique/pique.c42
-rw-r--r--pd/extra/sigmund~/GNUmakefile.am28
-rw-r--r--pd/extra/sigmund~/makefile2
-rw-r--r--pd/extra/sigmund~/sigmund~.c40
-rw-r--r--pd/extra/stdout/GNUmakefile.am28
-rw-r--r--pd/extra/stdout/makefile2
-rw-r--r--pd/m4/android.m4124
-rw-r--r--pd/m4/iphone.m4113
-rw-r--r--pd/m4/universal.m489
-rw-r--r--pd/man/Makefile.am1
-rw-r--r--pd/pd.pc.in22
-rw-r--r--pd/po/Makefile.am68
-rw-r--r--pd/po/af.po964
-rw-r--r--pd/po/az.po954
-rw-r--r--pd/po/be.po960
-rw-r--r--pd/po/bg.po955
-rw-r--r--pd/po/de.po1230
-rw-r--r--pd/po/el.po1152
-rw-r--r--pd/po/en_ca.po887
-rw-r--r--pd/po/eu.po953
-rw-r--r--pd/po/fr.po542
-rw-r--r--pd/po/gu.po956
-rw-r--r--pd/po/he.po939
-rw-r--r--pd/po/hi.po953
-rw-r--r--pd/po/hu.po895
-rw-r--r--pd/po/it.po893
-rw-r--r--pd/po/pa.po955
-rw-r--r--pd/po/pt_br.po1342
-rw-r--r--pd/po/pt_pt.po1144
-rw-r--r--pd/po/sq.po954
-rw-r--r--pd/po/sv.po921
-rw-r--r--pd/po/template.pot1338
-rw-r--r--pd/po/vi.po954
-rw-r--r--pd/portaudio/LICENSE.txt81
-rw-r--r--pd/portaudio/Makefile.am99
-rw-r--r--pd/portaudio/include/pa_asio.h16
-rw-r--r--pd/portaudio/include/pa_jack.h3
-rw-r--r--pd/portaudio/include/pa_linux_alsa.h10
-rw-r--r--pd/portaudio/include/pa_mac_core.h5
-rw-r--r--pd/portaudio/include/pa_win_waveformat.h199
-rw-r--r--pd/portaudio/include/pa_win_wmme.h24
-rw-r--r--pd/portaudio/include/portaudio.h6
-rw-r--r--pd/portaudio/src/common/pa_allocation.h8
-rw-r--r--pd/portaudio/src/common/pa_converters.c4
-rw-r--r--pd/portaudio/src/common/pa_debugprint.c7
-rw-r--r--pd/portaudio/src/common/pa_dither.c29
-rw-r--r--pd/portaudio/src/common/pa_dither.h18
-rw-r--r--pd/portaudio/src/common/pa_endianness.h30
-rw-r--r--pd/portaudio/src/common/pa_front.c31
-rw-r--r--pd/portaudio/src/common/pa_hostapi.h16
-rw-r--r--pd/portaudio/src/common/pa_memorybarrier.h123
-rw-r--r--pd/portaudio/src/common/pa_process.c10
-rw-r--r--pd/portaudio/src/common/pa_ringbuffer.c156
-rw-r--r--pd/portaudio/src/common/pa_ringbuffer.h90
-rw-r--r--pd/portaudio/src/common/pa_skeleton.c8
-rw-r--r--pd/portaudio/src/common/pa_stream.c10
-rw-r--r--pd/portaudio/src/common/pa_stream.h8
-rw-r--r--pd/portaudio/src/common/pa_trace.c4
-rw-r--r--pd/portaudio/src/common/pa_trace.h32
-rw-r--r--pd/portaudio/src/common/pa_util.h7
-rw-r--r--pd/portaudio/src/hostapi/alsa/pa_linux_alsa.c250
-rw-r--r--pd/portaudio/src/hostapi/asio/pa_asio.cpp1538
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/notes.txt22
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/pa_mac_core.c161
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c88
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h9
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h7
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c141
-rw-r--r--pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h31
-rw-r--r--pd/portaudio/src/hostapi/jack/pa_jack.c17
-rw-r--r--pd/portaudio/src/hostapi/oss/pa_unix_oss.c133
-rw-r--r--pd/portaudio/src/hostapi/wmme/pa_win_wmme.c565
-rw-r--r--pd/portaudio/src/os/unix/pa_unix_hostapis.c29
-rw-r--r--pd/portaudio/src/os/unix/pa_unix_util.c45
-rw-r--r--pd/portaudio/src/os/win/pa_win_hostapis.c6
-rw-r--r--pd/portaudio/src/os/win/pa_win_util.c10
-rw-r--r--pd/portaudio/src/os/win/pa_win_waveformat.c154
-rw-r--r--pd/portaudio/src/os/win/pa_win_wdmks_utils.c260
-rw-r--r--pd/portaudio/src/os/win/pa_win_wdmks_utils.h65
-rw-r--r--pd/portaudio/src/os/win/pa_x86_plain_converters.c2
-rw-r--r--pd/portmidi/Makefile.am44
-rw-r--r--pd/src/Makefile.am145
-rw-r--r--pd/src/configure.in31
-rw-r--r--pd/src/d_array.c56
-rw-r--r--pd/src/d_ctl.c2
-rw-r--r--pd/src/d_delay.c32
-rw-r--r--pd/src/d_fft_fftw.c138
-rw-r--r--pd/src/d_fftroutine.c41
-rw-r--r--pd/src/d_math.c23
-rw-r--r--pd/src/d_osc.c57
-rw-r--r--pd/src/d_soundfile.c6
-rw-r--r--pd/src/d_ugen.c2
-rw-r--r--pd/src/g_all_guis.c13
-rw-r--r--pd/src/g_array.c53
-rw-r--r--pd/src/g_bang.c8
-rw-r--r--pd/src/g_canvas.c89
-rw-r--r--pd/src/g_canvas.h5
-rw-r--r--pd/src/g_editor.c201
-rw-r--r--pd/src/g_graph.c32
-rw-r--r--pd/src/g_hdial.c8
-rw-r--r--pd/src/g_hslider.c13
-rw-r--r--pd/src/g_mycanvas.c2
-rw-r--r--pd/src/g_numbox.c8
-rw-r--r--pd/src/g_readwrite.c9
-rw-r--r--pd/src/g_rtext.c187
-rw-r--r--pd/src/g_template.c28
-rw-r--r--pd/src/g_text.c42
-rw-r--r--pd/src/g_toggle.c8
-rw-r--r--pd/src/g_vdial.c8
-rw-r--r--pd/src/g_vslider.c8
-rw-r--r--pd/src/g_vumeter.c14
-rw-r--r--pd/src/m_atom.c2
-rw-r--r--pd/src/m_binbuf.c164
-rw-r--r--pd/src/m_class.c10
-rw-r--r--pd/src/m_glob.c5
-rw-r--r--pd/src/m_obj.c28
-rw-r--r--pd/src/m_pd.h25
-rw-r--r--pd/src/m_sched.c18
-rw-r--r--pd/src/makefile.in3
-rw-r--r--pd/src/makefile.mingw297
-rw-r--r--pd/src/makefile.nt23
-rw-r--r--pd/src/notes.txt7
-rwxr-xr-xpd/src/pd.icobin0 -> 25214 bytes
-rw-r--r--pd/src/pd.rc25
-rw-r--r--pd/src/s_audio.c196
-rw-r--r--pd/src/s_audio_alsa.c39
-rw-r--r--pd/src/s_audio_alsa.h2
-rw-r--r--pd/src/s_audio_alsamm.c8
-rw-r--r--pd/src/s_audio_audiounit.c43
-rw-r--r--pd/src/s_audio_dummy.c37
-rw-r--r--pd/src/s_audio_esd.c135
-rw-r--r--pd/src/s_audio_jack.c517
-rw-r--r--pd/src/s_audio_mmio.c4
-rw-r--r--pd/src/s_audio_oss.c21
-rw-r--r--pd/src/s_audio_pa.c450
-rw-r--r--pd/src/s_audio_pablio.c350
-rw-r--r--pd/src/s_audio_pablio.h111
-rw-r--r--pd/src/s_audio_paring.c13
-rw-r--r--pd/src/s_audio_paring.h5
-rw-r--r--pd/src/s_file.c37
-rw-r--r--pd/src/s_inter.c124
-rw-r--r--pd/src/s_loader.c31
-rw-r--r--pd/src/s_main.c77
-rw-r--r--pd/src/s_midi.c16
-rw-r--r--pd/src/s_midi_alsa.c12
-rw-r--r--pd/src/s_midi_dummy.c34
-rw-r--r--pd/src/s_midi_pm.c1
-rw-r--r--pd/src/s_path.c144
-rw-r--r--pd/src/s_print.c187
-rw-r--r--pd/src/s_stuff.h124
-rw-r--r--pd/src/s_utf8.c280
-rw-r--r--pd/src/s_utf8.h88
-rw-r--r--pd/src/u_pdreceive.c2
-rw-r--r--pd/src/x_arithmetic.c13
-rw-r--r--pd/src/x_connective.c23
-rw-r--r--pd/src/x_gui.c13
-rw-r--r--pd/src/x_interface.c26
-rw-r--r--pd/src/x_misc.c47
-rw-r--r--pd/src/x_net.c8
-rw-r--r--pd/src/x_time.c7
-rw-r--r--pd/tcl/AppMain.tcl9
-rw-r--r--pd/tcl/Makefile.am16
-rw-r--r--pd/tcl/apple_events.tcl50
-rw-r--r--pd/tcl/dialog_array.tcl21
-rw-r--r--pd/tcl/dialog_audio.tcl251
-rw-r--r--pd/tcl/dialog_canvas.tcl26
-rw-r--r--pd/tcl/dialog_data.tcl53
-rw-r--r--pd/tcl/dialog_find.tcl145
-rw-r--r--pd/tcl/dialog_font.tcl61
-rw-r--r--pd/tcl/dialog_gatom.tcl26
-rw-r--r--pd/tcl/dialog_iemgui.tcl105
-rw-r--r--pd/tcl/dialog_message.tcl85
-rw-r--r--pd/tcl/dialog_midi.tcl15
-rw-r--r--pd/tcl/dialog_path.tcl70
-rw-r--r--pd/tcl/dialog_startup.tcl96
-rw-r--r--pd/tcl/helpbrowser.tcl272
-rw-r--r--pd/tcl/opt_parser.tcl40
-rw-r--r--pd/tcl/pd-gui.tcl506
-rwxr-xr-xpd/tcl/pd.icobin0 -> 25214 bytes
-rw-r--r--pd/tcl/pd_bindings.tcl303
-rw-r--r--pd/tcl/pd_connect.tcl28
-rw-r--r--pd/tcl/pd_menucommands.tcl217
-rw-r--r--pd/tcl/pd_menus.tcl447
-rw-r--r--pd/tcl/pdtk_canvas.tcl333
-rw-r--r--pd/tcl/pdtk_text.tcl53
-rw-r--r--pd/tcl/pdwindow.tcl391
-rw-r--r--pd/tcl/pkgIndex.tcl7
-rw-r--r--pd/tcl/scrollbox.tcl191
-rw-r--r--pd/tcl/scrollboxwindow.tcl94
-rw-r--r--pd/tcl/wheredoesthisgo.tcl119
247 files changed, 33606 insertions, 4005 deletions
diff --git a/pd/INSTALL.txt b/pd/INSTALL.txt
index a40aaa72..68e9b6b9 100644
--- a/pd/INSTALL.txt
+++ b/pd/INSTALL.txt
@@ -1,20 +1,26 @@
-Detailed installations instructions are in the HTML documentation, which
-you can find in doc/1.manual.
+Quick compilation instructions for Linux or Mac OSX:
-Quick compilation instructions for Linux or Mac OSX (assuming for Mac OSX that
-you've got Tck/Tk installed):
+There are two parallel build systems: the "old" one by Miller and the "new"
+one by Hans.
-Change to "src" subdirectory.
+Old build system: on Macintosh or linux, Change to "src" subdirectory.
+Type "./configure", possibly adding flags as follows:
-type "./configure", possibly adding flags as follows:
-
- To enable ALSA 0.9x (the latest one), add "--enable-alsa".
- To enable the older ALSA 0.5x, add "--enable-old-alsa".
- To enable Ritsch's RME 9652 driver, add --enable-rme".
To put Pd in /usr/bin instead of /usr/local/bin, add "--prefix=/bin".
+ To enable jack support: "--enable-jack"
-Type "make depend" and then "make"; or, if you prefer, as superuser
-type "make install".
+Then type "make"; and. if desired, as superuser type "make install".
To run pd, either type the full pathname as in /home/me/pd/bin/pd, or else
if you've chosen "make install", just type "pd".
+
+New build system: in this directory, type "./autogen.sh", then "./configure";
+then "make".
+
+Special instructions for Microsoft Windows: to use the old build system,
+install the Microsoft C compiler, cd to src and type "make -f makefile.nt".
+Then CD to the various subdirs of extra and type "make nt" in each. For the
+new build system, install cygwin and follow instructions as in linux or
+Macintosh.
+
+
diff --git a/pd/Makefile.am b/pd/Makefile.am
new file mode 100644
index 00000000..b55b4419
--- /dev/null
+++ b/pd/Makefile.am
@@ -0,0 +1,464 @@
+AUTOMAKE_OPTIONS = foreign
+ACLOCAL_AMFLAGS = -I m4/generated -I m4
+
+CFLAGS += @DEFS@
+EXTRA_SUBDIRS =
+
+# pkg-config support
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = pd.pc
+
+if ASIO
+EXTRA_SUBDIRS += asio
+endif
+
+if PORTAUDIO
+EXTRA_SUBDIRS += portaudio
+endif
+
+if PORTMIDI
+EXTRA_SUBDIRS += portmidi
+endif
+
+# files that are included but not built
+EXTRA_DIST = LICENSE.txt README.txt INSTALL.txt
+
+# subdirs that are built
+SUBDIRS = $(EXTRA_SUBDIRS) src man tcl po extra
+
+# subdirs that are always included in the dist, etc.
+DIST_SUBDIRS = asio extra man po portaudio portmidi src tcl
+
+BUILT_SOURCES =
+if MSGFMT
+BUILT_SOURCES += locales
+endif
+
+## FIXXXME
+## $(pkglibdir) is used throughout the other Makefile.amS
+## simply ignoring the special case for other OSs...
+if LINUX
+libpddir = $(pkglibdir)
+else
+libpddir = $(prefix)
+endif
+
+# Symlinks don't work on Windows/MinGW but they do on Cygwin.
+bin:
+ $(LN_S) src bin
+
+locales:
+ make -C po all
+
+install-data-local:
+ $(INSTALL) -d $(DESTDIR)$(libpddir)/startup
+ $(INSTALL) -d $(DESTDIR)$(libpddir)/startup/disabled
+
+# this is at the end because its loooong
+# these files go into libpddir defined above
+nobase_dist_libpd_DATA = \
+ doc/1.manual/1.introduction.txt \
+ doc/1.manual/fig1.1.png \
+ doc/1.manual/fig1.2.jpg \
+ doc/1.manual/fig1.3.jpg \
+ doc/1.manual/fig1.4.png \
+ doc/1.manual/fig1.5.jpg \
+ doc/1.manual/fig11.1.png \
+ doc/1.manual/fig11.2.png \
+ doc/1.manual/fig11.3.png \
+ doc/1.manual/fig11.4.png \
+ doc/1.manual/fig3.1.jpg \
+ doc/1.manual/fig3.10.jpg \
+ doc/1.manual/fig3.2.jpg \
+ doc/1.manual/fig3.3.jpg \
+ doc/1.manual/fig3.4.jpg \
+ doc/1.manual/fig3.5.jpg \
+ doc/1.manual/fig3.6.jpg \
+ doc/1.manual/fig3.7.jpg \
+ doc/1.manual/fig3.8.jpg \
+ doc/1.manual/fig3.9.jpg \
+ doc/1.manual/fig7.1.jpg \
+ doc/1.manual/fig7.2.jpg \
+ doc/1.manual/fig7.3.jpg \
+ doc/1.manual/fig7.4.jpg \
+ doc/1.manual/fig7.5.jpg \
+ doc/1.manual/fig7.6.jpg \
+ doc/1.manual/fig8.1.jpg \
+ doc/1.manual/fig8.2.jpg \
+ doc/1.manual/fig8.3.jpg \
+ doc/1.manual/fig8.4.jpg \
+ doc/1.manual/fig8.5.jpg \
+ doc/1.manual/fig8.6.jpg \
+ doc/1.manual/fig9.1.jpg \
+ doc/1.manual/fig9.2.jpg \
+ doc/1.manual/fig9.3.jpg \
+ doc/1.manual/index.htm \
+ doc/1.manual/pdmanual.css \
+ doc/1.manual/x1.htm \
+ doc/1.manual/x2.htm \
+ doc/1.manual/x3.htm \
+ doc/1.manual/x4.htm \
+ doc/1.manual/x5.htm \
+ doc/2.control.examples/00.INTRO.txt \
+ doc/2.control.examples/01.PART1.hello.pd \
+ doc/2.control.examples/02.editing.pd \
+ doc/2.control.examples/03.connections.pd \
+ doc/2.control.examples/04.messages.pd \
+ doc/2.control.examples/05.counter.pd \
+ doc/2.control.examples/06.more.counters.pd \
+ doc/2.control.examples/07.time.pd \
+ doc/2.control.examples/08.depthfirst.pd \
+ doc/2.control.examples/09.send_receive.pd \
+ doc/2.control.examples/10.more.messages.pd \
+ doc/2.control.examples/11.review.pd \
+ doc/2.control.examples/12.PART2.subpatch.pd \
+ doc/2.control.examples/13.locality.pd \
+ doc/2.control.examples/14.dollarsigns.pd \
+ doc/2.control.examples/15.array.pd \
+ doc/2.control.examples/15.file.txt \
+ doc/2.control.examples/16.more.arrays.pd \
+ doc/2.control.examples/17.PART3.midi.pd \
+ doc/2.control.examples/18.conditional.pd \
+ doc/2.control.examples/19.random.pd \
+ doc/2.control.examples/20.weighted-random.pd \
+ doc/2.control.examples/21.markov.chain.pd \
+ doc/2.control.examples/22.random-walk.pd \
+ doc/2.control.examples/23.sequencing.pd \
+ doc/2.control.examples/24.loops.pd \
+ doc/2.control.examples/dollarsign.pd \
+ doc/2.control.examples/dollarsign2.pd \
+ doc/2.control.examples/sendnumber.pd \
+ doc/3.audio.examples/A00.intro.pd \
+ doc/3.audio.examples/A00.intro.txt \
+ doc/3.audio.examples/A01.sinewave.pd \
+ doc/3.audio.examples/A02.amplitude.pd \
+ doc/3.audio.examples/A03.line.pd \
+ doc/3.audio.examples/A04.line2.pd \
+ doc/3.audio.examples/A05.output.subpatch.pd \
+ doc/3.audio.examples/A06.frequency.pd \
+ doc/3.audio.examples/A07.fusion.pd \
+ doc/3.audio.examples/A08.beating.pd \
+ doc/3.audio.examples/A09.frequency.mod.pd \
+ doc/3.audio.examples/A10.review.pd \
+ doc/3.audio.examples/adsr.pd \
+ doc/3.audio.examples/B01.wavetables.pd \
+ doc/3.audio.examples/B02.two-wavetables.pd \
+ doc/3.audio.examples/B03.tabread4.pd \
+ doc/3.audio.examples/B04.tabread4.interpolation.pd \
+ doc/3.audio.examples/B05.tabread.FM.pd \
+ doc/3.audio.examples/B06.table.switching.pd \
+ doc/3.audio.examples/B07.sampler.pd \
+ doc/3.audio.examples/B08.sampler.loop.pd \
+ doc/3.audio.examples/B09.sampler.loop.smooth.pd \
+ doc/3.audio.examples/B10.sampler.scratch.pd \
+ doc/3.audio.examples/B11.sampler.nodoppler.pd \
+ doc/3.audio.examples/B12.sampler.transpose.pd \
+ doc/3.audio.examples/B13.sampler.overlap.pd \
+ doc/3.audio.examples/B14.sampler.rockafella.pd \
+ doc/3.audio.examples/B15.tabread4~-onset.pd \
+ doc/3.audio.examples/B16.long-varispeed.pd \
+ doc/3.audio.examples/buttercoef3.pd \
+ doc/3.audio.examples/butterworth3~.pd \
+ doc/3.audio.examples/C01.nyquist.pd \
+ doc/3.audio.examples/C02.sawtooth-foldover.pd \
+ doc/3.audio.examples/C03.zipper.noise.pd \
+ doc/3.audio.examples/C04.control.to.signal.pd \
+ doc/3.audio.examples/C05.sampler.oneshot.pd \
+ doc/3.audio.examples/C06.signal.to.control.pd \
+ doc/3.audio.examples/C07.envelope.follower.pd \
+ doc/3.audio.examples/C08.analog.sequencer.pd \
+ doc/3.audio.examples/C09.sample.hold.pd \
+ doc/3.audio.examples/C10.monophonic.synth.pd \
+ doc/3.audio.examples/D01.envelope.gen.pd \
+ doc/3.audio.examples/D02.adsr.pd \
+ doc/3.audio.examples/D03.envelope.dB.pd \
+ doc/3.audio.examples/D04.envelope.quartic.pd \
+ doc/3.audio.examples/D05.envelope.pitch.pd \
+ doc/3.audio.examples/D06.envelope.portamento.pd \
+ doc/3.audio.examples/D07.additive.pd \
+ doc/3.audio.examples/D08.table.spectrum.pd \
+ doc/3.audio.examples/D09.shepard.tone.pd \
+ doc/3.audio.examples/D10.sampler.notes.pd \
+ doc/3.audio.examples/D11.sampler.poly.pd \
+ doc/3.audio.examples/D12.sampler.bis.pd \
+ doc/3.audio.examples/D13.additive.qlist.pd \
+ doc/3.audio.examples/D14.vibrato.pd \
+ doc/3.audio.examples/E01.spectrum.pd \
+ doc/3.audio.examples/E02.ring.modulation.pd \
+ doc/3.audio.examples/E03.octave.divider.pd \
+ doc/3.audio.examples/E04.difference.tone.pd \
+ doc/3.audio.examples/E05.chebychev.pd \
+ doc/3.audio.examples/E06.exponential.pd \
+ doc/3.audio.examples/E07.evenodd.pd \
+ doc/3.audio.examples/E08.phase.mod.pd \
+ doc/3.audio.examples/E09.FM.spectrum.pd \
+ doc/3.audio.examples/E10.complex.FM.pd \
+ doc/3.audio.examples/F01.pulse.pd \
+ doc/3.audio.examples/F02.just.say.pd \
+ doc/3.audio.examples/F03.pulse.spectrum.pd \
+ doc/3.audio.examples/F04.waveshaping.pulse.pd \
+ doc/3.audio.examples/F05.ring.modulation.pd \
+ doc/3.audio.examples/F06.packets.pd \
+ doc/3.audio.examples/F07.packet.spectrum.pd \
+ doc/3.audio.examples/F08.two.cosines.pd \
+ doc/3.audio.examples/F09.declickit.pd \
+ doc/3.audio.examples/F10.sweepable.FM.pd \
+ doc/3.audio.examples/F11.anharmonic.FM.pd \
+ doc/3.audio.examples/F12.paf.pd \
+ doc/3.audio.examples/F13.paf.control.pd \
+ doc/3.audio.examples/F14.wave.packet.pd \
+ doc/3.audio.examples/filter-graph1.pd \
+ doc/3.audio.examples/filter-graph2.pd \
+ doc/3.audio.examples/G01.delay.pd \
+ doc/3.audio.examples/G02.delay.loop.pd \
+ doc/3.audio.examples/G03.delay.variable.pd \
+ doc/3.audio.examples/G04.control.blocksize.pd \
+ doc/3.audio.examples/G05.execution.order.pd \
+ doc/3.audio.examples/G06.octave.doubler.pd \
+ doc/3.audio.examples/G07.shaker.pd \
+ doc/3.audio.examples/G08.reverb.pd \
+ doc/3.audio.examples/G09.pitchshift.pd \
+ doc/3.audio.examples/H01.low-pass.pd \
+ doc/3.audio.examples/H02.high-pass.pd \
+ doc/3.audio.examples/H03.band-pass.pd \
+ doc/3.audio.examples/H04.filter.sweep.pd \
+ doc/3.audio.examples/H05.filter.floyd.pd \
+ doc/3.audio.examples/H06.envelope.follower.pd \
+ doc/3.audio.examples/H07.measure.spectrum.pd \
+ doc/3.audio.examples/H08.heterodyning.pd \
+ doc/3.audio.examples/H09.ssb.modulation.pd \
+ doc/3.audio.examples/H10.measurement.pd \
+ doc/3.audio.examples/H11.shelving.pd \
+ doc/3.audio.examples/H12.peaking.pd \
+ doc/3.audio.examples/H13.butterworth.pd \
+ doc/3.audio.examples/H14.all.pass.pd \
+ doc/3.audio.examples/H15.phaser.pd \
+ doc/3.audio.examples/H16.adsr.filter.qlist.pd \
+ doc/3.audio.examples/I01.Fourier.analysis.pd \
+ doc/3.audio.examples/I02.Hann.window.pd \
+ doc/3.audio.examples/I03.resynthesis.pd \
+ doc/3.audio.examples/I04.noisegate.pd \
+ doc/3.audio.examples/I05.compressor.pd \
+ doc/3.audio.examples/I06.timbre.stamp.pd \
+ doc/3.audio.examples/I07.phase.vocoder.pd \
+ doc/3.audio.examples/I08.pvoc.reverb.pd \
+ doc/3.audio.examples/I09.sheep.from.goats.pd \
+ doc/3.audio.examples/I10.phase.bash.pd \
+ doc/3.audio.examples/J01.even.odd.pd \
+ doc/3.audio.examples/J02.trapezoids.pd \
+ doc/3.audio.examples/J03.pulse.width.mod.pd \
+ doc/3.audio.examples/J04.corners.pd \
+ doc/3.audio.examples/J05.triangle.pd \
+ doc/3.audio.examples/J06.enveloping.pd \
+ doc/3.audio.examples/J07.oversampling.pd \
+ doc/3.audio.examples/J08.classicsynth.pd \
+ doc/3.audio.examples/J09.bandlimited.pd \
+ doc/3.audio.examples/osc-voice.pd \
+ doc/3.audio.examples/output~.pd \
+ doc/3.audio.examples/partial.pd \
+ doc/3.audio.examples/qlist-sampler.txt \
+ doc/3.audio.examples/qlist.txt \
+ doc/3.audio.examples/qlist2.txt \
+ doc/3.audio.examples/reverb-echo.pd \
+ doc/3.audio.examples/sampvoice.pd \
+ doc/3.audio.examples/sampvoice2.pd \
+ doc/3.audio.examples/shepvoice.pd \
+ doc/3.audio.examples/sinevoice.pd \
+ doc/3.audio.examples/spectrum-partial.pd \
+ doc/4.data.structures/00.intro.txt \
+ doc/4.data.structures/01.scalars.pd \
+ doc/4.data.structures/02.getting.data.pd \
+ doc/4.data.structures/03.setting.data.pd \
+ doc/4.data.structures/04.append.pd \
+ doc/4.data.structures/05.array.pd \
+ doc/4.data.structures/06.file.pd \
+ doc/4.data.structures/07.sequencer.pd \
+ doc/4.data.structures/08.selection.pd \
+ doc/4.data.structures/09.scaling.pd \
+ doc/4.data.structures/10.onoff.pd \
+ doc/4.data.structures/11.array.controls.pd \
+ doc/4.data.structures/12.beat-patterns.pd \
+ doc/4.data.structures/13.sliderule.pd \
+ doc/4.data.structures/14.partialtracer.pd \
+ doc/4.data.structures/add-trace.pd \
+ doc/4.data.structures/beat-maker.pd \
+ doc/4.data.structures/data-array.pd \
+ doc/4.data.structures/data-start.pd \
+ doc/4.data.structures/file.txt \
+ doc/4.data.structures/osc-voice.pd \
+ doc/4.data.structures/output~.pd \
+ doc/4.data.structures/voice.pd \
+ doc/4.data.structures/z.txt \
+ doc/5.reference/0_all_guis-INTRO.txt \
+ doc/5.reference/abs~-help.pd \
+ doc/5.reference/acoustics-help.pd \
+ doc/5.reference/acoustics~-help.pd \
+ doc/5.reference/adc~_dac~-help.pd \
+ doc/5.reference/append-help.pd \
+ doc/5.reference/bag-help.pd \
+ doc/5.reference/bang-help.pd \
+ doc/5.reference/bang~-help.pd \
+ doc/5.reference/biquad~-help.pd \
+ doc/5.reference/block~-help.pd \
+ doc/5.reference/bng-help.pd \
+ doc/5.reference/bp~-help.pd \
+ doc/5.reference/canvas-help.pd \
+ doc/5.reference/change-help.pd \
+ doc/5.reference/clip~-help.pd \
+ doc/5.reference/cos~-help.pd \
+ doc/5.reference/cpole~-help.pd \
+ doc/5.reference/cputime-help.pd \
+ doc/5.reference/czero_rev~-help.pd \
+ doc/5.reference/czero~-help.pd \
+ doc/5.reference/declare-help.pd \
+ doc/5.reference/delay-help.pd \
+ doc/5.reference/delread~-help.pd \
+ doc/5.reference/delwrite~-help.pd \
+ doc/5.reference/drawnumber-help.pd \
+ doc/5.reference/drawpolygon-help.pd \
+ doc/5.reference/element-help.pd \
+ doc/5.reference/env~-help.pd \
+ doc/5.reference/exp~-help.pd \
+ doc/5.reference/fft~-help.pd \
+ doc/5.reference/float-help.pd \
+ doc/5.reference/framp~-help.pd \
+ doc/5.reference/gatom-help.pd \
+ doc/5.reference/get-help.pd \
+ doc/5.reference/getsize-help.pd \
+ doc/5.reference/graph-help.pd \
+ doc/5.reference/hdial-help.pd \
+ doc/5.reference/help-intro.pd \
+ doc/5.reference/hip~-help.pd \
+ doc/5.reference/hslider-help.pd \
+ doc/5.reference/int-help.pd \
+ doc/5.reference/key-help.pd \
+ doc/5.reference/line-help.pd \
+ doc/5.reference/line~-help.pd \
+ doc/5.reference/list-help.pd \
+ doc/5.reference/log~-help.pd \
+ doc/5.reference/lop~-help.pd \
+ doc/5.reference/makefilename-help.pd \
+ doc/5.reference/makenote-help.pd \
+ doc/5.reference/math-help.pd \
+ doc/5.reference/message-help.pd \
+ doc/5.reference/metro.pd \
+ doc/5.reference/midi-help.pd \
+ doc/5.reference/moses-help.pd \
+ doc/5.reference/my_canvas-help.pd \
+ doc/5.reference/namecanvas-help.pd \
+ doc/5.reference/netreceive-help.pd \
+ doc/5.reference/netsend-help.pd \
+ doc/5.reference/noise~-help.pd \
+ doc/5.reference/numbox2-help.pd \
+ doc/5.reference/openpanel-help.pd \
+ doc/5.reference/operators-help.pd \
+ doc/5.reference/osc~-help.pd \
+ doc/5.reference/otherbinops-help.pd \
+ doc/5.reference/pack-help.pd \
+ doc/5.reference/pd-help.pd \
+ doc/5.reference/phasor~-help.pd \
+ doc/5.reference/pipe-help.pd \
+ doc/5.reference/plot-help.pd \
+ doc/5.reference/pointer-help.pd \
+ doc/5.reference/poly-help.pd \
+ doc/5.reference/pow~-help.pd \
+ doc/5.reference/print-help.pd \
+ doc/5.reference/print~-help.pd \
+ doc/5.reference/qlist-help.pd \
+ doc/5.reference/qlist.txt \
+ doc/5.reference/random-help.pd \
+ doc/5.reference/readsf~-help.pd \
+ doc/5.reference/realtime-help.pd \
+ doc/5.reference/receive-help.pd \
+ doc/5.reference/route-help.pd \
+ doc/5.reference/rpole~-help.pd \
+ doc/5.reference/rsqrt~-help.pd \
+ doc/5.reference/rzero_rev~-help.pd \
+ doc/5.reference/rzero~-help.pd \
+ doc/5.reference/samphold~-help.pd \
+ doc/5.reference/savepanel-help.pd \
+ doc/5.reference/select-help.pd \
+ doc/5.reference/send-help.pd \
+ doc/5.reference/send~-help.pd \
+ doc/5.reference/set-help.pd \
+ doc/5.reference/setsize-help.pd \
+ doc/5.reference/setsize.txt \
+ doc/5.reference/sigbinops-help.pd \
+ doc/5.reference/sig~-help.pd \
+ doc/5.reference/snapshot~-help.pd \
+ doc/5.reference/soundfiler-help.pd \
+ doc/5.reference/spigot-help.pd \
+ doc/5.reference/sqrt~-help.pd \
+ doc/5.reference/stripnote-help.pd \
+ doc/5.reference/struct-help.pd \
+ doc/5.reference/sublist-help.pd \
+ doc/5.reference/swap-help.pd \
+ doc/5.reference/switch~-help.pd \
+ doc/5.reference/table.txt \
+ doc/5.reference/tabosc4~-help.pd \
+ doc/5.reference/tabplay~-help.pd \
+ doc/5.reference/tabread-help.pd \
+ doc/5.reference/tabread4~-help.pd \
+ doc/5.reference/tabreceive~-help.pd \
+ doc/5.reference/tabsend~-help.pd \
+ doc/5.reference/tabwrite-help.pd \
+ doc/5.reference/tabwrite~-help.pd \
+ doc/5.reference/text-help.pd \
+ doc/5.reference/textfile-help.pd \
+ doc/5.reference/textfile.txt \
+ doc/5.reference/threshold~-help.pd \
+ doc/5.reference/throw~-help.pd \
+ doc/5.reference/timer-help.pd \
+ doc/5.reference/toggle-help.pd \
+ doc/5.reference/trigger-help.pd \
+ doc/5.reference/unpack-help.pd \
+ doc/5.reference/until-help.pd \
+ doc/5.reference/value-help.pd \
+ doc/5.reference/vcf~-help.pd \
+ doc/5.reference/vdial-help.pd \
+ doc/5.reference/vd~-help.pd \
+ doc/5.reference/vline~-help.pd \
+ doc/5.reference/vslider-help.pd \
+ doc/5.reference/vu-help.pd \
+ doc/5.reference/wrap~-help.pd \
+ doc/5.reference/writesf~-help.pd \
+ doc/5.reference/x_all_guis.pd \
+ doc/6.externs/0.README.txt \
+ doc/6.externs/dspobj~.c \
+ doc/6.externs/makefile \
+ doc/6.externs/obj1.c \
+ doc/6.externs/obj2.c \
+ doc/6.externs/obj3.c \
+ doc/6.externs/obj4.c \
+ doc/6.externs/obj5.c \
+ doc/6.externs/test-dspobj~.pd \
+ doc/6.externs/test-obj1.pd \
+ doc/6.externs/test-obj2.pd \
+ doc/6.externs/test-obj3.pd \
+ doc/6.externs/test-obj4.pd \
+ doc/6.externs/test-obj5.pd \
+ doc/7.stuff/soundfile-tools/1.ring-mod.pd \
+ doc/7.stuff/soundfile-tools/2.bandpass.pd \
+ doc/7.stuff/soundfile-tools/3.phase.vocoder.pd \
+ doc/7.stuff/soundfile-tools/4.looper.pd \
+ doc/7.stuff/soundfile-tools/5.reverb.pd \
+ doc/7.stuff/soundfile-tools/6.vocoder.pd \
+ doc/7.stuff/soundfile-tools/README.txt \
+ doc/7.stuff/synth/1.poly.synth.pd \
+ doc/7.stuff/synth/gadsr.pd \
+ doc/7.stuff/synth/numset.pd \
+ doc/7.stuff/synth/preset.pd \
+ doc/7.stuff/synth/preset1.txt \
+ doc/7.stuff/synth/preset2.txt \
+ doc/7.stuff/synth/preset3.txt \
+ doc/7.stuff/synth/preset4.txt \
+ doc/7.stuff/synth/README.txt \
+ doc/7.stuff/synth/synthvoice.pd \
+ doc/7.stuff/synth/test-gadsr.pd \
+ doc/7.stuff/tools/latency.pd \
+ doc/7.stuff/tools/load-meter.pd \
+ doc/7.stuff/tools/testtone.pd \
+ doc/7.stuff/tools/testtone16.pd \
+ doc/sound/bell.aiff \
+ doc/sound/voice.wav \
+ doc/sound/voice2.wav
diff --git a/pd/README.txt b/pd/README.txt
index 867fb10e..e509786c 100644
--- a/pd/README.txt
+++ b/pd/README.txt
@@ -1,6 +1,6 @@
This is the README file for Pd, a free real-time computer music software
-package resembling Max. You can get Pd for Linux, Windows, Mac OSX, or IRIX
-from http://www.crca.ucsd.edu/~msp/software.html or ftp://felix.ucsd.edu.
+package resembling Max. You can get Pd for Linux, Mac OSX, or MS Windows,
+from http://www.crca.ucsd.edu/~msp/software.html.
Installation instructions are in the HTML DOCUMENTATION at:
http://www.crca.ucsd.edu/~msp/Pd_documentation/index.htm
@@ -9,15 +9,13 @@ If you download and unpack Pd, you will also find the html documentation
locally in the file, .../pd-whatever/doc/1.manual/index.htm. To unpack Pd:
LINUX (or freeBSD). Download Pd, which will be a ".tar.gz" file; to unpack it,
-type "zcat [name].tar.gz | tar xf -" to a shell. This creates a directory with
-a name like "pd-0.35". There are also RPMs available.
+type "zcat [name].tar.gz | tar xf -" to a shell. This creates a directory with a
+name like "pd-0.35". CD to "src". ./configiure, and make. There are also
+compiled packages available.
Microsoft Windows. Pd is distributed as a "zip" file. Unzip this,
creating a directory such as \pd.
-IRIX. Download Pd, which will be a "tar.Z" file. You can unpack this by
-typing "zcat [name].tar.Z | tar xf -" to a shell.
-
Macintosh. The web browser will automatically unpack the distributions
into a folder such as "pd-0.35" on your desktop.
diff --git a/pd/asio/Makefile.am b/pd/asio/Makefile.am
new file mode 100644
index 00000000..a311e93e
--- /dev/null
+++ b/pd/asio/Makefile.am
@@ -0,0 +1,26 @@
+# The ASIO sources are not free, so they are not included here. You can get
+# them for free (as in beer) from Steinberg:
+
+# http://www.steinberg.net/en/company/3rd_party_developer.html
+
+# First, download the ASIO SDK. You have to agree to Steinberg's license, then
+# submit an email address, then they'll send you the download URL in an
+# email. Download the asiosdk2.2.zip file to the pd/asio directory, then unzip
+# it right into that folder. You should have all of the ASIO files in
+# pd/asio/ASIOSDK2 when you are done unzipping.
+
+# this is built as a "libtool convenience library"
+# http://sources.redhat.com/automake/automake.html#Libtool-Convenience-Libraries
+
+AUTOMAKE_OPTIONS = foreign
+AM_CFLAGS =
+INCLUDES = -I./ASIOSDK2/host -I./ASIOSDK2/host/pc -I./ASIOSDK2/common
+
+noinst_LTLIBRARIES = libasio.la
+
+nodist_libasio_la_SOURCES = \
+ ASIOSDK2/common/asio.cpp \
+ ASIOSDK2/host/asiodrivers.cpp \
+ ASIOSDK2/host/pc/asiolist.cpp
+
+EXTRA_DIST = README.txt
diff --git a/pd/asio/README.txt b/pd/asio/README.txt
new file mode 100644
index 00000000..781afb67
--- /dev/null
+++ b/pd/asio/README.txt
@@ -0,0 +1,13 @@
+
+
+In order to build ASIO support into Pd on Windows, you need to download the
+ASIO sources from Steinberg directly. Their license does not let us
+redistribute their source files.
+
+- Download the ASIO SDK http://www.steinberg.net/en/company/3rd_party_developer.html
+ You have to agree to Steinberg's license, then submit an email address, then
+ they'll send you the download URL in an email.
+
+- Uncompress asiosdk2.2.zip into pd/asio
+
+
diff --git a/pd/autogen.sh b/pd/autogen.sh
new file mode 100755
index 00000000..8984034f
--- /dev/null
+++ b/pd/autogen.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+PATH=/sw/bin:$PATH
+
+PWD=${0%/*}
+
+
+## git cannot really handle empty directories
+## so let's create the missing ones
+mkdir -p ${PWD}/m4/generated
+
+case `uname -s` in
+ MINGW*)
+# autoreconf doesn't always work on MinGW
+ aclocal --force -I m4/generated -I m4 && \
+ libtoolize --install --force && \
+ autoconf --force && \
+ automake --add-missing --copy --force-missing && \
+ true
+ ;;
+ *)
+ autoreconf --install --force --verbose
+ ;;
+esac
diff --git a/pd/configure.ac b/pd/configure.ac
new file mode 100644
index 00000000..935151ff
--- /dev/null
+++ b/pd/configure.ac
@@ -0,0 +1,272 @@
+AC_PREREQ(2.59)
+AC_INIT(pd,0.43.0)
+AC_CONFIG_SRCDIR(src/m_pd.c)
+AC_CONFIG_AUX_DIR([m4/config])
+AM_INIT_AUTOMAKE
+AC_CONFIG_MACRO_DIR([m4/generated])
+
+AC_CANONICAL_HOST
+
+# you will need to install iPhone XCode on Mac OS X to use this:
+PD_CHECK_IPHONE(IPHONEOS=yes, IPHONEOS=no, AC_MSG_ERROR([iPhoneOS SDK not available]))
+PD_CHECK_ANDROID(ANDROID=yes, ANDROID=no , AC_MSG_ERROR([Android SDK not available]))
+
+case $host in
+*darwin*)
+ if test "x${IPHONEOS}" = "xno"; then
+ portaudio=yes
+ portmidi=yes
+ MACOSX=yes
+
+ EXTERNAL_CFLAGS="-fPIC"
+ EXTERNAL_EXTENSION=d_fat
+ else
+ portaudio=no
+
+ EXTERNAL_CFLAGS=
+ EXTERNAL_EXTENSION=pd_darwin
+ fi
+
+ CFLAGS="$CFLAGS -O3 -funroll-loops -fomit-frame-pointer"
+ INCLUDES="$INCLUDES -I/sw/include"
+ LDFLAGS="$LDFLAGS -L/sw/lib"
+ EXTERNAL_LDFLAGS="-bundle -undefined dynamic_lookup"
+ ;;
+*linux*|GNU|GNU/kFreeBSD)
+# GNU and GNU/kFreeBSD are for Debian, were they are treated very similar to linux
+ if test "x${host}" = "xGNU"; then
+ HURD=yes
+ fi
+ if test "x${ANDROID}" = "xno"; then
+ LINUX=yes
+ portaudio=yes
+ CFLAGS="$CFLAGS -O6 -funroll-loops -fomit-frame-pointer"
+ fi
+ EXTERNAL_CFLAGS="-fPIC"
+ EXTERNAL_LDFLAGS="-Wl,--export-dynamic -shared -fPIC"
+ EXTERNAL_EXTENSION=pd_linux
+ ;;
+*mingw*)
+ WINDOWS=yes
+ MINGW=yes
+# ASIO doesn't build yet with the autotools setup. We need to figure out how
+# to make the final linking phase use g++
+# asio=yes
+ portaudio=yes
+ CFLAGS="$CFLAGS -O6 -funroll-loops -fomit-frame-pointer"
+# ASIO is a C++ library, so if its included, then use g++ to build
+ CC=g++
+ EXTERNAL_CFLAGS="-mms-bitfields"
+ EXTERNAL_LDFLAGS="-s -shared -Wl,--enable-auto-import -lpd"
+ EXTERNAL_EXTENSION=dll
+ ;;
+*cygwin*)
+ WINDOWS=yes
+ CYGWIN=yes
+ portaudio=yes
+ CFLAGS="$CFLAGS -O6 -funroll-loops -fomit-frame-pointer"
+ EXTERNAL_CFLAGS=
+ EXTERNAL_LDFLAGS="-Wl,--export-dynamic -shared -lpd"
+ EXTERNAL_EXTENSION=dll
+ ;;
+esac
+
+PD_CHECK_UNIVERSAL(ARCH, universal=yes, universal=no)
+AM_CONDITIONAL(UNIVERSAL, test x$universal = xyes)
+if test "x${universal}" = "xyes"; then
+ CFLAGS="${CFLAGS} ${ARCH_CFLAGS}"
+ LDFLAGS="${LDFLAGS} ${ARCH_LDFLAGS}"
+fi
+
+AM_CONDITIONAL(ANDROID, test x$ANDROID = xyes)
+AM_CONDITIONAL(IPHONEOS, test x$IPHONEOS = xyes)
+AM_CONDITIONAL(LINUX, test x$LINUX = xyes)
+AM_CONDITIONAL(HURD, test x$HURD = xyes)
+AM_CONDITIONAL(MACOSX, test x$MACOSX = xyes)
+AM_CONDITIONAL(WINDOWS, test x$WINDOWS = xyes)
+AM_CONDITIONAL(CYGWIN, test x$MINGW = xyes)
+AM_CONDITIONAL(MINGW, test x$MINGW = xyes)
+
+# Configure libtool
+AC_LIBTOOL_DLOPEN
+AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_PROG_MAKE_SET
+AC_PROG_LN_S
+#AC_PROG_GREP
+#AC_PROG_SED
+
+AC_SUBST(EXTERNTARGET)
+AC_SUBST(INCLUDES)
+
+AC_SUBST(EXTERNAL_EXTENSION)
+AC_SUBST(EXTERNAL_CFLAGS)
+AC_SUBST(EXTERNAL_LDFLAGS)
+
+dnl Checks for libraries.
+AC_CHECK_LIB([dl], [dlopen])
+AC_CHECK_LIBM
+# AC_CHECK_LIBM computes LIBM but does not add to LIBS, hence we add it in
+# src/Makefile.am under pd_LDFLAGS as well
+
+# Checking for `pthread_create' function in -pthread (MinGW uses unusual names)
+## CHECK whether this can be replaced by AX_PTHREAD
+AC_CHECK_LIB([pthread], [pthread_create],LIBS="-lpthread $LIBS",
+ AC_CHECK_LIB([pthreadGC2], [pthread_create], LIBS="-lpthreadGC2 $LIBS",
+ AC_CHECK_LIB([pthreadGC1], [pthread_create], LIBS="-lpthreadGC1 $LIBS",
+ AC_CHECK_LIB([pthreadGC], [pthread_create], LIBS="-lpthreadGC $LIBS",
+ AC_MSG_WARN([pthreads required])))))
+
+AC_HEADER_STDC
+
+dnl Cygwin has sys/soundcard.h but Pd isn't ready for Cygwin since it only
+dnl includes OSS for UNIX
+AC_CHECK_HEADER(sys/soundcard.h, [oss=yes], [oss=no])
+AM_CONDITIONAL(OSS, test x$oss = xyes)
+
+AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [coreaudio=yes], [coreaudio=no])
+dnl AC_CHECK_HEADER(Jackmp/jack.h, [jack=yes], [jack=no])
+
+dnl portaudio/CoreAudio doesn't work with iPhone
+test x$IPHONEOS = xyes && coreaudio=no
+
+AM_CONDITIONAL(COREAUDIO, test x$coreaudio = xyes)
+
+dnl TODO implement debug and static
+#AC_ARG_ENABLE(static, [ --enable-static link statically],
+# static=$enableval)
+
+#AC_ARG_ENABLE([debug],
+# [AS_HELP_STRING([--enable-debug], [use debugging support])],
+# [debug=$enableval])
+#if test x$debug = xyes; then
+# CFLAGS="$CFLAGS -g"
+#fi
+
+dnl ALSA
+dnl shouldn't we use AM_PATH_ALSA from /usr/share/aclocal/alsa.m4
+dnl alternatively we could use pkg-config
+AC_ARG_ENABLE([alsa],
+ [AS_HELP_STRING([--disable-alsa],
+ [do not use ALSA audio driver])],
+ [alsa=$enableval], [alsa=yes])
+AS_IF([test x$alsa = xyes], [
+ AC_CHECK_LIB(asound,snd_pcm_info,LIBS="$LIBS -lasound",alsa=no)])
+AM_CONDITIONAL(ALSA, test x$alsa = xyes)
+
+dnl ASIO
+AC_ARG_ENABLE([asio],
+ [AS_HELP_STRING([--enable-asio],
+ [use ASIO audio driver])],
+ [asio=$enableval])
+AS_IF([test x$asio = xyes], [
+ AC_CHECK_FILE([asio/ASIOSDK2/common/asio.h],[asio=yes],[asio=no])])
+AM_CONDITIONAL(ASIO, test x$asio = xyes)
+
+dnl JACK
+dnl shouldn't we use pkg-config?
+dnl TODO support jack xrun
+AC_ARG_ENABLE([jack],
+ [AS_HELP_STRING([--enable-jack],
+ [use JACK audio server])],
+ [jack=$enableval])
+dnl on Mac OS X, use the JackOSX.com Jackmp.framework not the jack lib.
+dnl this is set in src/Makefile.am based on the JACK var
+AS_IF([test x$MACOSX != xyes], [
+ AS_IF([test x$jack = xyes], [
+ AC_CHECK_LIB(rt,shm_open,LIBS="$LIBS -lrt")
+ AC_CHECK_LIB(jack,jack_set_xrun_callback,LIBS="$LIBS -ljack";jack=xrun)
+ AC_CHECK_LIB(jack,jack_set_error_function,LIBS="$LIBS -ljack";jack=yes,
+ jack=no)])])
+AM_CONDITIONAL(JACK, test x$jack = xyes)
+
+dnl portaudio
+AC_ARG_ENABLE([portaudio],
+ [AS_HELP_STRING([--disable-portaudio],
+ [do not use portaudio])],
+ [portaudio=$enableval])
+AM_CONDITIONAL(PORTAUDIO, test x$portaudio = xyes)
+
+dnl portmidi
+AC_ARG_ENABLE([portmidi],
+ [AS_HELP_STRING([--enable-portmidi],
+ [use portmidi])],
+ [portmidi=$enableval])
+AM_CONDITIONAL(PORTMIDI, test x$portmidi = xyes)
+if test x$portmidi = xyes; then echo Using included portmidi; fi
+
+dnl fftw v2
+AC_ARG_ENABLE([fftw],
+ [AS_HELP_STRING([--enable-fftw],
+ [use FFTW package])],
+ [fftw=$enableval])
+if test x$fftw = xyes; then
+ AC_CHECK_LIB(fftw, fftw_one, [LIBS="$LIBS -lfftw"],
+ [AC_MSG_NOTICE([fftw package not found - using built-in FFT]); fftw=no])
+fi
+AM_CONDITIONAL(FFTW, test x$fftw = xyes)
+
+# Checks for header files.
+AC_FUNC_ALLOCA
+AC_CHECK_HEADERS([fcntl.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/soundcard.h sys/time.h sys/timeb.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS([dup2 floor getcwd gethostbyname gettimeofday memmove memset pow regcomp select socket sqrt strchr strerror strrchr strstr strtol])
+
+# check for programs
+AC_CHECK_PROG(HAVE_MSGFMT, [msgfmt], yes, no)
+test x$HAVE_MSGFMT = xyes || AC_MSG_WARN([Install GNU gettext with msgfmt if you want localizations to be compiled!])
+AM_CONDITIONAL(MSGFMT, test x$HAVE_MSGFMT = xyes)
+
+# Specify what files are to be created.
+AC_CONFIG_FILES([Makefile
+ asio/Makefile
+ man/Makefile
+ portaudio/Makefile
+ portmidi/Makefile
+ tcl/Makefile
+ po/Makefile
+ src/Makefile
+ extra/Makefile
+ extra/bonk~/GNUmakefile
+ extra/choice/GNUmakefile
+ extra/expr~/GNUmakefile
+ extra/fiddle~/GNUmakefile
+ extra/loop~/GNUmakefile
+ extra/lrshift~/GNUmakefile
+ extra/pd~/GNUmakefile
+ extra/pique/GNUmakefile
+ extra/sigmund~/GNUmakefile
+ extra/stdout/GNUmakefile
+ pd.pc
+ ])
+
+AC_OUTPUT
+
+dnl output some messages at the end
+
+AS_IF([test x$windows = xyes], [
+ AS_IF([test x$asio = xno], [
+ AC_MSG_RESULT(
+ASIO SDK not found! You need to download asiosdk2.2.zip from:
+ http://www.steinberg.net/en/company/3rd_party_developer.html)])])
+
+
diff --git a/pd/doc/1.manual/1.introduction.txt b/pd/doc/1.manual/1.introduction.txt
index 97967523..f3979d23 100644
--- a/pd/doc/1.manual/1.introduction.txt
+++ b/pd/doc/1.manual/1.introduction.txt
@@ -1,8 +1,7 @@
PD_VERSION
A real-time graphical programming environment for live interactive
-computer music, Pd works on SGI machines, Microsoft Windows,
-Linux, and Mac OSX.
+computer music, Pd works on Linux, Macintosh OSX, and Microsoft Windows.
Pd is copyrighted, but is free for you to use for any reasonable purpose.
See the file:
@@ -13,11 +12,12 @@ Reference documentation for Pd lives in:
or:
http://www.crca.ucsd.edu/~msp/Pd_documentation/index.htm
-Much more documentation and other resources live on:
+More extensive FLOSS documentation is available on:
+ http://en.flossmanuals.net/PureData/ (English)
+ http://fr.flossmanuals.net/PureData/ (Francais)
+
+Information of all sorts (guides, development, meetings, etc):
http://puredata.org
The Pd mailing list archive lives in:
- http://iem.kug.ac.at/mailinglists/pd-list/
-
-
-Many more useful links are listed in the HTML documentation, section 1.2.
+ http://iem.at/mailinglists/pd-list/
diff --git a/pd/doc/1.manual/index.htm b/pd/doc/1.manual/index.htm
index 519a5102..4e8bb364 100644
--- a/pd/doc/1.manual/index.htm
+++ b/pd/doc/1.manual/index.htm
@@ -51,7 +51,7 @@ can be found at:
<LI> <A href="x2.htm#s3.2"> depth first message passing </A>
<LI> <A href="x2.htm#s3.3">
hot and cold inlets and right to left outlet order </A>
- <LI> <A href="x2.htm#s3.3"> message boxes </A>
+ <LI> <A href="x2.htm#s3.4"> message boxes </A>
</OL>
<LI> <A href="x2.htm#s4"> audio signals </A>
<OL>
diff --git a/pd/doc/1.manual/x1.htm b/pd/doc/1.manual/x1.htm
index 00fa7da1..92585e69 100644
--- a/pd/doc/1.manual/x1.htm
+++ b/pd/doc/1.manual/x1.htm
@@ -48,20 +48,16 @@ This manual has five sections:
<LI> <A href="x5.htm"> release notes and known bugs </A>
</OL>
-<P> In order to consult the reference and example patches, you'll first have
-to get Pd started as explained in this manual.
-
<P>
For a list of all the objects you can use in Pd, see the text file,
"0.INTRO.txt" in the directory, "../5.reference". To get help on any
Pd object you can right click on it; or you can browse the help patches
-by choosing "Pure Documentation..." in the Pd help menu and looking in
+by choosing "Browser..." in the Pd help menu and looking in
5.reference.
<P>
-The example patches are also available from the "Pure Documentation..." item
-in Pd's
-"help" menu. The example patches appear in subdirectories named
+The example patches are also available from the "Browser..." item
+in Pd's "help" menu. They appear in subdirectories named
"2.control.examples", "3.audio.examples" and "4.fft.examples." Some additional
patches in "7.stuff" might also be helpful.
@@ -70,73 +66,53 @@ To get started writing your own C extensions, refer to chapter 4 of this manual.
<H3> <A name=s2> 1.2. other resources </A> </H3>
-<P> There is a new Pd community web site,
+<P> There is a very extensive Pd community web site,
<a href="http://www.pure-data.info/"> pure-data.info</a>, which aims to be the
central resource for Pd, from documentation and
downloads; to forums, member pages, and a patch exchange.
-<P> There is a growing number of Pd-related projects hosted at
-<A HREF="http://pure-data.sf.net">SourceForge</A>. This is open to all Pd
-developers, and all are encouraged to join; send an email to the pd-dev list
-(see below).
+<P> More documentation is avalable on the Pd FLOSS site:
+<A href=http://en.flossmanuals.net/PureData/>
+en.flossmanuals.net/PureData/</A> (English) and
+<A href=http://fr.flossmanuals.net/PureData/>
+fr.flossmanuals.net/PureData/</A> (French).
<P>
-Most of the interesting resources related to Pd show up on the Pd mailing list,
+Most of the interesting news related to Pd shows up on the Pd mailing list,
maintained by Iohannes Zmoelnig. To subscribe or browse the archives
visit:
- <A href="http://iem.kug.ac.at/mailinglists/pd-list/">
- http://iem.kug.ac.at/mailinglists/pd-list/</A>.
+ <A href="http://iem.at/mailinglists/pd-list/">
+ http://iem.at/mailinglists/pd-list/</A>.
-. This is the
+This is the
best source of recent information regarding installation problems and bugs. It
is perfectly reasonable to post "newbie" questions on this list; alternatively
you can contact msp@ucsd.edu for help.
-<P> Many extensions to Pd are announced on the mailing list. In particular,
-for people interested in graphics, there is a A 3D graphics rendering package,
-named GEM, based on OpenGL, written by Mark Danks, adapted to Linux by
-Guenter Geiger, and now maintained by Iohannes Zmoelnig. GEM runs on
-Windows and Linux and probably will run with some coaxing on IRIX. You can get
-it from: <A href="http://iem.kug.ac.at/GEM">http://iem.kug.ac.at/GEM</A> .
-
-<P> At least three video processing packages are available for Pd. The oldest
-is Framestein, by Juha Vehvilainen. This runs on Windows only: <A
-href="http://framestein.org"> http://framestein.org </A>.
-The newer PDP
-library, by Tom Schouten, and its extension <A
-href="http://ydegoyon.free.fr/pidip.html"> PiDiP </A> by Yves Degoyon, run well
-in linux and have been ported to Windows and MacOS.
-Mathieu Bouchard has written <A href=http://artengine.ca/gridflow/>
-Gridflow </A>, which runs on linux and MacOSX. The mathematical operators are
-more powerful than in PDP, and the design makes smarter use of cache behavior
-in modern CPUs.
-
-<P> the Pd extended package, maintained by Hans-Christof Steiner, can be
+<P> the Pd Extended package, maintained by Hans-Christophe Steiner, can be
downloaded from the <A href=http://sourceforge.net/projects/pure-data/> Pd's
sourceforge site </A>. All this and much more is described in detail on <A
href="http://puredata.info/"> http://puredata.info/</A>.
+<P> Many extensions to Pd are announced on the mailing list. In particular,
+for people interested in graphics, there is a 3D graphics rendering package,
+named GEM, based on OpenGL, written by Mark Danks, adapted to Linux by
+Guenter Geiger, and now maintained by Iohannes Zmoelnig. You can get
+it from: <A href="http://iem.at/GEM">http://iem.kug.ac.at/GEM</A>, or by
+installing Pd Extended.
<P>
-Here are some more Pd links (in the order I found them): <BR>
-
+Here are some more Pd links (updated 2/2011): <BR>
+<a href="http://obiwannabe.co.uk/tutorials/html/tutorials_main.html">
+Andy Farnell's Tutorial</A><BR>
+<a href="http://sites.google.com/site/porres/TutorialPd.zip">
+Alexandre Porres's Tutorial (Portuguese)</A><BR>
+<A HREF="http://www.crca.ucsd.edu/~msp/techniques.htm">
+Puckette's book, <I> Theory and Techniques of Electronic Music</A> </I> <br>
<a href="http://www.crca.ucsd.edu/~msp"> Miller Puckette's home page</a><br>
-<a href="http://gige.epy.co.at/"> Guenter Geiger's home page</a><br>
-<a href="http://www.danks.org/mark"> Mark Dank's home page</a><br>
-<a href="http://iem.kug.ac.at/~zmoelnig/index.html">
+<a href="http://iem.at/~zmoelnig/index.html">
Johannes M Zmoelnig</a><br>
-<a href="http://suita.chopin.edu.pl/~czaja/miXed/externs/xeq.html">
-Krzysztof Czaja's MIDI file support </a><br>
-<a href="http://www.davesabine.com/media/puredata.asp?action=pddp">
-David Sabine's Pd Documentation Project:
-new, highly detailed help windows</a><br>
<a href="http://www-ccrma.stanford.edu/planetccrma/software/soundapps.html#pd">
-Fernando Pablo Lopez's augmented Pd RPMs from Planet CCRMA</a><br>
-<a href="http://suita.chopin.edu.pl/~czaja/miXed/externs/cyclone.html">
-Cyclone - Krzysztof Czaja's Max compatibility library</a><br>
-On-line book:
-<A HREF="http://www.crca.ucsd.edu/~msp/techniques.htm"
-<I> Theory and Techniques of Electronic Music </I> <br>
-
+Fernando Pablo Lopez's RPMs from Planet CCRMA</a><br>
</BODY>
</HTML>
diff --git a/pd/doc/1.manual/x2.htm b/pd/doc/1.manual/x2.htm
index 05b4d84b..771c9c3e 100644
--- a/pd/doc/1.manual/x2.htm
+++ b/pd/doc/1.manual/x2.htm
@@ -21,11 +21,9 @@
<P> The purpose of this chapter is to describe Pd's design and how it is
supposed to work. Practical details about how to obtain, install, and run Pd
-are described in the next chapter. To learn digital audio processing basics
-such as how to generate time-varying sounds that don't click or fold over, try
-the on-line book,
-<A HREF="http://www.crca.ucsd.edu/~msp/techniques.htm"
-<I> Theory and Techniques of Electronic Music </I></A>.
+are described in the <A href=x3.htm>next chapter</A>. Links to more extensive guidaes (and to
+more theoretical information about computer music) can be found in the
+<A href=x1.htm>previous chapter</A>.
<H3> <A name=s1> 2.1 overview </A> </H3>
diff --git a/pd/doc/1.manual/x3.htm b/pd/doc/1.manual/x3.htm
index 833d6ac7..747c6548 100644
--- a/pd/doc/1.manual/x3.htm
+++ b/pd/doc/1.manual/x3.htm
@@ -17,18 +17,22 @@
<BR><BR>
</P>
+<P> The following are basic instructions on how to get Pd installed and running
+on your machine. More details are maintined online on the
+<A href=http://www.pure-data.info/>pure-data.info</A> site.
+
<P>Pd runs under Microsoft Windows, Linux, and MacOS (10.2 or later). How to
get Pd up and running depends on your operating system, but the overall strategy
is the same. You must first get and install it, and then untangle whatever
problems arise in handling audio and MIDI input and output, and finally get Pd
to meet its real-time obligations reliably.
-<P> Installation instructions are platform-specfic; the following four
+<P> Installation instructions are platform-specfic; the following three
sections
will describe what to do for various operating systems you might have.
In case of trouble also consult the Pd mailing list archive on
- <A href="http://iem.kug.ac.at/mailinglists/pd-list/">
- http://iem.kug.ac.at/mailinglists/pd-list/</A>
+ <A href="http://iem.at/mailinglists/pd-list/">
+ http://iem.at/mailinglists/pd-list/</A>
, which often has late-breaking news about configuration problems and solutions.
The rest of this section describes how to get audio and MIDI to work.
@@ -217,9 +221,10 @@ compile your own copy of Pd and that is the approach described here.
<P> Before you start, you might want to check that you have the resources Pd
needs. The main things you need are the C compiler, X windows (including
-the X development package for Pd to link against) and TK. It's almost
-always enough to load "tcl-devel" and "tk-devel" packages using yum or
-apt-get.
+the X development package for Pd to link against), TK, and the ALSA "devel"
+headers. It should be
+enough to load "tcl-devel", "tk-devel", and "alsa-devel" packages using
+yum or apt-get.
<P>
Download Pd, perhaps from
@@ -244,7 +249,7 @@ to "pd/src" and type
<PRE>
To enable debugging (and losing code optimization) add "--enable-debug".
- To use Portaudio version 19 (experimental), add "--enable-portaudio".
+ To use Portaudio, add "--enable-portaudio".
To put Pd in /usr/bin instead of /usr/local/bin, add "--prefix=/bin".
</PRE>
@@ -291,15 +296,13 @@ audio latency your audio system can handle.
<H3> Audio hardware in Linux </H3>
<P>
-Be forewarned: installing and testing audio and MIDI drivers in Linux can take
+Installing and testing audio and MIDI drivers in Linux can take
days or weeks. There apears to be no single place where you can get detailed
-information on Linux audio. One good source of information lives at:
-<A href=http://www.djcj.org/LAU/guide/index.php>
-http://www.djcj.org/LAU/guide/index.php </A>.
+information on Linux audio.
<P>
-There are two widely-used driver sets, called "OSS" and "ALSA". OSS is
-included in the standard Linux kernels since version 2.2. However, for some
+There are two widely-used driver sets, called "OSS" and "ALSA". ALSA is
+included in the standard Linux kernel since 2.4 or so. However, for some
audio cards you can find newer versions than are included in the kernel
releases. You can get ALSA from
@@ -307,14 +310,11 @@ releases. You can get ALSA from
http://www.alsa-project.org/</A> .
<P> ALSA is able to emulate OSS, so that you can usually run Pd using the
-default "OSS" settings even if it's actually ALSA that's running.
-ALSA is newer, hence less stable and harder to use, than OSS.
-Installing ALSA can be tricky and/or confusing.
+"OSS" driver settings even if it's actually ALSA that's running.
-<P> By default, Pd uses OSS. If you are running ALSA, Pd will use ALSA's OSS
-emulation. To make Pd use ALSA "natively", i.e., the way ALSA is designed
-to be used, include the "-alsa" flag in the command line or bang on the "media"
-menu items.
+<P> By default, Pd uses ALSA. You can ask Pd to use ALSA's OSS emulation by
+adding the "-oss" flag to the command line or fooling with the "media" menu
+items.
<P> You can add ALSA devices by name on the Pd command line:
<PRE>
@@ -330,7 +330,7 @@ also the Pd mailing list archives.
<H6> RME 9652 (Hammerfall) </H6>
-<P> This is the best sound card out there; it costs around $500 and has 3 ADAT
+<P> This is the best PCI sound card out there; it costs around $500 and has 3 ADAT
I/O ports and one SPDIF. There is a "baby hammerfall" also, which I think is
the "9632." DO NOT CONFUSE THE 9652/9632 WITH OTHER RME BOARDS WHICH MIGHT
NOT WORK WITH PD.
@@ -349,16 +349,14 @@ with between 4 and 10 channels in and out, for
which there are ALSA drivers. These are also very good, and they are a
bit cheaper than Hammerfalls. The driver name is "ice1712".
-<P> Alsa provides an "envy24control" program (in "utils". You should run
-this and check that your ice1712's sync source is internal if you have no
-SPDIF input, or "SPDIF" if you do. I think the default is now "internal"
-but don't take it for granted...
+<H6> USB sound devices</H6>
-<H6> warning about i810/i815 drivers...</H6>
+<P> Ed Kelly reports success with the Lexicon series of USB 1.0 devices (e.g.,
+the Omega Studio; apparently 4 channels in and 4 out). Also known to work well is the
+Edirol box (2 channels in and out).
-<P>As of RedHat 7.0, motherboards with native i810 audio systems didn't work in
-full duplex (they crashed linux). Either run Pd -noadc or else (better)
-install ALSA. This ought to be fixed by now...
+<P> As of Feb. 2011, USB 2.0 devices are starting to appear but the ALSA
+driver support is not yet there; watch the Pd mailing list.
<H3> <A name="s1.3"> 3.4. Installing Pd in Macintosh OSX </A> </H3>
diff --git a/pd/doc/1.manual/x5.htm b/pd/doc/1.manual/x5.htm
index c07d48dd..a781ae5c 100644
--- a/pd/doc/1.manual/x5.htm
+++ b/pd/doc/1.manual/x5.htm
@@ -20,6 +20,11 @@
<H3> <A name="s2"> 5.1. release notes </A> </H3>
+<P> ------------------ 0.43 ---------------------------
+
+<P> Completely new TCL front end, thanks to Hans-Christophe Steiner,
+Iohannes Zmoelnig, and others.
+
<P> ------------------ 0.42-5 ---------------------------
<P> broken abs~ and log~ fixed
@@ -1665,53 +1670,9 @@ The following max-like objects are included:
<H3> <A name="s2"> 5.2. known bugs </A> </H3>
-<P> In the list below, starred items are still things needing attention.
-This list is no longer maintained; see the sourceforge bug tracker on
-https://sourceforge.net/tracker/?group_id=55736
-
-<P> *1. Timing of MIDI input/output is very shaky. Audio I/O is primitive, but
-there's at least a way to detect errors now for linux and NT.
-
-<P> *2. There is no flow control for graphical updates yet; the
-real-time process can easily block trying to write too fast to the GUI.
-
-<P> 3. PD dies if your patch has an infinite loop [fixed in 0.30 release.]
-
-<P> *4. If you cut a box which is a "Pd" or abstraction whose subpatch has
-items selected, Pd dies.
-
-<P> *5. Tables and other drawable items can draw far outside the window; there's
-no sanity check, Huge tables (>1000 points) are only partially drawn
-(the first 1000 points.)
-
-<P> 6. There's no way to order force a delread~ to make it read after
-a delwrite~ has written. [but see under 3.audio.examples how to do this now.]
-
-<P> 7. Pd doesn't know to suspend graphics updates when you minimize objects.
-Presumably minimization makes things better but it doesn't cut off graphics
-computation entirely as it should. [fixed for 0.34]
-
-<P> 8. If you load a nonexistent extern you get a spurious message,
-"consistency check failed: canvas_setargs". [fixed for 0.27 release.]
-
-<P> 9. Typing backslashes into objects upsets Tk [0.29 should suppress all
-backslashes; a real fix might come later.]
-
-<P> 10. Never type a dollar sign into a comment; you may have trouble
-opening your patch afterward... [fixed somewhere around 0.32]
-
-<P> *11. You'd better Turn DSP off before you type into a box that currently
-holds a "pd" object with tilde objects in the subpatch.
-
-<P> *12. In Linux, if you hit control C while Pd is opening MIDI, Pd hangs.
-
-<P> *13. In linux, Pd doesn't report audio data-late errors yet.
-
-<P> *14. Several objects, notably dac~, adc~, and env~, are incompatible with
-uses of block~ or switch~ objects that change block size from the default of
-64. Using switch~ without reblocking causes no problem. Don't try to
-read/write delay lines or use send~/receive~, or throw~/catch~, between
-windows with different block sizes.
+<P> These are now tracked on the
+<A href=https://sourceforge.net/projects/pure-data/>
+Pd Sourceforge project page</A>.
<H3> <A name="s3"> 5.3. differences from Max/MSP </A> </H3>
@@ -1721,10 +1682,11 @@ Pd than in Max/MSP, the choices in Pd tend to hew to those in Max/MSP.
Moreover, some effort has been undertaken (but more is needed) to make the
two interoperable.
-<P> You can use Pd to import and export patches to Max/MSP; just save as
-text to a file with extension ".pat", and then open it in Pd. You'll at
-least get something. If you stick to common or commonizable features
-you can actually develop patches for both platforms.
+<P> You can use Pd to import and export patches to Max/MSP; just save as text to
+a file with extension ".pat", and then open in the other program. You'll at
+least get something. If you stick to common or commonizable features you can
+actually develop patches for both platforms. Pd importing of Max patches works
+best if you use the Pd Extended package; there are many more compatible objects.
<P> When specific objects exist on one platform and not on the other, it's
often possible to make abstractions to imitate the missing objects, in a
diff --git a/pd/doc/3.audio.examples/E04.difference.tone.pd b/pd/doc/3.audio.examples/E04.difference.tone.pd
index 7272222b..982c6715 100644
--- a/pd/doc/3.audio.examples/E04.difference.tone.pd
+++ b/pd/doc/3.audio.examples/E04.difference.tone.pd
@@ -1,4 +1,4 @@
-#N canvas 266 135 637 523 12;
+#N canvas 263 112 637 523 12;
#X obj 19 128 +~;
#X obj 18 209 output~;
#X text 141 3 NONLINEAR DISTORTION AND DIFFERENCE TONES;
@@ -6,7 +6,6 @@
#X floatatom 154 151 5 0 500 0 - - -;
#X obj 18 181 clip~ -1 1;
#X floatatom 42 81 5 0 0 0 - - -;
-#X obj 42 103 osc~ 200;
#X obj 18 155 *~;
#X obj 42 35 loadbang;
#X msg 154 127 50;
@@ -30,16 +29,17 @@ no longer as if the two sinusoids had been processed separately. Instead
At 300 and 225 Hz \, the subharmonic is at 75 \, two octaves below
the upper tone and a twelveth below the lower one. Change the frequency
of the second tone and you will hear a variety of effects.;
-#X connect 0 0 8 0;
-#X connect 3 0 8 1;
+#X obj 42 103 osc~;
+#X connect 0 0 7 0;
+#X connect 3 0 7 1;
#X connect 4 0 3 0;
#X connect 5 0 1 0;
#X connect 5 0 1 1;
-#X connect 6 0 7 0;
-#X connect 7 0 0 1;
-#X connect 8 0 5 0;
-#X connect 9 0 17 0;
-#X connect 10 0 4 0;
-#X connect 11 0 10 0;
-#X connect 16 0 0 0;
-#X connect 17 0 6 0;
+#X connect 6 0 19 0;
+#X connect 7 0 5 0;
+#X connect 8 0 16 0;
+#X connect 9 0 4 0;
+#X connect 10 0 9 0;
+#X connect 15 0 0 0;
+#X connect 16 0 6 0;
+#X connect 19 0 0 1;
diff --git a/pd/doc/3.audio.examples/E06.exponential.pd b/pd/doc/3.audio.examples/E06.exponential.pd
index 02fe058b..7247e44d 100644
--- a/pd/doc/3.audio.examples/E06.exponential.pd
+++ b/pd/doc/3.audio.examples/E06.exponential.pd
@@ -1,10 +1,10 @@
-#N canvas 88 112 754 729 12;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 85 89 754 729 12;
+#N canvas 0 0 450 300 (subpatch) 0;
#X array E06-signal 882 float 0;
#X coords 0 1.02 882 -1.02 200 130 1;
#X restore 509 46 graph;
#X obj 14 265 hip~ 5;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 0 0 450 300 (subpatch) 0;
#X array E06-spectrum 128 float 0;
#X coords 0 4300 127 -40 257 130 1;
#X restore 463 222 graph;
@@ -99,7 +99,7 @@ frequency for showing spectra: the 16th bin in a 4096-point spectrum
#X text 722 276 0.5;
#X obj 82 238 tgl 18 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 0 0 450 300 (subpatch) 0;
#X array E06-tab 1003 float 1;
#A 0 1.01005 1 0.99005 0.980199 0.970446 0.960789 0.951229 0.941765
0.932394 0.923116 0.913931 0.904837 0.895834 0.88692 0.878095 0.869358
@@ -278,7 +278,7 @@ frequency for showing spectra: the 16th bin in a 4096-point spectrum
#X connect 7 0 10 0;
#X connect 8 0 4 1;
#X restore 302 258 pd make-table;
-#X text 251 95 waveshaping function;
+#X text 252 85 waveshaping function;
#X text 438 210 0;
#X text 437 114 1;
#X obj 12 168 +~ 1;
diff --git a/pd/doc/3.audio.examples/E07.evenodd.pd b/pd/doc/3.audio.examples/E07.evenodd.pd
index e6d3851e..6de461b9 100644
--- a/pd/doc/3.audio.examples/E07.evenodd.pd
+++ b/pd/doc/3.audio.examples/E07.evenodd.pd
@@ -1,9 +1,9 @@
-#N canvas 187 149 784 591 12;
+#N canvas 184 126 784 591 12;
#X obj 230 101 f;
#X obj 264 77 + 1;
#X obj 264 101 mod 11;
-#N canvas 0 0 450 300 graph1 0;
-#X array E07 11 float 0;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array E07 11 float 2;
#X coords 0 96 11 36 100 160 1;
#X restore 528 15 graph;
#X floatatom 320 53 0 10 999 0 - - -;
@@ -28,7 +28,7 @@
#X text 354 79 <--increment;
#X text 355 56 <--msec;
#X obj 26 193 *~ 0.01;
-#X obj 230 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+#X obj 230 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1
;
#X obj 27 321 output~;
#X text 527 562 updated for Pd version 0.37;
@@ -36,13 +36,13 @@
#X obj 230 150 +;
#X floatatom 265 150 0 -48 120 0 - - -;
#X text 299 152 <--transpose;
-#N canvas 0 0 538 208 make-table 0;
+#N canvas 61 76 538 208 make-table 0;
#X obj 38 71 loadbang;
#X text 16 11 This patch loads a sequence of pitches into E07. The
values are floating-point \, so we could use microtones (60.5 \, for
example) if we wish.;
-#X msg 38 99 \; E07 0 55 56 57 55 57 61 55 61 63 57 63 \; E07
-yticks 36 12 1 \; E07 ylabel 12 36 48 60 72 84 96;
+#X msg 38 99 \; E07 0 54 55 57 63 61 67 71 57 70 61 63 \; E07 yticks
+36 12 1 \; E07 ylabel 12 36 48 60 72 84 96;
#X connect 0 0 2 0;
#X restore 527 195 pd make-table;
#X obj 176 50 sel 0;
diff --git a/pd/doc/3.audio.examples/I07.phase.vocoder.pd b/pd/doc/3.audio.examples/I07.phase.vocoder.pd
index 735b8cd2..11028419 100644
--- a/pd/doc/3.audio.examples/I07.phase.vocoder.pd
+++ b/pd/doc/3.audio.examples/I07.phase.vocoder.pd
@@ -1,4 +1,4 @@
-#N canvas 425 33 744 599 12;
+#N canvas 0 0 742 597 12;
#X floatatom 494 315 5 0 0 0 - transpo-set -;
#X floatatom 167 383 3 0 0 0 - speed-set -;
#X floatatom 55 385 7 0 0 0 - location-set -;
@@ -347,11 +347,11 @@ shifts the signal to the left or right depending on its argument.)
#X connect 54 0 21 0;
#X restore 55 480 pd fft-analysis;
#N canvas 260 23 647 768 phase-tables 0;
-#N canvas 0 0 450 300 graph2 0;
+#N canvas 0 0 450 300 (subpatch) 0;
#X array prev-imag 4096 float 0;
#X coords 0 1000 4096 -1000 400 300 1;
#X restore 169 326 graph;
-#N canvas 0 0 450 300 graph3 0;
+#N canvas 0 0 450 300 (subpatch) 0;
#X array prev-real 4096 float 0;
#X coords 0 500 4096 -500 400 300 1;
#X restore 170 17 graph;
@@ -362,9 +362,9 @@ shifts the signal to the left or right depending on its argument.)
#X text 389 359 normal;
#X obj 56 517 output~;
#N canvas 0 110 565 454 hann-window 0;
-#N canvas 0 0 450 300 graph1 0;
-#X array \$0-hann 1024 float 0;
-#X coords 0 1 1023 0 300 100 1;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array \$0-hann 2048 float 0;
+#X coords 0 1 2047 0 300 100 1;
#X restore 82 311 graph;
#X obj 378 165 osc~;
#X obj 378 190 *~ -0.5;
@@ -412,9 +412,9 @@ and window-msec (analysis window size in seconds and msec).;
#X connect 19 1 18 0;
#X restore 440 528 pd hann-window;
#N canvas 388 86 694 447 insample 0;
-#N canvas 0 0 450 300 graph1 0;
-#X array \$0-sample 160161 float 0;
-#X coords 0 1 160160 -1 400 150 1;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array \$0-sample 62079 float 0;
+#X coords 0 1 62078 -1 400 150 1;
#X restore 281 135 graph;
#X obj 28 133 r read-sample;
#X obj 28 184 unpack s f;
@@ -495,7 +495,6 @@ and window-msec (analysis window size in seconds and msec).;
#X text 57 361 motion);
#X text 165 348 motion in;
#X text 232 464 read input sound;
-#X text 103 7 PHASE VOCODER FOR TIME STETCHING AND CONTRACTION;
#X text 604 479 length \, msec;
#X floatatom 607 419 5 0 0 0 - window-size -;
#X msg 607 307 512;
@@ -527,6 +526,7 @@ to see the workings.;
#X obj 535 460 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X text 466 458 file ->;
+#X text 103 7 PHASE VOCODER FOR TIME STRETCHING AND CONTRACTION;
#X connect 0 0 5 0;
#X connect 1 0 21 0;
#X connect 2 0 20 0;
@@ -538,11 +538,11 @@ to see the workings.;
#X connect 17 0 11 0;
#X connect 19 0 29 0;
#X connect 22 0 23 0;
-#X connect 24 0 49 0;
-#X connect 25 0 49 0;
-#X connect 26 0 49 0;
-#X connect 39 0 43 0;
-#X connect 40 0 43 0;
-#X connect 41 0 43 0;
-#X connect 42 0 43 0;
-#X connect 53 0 11 1;
+#X connect 24 0 48 0;
+#X connect 25 0 48 0;
+#X connect 26 0 48 0;
+#X connect 38 0 42 0;
+#X connect 39 0 42 0;
+#X connect 40 0 42 0;
+#X connect 41 0 42 0;
+#X connect 52 0 11 1;
diff --git a/pd/doc/5.reference/bang-help.pd b/pd/doc/5.reference/bang-help.pd
index 1f522268..5a289050 100644
--- a/pd/doc/5.reference/bang-help.pd
+++ b/pd/doc/5.reference/bang-help.pd
@@ -2,7 +2,7 @@
#X obj 49 182 print;
#X text 107 183 Output is in the printout window.;
#X obj 66 15 bang;
-#X text 112 14 - SEND "BANG" MSSESSAGE;
+#X text 112 14 - SEND "BANG" MESSAGE;
#X msg 61 105 walk the cat;
#X msg 49 79 45;
#X obj 49 152 bang;
diff --git a/pd/doc/5.reference/block~-help.pd b/pd/doc/5.reference/block~-help.pd
index 4d2bdbdc..97e2207b 100644
--- a/pd/doc/5.reference/block~-help.pd
+++ b/pd/doc/5.reference/block~-help.pd
@@ -1,4 +1,4 @@
-#N canvas 21 2 607 676 12;
+#N canvas 0 0 603 672 12;
#X obj 48 10 block~;
#X text 112 11 (and switch~) - block size and on/off control for DSP
;
@@ -74,7 +74,6 @@ may be switched with impunity \, but not catch~.;
#X text 32 11 INTERACTIONS BETWEEN BLOCK~/SWITCH~ AND OTHER OBJECTS
IN PD;
#X restore 40 482 pd block-interations;
-#X text 227 483 INTERACTIONS WITH OTHER OBJECTS;
#X text 44 269 Pd's default block size is 64 samples. The inlet~ and
outlet~ objects reblock signals to adjust for differences between parent
and subpatch \, but only power-of-two adjustments are possible. So
@@ -85,4 +84,27 @@ any other block size. This is intended for later use in video processing.
#X text 45 395 Switch~ takes a "bang" message that causes one block
of DSP to be computed. This might be useful for pre-computing waveforms
or window functions \, or also for video processing.;
-#X text 337 604 updated for Pd version 0.4;
+#X text 198 484 <-- BUG!! block~/switch~ and dac~/adc~ are incompatible
+;
+#N canvas 0 0 581 315 block-interations 0;
+#X text 32 11 You can use the switch~ object to single-step dsp in
+a subpatch. This might be useful for block operations that don't want
+to be synced to the sample clock: loading a wondiw function in a table
+\, or copying one table to another:;
+#X obj 136 193 noise~;
+#X obj 136 225 tabwrite~ zzzz;
+#X obj 33 154 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array zzzz 256 float 2;
+#X coords 0 1 256 -1 256 140 1;
+#X restore 300 116 graph;
+#X obj 33 228 switch~ 256;
+#X text 25 111 turn DSP on and click to;
+#X text 26 127 randomize the table at right:;
+#X connect 1 0 2 0;
+#X connect 3 0 2 0;
+#X connect 3 0 5 0;
+#X restore 40 505 pd block-interations;
+#X text 198 506 <-- wierd 'bang' feature lets you single-step DSP;
+#X text 337 604 updated for Pd version 0.43;
diff --git a/pd/doc/5.reference/delay-help.pd b/pd/doc/5.reference/delay-help.pd
index 5f90cd4b..119f2a31 100644
--- a/pd/doc/5.reference/delay-help.pd
+++ b/pd/doc/5.reference/delay-help.pd
@@ -1,30 +1,33 @@
#N canvas 3 0 513 348 12;
#X obj 66 15 delay;
-#X obj 13 229 50;
-#X msg 13 98 bang;
-#X floatatom 13 255;
-#X floatatom 116 182;
-#X obj 51 230 0;
+#X floatatom 116 182 0 0 0 0 - - -;
#X text 111 16 - CALLBACK AFTER TIME DELAY;
#X text 130 205 <-- creation argument initializes delay time;
-#X text 6 41 The delay object sends a bang to its outlet after a delay in milliseconds specified by its right inlet or its creation argument.;
+#X text 6 41 The delay object sends a bang to its outlet after a delay
+in milliseconds specified by its right inlet or its creation argument.
+;
#X obj 51 204 delay 1000;
-#X text 58 86 Click here to test the delay object by initializing the number box below to 50 and then clearing it after the specified delay.;
#X text 94 132 Click here to CANCEL delay's action;
#X msg 51 133 stop;
#X text 43 324 see also:;
#X obj 155 323 timer;
#X obj 111 323 metro;
#X msg 62 155 2000;
-#X text 102 154 Number in right inlet sets time and schedules the action.;
-#X text 316 320 updated for Pd version 0.3;
+#X text 102 154 Number in right inlet sets time and schedules the action.
+;
#X text 145 183 <-- scroll to change delay time in milliseconds;
-#X text 14 280 Note: sending a bang to a delay which is already set will reschedule its output \, cancelling the old one.;
-#X connect 1 0 3 0;
-#X connect 2 0 1 0;
-#X connect 2 0 9 0;
-#X connect 4 0 9 1;
-#X connect 5 0 3 0;
-#X connect 9 0 5 0;
-#X connect 12 0 9 0;
-#X connect 16 0 9 0;
+#X text 14 280 Note: sending a bang to a delay which is already set
+will reschedule its output \, cancelling the old one.;
+#X obj 52 231 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 34 112 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X text 55 109 bang to set it;
+#X obj 224 258 del;
+#X text 115 256 Also known as:;
+#X text 317 320 updated for Pd version 0.43;
+#X connect 1 0 5 1;
+#X connect 5 0 15 0;
+#X connect 7 0 5 0;
+#X connect 11 0 5 0;
+#X connect 16 0 5 0;
diff --git a/pd/doc/5.reference/drawpolygon-help.pd b/pd/doc/5.reference/drawpolygon-help.pd
index 7b3dfd24..cfc3cd10 100644
--- a/pd/doc/5.reference/drawpolygon-help.pd
+++ b/pd/doc/5.reference/drawpolygon-help.pd
@@ -12,7 +12,7 @@ dog float weasel;
#N canvas 177 100 580 549 help-drawpolygon-template 1;
#X obj 19 24 drawpolygon 0 2 0 0 0 weasel;
#X obj 18 300 filledpolygon 900 dog 3 10 0 20 cat 30 0;
-#X text 30 322 filledpolyconn and filledcurve take the same arguments
+#X text 30 322 filledpolygon and filledcurve take the same arguments
\, except that a new first argument is added to specify interior color.
Here the interior color is red (900) \, the outline color is controlled
by the "dog" field \, and the three points describe a triangle of altitude
diff --git a/pd/doc/5.reference/line-help.pd b/pd/doc/5.reference/line-help.pd
index f5d5ad38..d56c262a 100644
--- a/pd/doc/5.reference/line-help.pd
+++ b/pd/doc/5.reference/line-help.pd
@@ -1,35 +1,44 @@
-#N canvas 31 15 669 403 12;
-#X floatatom 22 339 0 0 0 0 - - -;
-#X msg 31 205 0 1000;
-#X msg 46 227 39;
+#N canvas 372 214 597 464 12;
+#X floatatom 22 416 8 0 0 0 - - -;
+#X msg 32 219 0 1000;
+#X msg 47 241 39;
#X obj 66 15 line;
#X text 106 14 - ramp generator;
-#X msg 22 182 1 1000;
-#X text 18 36 The line object takes (target \, time) pairs and slews
+#X msg 23 196 1 1000;
+#X text 22 38 The line object takes (target \, time) pairs and slews
to the specified target over the time given \, updating its output
-at a "grain rate" given by the creation argument. If you dont' specify
+at a "grain rate" given by the creation argument. If you don't specify
a time \, line jumps immediately to the target. Note that the inlet
does not remember old values (unlike every other inlet in Pd) -- sending
a float causes a jump in the output regardless of whatever time value
was specified in some previous message. If the line object receives
a message specifying some new target before reaching the previous one
\, it takes off from its current value.;
-#X text 93 194 send a pair to ramp to a new value;
-#X text 105 224 send a single number to jump;
-#X text 46 363 see also:;
-#X obj 132 361 line~;
-#X msg 57 252 stop;
-#X text 98 251 "stop" message to stop output;
-#X obj 22 313 line 0 100;
-#X text 383 369 updated for Pd version 0.37;
-#X text 125 310 creation arguments:;
-#X text 316 310 1 initial value;
-#X text 318 330 2 time grain in milliseconds;
-#X msg 51 282 set 5;
-#X text 99 282 "set" to change value (and stop) without output;
+#X text 94 208 send a pair to ramp to a new value;
+#X text 97 243 send a single number to jump;
+#X text 106 443 see also:;
+#X obj 176 440 line~;
+#X msg 58 266 stop;
+#X text 103 268 "stop" message to stop output;
+#X obj 22 390 line 0 100;
+#X text 122 396 creation arguments:;
+#X text 271 388 1 initial value;
+#X msg 52 296 set 5;
+#X text 105 296 "set" to change value (and stop) without output;
+#X text 394 441 updated for Pd version 0.43;
+#X obj 222 440 vline~;
+#X floatatom 91 352 0 0 0 0 - - -;
+#X floatatom 91 328 0 0 0 0 - - -;
+#X text 126 328 first inlet sets next ramp time (cleared when ramp
+starts!);
+#X text 125 354 second inlet sets grain (not cleared \, acts as normal
+inlet);
+#X text 270 404 2 time grain in milliseconds (20 by default);
#X connect 1 0 13 0;
#X connect 2 0 13 0;
#X connect 5 0 13 0;
#X connect 11 0 13 0;
#X connect 13 0 0 0;
-#X connect 18 0 13 0;
+#X connect 16 0 13 0;
+#X connect 20 0 13 2;
+#X connect 21 0 13 1;
diff --git a/pd/doc/5.reference/route-help.pd b/pd/doc/5.reference/route-help.pd
index 224fb0ea..578795bc 100644
--- a/pd/doc/5.reference/route-help.pd
+++ b/pd/doc/5.reference/route-help.pd
@@ -1,4 +1,4 @@
-#N canvas 0 0 815 537 12;
+#N canvas 58 56 699 665 12;
#X obj 183 213 print x1;
#X obj 261 213 print x2;
#X obj 339 213 print x3;
@@ -45,9 +45,17 @@ of arguments plus one.;
the list contining only the number 5 \, both messages match "float"
\, and ditto for symbols. An empty list matches "bang". In Pd these
are all considered special cases of lists.;
-#X text 545 506 updated for Pd version 0.35;
#X text 97 9 - route messages according to their first element;
#X obj 43 8 route;
+#X text 482 627 updated for Pd version 0.43;
+#X obj 132 564 route 4;
+#X msg 84 539 1 2 3;
+#X floatatom 187 540 5 0 0 0 - - -;
+#X msg 132 539 4 5 6;
+#X obj 131 590 print w1;
+#X obj 200 591 print w2;
+#X text 278 549 With zero or one argument \, route sprouts an inlet
+to set the arument (which may be float or symbol).;
#X connect 4 0 0 0;
#X connect 4 1 1 0;
#X connect 4 2 2 0;
@@ -78,3 +86,8 @@ are all considered special cases of lists.;
#X connect 30 2 31 0;
#X connect 30 3 32 0;
#X connect 30 4 33 0;
+#X connect 41 0 45 0;
+#X connect 41 1 46 0;
+#X connect 42 0 41 0;
+#X connect 43 0 41 1;
+#X connect 44 0 41 0;
diff --git a/pd/doc/5.reference/spigot-help.pd b/pd/doc/5.reference/spigot-help.pd
index 10ff1569..8e6a0d19 100644
--- a/pd/doc/5.reference/spigot-help.pd
+++ b/pd/doc/5.reference/spigot-help.pd
@@ -15,7 +15,6 @@ ignored.;
#X text 349 310 updated for Pd version 0.38;
#X obj 92 244 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
;
-#X text 450 267;
#X text 125 267 optional arg sets the initial state (0 by default)
;
#X connect 3 0 8 0;
diff --git a/pd/doc/5.reference/tabread-help.pd b/pd/doc/5.reference/tabread-help.pd
index fa671a21..25c9bfd9 100644
--- a/pd/doc/5.reference/tabread-help.pd
+++ b/pd/doc/5.reference/tabread-help.pd
@@ -1,21 +1,38 @@
-#N canvas 44 26 703 454 12;
-#X text 52 181 index;
+#N canvas 58 46 685 536 12;
+#X text 89 188 index;
#X obj 36 9 tabread;
-#X obj 15 244 tabread array99;
-#X floatatom 15 182 0 0 0;
-#X floatatom 15 278 0 0 0;
-#X graph graph1 0 0 10 10 362 379 612 179;
-#X array array99 10 float;
-#X pop;
-#X msg 31 56 \; readout 1 \; array99 resize 10 \; array99 bounds 0 0 10 10 \; array99 xlabel -0.5 0 1 2 3 4 5 6 7 8 9 10 \; array99 ylabel -1 0 1 2 3 4 5 6 7 8 9 10 \; array99 0 1 4 2 8 5 6 1 4 2 8;
-#X text 60 276 output = array99[index];
-#X text 141 33 click here to initialize;
-#X text 159 236 creation argument;
-#X text 155 254 gives array name;
-#X msg 25 204 set array99;
-#X text 137 204 change array name;
-#X text 422 407 updated for Pd version 0.33;
-#X text 110 8 - read numbers from a table;
+#X obj 52 251 tabread array99;
+#X floatatom 52 189 0 0 0 0 - - -;
+#X floatatom 52 285 0 0 0 0 - - -;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array array99 10 float 3;
+#A 0 9 0 8 1 7 2 6 3 5 4;
+#X coords 0 10 10 0 250 200 1 0 0;
+#X restore 398 219 graph;
+#X text 90 286 output = array99[index];
+#X text 196 243 creation argument;
+#X text 198 259 gives array name;
+#X msg 62 211 set array99;
+#X text 174 211 change array name;
+#X text 109 9 - read numbers from a table;
+#X msg 36 363 \; array99 xlabel -0.5 0 1 2 3 4 5 6 7 8 9 10 \; array99
+ylabel -1 0 1 2 3 4 5 6 7 8 9 10;
+#X text 449 486 updated for Pd version 0.43;
+#X obj 37 337 loadbang;
+#X text 8 433 see also the "array" tutorial in section 2 of the Pd
+documentation \, and these objects:;
+#X obj 9 472 tabwrite~;
+#X obj 213 472 tabwrite;
+#X obj 278 472 tabsend~;
+#X obj 343 472 tabreceive~;
+#X obj 80 472 tabplay~;
+#X obj 148 472 tabread4;
+#X text 59 45 The tabread object reads values from an array ("table")
+according to an index. The index is rounded down to the next lower
+integer. Values in the table correspond to indices starting at 0 Indices
+outside of the range are replaced by the nearest index in range (from
+0 to 9 in this example).;
#X connect 2 0 4 0;
#X connect 3 0 2 0;
-#X connect 11 0 2 0;
+#X connect 9 0 2 0;
+#X connect 14 0 12 0;
diff --git a/pd/doc/5.reference/tabread4-help.pd b/pd/doc/5.reference/tabread4-help.pd
new file mode 100644
index 00000000..fea18fb4
--- /dev/null
+++ b/pd/doc/5.reference/tabread4-help.pd
@@ -0,0 +1,39 @@
+#N canvas 61 69 685 536 12;
+#X text 89 188 index;
+#X obj 36 9 tabread;
+#X floatatom 52 189 0 0 0 0 - - -;
+#X floatatom 52 285 0 0 0 0 - - -;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array array99 10 float 3;
+#A 0 9 0 8 1 7 2 6 3 5 4;
+#X coords 0 10 10 0 250 200 1 0 0;
+#X restore 398 219 graph;
+#X text 90 286 output = array99[index];
+#X text 196 243 creation argument;
+#X text 198 259 gives array name;
+#X msg 62 211 set array99;
+#X text 174 211 change array name;
+#X text 109 9 - read numbers from a table;
+#X msg 36 363 \; array99 xlabel -0.5 0 1 2 3 4 5 6 7 8 9 10 \; array99
+ylabel -1 0 1 2 3 4 5 6 7 8 9 10;
+#X text 449 486 updated for Pd version 0.43;
+#X obj 37 337 loadbang;
+#X text 8 433 see also the "array" tutorial in section 2 of the Pd
+documentation \, and these objects:;
+#X obj 9 472 tabwrite~;
+#X obj 213 472 tabwrite;
+#X obj 278 472 tabsend~;
+#X obj 343 472 tabreceive~;
+#X obj 80 472 tabplay~;
+#X obj 52 251 tabread4 array99;
+#X obj 148 472 tabread;
+#X text 59 44 The tabread4 object reads values from an array ("table")
+according to an index \, applying four-point polynomial interpolation.
+Indices should range from 1 to (size-2) so that the 4-point interpolation
+is meaningful. You can shift-drag the number box to see the effect
+of interpolation.Indices outside of the range are replaced by the nearest
+index in range (from 1 to 8 in this example).;
+#X connect 2 0 20 0;
+#X connect 8 0 20 0;
+#X connect 13 0 11 0;
+#X connect 20 0 3 0;
diff --git a/pd/doc/5.reference/tabread~-help.pd b/pd/doc/5.reference/tabread~-help.pd
new file mode 100644
index 00000000..e27523e6
--- /dev/null
+++ b/pd/doc/5.reference/tabread~-help.pd
@@ -0,0 +1,45 @@
+#N canvas 320 156 845 474 12;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array array99 10 float 3;
+#A 0 -0.5 0.5 -0.4 0.4 -0.3 0.3 -0.2 0.2 -0.1 0.1;
+#X coords 0 1 10 -1 250 200 1;
+#X restore 562 167 graph;
+#X obj 16 362 snapshot~;
+#X obj 35 336 metro 200;
+#X obj 16 149 sig~;
+#X floatatom 16 123 6 0 10 0 - - -;
+#X obj 35 310 r readout;
+#X floatatom 16 388 0 0 0 0 - - -;
+#X msg 28 186 set array99;
+#X text 118 185 "set" message permits you to switch between arrays
+;
+#X text 144 274 creation argument initializes array name;
+#X text 11 403 see also the "array" tutorial in section 2 of the Pd
+documentation \, and these objects:;
+#X text 563 16 click here to test;
+#X obj 91 445 tabwrite~;
+#X obj 236 445 tabread;
+#X obj 359 446 tabwrite;
+#X obj 424 446 tabsend~;
+#X obj 489 446 tabreceive~;
+#X obj 162 445 tabplay~;
+#X msg 582 40 \; readout 1 \; pd dsp 1 \;;
+#X text 24 230 signal input;
+#X obj 47 21 tabread~;
+#X text 127 21 non-interpolating table lookup;
+#X text 7 58 Tabread~ looks up values out of the named array. Incoming
+values are truncated to the next lower integer \, and values out of
+bounds get the nearest (first or last) point.;
+#X text 64 117 incoming signal is index. Indices should range from
+0 to (size-1).;
+#X obj 16 274 tabread~ array99;
+#X obj 16 446 tabread4~;
+#X obj 294 445 tabread4;
+#X text 625 451 updated for Pd version 0.43;
+#X connect 1 0 6 0;
+#X connect 2 0 1 0;
+#X connect 3 0 24 0;
+#X connect 4 0 3 0;
+#X connect 5 0 2 0;
+#X connect 7 0 24 0;
+#X connect 24 0 1 0;
diff --git a/pd/doc/7.stuff/tools/latency.pd b/pd/doc/7.stuff/tools/latency.pd
index bedb0ea1..6e9febb5 100644
--- a/pd/doc/7.stuff/tools/latency.pd
+++ b/pd/doc/7.stuff/tools/latency.pd
@@ -1,99 +1,264 @@
-#N canvas 37 0 825 630 12;
-#X obj 132 166 metro 500;
-#X msg 91 217 0.5;
-#X obj 130 192 del 3;
-#X msg 130 217 0;
-#X obj 34 323 dac~;
-#X obj 286 216 adc~;
-#X obj 291 310 timer;
-#X obj 93 333 env~ 65536;
-#X floatatom 93 360 4 0 0 0 - - -;
-#X floatatom 339 170 4 0 0 0 - - -;
-#X obj 339 193 + 100;
-#X obj 339 218 dbtorms;
-#X obj 181 333 env~ 65536;
-#X floatatom 181 362 4 0 0 0 - - -;
-#X floatatom 291 347 4 0 0 0 - - -;
-#X obj 312 245 *~ 1;
-#X obj 348 278 threshold~ 0.1 5 0.05 5;
-#X obj 634 160 bonk~;
-#X obj 634 188 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+#N canvas 166 252 718 504 12;
+#X floatatom 239 98 4 0 0 0 - - adc-gain;
+#X text 317 17 latency measurement;
+#N canvas 31 48 928 842 guts 0;
+#X obj 292 35 adc~ 1 2 3 4 5 6 7 8;
+#X obj 318 102 == 1;
+#X obj 293 126 *~ 0;
+#X obj 355 128 *~ 0;
+#X obj 418 129 *~ 0;
+#X obj 480 131 *~ 0;
+#X obj 541 134 *~ 0;
+#X obj 603 136 *~ 0;
+#X obj 666 137 *~ 0;
+#X obj 728 139 *~ 0;
+#X obj 380 104 == 2;
+#X obj 443 105 == 3;
+#X obj 505 107 == 4;
+#X obj 566 110 == 5;
+#X obj 628 112 == 6;
+#X obj 691 113 == 7;
+#X obj 753 115 == 8;
+#X obj 46 34 loadbang;
+#X obj 59 153 r inchannel;
+#X msg 59 177 set \$1;
+#X obj 59 201 s inchannel-set;
+#N canvas 0 22 450 300 (subpatch) 0;
+#X array pulse 120 float 3;
+#A 0 0 0 0 0 0 0 0 0 0 0 -0 -6.19458e-05 -0.000494103 -0.00165937 -0.00390618
+-0.00756153 -0.0129244 -0.0202596 -0.0297923 -0.0417031 -0.0561239
+-0.0731343 -0.0927595 -0.114969 -0.139674 -0.166732 -0.195943 -0.227055
+-0.259767 -0.293732 -0.328561 -0.363831 -0.39909 -0.433862 -0.467657
+-0.499977 -0.530324 -0.558209 -0.583156 -0.604713 -0.622461 -0.636015
+-0.645036 -0.649234 -0.648374 -0.642282 -0.630843 -0.614012 -0.591808
+-0.564318 -0.531698 -0.494168 -0.452014 -0.405579 -0.355267 -0.301528
+-0.244862 -0.185805 -0.124926 -0.0628189 -9.26574e-05 0.0626345 0.124745
+0.185628 0.244691 0.301365 0.355113 0.405437 0.451883 0.494051 0.531595
+0.56423 0.591735 0.613955 0.630802 0.642256 0.648364 0.649239 0.645055
+0.636048 0.622507 0.604771 0.583224 0.558287 0.53041 0.500069 0.467754
+0.433963 0.399193 0.363935 0.328665 0.293834 0.259866 0.22715 0.196032
+0.166815 0.139751 0.115038 0.0928211 0.0731882 0.0561701 0.0417419
+0.0298239 0.0202844 0.012943 0.00757468 0.00391473 0.00166424 0.000496283
+6.24961e-05 0 0 0 0 0 0 0 0 0 0;
+#X coords 0 1 119 -1 200 140 1;
+#X restore 25 399 graph;
+#X obj 52 587 t b b;
+#X obj 123 648 f;
+#X obj 161 648 + 1;
+#X obj 52 616 until;
+#X obj 123 676 t f f;
+#X obj 46 780 tabwrite pulse;
+#X obj 50 563 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
-#X obj 508 188 osc~ 440;
-#X obj 530 214 *~ 0;
-#X obj 582 189 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+#X msg 143 570 \; pulse const 0;
+#X msg 140 620 0;
+#X obj 44 676 sel 100;
+#X obj 157 780 + 10;
+#X obj 67 712 * 0.06283;
+#X obj 615 264 metro 1000;
+#X obj 615 218 r metro-on;
+#X obj 614 243 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
-#X obj 571 211 * 0.1;
-#X obj 79 25 vdl 15 1 0 3 empty empty empty 0 -6 0 8 -262144 -1 -1
-0;
-#X msg 17 138 \; pd dsp 1;
-#X obj 634 132 *~;
-#X obj 16 113 sel 0;
-#X text 100 20 off;
-#X obj 132 142 == 1;
-#X obj 80 78 t f;
-#X text 102 36 measure latency;
-#X text 100 53 test continuity;
-#X obj 582 97 == 2;
-#X text 90 379 level out;
-#X text 182 380 level in;
-#X obj 530 244 dac~;
-#X text 292 368 latency in;
-#X text 293 384 msec;
-#X text 656 188 this flashes when;
-#X text 656 207 a discontinuity is;
-#X text 657 226 detected;
-#X obj 642 105 adc~;
-#X text 328 131 you can;
-#X text 324 147 adjust gain here;
-#X text 538 66 --- continuity check ---;
-#X text 169 105 --- latency measurement ---;
-#X text 67 420 To use this patch \, connect your audio output back
-to the audio input (channel 1 should suffice.) The latency measurement
-assumes the feedback gain is at least about -14 dB - you can increase
-the input sensitivity if need be.;
-#X text 70 491 If you select "measure latency" a series of pulses are
-timed using the "threshold~" object - note that it has an uncertainty
-of 1.45 msec (at 44K1) \, so you might see the number jitter even if
-the latency is constant.;
-#X text 70 564 Select "test continuity' to see if there are interruptions
-in the sound \, either at the input or output stage. If there are \,
-the button will flash.;
-#X obj 94 243 vline~;
-#X obj 133 279 threshold~ 0.1 5 0.05 5;
-#X connect 0 0 1 0;
+#X obj 628 326 vline~;
+#X obj 627 357 tabread4~ pulse;
+#X obj 687 31 r inchannel;
+#X obj 291 186 hip~ 20;
+#X obj 411 516 *~ 1e+10;
+#X obj 411 543 clip~ 0 1;
+#X obj 411 567 *~ 1e+10;
+#X obj 412 603 lop~ 3;
+#X obj 413 627 clip~ 0 1;
+#X msg 355 574 clear;
+#X msg 629 295 0 \, 12000 10;
+#X obj 744 359 osc~ 220;
+#X obj 744 386 *~ 0.03;
+#X obj 649 526 +~;
+#X obj 650 581 dac~ 1 2 3 4 5 6 7 8;
+#X obj 431 268 bp~ 220 0.7;
+#X obj 693 622 env~ 65536;
+#X floatatom 693 649 4 0 0 0 - - -;
+#X floatatom 749 329 5 0 0 0 - - -;
+#X obj 704 414 +~;
+#X obj 430 292 rzero~ -1;
+#X obj 431 317 rzero~ -1;
+#X obj 431 343 *~ 0.15;
+#X obj 287 316 rzero~ 1;
+#X obj 288 341 rzero~ 1;
+#X obj 45 747 expr -0.5 * (1-cos($f1)) * sin($f1);
+#X obj 288 292 bp~ 2000 0.7;
+#X obj 413 465 *~ 20;
+#X obj 629 382 *~ 0.1;
+#X obj 332 220 + 100;
+#X obj 332 245 dbtorms;
+#X obj 290 246 *~ 1;
+#X obj 160 281 env~ 65536;
+#X floatatom 160 308 4 0 0 0 - - -;
+#X obj 431 370 bonk~;
+#X obj 431 395 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 412 489 -~ 0.1;
+#X obj 414 656 -~ 1;
+#X obj 414 683 *~ -1;
+#X obj 565 747 phasor~;
+#X msg 616 714 0;
+#X obj 664 703 del 800;
+#X obj 665 728 snapshot~;
+#X floatatom 665 779 6 0 0 0 - - -;
+#X obj 666 756 * 1000;
+#X obj 87 328 s adc-db;
+#X obj 733 646 s dac-db;
+#X obj 728 774 s latency;
+#X obj 354 196 r adc-gain;
+#X msg 47 61 \; inchannel 1 \; metro-on 1 \; pd dsp 1;
+#X obj 474 397 s discontinuity;
+#X obj 496 514 *~ 1e+10;
+#X obj 496 541 clip~ 0 1;
+#X obj 496 565 *~ 1e+10;
+#X obj 497 601 lop~ 3;
+#X obj 498 625 clip~ 0 1;
+#X obj 497 487 -~ 0.1;
+#X obj 497 463 *~ 20;
+#X obj 514 709 *~;
#X connect 0 0 2 0;
-#X connect 1 0 49 0;
-#X connect 2 0 3 0;
-#X connect 3 0 49 0;
-#X connect 5 0 15 0;
-#X connect 6 0 14 0;
-#X connect 7 0 8 0;
-#X connect 9 0 10 0;
-#X connect 10 0 11 0;
-#X connect 11 0 15 1;
-#X connect 12 0 13 0;
-#X connect 15 0 12 0;
-#X connect 15 0 16 0;
-#X connect 16 0 6 1;
-#X connect 17 0 18 0;
+#X connect 0 1 3 0;
+#X connect 0 2 4 0;
+#X connect 0 3 5 0;
+#X connect 0 4 6 0;
+#X connect 0 5 7 0;
+#X connect 0 6 8 0;
+#X connect 0 7 9 0;
+#X connect 1 0 2 1;
+#X connect 2 0 40 0;
+#X connect 3 0 40 0;
+#X connect 4 0 40 0;
+#X connect 5 0 40 0;
+#X connect 6 0 40 0;
+#X connect 7 0 40 0;
+#X connect 8 0 40 0;
+#X connect 9 0 40 0;
+#X connect 10 0 3 1;
+#X connect 11 0 4 1;
+#X connect 12 0 5 1;
+#X connect 13 0 6 1;
+#X connect 14 0 7 1;
+#X connect 15 0 8 1;
+#X connect 16 0 9 1;
+#X connect 17 0 86 0;
+#X connect 18 0 19 0;
#X connect 19 0 20 0;
-#X connect 20 0 35 0;
-#X connect 20 0 35 1;
-#X connect 21 0 22 0;
-#X connect 22 0 20 1;
-#X connect 23 0 29 0;
-#X connect 25 0 17 0;
-#X connect 26 1 24 0;
-#X connect 28 0 0 0;
-#X connect 29 0 26 0;
-#X connect 29 0 28 0;
-#X connect 29 0 32 0;
-#X connect 32 0 21 0;
-#X connect 32 0 25 1;
-#X connect 41 0 25 0;
-#X connect 49 0 7 0;
-#X connect 49 0 4 0;
-#X connect 49 0 4 1;
-#X connect 49 0 50 0;
-#X connect 50 0 6 0;
+#X connect 22 0 25 0;
+#X connect 22 1 30 0;
+#X connect 22 1 29 0;
+#X connect 23 0 24 0;
+#X connect 23 0 26 0;
+#X connect 23 0 31 0;
+#X connect 24 0 23 1;
+#X connect 25 0 23 0;
+#X connect 26 0 33 0;
+#X connect 26 1 32 0;
+#X connect 28 0 22 0;
+#X connect 30 0 23 1;
+#X connect 31 0 25 1;
+#X connect 32 0 27 1;
+#X connect 33 0 62 0;
+#X connect 34 0 47 0;
+#X connect 34 0 46 0;
+#X connect 34 0 77 0;
+#X connect 34 0 78 0;
+#X connect 35 0 36 0;
+#X connect 36 0 34 0;
+#X connect 37 0 38 0;
+#X connect 38 0 65 0;
+#X connect 39 0 1 0;
+#X connect 39 0 10 0;
+#X connect 39 0 11 0;
+#X connect 39 0 12 0;
+#X connect 39 0 13 0;
+#X connect 39 0 14 0;
+#X connect 39 0 15 0;
+#X connect 39 0 16 0;
+#X connect 40 0 68 0;
+#X connect 41 0 42 0;
+#X connect 42 0 43 0;
+#X connect 43 0 44 0;
+#X connect 44 0 45 0;
+#X connect 45 0 74 0;
+#X connect 46 0 44 0;
+#X connect 47 0 37 0;
+#X connect 48 0 49 0;
+#X connect 49 0 56 1;
+#X connect 50 0 51 0;
+#X connect 50 0 51 1;
+#X connect 50 0 51 2;
+#X connect 50 0 51 3;
+#X connect 50 0 51 4;
+#X connect 50 0 51 5;
+#X connect 50 0 51 6;
+#X connect 50 0 51 7;
+#X connect 50 0 53 0;
+#X connect 52 0 57 0;
+#X connect 53 0 54 0;
+#X connect 53 0 83 0;
+#X connect 55 0 48 0;
+#X connect 56 0 50 0;
+#X connect 57 0 58 0;
+#X connect 58 0 59 0;
+#X connect 59 0 71 0;
+#X connect 60 0 61 0;
+#X connect 61 0 64 0;
+#X connect 62 0 27 0;
+#X connect 63 0 60 0;
+#X connect 64 0 73 0;
+#X connect 65 0 56 0;
+#X connect 65 0 94 0;
+#X connect 66 0 67 0;
+#X connect 67 0 68 1;
+#X connect 68 0 69 0;
+#X connect 68 0 63 0;
+#X connect 68 0 52 0;
+#X connect 69 0 70 0;
+#X connect 69 0 82 0;
+#X connect 71 0 72 0;
+#X connect 71 0 87 0;
+#X connect 73 0 41 0;
+#X connect 74 0 75 0;
+#X connect 75 0 95 0;
+#X connect 76 0 79 0;
+#X connect 77 0 76 1;
+#X connect 78 0 79 0;
+#X connect 79 0 81 0;
+#X connect 81 0 80 0;
+#X connect 81 0 84 0;
+#X connect 85 0 66 0;
+#X connect 88 0 89 0;
+#X connect 89 0 90 0;
+#X connect 90 0 91 0;
+#X connect 91 0 92 0;
+#X connect 92 0 95 1;
+#X connect 93 0 88 0;
+#X connect 94 0 93 0;
+#X connect 95 0 76 0;
+#X restore 595 387 pd guts;
+#X floatatom 242 50 4 1 8 0 inchannel inchannel-set inchannel;
+#X floatatom 626 267 6 0 0 0 - latency -;
+#X text 108 96 adjust gain here:;
+#X text 457 267 latency in milliseconds;
+#X text 571 245 THE ANSWER IS:;
+#X floatatom 528 143 4 0 0 0 - adc-db -;
+#X floatatom 527 92 4 0 0 0 - dac-db -;
+#X text 562 145 RMS amplitude in;
+#X text 564 93 RMS amplitude out;
+#X text 106 142 so that RMS amplitude in is between 60 and 70;
+#X text 108 121 (typically between -20 and 20);
+#X text 497 466 updated for Pd version 0.43;
+#X obj 228 259 bng 25 250 50 0 empty discontinuity empty 17 7 0 10
+-262144 -1 -1;
+#X text 40 235 discontinuity: this flashes if there are audio errors
+;
+#X text 67 343 To use this patch \, connect your audio output back
+to the audio input (any input and output channel from 1 to 8 \, but
+the input channel should agree wih the "inchannel" control at top).
+Then adjust gain so that "RMS amplitude in" is about 65 (anywhere from
+60 to 70 will do.) The latency is measured once per second. If there
+are interruptions in the audio the button above should flash (whether
+or not the audio system reports the error).;
diff --git a/pd/doc/7.stuff/tools/testtone.pd b/pd/doc/7.stuff/tools/testtone.pd
index 45d60e24..5ee9b5e6 100644
--- a/pd/doc/7.stuff/tools/testtone.pd
+++ b/pd/doc/7.stuff/tools/testtone.pd
@@ -1,4 +1,4 @@
-#N canvas 337 61 494 364 12;
+#N canvas 163 337 492 362 12;
#X floatatom 72 273 3 0 0 0 - - -;
#X obj 27 221 notein;
#X obj 27 247 stripnote;
@@ -121,7 +121,7 @@
#X obj 84 90 vradio 15 1 0 2 tone-type tone-type-set empty 0 -6 0 8
-262144 -1 -1 1;
#X obj 22 91 vradio 15 1 0 3 tone-radio tone-radio-set empty 0 -6 0
-8 -262144 -1 -1 1;
+8 -262144 -1 -1 0;
#X floatatom 376 93 3 0 0 0 - tone-vu7 -;
#X floatatom 404 93 3 0 0 0 - tone-vu8 -;
#X obj 375 126 tgl 20 0 tone-ch7 tone-ch7 7 5 -8 0 12 -262144 -1 -1
diff --git a/pd/doc/7.stuff/tools/z.pd b/pd/doc/7.stuff/tools/z.pd
new file mode 100644
index 00000000..0e95bd41
--- /dev/null
+++ b/pd/doc/7.stuff/tools/z.pd
@@ -0,0 +1,247 @@
+#N canvas 392 172 718 504 12;
+#X floatatom 239 98 4 0 0 0 - - adc-gain;
+#X text 317 17 latency measurement;
+#N canvas 68 36 965 906 guts 0;
+#X obj 305 67 adc~ 1 2 3 4 5 6 7 8;
+#X obj 331 134 == 1;
+#X obj 306 158 *~ 0;
+#X obj 368 160 *~ 0;
+#X obj 431 161 *~ 0;
+#X obj 493 163 *~ 0;
+#X obj 554 166 *~ 0;
+#X obj 616 168 *~ 0;
+#X obj 679 169 *~ 0;
+#X obj 741 171 *~ 0;
+#X obj 393 136 == 2;
+#X obj 456 137 == 3;
+#X obj 518 139 == 4;
+#X obj 579 142 == 5;
+#X obj 641 144 == 6;
+#X obj 704 145 == 7;
+#X obj 766 147 == 8;
+#X obj 541 323 loadbang;
+#X obj 805 237 r inchannel;
+#X msg 805 261 set \$1;
+#X obj 805 285 s inchannel-set;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array pulse 120 float 3;
+#A 0 0 0 0 0 0 0 0 0 0 0 -0 -6.19458e-05 -0.000494103 -0.00165937 -0.00390618
+-0.00756153 -0.0129244 -0.0202596 -0.0297923 -0.0417031 -0.0561239
+-0.0731343 -0.0927595 -0.114969 -0.139674 -0.166732 -0.195943 -0.227055
+-0.259767 -0.293732 -0.328561 -0.363831 -0.39909 -0.433862 -0.467657
+-0.499977 -0.530324 -0.558209 -0.583156 -0.604713 -0.622461 -0.636015
+-0.645036 -0.649234 -0.648374 -0.642282 -0.630843 -0.614012 -0.591808
+-0.564318 -0.531698 -0.494168 -0.452014 -0.405579 -0.355267 -0.301528
+-0.244862 -0.185805 -0.124926 -0.0628189 -9.26574e-05 0.0626345 0.124745
+0.185628 0.244691 0.301365 0.355113 0.405437 0.451883 0.494051 0.531595
+0.56423 0.591735 0.613955 0.630802 0.642256 0.648364 0.649239 0.645055
+0.636048 0.622507 0.604771 0.583224 0.558287 0.53041 0.500069 0.467754
+0.433963 0.399193 0.363935 0.328665 0.293834 0.259866 0.22715 0.196032
+0.166815 0.139751 0.115038 0.0928211 0.0731882 0.0561701 0.0417419
+0.0298239 0.0202844 0.012943 0.00757468 0.00391473 0.00166424 0.000496283
+6.24961e-05 0 0 0 0 0 0 0 0 0 0;
+#X coords 0 1 119 -1 200 140 1;
+#X restore 39 448 graph;
+#X obj 337 538 t b b;
+#X obj 408 599 f;
+#X obj 446 599 + 1;
+#X obj 337 567 until;
+#X obj 408 627 t f f;
+#X obj 331 731 tabwrite pulse;
+#X obj 335 514 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X msg 428 521 \; pulse const 0;
+#X msg 425 571 0;
+#X obj 329 627 sel 100;
+#X obj 442 731 + 10;
+#X obj 352 663 * 0.06283;
+#X obj 697 338 metro 1000;
+#X obj 697 292 r metro-on;
+#X obj 696 317 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 710 400 vline~;
+#X obj 709 431 tabread4~ pulse;
+#X obj 700 63 r inchannel;
+#X obj 305 235 hip~ 20;
+#X obj 675 660 *~ 1e+10;
+#X obj 675 687 clip~ 0 1;
+#X obj 675 711 *~ 1e+10;
+#X obj 676 739 lop~ 3;
+#X obj 677 763 clip~ 0 1;
+#X msg 619 718 clear;
+#X msg 711 369 0 \, 12000 10;
+#X obj 852 451 osc~ 220;
+#X obj 852 478 *~ 0.03;
+#X obj 803 633 +~;
+#X obj 804 688 dac~ 1 2 3 4 5 6 7 8;
+#X obj 411 345 bp~ 220 0.7;
+#X obj 847 729 env~ 65536;
+#X floatatom 847 756 4 0 0 0 - - -;
+#X floatatom 857 421 5 0 0 0 - - -;
+#X obj 793 523 +~;
+#X obj 410 369 rzero~ -1;
+#X obj 411 394 rzero~ -1;
+#X obj 411 420 *~ 0.15;
+#X obj 301 365 rzero~ 1;
+#X obj 302 390 rzero~ 1;
+#X obj 330 698 expr -0.5 * (1-cos($f1)) * sin($f1);
+#X obj 302 341 bp~ 2000 0.7;
+#X obj 301 415 *~ 20;
+#X obj 711 456 *~ 0.1;
+#X obj 346 269 + 100;
+#X obj 346 294 dbtorms;
+#X obj 304 295 *~ 1;
+#X obj 174 330 env~ 65536;
+#X floatatom 174 357 4 0 0 0 - - -;
+#X obj 411 447 bonk~;
+#X obj 411 472 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 676 633 -~ 0.1;
+#X obj 678 792 -~ 1;
+#X obj 681 822 *~ -1;
+#X obj 719 854 phasor~;
+#X msg 751 813 0;
+#X obj 818 810 del 800;
+#X obj 819 835 snapshot~;
+#X floatatom 819 886 6 0 0 0 - - -;
+#X obj 820 863 * 1000;
+#X obj 101 377 s adc-db;
+#X obj 887 753 s dac-db;
+#X obj 882 881 s latency;
+#X obj 368 245 r adc-gain;
+#X msg 542 350 \; inchannel 1 \; metro-on 1 \; pd dsp 1;
+#X obj 454 474 s discontinuity;
+#X connect 0 0 2 0;
+#X connect 0 1 3 0;
+#X connect 0 2 4 0;
+#X connect 0 3 5 0;
+#X connect 0 4 6 0;
+#X connect 0 5 7 0;
+#X connect 0 6 8 0;
+#X connect 0 7 9 0;
+#X connect 1 0 2 1;
+#X connect 2 0 40 0;
+#X connect 3 0 40 0;
+#X connect 4 0 40 0;
+#X connect 5 0 40 0;
+#X connect 6 0 40 0;
+#X connect 7 0 40 0;
+#X connect 8 0 40 0;
+#X connect 9 0 40 0;
+#X connect 10 0 3 1;
+#X connect 11 0 4 1;
+#X connect 12 0 5 1;
+#X connect 13 0 6 1;
+#X connect 14 0 7 1;
+#X connect 15 0 8 1;
+#X connect 16 0 9 1;
+#X connect 17 0 86 0;
+#X connect 18 0 19 0;
+#X connect 19 0 20 0;
+#X connect 22 0 25 0;
+#X connect 22 1 30 0;
+#X connect 22 1 29 0;
+#X connect 23 0 24 0;
+#X connect 23 0 26 0;
+#X connect 23 0 31 0;
+#X connect 24 0 23 1;
+#X connect 25 0 23 0;
+#X connect 26 0 33 0;
+#X connect 26 1 32 0;
+#X connect 28 0 22 0;
+#X connect 30 0 23 1;
+#X connect 31 0 25 1;
+#X connect 32 0 27 1;
+#X connect 33 0 62 0;
+#X connect 34 0 47 0;
+#X connect 34 0 46 0;
+#X connect 34 0 77 0;
+#X connect 34 0 78 0;
+#X connect 35 0 36 0;
+#X connect 36 0 34 0;
+#X connect 37 0 38 0;
+#X connect 38 0 65 0;
+#X connect 39 0 1 0;
+#X connect 39 0 10 0;
+#X connect 39 0 11 0;
+#X connect 39 0 12 0;
+#X connect 39 0 13 0;
+#X connect 39 0 14 0;
+#X connect 39 0 15 0;
+#X connect 39 0 16 0;
+#X connect 40 0 68 0;
+#X connect 41 0 42 0;
+#X connect 42 0 43 0;
+#X connect 43 0 44 0;
+#X connect 44 0 45 0;
+#X connect 45 0 74 0;
+#X connect 46 0 44 0;
+#X connect 47 0 37 0;
+#X connect 48 0 49 0;
+#X connect 49 0 56 1;
+#X connect 50 0 51 0;
+#X connect 50 0 51 1;
+#X connect 50 0 51 2;
+#X connect 50 0 51 3;
+#X connect 50 0 51 4;
+#X connect 50 0 51 5;
+#X connect 50 0 51 6;
+#X connect 50 0 51 7;
+#X connect 50 0 53 0;
+#X connect 52 0 57 0;
+#X connect 53 0 54 0;
+#X connect 53 0 83 0;
+#X connect 55 0 48 0;
+#X connect 56 0 50 0;
+#X connect 57 0 58 0;
+#X connect 58 0 59 0;
+#X connect 59 0 71 0;
+#X connect 60 0 61 0;
+#X connect 61 0 64 0;
+#X connect 62 0 27 0;
+#X connect 63 0 60 0;
+#X connect 64 0 73 0;
+#X connect 65 0 56 0;
+#X connect 66 0 67 0;
+#X connect 67 0 68 1;
+#X connect 68 0 69 0;
+#X connect 68 0 63 0;
+#X connect 68 0 52 0;
+#X connect 69 0 70 0;
+#X connect 69 0 82 0;
+#X connect 71 0 72 0;
+#X connect 71 0 87 0;
+#X connect 73 0 41 0;
+#X connect 74 0 75 0;
+#X connect 75 0 76 0;
+#X connect 76 0 79 0;
+#X connect 77 0 76 1;
+#X connect 78 0 79 0;
+#X connect 79 0 81 0;
+#X connect 81 0 80 0;
+#X connect 81 0 84 0;
+#X connect 85 0 66 0;
+#X restore 595 387 pd guts;
+#X floatatom 242 50 4 1 8 0 inchannel inchannel-set inchannel;
+#X floatatom 626 267 6 0 0 0 - latency -;
+#X text 108 96 adjust gain here:;
+#X text 457 267 latency in milliseconds;
+#X text 571 245 THE ANSWER IS:;
+#X floatatom 528 143 4 0 0 0 - adc-db -;
+#X floatatom 527 92 4 0 0 0 - dac-db -;
+#X text 562 145 RMS amplitude in;
+#X text 564 93 RMS amplitude out;
+#X text 106 142 so that RMS amplitude in is between 60 and 70;
+#X text 108 121 (typically between -20 and 20);
+#X text 497 466 updated for Pd version 0.43;
+#X obj 228 259 bng 25 250 50 0 empty discontinuity empty 17 7 0 10
+-262144 -1 -1;
+#X text 40 235 discontinuity: this flashes if there are audio errors
+;
+#X text 67 343 To use this patch \, connect your audio output back
+to the audio input (any input and output channel from 1 to 8 \, but
+the input channel should agree wih the "inchannel" control at top).
+Then adjust gain so that "RMS amplitude in" is about 65 (anywhere from
+60 to 70 will do.) The latency is measured once per second. If there
+are interruptions in the audio the button above should flash (whether
+or not the audio system reports the error).;
diff --git a/pd/extra/Makefile.am b/pd/extra/Makefile.am
new file mode 100644
index 00000000..766073d4
--- /dev/null
+++ b/pd/extra/Makefile.am
@@ -0,0 +1,10 @@
+SUBDIRS=bonk~ choice expr~ fiddle~ loop~ lrshift~ pd~ pique sigmund~ stdout
+
+DIST_SUBDIRS=$(SUBDIRS)
+
+PATCHES =complex-mod~.pd hilbert~.pd rev1-final.pd rev1~.pd rev1-stage.pd rev2~.pd rev3~.pd
+HELPPATCHES=complex-mod~-help.pd hilbert~-help.pd rev1~-help.pd rev2~-help.pd rev3~-help.pd
+
+libpdextradir = $(pkglibdir)/extra
+
+dist_libpdextra_DATA = $(PATCHES) $(HELPPATCHES)
diff --git a/pd/extra/bonk~/GNUmakefile.am b/pd/extra/bonk~/GNUmakefile.am
new file mode 100644
index 00000000..fb9c2ce8
--- /dev/null
+++ b/pd/extra/bonk~/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=bonk~
+
+external_LTLIBRARIES = bonk~.la
+SOURCES = bonk~.c
+PATCHES = bonk~-help.pd
+OTHERDATA = templates.txt
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/bonk~/bonk~-help.pd b/pd/extra/bonk~/bonk~-help.pd
index e52b7c50..4666d6f5 100644
--- a/pd/extra/bonk~/bonk~-help.pd
+++ b/pd/extra/bonk~/bonk~-help.pd
@@ -1,4 +1,4 @@
-#N canvas 43 123 1054 583 12;
+#N canvas 0 0 1052 581 12;
#X obj 382 492 spigot;
#X msg 484 293 bang;
#X obj 483 454 bonk~;
@@ -107,7 +107,7 @@ Bonk check the attack against a collection of stored templates to try
to guess which of two or more instruments was hit. Bonk is described
theoretically in the 1998 ICMC proceedings \, reprinted on crca.ucsd.edu/~msp
.;
-#N canvas 723 241 701 719 creation-arguments 0;
+#N canvas 0 0 699 717 creation-arguments 1;
#X text 228 14 creation arguments for bonk~;
#X text 70 272 -npts 256;
#X text 44 244 default value:;
diff --git a/pd/extra/bonk~/bonk~.c b/pd/extra/bonk~/bonk~.c
index d0f18de9..7aaf48da 100644
--- a/pd/extra/bonk~/bonk~.c
+++ b/pd/extra/bonk~/bonk~.c
@@ -82,7 +82,9 @@ void *bonk_class;
static t_class *bonk_class;
#endif
-#ifndef _MSC_VER
+#ifdef _WIN32
+#include <malloc.h>
+#elif ! defined(_MSC_VER)
#include <alloca.h>
#endif
@@ -221,6 +223,8 @@ typedef struct _bonk
double x_learndebounce; /* debounce time (in "learn" mode only) */
int x_attackbins; /* number of bins to wait for attack */
+ t_canvas *x_canvas; /* ptr to current canvas --fbar */
+
t_filterbank *x_filterbank;
t_hist x_hist[MAXNFILTERS];
t_template *x_template;
@@ -962,11 +966,18 @@ static void bonk_bang(t_bonk *x)
static void bonk_read(t_bonk *x, t_symbol *s)
{
- FILE *fd = fopen(s->s_name, "r");
float vec[MAXNFILTERS];
int i, ntemplate = 0, remaining;
float *fp, *fp2;
- if (!fd)
+
+ /* fbar: canvas_open code taken from g_array.c */
+ FILE *fd;
+ char buf[MAXPDSTRING], *bufptr;
+ int filedesc;
+
+ if ((filedesc = canvas_open(x->x_canvas,
+ s->s_name, "", buf, &bufptr, MAXPDSTRING, 0)) < 0
+ || !(fd = fdopen(filedesc, "r")))
{
post("%s: open failed", s->s_name);
return;
@@ -1001,11 +1012,18 @@ nomore:
static void bonk_write(t_bonk *x, t_symbol *s)
{
- FILE *fd = fopen(s->s_name, "w");
+ FILE *fd;
+ char buf[MAXPDSTRING]; /* fbar */
int i, ntemplate = x->x_ntemplate;
t_template *tp = x->x_template;
float *fp;
- if (!fd)
+
+ /* fbar: canvas-code as in g_array.c */
+ canvas_makefilename(x->x_canvas, s->s_name,
+ buf, MAXPDSTRING);
+ sys_bashfilename(buf, buf);
+
+ if (!(fd = fopen(buf, "w")))
{
post("%s: couldn't create", s->s_name);
return;
@@ -1048,6 +1066,7 @@ static void *bonk_new(t_symbol *s, int argc, t_atom *argv)
firstbin = DEFFIRSTBIN, minbandwidth = DEFMINBANDWIDTH;
t_insig *g;
+ x->x_canvas = canvas_getcurrent(); /* fbar: bind current canvas to x */
if (argc > 0 && argv[0].a_type == A_FLOAT)
{
/* old style args for compatibility */
diff --git a/pd/extra/bonk~/makefile b/pd/extra/bonk~/makefile
index af6399cc..7d56ed4d 100644
--- a/pd/extra/bonk~/makefile
+++ b/pd/extra/bonk~/makefile
@@ -1,4 +1,4 @@
NAME=bonk~
CSYM=bonk_tilde
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/choice/GNUmakefile.am b/pd/extra/choice/GNUmakefile.am
new file mode 100644
index 00000000..5ed60350
--- /dev/null
+++ b/pd/extra/choice/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=choice
+
+external_LTLIBRARIES = choice.la
+SOURCES = choice.c
+PATCHES = choice-help.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/choice/choice.c b/pd/extra/choice/choice.c
index b7bf23ab..a50c66ac 100644
--- a/pd/extra/choice/choice.c
+++ b/pd/extra/choice/choice.c
@@ -18,7 +18,7 @@ static t_class *choice_class;
typedef struct _elem
{
float e_age;
- float e_weight[DIMENSION];
+ t_float e_weight[DIMENSION];
} t_elem;
typedef struct _choice
diff --git a/pd/extra/choice/makefile b/pd/extra/choice/makefile
index 7fc71159..ee63e8fd 100644
--- a/pd/extra/choice/makefile
+++ b/pd/extra/choice/makefile
@@ -1,4 +1,4 @@
NAME=choice
CSYM=choice
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/expr~/GNUmakefile.am b/pd/extra/expr~/GNUmakefile.am
new file mode 100644
index 00000000..a9074b92
--- /dev/null
+++ b/pd/extra/expr~/GNUmakefile.am
@@ -0,0 +1,50 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+NAME=expr~
+
+external_LTLIBRARIES = expr~.la
+expr__la_SOURCES = vexp.c vexp_fun.c vexp_if.c
+PATCHES = ../expr-help.pd
+OTHERDATA = LICENSE.txt README.txt
+
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+noinst_HEADERS = fts_to_pd.h vexp.h
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+# install-exec-hook seems to be called before $(DESTDIR)$(externaldir) is created...
+# so we install everything in the install-data-hook
+install-data-hook:
+ cd $(DESTDIR)$(externaldir) && ( \
+ $(LN_S) expr~.@EXTERNAL_EXTENSION@ expr.@EXTERNAL_EXTENSION@; \
+ $(LN_S) expr~.@EXTERNAL_EXTENSION@ fexpr~.@EXTERNAL_EXTENSION@; \
+ cd ..; \
+ $(LN_S) $(NAME)/expr.@EXTERNAL_EXTENSION@ expr.@EXTERNAL_EXTENSION@; \
+ $(LN_S) $(NAME)/expr~.@EXTERNAL_EXTENSION@ expr~.@EXTERNAL_EXTENSION@; \
+ $(LN_S) $(NAME)/fexpr~.@EXTERNAL_EXTENSION@ fexpr~.@EXTERNAL_EXTENSION@; \
+ $(LN_S) $(NAME)/expr-help.pd expr-help.pd; \
+ $(LN_S) $(NAME)/expr-help.pd expr~-help.pd; \
+ $(LN_S) $(NAME)/expr-help.pd fexpr~-help.pd; \
+ )
+
+uninstall-hook:
+ cd $(DESTDIR)$(externaldir) && ( \
+ rm -f expr.@EXTERNAL_EXTENSION@ fexpr~.@EXTERNAL_EXTENSION@; \
+ cd ..; \
+ rm -f expr~.@EXTERNAL_EXTENSION@ expr.@EXTERNAL_EXTENSION@ fexpr~.@EXTERNAL_EXTENSION@; \
+ rm -f expr-help.pd expr~-help.pd fexpr~-help.pd; \
+ )
+
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/expr~/makefile b/pd/extra/expr~/makefile
index 4c648140..5dee147a 100644
--- a/pd/extra/expr~/makefile
+++ b/pd/extra/expr~/makefile
@@ -6,7 +6,7 @@ install: install_linux
clean: clean_linux
-PDEXTERN=/usr/local/lib/pd/externs
+PDEXTERN=/usr/local/lib/pd/extra
# ----------------------- NT -----------------------
@@ -89,7 +89,6 @@ LINUXINCLUDE = -I../../src
expr.pd_linux: $(LINUXOBJ)
$(CC) -shared -o expr.pd_linux $(LINUXOBJ) -lc -lm
- strip --strip-unneeded expr.pd_linux
expr~.pd_linux: expr.pd_linux
-ln -s expr.pd_linux expr~.pd_linux
@@ -110,12 +109,11 @@ install_linux:
install expr.pd_linux $(PDEXTERN)
rm -f $(PDEXTERN)/expr~.pd_linux
rm -f $(PDEXTERN)/fexpr~.pd_linux
- cd $(PDEXTERN); \
- -ln -s expr.pd_linux expr~.pd_linux
- -ln -s expr.pd_linux fexpr~.pd_linux
+ cd $(PDEXTERN); ln -s expr.pd_linux expr~.pd_linux
+ cd $(PDEXTERN); ln -s expr.pd_linux fexpr~.pd_linux
-linux_clean:
+clean_linux:
rm -f *.pd_linux_o *.o
# ----------------------- MAC OSX -----------------------
diff --git a/pd/extra/expr~/vexp_if.c b/pd/extra/expr~/vexp_if.c
index 648aba73..aaaf4ef3 100644
--- a/pd/extra/expr~/vexp_if.c
+++ b/pd/extra/expr~/vexp_if.c
@@ -381,7 +381,7 @@ SDY the following coredumps why?
post("expr: internal error expr_new");
default:
pd_error(x, "expr: bad type (%lx) inlet = %d\n",
- eptr->ex_type, i + 1, 0, 0, 0);
+ eptr->ex_type, i + 1);
break;
}
}
@@ -955,7 +955,7 @@ if (!sym || !(garray = (t_garray *)pd_findbyclass(sym, garray_class)) || \
!garray_getfloatwords(garray, &size, &vec)) { \
optr->ex_type = ET_FLT; \
optr->ex_int = 0; \
- error("no such table '%s'", sym->s_name); \
+ error("no such table '%s'", sym?(sym->s_name):"(null)"); \
return; \
}
diff --git a/pd/extra/fiddle~/GNUmakefile.am b/pd/extra/fiddle~/GNUmakefile.am
new file mode 100644
index 00000000..a45338fd
--- /dev/null
+++ b/pd/extra/fiddle~/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=fiddle~
+
+external_LTLIBRARIES = fiddle~.la
+SOURCES = fiddle~.c
+PATCHES = fiddle~-help.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/fiddle~/makefile b/pd/extra/fiddle~/makefile
index 247c905e..0820a838 100644
--- a/pd/extra/fiddle~/makefile
+++ b/pd/extra/fiddle~/makefile
@@ -1,4 +1,4 @@
NAME=fiddle~
CSYM=fiddle_tilde
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/loop~/GNUmakefile.am b/pd/extra/loop~/GNUmakefile.am
new file mode 100644
index 00000000..fce3b2fc
--- /dev/null
+++ b/pd/extra/loop~/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=loop~
+
+external_LTLIBRARIES = loop~.la
+SOURCES = loop~.c
+PATCHES = loop~-help.pd test-loop~.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/loop~/loop~-help.pd b/pd/extra/loop~/loop~-help.pd
index a445b805..ff3d3a63 100644
--- a/pd/extra/loop~/loop~-help.pd
+++ b/pd/extra/loop~/loop~-help.pd
@@ -1,4 +1,4 @@
-#N canvas 33 0 647 662 12;
+#N canvas 234 90 647 662 12;
#X floatatom 41 204 0 0 0 0 - - -;
#X obj 254 382 print~;
#X msg 254 347 bang;
@@ -7,7 +7,7 @@
#X msg 55 252 bang;
#X obj 183 382 print~;
#X msg 183 347 bang;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 0 0 450 300 (subpatch) 0;
#X array array2 150000 float 0;
#X coords 0 1 150000 -1 200 150 1;
#X restore 393 464 graph;
@@ -22,7 +22,6 @@
#X floatatom 96 303 0 0 0 0 - - -;
#X obj 96 326 *~ 1000;
#X msg 43 568 read ../doc/sound/bell.aiff array2;
-#X msg 43 591 read ../doc/sound/vocal.aiff array2;
#X msg 47 229 set 0.5;
#X text 95 196 left signal input is transposition (1 is normal \, 2
is up an octave \, etc);
@@ -46,6 +45,7 @@ that changing window size doesn't change the transposition.;
to zero--you should mute the output before doing so. This may be desirable
if you've set a large window size but then want to decrease it without
waiting for the next phase crossing.;
+#X msg 43 591 read ../doc/sound/voice.wav array2;
#X connect 0 0 3 0;
#X connect 2 0 1 0;
#X connect 3 0 6 0;
@@ -56,7 +56,7 @@ waiting for the next phase crossing.;
#X connect 4 0 3 1;
#X connect 5 0 3 0;
#X connect 7 0 6 0;
-#X connect 11 0 28 0;
+#X connect 11 0 27 0;
#X connect 12 0 16 0;
#X connect 14 0 13 0;
#X connect 14 0 13 1;
@@ -65,10 +65,10 @@ waiting for the next phase crossing.;
#X connect 17 0 18 0;
#X connect 18 0 15 0;
#X connect 19 0 10 0;
-#X connect 20 0 10 0;
-#X connect 21 0 3 0;
-#X connect 28 0 14 0;
-#X connect 29 0 31 0;
-#X connect 30 0 28 1;
-#X connect 31 0 32 0;
-#X connect 32 0 30 0;
+#X connect 20 0 3 0;
+#X connect 27 0 14 0;
+#X connect 28 0 30 0;
+#X connect 29 0 27 1;
+#X connect 30 0 31 0;
+#X connect 31 0 29 0;
+#X connect 36 0 10 0;
diff --git a/pd/extra/loop~/loop~.c b/pd/extra/loop~/loop~.c
index 2f440030..2fc3193e 100644
--- a/pd/extra/loop~/loop~.c
+++ b/pd/extra/loop~/loop~.c
@@ -13,20 +13,24 @@ This file is downloadable from http://www.crca.ucsd.edu/~msp .
#ifdef PD
#include "m_pd.h"
+#else
+#define t_sample float
#endif
+
+
typedef struct _loopctl
{
double l_phase;
- float l_invwindow;
- float l_window;
+ t_sample l_invwindow;
+ t_sample l_window;
int l_resync;
} t_loopctl;
-static void loopctl_run(t_loopctl *x, float *transposein,
- float *windowin, float *rawout, float *windowout, int n)
+static void loopctl_run(t_loopctl *x, t_sample *transposein,
+ t_sample *windowin, t_sample *rawout, t_sample *windowout, int n)
{
- float window, invwindow;
+ t_sample window, invwindow;
double phase = x->l_phase;
if (x->l_resync)
{
@@ -55,7 +59,7 @@ static void loopctl_run(t_loopctl *x, float *transposein,
{
double phaseinc = invwindow * *transposein++;
double newphase;
- float nwind = *windowin++;
+ t_sample nwind = *windowin++;
if (phaseinc >= 1 || phaseinc < 0)
phaseinc = 0;
newphase = phase + phaseinc;
@@ -77,7 +81,7 @@ static void loopctl_run(t_loopctl *x, float *transposein,
newphase -= 1.;
}
phase = newphase;
- *rawout++ = (float)phase;
+ *rawout++ = (t_sample)phase;
*windowout++ = window;
}
x->l_invwindow = invwindow;
@@ -124,10 +128,10 @@ static void *loop_new(void)
static t_int *loop_perform(t_int *w)
{
t_loopctl *ctl = (t_loopctl *)(w[1]);
- t_float *in1 = (t_float *)(w[2]);
- t_float *in2 = (t_float *)(w[3]);
- t_float *out1 = (t_float *)(w[4]);
- t_float *out2 = (t_float *)(w[5]);
+ t_sample *in1 = (t_sample *)(w[2]);
+ t_sample *in2 = (t_sample *)(w[3]);
+ t_sample *out1 = (t_sample *)(w[4]);
+ t_sample *out2 = (t_sample *)(w[5]);
int n = (int)(w[6]);
loopctl_run(ctl, in1, in2, out1, out2, n);
return (w+7);
diff --git a/pd/extra/loop~/makefile b/pd/extra/loop~/makefile
index fd21f2b4..dc367b20 100644
--- a/pd/extra/loop~/makefile
+++ b/pd/extra/loop~/makefile
@@ -1,4 +1,4 @@
NAME=loop~
CSYM=loop_tilde
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/lrshift~/GNUmakefile.am b/pd/extra/lrshift~/GNUmakefile.am
new file mode 100644
index 00000000..4023a70e
--- /dev/null
+++ b/pd/extra/lrshift~/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=lrshift~
+
+external_LTLIBRARIES = lrshift~.la
+SOURCES = lrshift~.c
+PATCHES = lrshift~-help.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/lrshift~/lrshift~.c b/pd/extra/lrshift~/lrshift~.c
index 166facc1..b3c90ff6 100644
--- a/pd/extra/lrshift~/lrshift~.c
+++ b/pd/extra/lrshift~/lrshift~.c
@@ -13,8 +13,8 @@ typedef struct _lrshift_tilde
static t_int *leftshift_perform(t_int *w)
{
- t_float *in = (t_float *)(w[1]);
- t_float *out= (t_float *)(w[2]);
+ t_sample *in = (t_sample *)(w[1]);
+ t_sample *out= (t_sample *)(w[2]);
int n = (int)(w[3]);
int shift = (int)(w[4]);
in += shift;
@@ -28,8 +28,8 @@ static t_int *leftshift_perform(t_int *w)
static t_int *rightshift_perform(t_int *w)
{
- t_float *in = (t_float *)(w[1]);
- t_float *out= (t_float *)(w[2]);
+ t_sample *in = (t_sample *)(w[1]);
+ t_sample *out= (t_sample *)(w[2]);
int n = (int)(w[3]);
int shift = (int)(w[4]);
n -= shift;
diff --git a/pd/extra/lrshift~/makefile b/pd/extra/lrshift~/makefile
index d6a24cfe..cbd9e8a0 100644
--- a/pd/extra/lrshift~/makefile
+++ b/pd/extra/lrshift~/makefile
@@ -1,4 +1,4 @@
NAME=lrshift~
CSYM=lrshift_tilde
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/makefile b/pd/extra/makefile.subdir
index ee028616..9dfadc41 100644
--- a/pd/extra/makefile
+++ b/pd/extra/makefile.subdir
@@ -1,3 +1,9 @@
+# this is the UNIX-style complicated layout dir, simple goes to $(prefix)/po
+prefix = /usr/local
+libpddir = $(prefix)/lib/pd
+
+.PHONY:
+
current: pd_linux
# ----------------------- NT -----------------------
@@ -6,7 +12,8 @@ pd_nt: $(NAME).dll
.SUFFIXES: .dll
-PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo -D_CRT_SECURE_NO_WARNINGS
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo -D_CRT_SECURE_NO_WARNINGS \
+ -D_CRT_NONSTDC_NO_DEPRECATE
# VC="C:\Program Files\Microsoft Visual Studio\Vc98"
VC = "C:\Program Files\Microsoft Visual Studio 9.0\VC"
VSTK = "C:\Program Files\Microsoft SDKs\Windows\v6.0A"
@@ -38,7 +45,6 @@ LINUXINCLUDE = -I../../src
.c.pd_linux:
$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
$(CC) -shared -o $*.pd_linux $*.o -lc -lm
- strip --strip-unneeded $*.pd_linux
rm -f $*.o
# ----------------------- Mac OSX -----------------------
@@ -64,5 +70,13 @@ DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
# ----------------------------------------------------------
-clean:
- rm -f *.o *.pd_* so_locations
+distclean clean: clean-externals
+ rm -f *.o *.pd_* *.l_* *.d_* *.m_* so_locations
+
+# ----------------------------------------------------------
+# ----------------------------------------------------------
+
+install:
+ install -d $(DESTDIR)$(libpddir)/extra/$(NAME)
+ install -m644 -p *.*_* $(DESTDIR)$(libpddir)/extra/$(NAME)
+ install -m644 -p *.pd $(DESTDIR)$(libpddir)/extra/$(NAME)
diff --git a/pd/extra/pd~/GNUmakefile.am b/pd/extra/pd~/GNUmakefile.am
new file mode 100644
index 00000000..6110c88c
--- /dev/null
+++ b/pd/extra/pd~/GNUmakefile.am
@@ -0,0 +1,31 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=pd~
+
+PATCHES = pd~-help.pd pd~-subprocess.pd
+OTHERDATA =
+
+pd__la_SOURCES = pd~.c
+pdsched_la_SOURCES = pdsched.c
+
+external_LTLIBRARIES = pd~.la pdsched.la
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+
+
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/pd~/makefile b/pd/extra/pd~/makefile
index d069c73d..5fc5d26b 100644
--- a/pd/extra/pd~/makefile
+++ b/pd/extra/pd~/makefile
@@ -1,7 +1,7 @@
NAME=pd~
CSYM=pd_tilde
-include ../makefile
+include ../makefile.subdir
pd_linux: pdsched.pd_linux
@@ -11,5 +11,4 @@ d_ppc: pdsched.d_ppc
pdsched.pd_linux: pdsched.c
$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
$(CC) -shared -o $*.pd_linux $*.o -lc -lm
- strip --strip-unneeded $*.pd_linux
rm -f $*.o
diff --git a/pd/extra/pd~/pdsched.c b/pd/extra/pd~/pdsched.c
index 7efe49a9..6c6060c1 100644
--- a/pd/extra/pd~/pdsched.c
+++ b/pd/extra/pd~/pdsched.c
@@ -17,15 +17,33 @@ outputs audio and messages. */
#define BUFSIZE 65536
static char inbuf[BUFSIZE];
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+void glob_watchdog(t_pd *dummy);
+
+static void pollwatchdog( void)
+{
+ static int sched_diddsp, sched_nextpingtime;
+ sched_diddsp++;
+ 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
+
int pd_extern_sched(char *flags)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int i, j, rate, advance, callback, chin, chout, fill = 0, c;
+ int i, j, rate, advance, callback, chin, chout, fill = 0, c, blocksize;
t_binbuf *b = binbuf_new();
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
chin = (naudioindev < 1 ? 0 : chindev[0]);
chout = (naudiooutdev < 1 ? 0 : choutdev[0]);
@@ -57,6 +75,9 @@ int pd_extern_sched(char *flags)
*fp++ = 0;
sched_tick(sys_time+sys_time_per_dsp_tick);
sys_pollgui();
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+ pollwatchdog();
+#endif
printf(";\n");
for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++)
{
diff --git a/pd/extra/pd~/pd~.c b/pd/extra/pd~/pd~.c
index 165065f8..dc2eca4c 100644
--- a/pd/extra/pd~/pd~.c
+++ b/pd/extra/pd~/pd~.c
@@ -15,7 +15,7 @@
#include <sys/stat.h>
#include <sys/wait.h>
-#ifdef NT
+#ifdef _MSC_VER
#pragma warning (disable: 4305 4244)
#endif
@@ -47,7 +47,7 @@ char *class_gethelpdir(t_class *c);
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#ifdef __x86_64__
static char pd_tilde_dllextent[] = ".l_ia64",
pd_tilde_dllextent2[] = ".pd_linux";
@@ -60,6 +60,9 @@ static char pd_tilde_dllextent[] = ".l_i386",
static char pd_tilde_dllextent[] = ".d_fat",
pd_tilde_dllextent2[] = ".pd_darwin";
#endif
+#if defined(_WIN32) || defined(__CYGWIN__)
+static char pd_tilde_dllextent[] = ".m_i386", pd_tilde_dllextent2[] = ".dll";
+#endif
/* ------------------------ pd_tilde~ ----------------------------- */
@@ -512,7 +515,7 @@ static void *pd_tilde_new(t_symbol *s, int argc, t_atom *argv)
int ninsig = 2, noutsig = 2, j, fifo = 5;
float sr = sys_getsr();
t_sample **g;
- t_symbol *pddir = sys_guidir,
+ t_symbol *pddir = sys_libdir,
*scheddir = gensym(class_gethelpdir(pd_tilde_class));
/* fprintf(stderr, "pd %s, sched %s\n", pddir->s_name, scheddir->s_name); */
while (argc > 0)
diff --git a/pd/extra/pique/GNUmakefile.am b/pd/extra/pique/GNUmakefile.am
new file mode 100644
index 00000000..61ce1715
--- /dev/null
+++ b/pd/extra/pique/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=pique
+
+external_LTLIBRARIES = pique.la
+SOURCES = pique.c
+PATCHES = pique-help.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/pique/makefile b/pd/extra/pique/makefile
index 562ce23b..ebcbd93a 100644
--- a/pd/extra/pique/makefile
+++ b/pd/extra/pique/makefile
@@ -1,4 +1,4 @@
NAME=pique
CSYM=pique
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/pique/pique.c b/pd/extra/pique/pique.c
index a53ad765..19cee2ae 100644
--- a/pd/extra/pique/pique.c
+++ b/pd/extra/pique/pique.c
@@ -51,7 +51,7 @@ static float hanning(float pidetune, float sinpidetune)
(sinpidetune/(pidetune+pi) + sinpidetune/(pidetune-pi)));
}
-static float peakerror(float *fpreal, float *fpimag, float pidetune,
+static float peakerror(t_word *fpreal, t_word *fpimag, float pidetune,
float norm, float peakreal, float peakimag)
{
float sinpidetune = sin(pidetune);
@@ -61,8 +61,10 @@ static float peakerror(float *fpreal, float *fpimag, float pidetune,
peakreal * cospidetune + peakimag * sinpidetune);
float imagshould = windowshould * (
peakimag * cospidetune - peakreal * sinpidetune);
- float realgot = norm * (fpreal[0] - 0.5 * (fpreal[1] + fpreal[-1]));
- float imaggot = norm * (fpimag[0] - 0.5 * (fpimag[1] + fpimag[-1]));
+ float realgot = norm * (fpreal[0].w_float -
+ 0.5 * (fpreal[1].w_float + fpreal[-1].w_float));
+ float imaggot = norm * (fpimag[0].w_float -
+ 0.5 * (fpimag[1].w_float + fpimag[-1].w_float));
float realdev = realshould - realgot, imagdev = imagshould - imaggot;
/* post("real %f->%f; imag %f->%f", realshould, realgot,
@@ -70,7 +72,7 @@ static float peakerror(float *fpreal, float *fpimag, float pidetune,
return (realdev * realdev + imagdev * imagdev);
}
-static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
+static void pique_doit(int npts, t_word *fpreal, t_word *fpimag,
int npeak, int *nfound, t_float *fpfreq, t_float *fpamp,
t_float *fpampre, t_float *fpampim, float errthresh)
{
@@ -78,13 +80,15 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
float oneovern = 1.0/ (float)npts;
float fperbin = srate * oneovern;
float pow1, pow2 = 0, pow3 = 0, pow4 = 0, pow5 = 0;
- float re1, re2 = 0, re3 = *fpreal;
+ float re1, re2 = 0, re3 = fpreal->w_float;
float im1, im2 = 0, im3 = 0, powthresh, relativeerror;
int count, peakcount = 0, n2 = (npts >> 1);
float *fp1, *fp2;
- for (count = n2, fp1 = fpreal, fp2 = fpimag, powthresh = 0;
- count--; fp1++, fp2++)
- powthresh += (*fp1) * (*fp1) + (*fp2) * (*fp2) ;
+ t_word *wp1, *wp2;
+ for (count = n2, wp1 = fpreal, wp2 = fpimag, powthresh = 0;
+ count--; wp1++, wp2++)
+ powthresh += (wp1->w_float) * (wp1->w_float) +
+ (wp2->w_float) * (wp2->w_float) ;
powthresh *= 0.00001;
for (count = 1; count < n2; count++)
{
@@ -98,10 +102,10 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
fpimag++;
re1 = re2;
re2 = re3;
- re3 = *fpreal;
+ re3 = fpreal->w_float;
im1 = im2;
im2 = im3;
- im3 = *fpimag;
+ im3 = fpimag->w_float;
if (count < 2) continue;
pow1 = pow2;
pow2 = pow3;
@@ -118,12 +122,12 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
|| pow3 < powthresh)
continue;
/* go back for the raw FFT values around the peak. */
- rpeak = fpreal[-3];
- rpeaknext = fpreal[-2];
- rpeakprev = fpreal[-4];
- ipeak = fpimag[-3];
- ipeaknext = fpimag[-2];
- ipeakprev = fpimag[-4];
+ rpeak = fpreal[-3].w_float;
+ rpeaknext = fpreal[-2].w_float;
+ rpeakprev = fpreal[-4].w_float;
+ ipeak = fpimag[-3].w_float;
+ ipeaknext = fpimag[-2].w_float;
+ ipeakprev = fpimag[-4].w_float;
/* recalculate Hanning-windowed spectrum by convolution */
windreal = rpeak - 0.5 * (rpeaknext + rpeakprev);
windimag = ipeak - 0.5 * (ipeaknext + ipeakprev);
@@ -180,15 +184,15 @@ static void pique_list(t_pique *x, t_symbol *s, int argc, t_atom *argv)
int npeak = atom_getintarg(3, argc, argv);
int n;
t_garray *a;
- t_float *fpreal, *fpimag;
+ t_word *fpreal, *fpimag;
if (npts < 8 || npeak < 1) error("pique: bad npoints or npeak");
if (npeak > x->x_n) npeak = x->x_n;
if (!(a = (t_garray *)pd_findbyclass(symreal, garray_class)) ||
- !garray_getfloatarray(a, &n, &fpreal) ||
+ !garray_getfloatwords(a, &n, &fpreal) ||
n < npts)
error("%s: missing or bad array", symreal->s_name);
else if (!(a = (t_garray *)pd_findbyclass(symimag, garray_class)) ||
- !garray_getfloatarray(a, &n, &fpimag) ||
+ !garray_getfloatwords(a, &n, &fpimag) ||
n < npts)
error("%s: missing or bad array", symimag->s_name);
else
diff --git a/pd/extra/sigmund~/GNUmakefile.am b/pd/extra/sigmund~/GNUmakefile.am
new file mode 100644
index 00000000..840e087b
--- /dev/null
+++ b/pd/extra/sigmund~/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=sigmund~
+
+external_LTLIBRARIES = sigmund~.la
+SOURCES = sigmund~.c
+PATCHES = sigmund~-help.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/sigmund~/makefile b/pd/extra/sigmund~/makefile
index 3dc176b3..3c2f8f1c 100644
--- a/pd/extra/sigmund~/makefile
+++ b/pd/extra/sigmund~/makefile
@@ -1,4 +1,4 @@
NAME=sigmund~
CSYM=sigmund_tilde
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/extra/sigmund~/sigmund~.c b/pd/extra/sigmund~/sigmund~.c
index 92604b7e..968c5c63 100644
--- a/pd/extra/sigmund~/sigmund~.c
+++ b/pd/extra/sigmund~/sigmund~.c
@@ -13,7 +13,7 @@
and usable in other contexts. The one external requirement is a real
single-precision FFT, invoked as in the Mayer one: */
-#ifdef NT
+#ifdef _MSC_VER /* this is only needed with Microsoft's compiler */
__declspec(dllimport) extern
#endif
void mayer_realfft(int npoints, float *buf);
@@ -28,7 +28,7 @@ for example, defines this in the file d_fft_mayer.c or d_fft_fftsg.c. */
#include <string.h>
#ifdef _WIN32
#include <malloc.h>
-#else
+#elif ! defined(_MSC_VER)
#include <alloca.h>
#endif
#include <stdlib.h>
@@ -230,9 +230,12 @@ static void sigmund_remask(int maxbin, int bestindex, float powmask,
}
}
+#define PEAKMASKFACTOR 1.
+#define PEAKTHRESHFACTOR 0.6
+
static void sigmund_getrawpeaks(int npts, float *insamps,
int npeak, t_peak *peakv, int *nfound, float *power, float srate, int loud,
- float param1, float param2, float param3, float hifreq)
+ float hifreq)
{
float oneovern = 1.0/ (float)npts;
float fperbin = 0.5 * srate * oneovern, totalpower = 0;
@@ -242,7 +245,6 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
float *rawreal, *rawimag, *maskbuf, *powbuf;
float *bigbuf = alloca(sizeof (float ) * (2*NEGBINS + 6*npts));
int maxbin = hifreq/fperbin;
- int tweak = (param3 == 0);
if (maxbin > npts - NEGBINS)
maxbin = npts - NEGBINS;
/* if (loud) post("tweak %d", tweak); */
@@ -294,7 +296,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
pow1 = powbuf[bin];
if (pow1 > maxpower && pow1 > maskbuf[bin])
{
- float thresh = param2 * (powbuf[bin-2]+powbuf[bin+2]);
+ float thresh = PEAKTHRESHFACTOR * (powbuf[bin-2]+powbuf[bin+2]);
if (pow1 > thresh)
maxpower = pow1, bestindex = bin;
}
@@ -304,7 +306,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
break;
fp1 = rawreal+bestindex;
fp2 = rawimag+bestindex;
- powmask = maxpower * exp(-param1 * log(10.) / 10.);
+ powmask = maxpower * PEAKMASKFACTOR;
/* if (loud > 2)
post("maxpower %f, powmask %f, param1 %f",
maxpower, powmask, param1); */
@@ -344,11 +346,8 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
peakv[peakcount].p_ampreal = oneovern * ampoutreal;
peakv[peakcount].p_ampimag = oneovern * ampoutimag;
}
- if (tweak)
- {
- sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
- sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
- }
+ sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
+ sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
for (i = 0; i < peakcount; i++)
{
peakv[i].p_pit = sigmund_ftom(peakv[i].p_freq);
@@ -360,13 +359,12 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
/*************** Routines for finding fundamental pitch *************/
#define PITCHNPEAK 12
-#define PITCHUNCERTAINTY 0.3
#define HALFTONEINC 0.059
#define SUBHARMONICS 16
#define DBPERHALFTONE 0.0
static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
- float npts, float srate, int loud)
+ float npts, float srate, float nharmonics, float amppower, int loud)
{
float fperbin = 0.5 * srate / npts;
int npit = 48 * sigmund_ilog2(npts), i, j, k, nsalient;
@@ -407,7 +405,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
t_peak *thispeak = bigpeaks[i];
float weightindex = (48./LOG2) *
log(thispeak->p_freq/(2.*fperbin));
- float loudness = sqrt(thispeak->p_amp);
+ float loudness = pow(thispeak->p_amp, amppower);
/* post("index %f, uncertainty %f", weightindex, pitchuncertainty); */
for (j = 0; j < SUBHARMONICS; j++)
{
@@ -422,7 +420,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
if (loindex < 0)
loindex = 0;
for (k = loindex; k <= hiindex; k++)
- weights[k] += loudness * 6. / (6. + j);
+ weights[k] += loudness * nharmonics / (nharmonics + j);
}
sumweight += loudness;
}
@@ -860,8 +858,8 @@ typedef struct _sigmund
static void sigmund_preinit(t_sigmund *x)
{
x->x_npts = NPOINTS_DEF;
- x->x_param1 = 0;
- x->x_param2 = 0.6;
+ x->x_param1 = 6;
+ x->x_param2 = 0.5;
x->x_param3 = 0;
x->x_hop = HOP_DEF;
x->x_mode = MODE_STREAM;
@@ -977,10 +975,10 @@ static void sigmund_doit(t_sigmund *x, int npts, float *arraypoints,
int nfound, i, cnt;
float freq = 0, power, note = 0;
sigmund_getrawpeaks(npts, arraypoints, x->x_npeak, peakv,
- &nfound, &power, srate, loud, x->x_param1, x->x_param2, x->x_param3,
- x->x_maxfreq);
+ &nfound, &power, srate, loud, x->x_maxfreq);
if (x->x_dopitch)
- sigmund_getpitch(nfound, peakv, &freq, npts, srate, loud);
+ sigmund_getpitch(nfound, peakv, &freq, npts, srate,
+ x->x_param1, x->x_param2, loud);
if (x->x_donote)
notefinder_doit(&x->x_notefinder, freq, power, &note, x->x_vibrato,
1 + x->x_stabletime * 0.001f * x->x_sr / (float)x->x_hop,
@@ -1112,7 +1110,7 @@ static void sigmund_tick(t_sigmund *x)
static t_int *sigmund_perform(t_int *w)
{
t_sigmund *x = (t_sigmund *)(w[1]);
- float *in = (float *)(w[2]);
+ t_sample *in = (float *)(w[2]);
int n = (int)(w[3]);
if (x->x_hop % n)
diff --git a/pd/extra/stdout/GNUmakefile.am b/pd/extra/stdout/GNUmakefile.am
new file mode 100644
index 00000000..cc2a517f
--- /dev/null
+++ b/pd/extra/stdout/GNUmakefile.am
@@ -0,0 +1,28 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+NAME=stdout
+
+external_LTLIBRARIES = stdout.la
+SOURCES = stdout.c
+PATCHES = stdout-help.pd
+OTHERDATA =
+
+###############################
+# you shouldn't need to add anything below here
+dist_external_DATA = $(PATCHES) $(OTHERDATA)
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
+AM_CFLAGS = @ARCH_CFLAGS@
+AM_LIBS = $(LIBM)
+AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
+
+externaldir = $(pkglibdir)/extra/$(NAME)
+
+
+if MINGW
+AM_LIBS += -lpd
+endif
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
diff --git a/pd/extra/stdout/makefile b/pd/extra/stdout/makefile
index 67801999..6041eeb7 100644
--- a/pd/extra/stdout/makefile
+++ b/pd/extra/stdout/makefile
@@ -1,4 +1,4 @@
NAME=stdout
CSYM=stdout
-include ../makefile
+include ../makefile.subdir
diff --git a/pd/m4/android.m4 b/pd/m4/android.m4
new file mode 100644
index 00000000..c63927e2
--- /dev/null
+++ b/pd/m4/android.m4
@@ -0,0 +1,124 @@
+dnl Copyright (C) 2010 IOhannes m zmölnig
+dnl This file is free software; IOhannes m zmölnig
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+# AM_CHECK_ANDROID (ACTION_IF_FOUND, ACTION_IF_NOT_FOUND, [ACTION_IF_FAILED])
+# enables the "--with-android" flag;
+# if the androidSDK is detected, this will
+# - set the CC & CPP to the cross-compiler ( resp preprocessor)
+# - as well as the apropriate CFLAGS, INCLUDES and LDFLAGS
+# - these values can also be found in ANDROID_CC, ANDROID_CPP,
+# ANDROID_INCLUDES, ANDROID_ARCH, ANDROID_CFLAGS, ANDROID_LDFLAGS
+# it will then call ACTION_IF_FOUND
+# elif ACTION_IF_FAILED is set and the androidSDK is not detected even though the user
+# requested it (by specifying a path, or simply saying "--with-android=yes"),
+# then ACTION_IF_FAILED is called
+# else
+# ACTION_IF_NOT_FOUND is called
+#
+# TODO: only run checks when architecture is right (x-compiling)
+# hc's code used "arm-linux"
+# --------------------------------------------------------------
+AC_DEFUN([PD_CHECK_ANDROID],
+[
+define([androidpath_default],[${HOME}/src/android/android-ndk-1.6_r1])
+define([androidversion_default],[android-4])
+
+AC_ARG_WITH([android],
+ AS_HELP_STRING( [--with-android=</path/to/sdk>],
+ [specify path to Android SDK (only used when building for Android) [androidpath_default]]),
+ android_path=$withval)
+AC_ARG_WITH([androidversion],
+ AS_HELP_STRING( [--with-androidversion=<sdk-version>],
+ [specify Android target version (only used when building for Android) [androidversion_default]]),
+ android_target_platform=$withval)
+
+
+case $host in
+ arm-linux)
+ ;;
+ *)
+ AC_MSG_NOTICE([Android SDK only available for arm-linux hosts, skipping tests])
+ with_android="no"
+ ;;
+esac
+
+
+if test "x${with_android}" != "xno" ; then
+ AC_MSG_CHECKING([android SDK])
+
+ if test "x${android_path}" = "xyes"; then
+ android_path=androidpath_default
+ fi
+ if test "x${android_target_platform}" = "x"; then
+ android_target_platform=androidversion_default
+ fi
+
+ android_target_arch_abi=arm
+ android_gcc_path="${android_path}/build/prebuilt/linux-x86/arm-eabi-4.2.1/bin"
+ ANDROID_CPP="${android_gcc_path}/arm-eabi-cpp"
+ ANDROID_CC="${android_gcc_path}/arm-eabi-gcc"
+ ANDROID_LD="${android_gcc_path}/arm-eabi-ld"
+ ANDROID_SYSROOT="${android_path}/build/platforms/${android_target_platform}/arch-${android_target_arch_abi}"
+
+ if test -d "${ANDROID_SYSROOT}/usr/include" &&
+ test -x "${ANDROID_CC}" &&
+ test -x "${ANDROID_LD}" &&
+ test -x "${ANDROID_CPP}"; then
+ CPP="${ANDROID_CPP}"
+ CC="${ANDROID_CC}"
+ LD="${ANDROID_LD}"
+ android_target_libgcc=$(${ANDROID_CC} -print-libgcc-file-name)
+
+ #ah, i don't like all this...
+
+ #why do we have to specify _HAVE_UNISTD_H and HAVE_GL: can't we use autoconf tests?
+ ANDROID_DEFS="-DANDROID -D__linux__ -D_HAVE_UNISTD_H -DHAVE_LIBGL -D__BSD_VISIBLE=
+ 1"
+ ANDROID_INCLUDES="-I${ANDROID_SYSROOT}/usr/include"
+
+ # what broken compiler is this, if we have to specify all the architecture defines manually?
+ ANDROID_ARCH_CFLAGS="-march=armv5te -mtune=xscale -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__"
+
+ #shan't we test for these flags?
+ ANDROID_OPT_CFLAGS=" -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -mthumb -fno-strict-aliasing -finline-limit=64 -O2"
+
+ ANDROID_CFLAGS="${ANDROID_ARCH_CFLAGS} ${ANDROID_OPT_CFLAGS}"
+ ANDROID_LDFLAGS="-nostdlib -Wl,--no-undefined -Wl,-rpath-link=${ANDROID_SYSROOT}/usr/lib ${android_target_libgcc}"
+
+ INCLUDES="${INCLUDES} ${ANDROID_INCLUDES}"
+ CFLAGS="${CFLAGS} ${ANDROID_CFLAGS}"
+ LDFLAGS="${LDFLAGS} ${ANDROID_LDFLAGS}"
+
+ # workaround for rpl_malloc/rpl_realloc bug in autoconf when cross-compiling
+ ac_cv_func_malloc_0_nonnull=yes
+ ac_cv_func_realloc_0_nonnull=yes
+
+ AC_MSG_RESULT([yes])
+ [$1]
+ else
+ ANDROID_CPP=""
+ ANDROID_CC=""
+ ANDROID_LD=""
+ ANDROID_SYSROOT=""
+
+ if test "x${with_android}" = "x"; then
+ with_android="no"
+ fi
+
+ AC_MSG_RESULT([no])
+ if test "x${with_android}" = "xno"; then
+ :
+ [$2]
+ else
+ :
+ ifelse([$3], , [$2], [$3])
+ fi
+ fi
+else
+# --without-android
+ [$2]
+fi
+undefine([androidpath_default])
+undefine([androidversion_default])
+]) \ No newline at end of file
diff --git a/pd/m4/iphone.m4 b/pd/m4/iphone.m4
new file mode 100644
index 00000000..2a774807
--- /dev/null
+++ b/pd/m4/iphone.m4
@@ -0,0 +1,113 @@
+dnl Copyright (C) 2010 IOhannes m zmölnig
+dnl This file is free software; IOhannes m zmölnig
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+# AM_CHECK_IPHONE (ACTION_IF_FOUND, ACTION_IF_NOT_FOUND, [ACTION_IF_FAILED])
+# enables the "--with-iphone" flag;
+# if the iPhoneSDK is detected, this will
+# - set the CC & CPP to the cross-compiler ( resp preprocessor)
+# - as well as the apropriate CFLAGS, INCLUDES and LDFLAGS
+# - these values can also be found in IPHONE_CC, IPHONE_CPP,
+# IPHONE_INCLUDES, IPHONE_ARCH, IPHONE_CFLAGS, IPHONE_LDFLAGS
+# it will then call ACTION_IF_FOUND
+# elif ACTION_IF_FAILED is set and the iPhoneSDK is not detected even though the user
+# requested it (by specifying a path, or simply saying "--with-iphone=yes"),
+# then ACTION_IF_FAILED is called
+# else
+# ACTION_IF_NOT_FOUND is called
+#
+# TODO: only run checks when architecture is right (x-compiling)
+# hc's code used "arm*darwin*"
+# --------------------------------------------------------------
+AC_DEFUN([PD_CHECK_IPHONE],
+[
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+define([iphonepath_default],[/Developer/Platforms/iPhoneOS.platform/Developer])
+define([iphoneversion_default],[3.0])
+
+AC_ARG_WITH([iphone],
+ AS_HELP_STRING( [--with-iphone=</path/to/sdk>],
+ [specify iPhone BaseDirectory (only used when building for iPhone) [iphonepath_default]]),
+ iphonepath=$withval)
+AC_ARG_WITH([iphoneversion],
+ AS_HELP_STRING( [--with-iphoneversion=<sdk-version>],
+ [specify iPhone SDK version (only used when building for iPhone) [iphoneversion_default]]),
+ iphone_version=$withval)
+
+
+case $host in
+ arm*darwin*)
+ ;;
+ *)
+ AC_MSG_NOTICE([iPhone SDK only available for arm-apple-darwin hosts, skipping tests])
+ with_iphone="no"
+ ;;
+esac
+
+if test "x${with_iphone}" != "xno" ; then
+ AC_MSG_CHECKING([iPhone SDK])
+
+ if test "x${iphonepath}" = "xyes" || test "x${iphonepath}" = "x"; then
+ iphonepath=iphonepath_default
+ fi
+ if test "x${iphone_version}" = "x"; then
+ iphone_version=iphoneversion_default
+ fi
+
+ IPHONE_CC="${iphonepath}/usr/bin/gcc"
+ IPHONE_CPP="${iphonepath}/usr/bin/cpp"
+ IPHONE_SYSROOT="${iphonepath}/SDKs/iPhoneOS${iphone_version}.sdk"
+
+#echo "sysroot = ${IPHONE_SYSROOT}"
+#echo "cpp = ${IPHONE_CPP}"
+#echo "cc = ${IPHONE_CC}"
+
+ if test -d "${IPHONE_SYSROOT}" &&
+ test -x "${IPHONE_CC}" &&
+ test -x "${IPHONE_CPP}"; then
+ CC="${IPHONE_CC}"
+ CPP="${IPHONE_CPP}"
+
+ IPHONE_ARCH="-arch armv6"
+ IPHONE_CFLAGS="-miphoneos-version-min=${iphone_version} -isysroot ${IPHONE_SYSROT}"
+ IPHONE_LDFLAGS=""
+
+ CFLAGS="${CFLAGS} ${IPHONE_CFLAGS} ${IPHONE_ARCH}"
+ LDFLAGS="${LDFLAGS} ${IPHONE_ARCH} ${LDFLAGS}"
+
+ # workaround for rpl_malloc/rpl_realloc bug in autoconf when cross-compiling
+ ac_cv_func_malloc_0_nonnull=yes
+ ac_cv_func_realloc_0_nonnull=yes
+
+ _iphone_result=yes
+
+ AC_MSG_RESULT([yes])
+ [$1]
+ else
+ _iphone_result=no
+ IPHONE_CC=""
+ IPHONE_CPP=""
+ IPHONE_SYSROOT=""
+
+ if test "x${with_iphone}" = "x"; then
+ with_iphone="no"
+ fi
+
+ AC_MSG_RESULT([no])
+ if test "x${with_iphone}" = "xno"; then
+ :
+ [$2]
+ else
+ :
+ ifelse([$3], , [$2], [$3])
+ fi
+ fi
+else
+# --without-iphone
+ [$2]
+fi
+
+undefine([iphonepath_default])
+undefine([iphoneversion_default])
+]) \ No newline at end of file
diff --git a/pd/m4/universal.m4 b/pd/m4/universal.m4
new file mode 100644
index 00000000..8ab7255d
--- /dev/null
+++ b/pd/m4/universal.m4
@@ -0,0 +1,89 @@
+dnl Copyright (C) 2005-2010 IOhannes m zmölnig
+dnl This file is free software; IOhannes m zmölnig
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# PD_CHECK_UNIVERSAL([VARIABLE-NAME], [ACTION-IF-SUCCESS], [ACTION-IF-NO-SUCCESS])
+# will enable the "--enable-universal=<ARCHS>" flag
+# if <ARCH> is "yes", platform defaults are used
+# the system tries to build a test program with the archs, on succes it calls ACTION-IF-SUCCESS, and ACTION-IF-NO-SUCCESS otherwise
+# on success it will also add the flags to:
+# [VARIABLE-NAME]_CFLAGS will hold a list of cflags to compile for all requested archs
+# [VARIABLE-NAME]_LDFLAGS will hold a list of ldflags to link for all requested archs
+
+AC_DEFUN([PD_CHECK_UNIVERSAL],
+[
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+AC_ARG_ENABLE(universal,
+ [ --enable-universal=<ARCHS>
+ build an Apple Multi Architecture Binary (MAB);
+ ARCHS is a comma-delimited list of architectures for
+ which to build; if ARCHS is omitted, then the package
+ will be built for all architectures supported by the
+ platform (e.g. "ppc,i386" for MacOS/X and Darwin);
+ if this option is disabled or omitted entirely, then
+ the package will be built only for the target
+ platform],
+ [universal_binary=$enableval], [universal_binary=no])
+
+if test "$universal_binary" != no; then
+ AC_MSG_CHECKING([target architectures])
+
+ # Respect TARGET_ARCHS setting from environment if available.
+ if test -z "$TARGET_ARCHS"; then
+ # Respect ARCH given to --enable-universal-binary if present.
+ if test "$universal_binary" != yes; then
+ TARGET_ARCHS=$(echo "$universal_binary" | tr ',' ' ')
+ else
+ # Choose a default set of architectures based upon platform.
+ case $host in
+ *darwin*)
+ TARGET_ARCHS="ppc i386"
+ ;;
+ *)
+ TARGET_ARCHS=""
+ ;;
+ esac
+ fi
+ fi
+ AC_MSG_RESULT([$TARGET_ARCHS])
+
+ # /usr/lib/arch_tool -archify_list $TARGET_ARCHS
+ _pd_universal=""
+ for archs in $TARGET_ARCHS
+ do
+ _pd_universal="$_pd_universal -arch $archs"
+ done
+
+dnl run checks whether the compiler linker like this...
+ if test "x$_pd_universal" != "x"; then
+ tmp_arch_cflags="$CFLAGS"
+ tmp_arch_ldflags="$LDFLAGS"
+
+ CFLAGS="$CFLAGS $_pd_universal"
+ LDFLAGS="$LDFLAGS $_universal"
+ AC_TRY_LINK([], [return 0;], [
+ if test "x$1" != "x"; then
+ $1[]_CFLAGS="$[]$1[]_CFLAGS $_pd_universal"
+ $1[]_LDFLAGS="$[]$1[]_LDFLAGS $_pd_universal"
+ AC_SUBST($1[]_CFLAGS)
+ AC_SUBST($1[]_LDFLAGS)
+ fi
+ [$2]
+ ], [
+ :
+ [$3]
+ ])
+
+ CFLAGS="$tmp_arch_cflags"
+ LDFLAGS="$tmp_arch_ldflags"
+ else
+ :
+ [$3]
+ fi
+else
+ :
+ [$3]
+fi
+])# GEM_CHECK_UNIVERSAL
diff --git a/pd/man/Makefile.am b/pd/man/Makefile.am
new file mode 100644
index 00000000..e6c37f72
--- /dev/null
+++ b/pd/man/Makefile.am
@@ -0,0 +1 @@
+dist_man_MANS = pd.1 pdsend.1 pdreceive.1
diff --git a/pd/pd.pc.in b/pd/pd.pc.in
new file mode 100644
index 00000000..c81c8138
--- /dev/null
+++ b/pd/pd.pc.in
@@ -0,0 +1,22 @@
+# Pure data pkg-config file
+# LATER: shouldn't "--libs" output all flags for building an external?
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+###############################
+# variables
+# the default file-extension for externals (e.g. "l_i386")
+extension=@EXTERNAL_EXTENSION@
+# where to install externals
+externaldir=${libdir}/pd/extra
+
+###############################
+# core configuration
+Name: pd
+Description: Pure data externals
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}/pd -DPD @EXTERNAL_CFLAGS@
+Libs: @EXTERNAL_LDFLAGS@
diff --git a/pd/po/Makefile.am b/pd/po/Makefile.am
new file mode 100644
index 00000000..7ab45eec
--- /dev/null
+++ b/pd/po/Makefile.am
@@ -0,0 +1,68 @@
+AUTOMAKE_OPTIONS = foreign
+
+SUFFIXES = .po .pot .msg
+
+# this is the only way to get gettext 0.17 with Fink
+#UNAME := $(shell uname -s)
+#ifeq ($(UNAME),Darwin)
+if MACOSX
+ PATH := /sw/lib/gettext-tools-0.17/bin:${PATH}
+endif
+
+TCLFILES = apple_events.tcl dialog_canvas.tcl dialog_gatom.tcl dialog_path.tcl pd_bindings.tcl pd_menus.tcl pdwindow.tcl scrollboxwindow.tcl AppMain.tcl dialog_data.tcl dialog_iemgui.tcl dialog_startup.tcl pd_connect.tcl pdtk_array.tcl pkgIndex.tcl wheredoesthisgo.tcl dialog_array.tcl dialog_find.tcl dialog_message.tcl helpbrowser.tcl pdtk_canvas.tcl pkg_mkIndex.tcl dialog_audio.tcl dialog_font.tcl dialog_midi.tcl opt_parser.tcl pd_menucommands.tcl pdtk_text.tcl scrollbox.tcl
+
+FILES=$(addprefix ../tcl/, $(TCLFILES))
+
+# these are the supported languages,
+ALL_LINGUAS = af az be bg de el en_ca eu fr gu he hi hu it pa pt_br pt_pt sq sv vi
+POFILES = $(ALL_LINGUAS:=.po)
+MSGFILES = $(ALL_LINGUAS:=.msg)
+
+TEMPLATE = template.pot
+
+libpdpodir = $(pkglibdir)/po
+libpdpo_DATA = $(MSGFILES)
+dist_libpdpo_DATA =
+
+EXTRA_DIST = $(POFILES)
+
+# generate .msg files from the .po files
+all-local: $(MSGFILES)
+
+
+
+# refresh .po files from the template
+clean-local:
+ -rm -f -- $(MSGFILES)
+ -rm -f -- $(POFILES:=~)
+
+po: $(POFILES)
+
+# refresh the template from the source code
+template: $(TEMPLATE)
+
+$(TEMPLATE): $(FILES)
+ xgettext --join-existing \
+ --from-code=UTF-8 --language=Tcl --keyword=_ \
+ --sort-by-file --output=$(TEMPLATE) \
+ --package-name="Pure Data" --package-version=0.43 \
+ --copyright-holder='This file is put in the public domain' \
+ --msgid-bugs-address=pd-dev@iem.at \
+ $(FILES)
+# fink's and MinGW's xgettext are too old for these flags, needs 0.17
+# --package-name="Pure Data" --package-version=0.43
+
+# I guess officially, the .po file should depend on the template.pot, but its
+# mostly annoying since it wasnts to update the template.pot and .po files any
+# time a .tcl file changes
+# $(POFILES): %.po: $(TEMPLATE)
+$(POFILES): %.po:
+ msgmerge --sort-by-file --update $< $(TEMPLATE)
+
+
+%.msg: %.po
+ msgfmt --check --tcl --locale=$* -d . $<
+
+
+etags: TAGS
+ etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl
diff --git a/pd/po/af.po b/pd/po/af.po
new file mode 100644
index 00000000..bc8a913f
--- /dev/null
+++ b/pd/po/af.po
@@ -0,0 +1,964 @@
+# Afrikaans translation of Pure Data
+# This file is put in the public domain.
+# Petri Jooste <rkwjpj@puk.ac.za>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 2.0.8pre1\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2004-03-17 14:45+0200\n"
+"Last-Translator: Petri Jooste <rkwjpj@puk.ac.za>\n"
+"Language-Team: Afrikaans <i18n@af.org.za>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Datum"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+msgid "Undo cut"
+msgstr ""
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Kopieer"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Datum"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Naam"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#, fuzzy
+msgid "Size:"
+msgstr "Grootte"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "Inhoud"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Poort"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Pole"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Laaste Verander..."
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Uitwis"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "/Skommel lys"
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+#, fuzzy
+msgid "Cancel"
+msgstr "Kanselleer"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+#, fuzzy
+msgid "Apply"
+msgstr "Pas toe"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Kanselleer"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Stoor"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Merk voor:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Find"
+msgstr "Soek:"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "Volgrote teks soektog..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Poort:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+#, fuzzy
+msgid "Close"
+msgstr "Toemaak"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Description=Stuur Lêer"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Font:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Font:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr ""
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Maatjie Lyste"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "Gebruiker"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "Links"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Regs"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Bo"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Onder"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "Boodskap"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Ontvanger"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Agtergrond:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Voorgrond:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Die kleure aandui:"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Nooi"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+#, fuzzy
+msgid "Save"
+msgstr "Stoor"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Kleure"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Agtergrond:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Font:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Toets almal"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "Twm: Tab Vensterbestuurder"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Lêer"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "Biep op fout"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+#, fuzzy
+msgid "Message"
+msgstr "Boodskap"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Font:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "Voorkeure..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "/Laai"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "File"
+msgstr "Lêer"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+#, fuzzy
+msgid "Help"
+msgstr "hulp"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Name=Makedoniese"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "<venster %d>"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+#, fuzzy
+msgid "New"
+msgstr "Nuwe"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+#, fuzzy
+msgid "Open"
+msgstr "Open"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "Stoor As"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "/Laai"
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "Uganda "
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "Rede"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Datum"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Uitvee Alle"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Kleure"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Maak lys skoon"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Redigeermodus"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Nommer"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Instruksie"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Bhutan"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Togo"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Nommer"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "Weggesteek"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Weergawe"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Kanada"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Grafiek"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Andorra"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Description=Stuur Lêer"
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Af"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Meter Af"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Onder"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Description=Stuur Lêer"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "Aangaande"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Blaai..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+#, fuzzy
+msgid "Preferences..."
+msgstr "Voorkeure..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+#, fuzzy
+msgid "Quit"
+msgstr "Verlaat"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Maak lys skoon"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Af"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Lêer"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/az.po b/pd/po/az.po
new file mode 100644
index 00000000..429fe196
--- /dev/null
+++ b/pd/po/az.po
@@ -0,0 +1,954 @@
+# translation of Pure Data 0.43 to Azerbaijani Turkish
+# This file is put in the public domain.
+# Metin Amiroff <metin@karegen.com>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2004-03-12 22:22+0200\n"
+"Last-Translator: Metin Amiroff <metin@karegen.com>\n"
+"Language-Team: Azerbaijani <translation-team-az@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Tarix"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "Uqanda"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Köçür"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Tarix"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Ad"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#, fuzzy
+msgid "Size:"
+msgstr "Böyüklük"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "_Məzmun"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Port"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Polşa"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Son ismarış: %s"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Sil"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "Ban Siyahısı..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Ləğv Et"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Tətbiq Et"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Ləğv Et"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Qeyd Et"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Ön işarə:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Axtar"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "Mətni Axtar..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Qapı:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Bağla"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Fayl Yolla"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Yazı növü:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Böyüklük"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "Başlanğıc Vaxtı"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Siyahılar"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "İstifadəçi"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "Solda"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Sağda"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Üstdə"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Altda"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "İsmarış"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Alıcı"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Arxa plan:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Ön plan:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Rəng seç"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Dəvət Et"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Qeyd Et"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Rənglər"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Arxa plan:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Yazı növü:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Hamısı Sına"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "Bu səkmə/pəncərəni bağla"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Fayl"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "İsmarış"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "İsmarış"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Yazı növü:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "Seçimlər..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "_Yüklə..."
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Fayl"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Yardım"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Makedoniya"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "_Pəncərə"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Yeni"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Aç"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "Fərqli Qeyd Et"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "_Yüklə..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "Uqanda"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "Səbəb"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Tarix"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Hamısı Sil"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Rənglər"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Siyahını təmizlə"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Təfərruatlar"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Nömrəsi"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Əmr"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Ban-la"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Toqo"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Nömrəsi"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "Göstərmə"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Buraxılış"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Kanada"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Qrafika"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Andorra"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Fayl Göndərilməsi..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Bağlı"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Lag ölçəni:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Altda"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Fayl Yolla"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "_Haqqında"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Gəz..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Seçimlər..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Çıx"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Siyahını təmizlə"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Bağlı"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Fayl"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/be.po b/pd/po/be.po
new file mode 100644
index 00000000..90b3ddb8
--- /dev/null
+++ b/pd/po/be.po
@@ -0,0 +1,960 @@
+# Translation of Pure Data-0.43.po to Belarusian.
+# This file is put in the public domain.
+# Pavel Piatruk <berserker@neolocation.com>, 2006, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2007-06-26 12:02+0300\n"
+"Last-Translator: Pavel Piatruk <berserker@neolocation.com>\n"
+"Language-Team: Belarusian <i18n@mova.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.10.2\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Дата"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "Уганда"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Капіяваць"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Дата"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Імя"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#, fuzzy
+msgid "Size:"
+msgstr "Памер"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "_Змест"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Порт"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Польшча"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Апошняе паведамленне:"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Выдаліць"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "Спіс забароненых..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Адмяніць"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr ""
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Адмяніць"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Захаваць"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "да"
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Лінія-адзнака:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Find"
+msgstr "Знайсці:"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "_Пошук"
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Порт:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+#, fuzzy
+msgid "Close"
+msgstr "_Закрыць"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Акно дасылкі"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Шрыфт:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Шрыфт:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr ""
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+#, fuzzy
+msgid "X only"
+msgstr "Паказаць толькі:"
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+#, fuzzy
+msgid "Y only"
+msgstr "Паказаць толькі:"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Абмежаванне карыстальніка"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "Карыстальнік:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Верх"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Ніз"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "Паведамленне"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Акно атрымання"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Фон:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Колер літар:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Лакальныя колеры:"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Запрашэнне"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Захаваць"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Колеры"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Фон:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Шрыфт:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Праверыць усё"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "_Закрыць акно"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Файл"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "Паведамленне"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Паведамленне"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Шрыфт:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "_Асаблівасці"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "_Рэдагаваць"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Файл"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Дапамога"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Македонія"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "Акно"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+#, fuzzy
+msgid "New"
+msgstr "_Новы"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+#, fuzzy
+msgid "Open"
+msgstr "Аперацыя"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Захаваць як..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "_Змяніць..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "Уганда"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "Чырвоны"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Дата"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Вылучце колер"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Колеры тэксту"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Ачысціць спіс"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Рэжым"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Лічба"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Каманда"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Забараніць"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Тога"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Лічба"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "С_хаваць"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Версія"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Канада"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Графік"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Андора"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Знайсці:"
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Выкл"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+#, fuzzy
+msgid "Minimize"
+msgstr "_Паменшыць у сподак"
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Ніз"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Акно дасылкі"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "Аб праграме"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Агляд.."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+#, fuzzy
+msgid "Preferences..."
+msgstr "_Асаблівасці"
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+#, fuzzy
+msgid "Quit"
+msgstr "_Выйсці"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Ачысціць спіс"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Выкл"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Файл"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/bg.po b/pd/po/bg.po
new file mode 100644
index 00000000..fc49699b
--- /dev/null
+++ b/pd/po/bg.po
@@ -0,0 +1,955 @@
+# Bulgarian translation of Pure Data
+# This file is put in the public domain.
+# Rostislav Raykov <zbrox@i-space.org>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-05-20 17:51+0300\n"
+"Last-Translator: Rostislav Raykov <zbrox@i-space.org>\n"
+"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Дата"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "Уганда"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Копиране"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Дата"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Име"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#, fuzzy
+msgid "Size:"
+msgstr "Размер"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "_Потребителско ръководство"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Порт"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Полша"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Последно съобщение: %s"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Изтриване"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "Списък със забранение адреси..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Отмяна"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Прилагане"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Отмяна"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Запазване"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Отбелязваща линия:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Търсене"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "Търсене из текста..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Порт:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Затваряне"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Прозореца за изпращане на файлове"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Шрифт:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Размер"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "Време на начало"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Списъци"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "Потребител"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "Ляво"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Дясно"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Горе"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Долу"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "Съобщение"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Прозореца за получване на файлове"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Фон:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Цвят:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Избор на цвят"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Покана"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Запазване"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Цветове"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Фон:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Шрифт:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Тестване на всички"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "Затваряне на този таб/прозорец"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Файл"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "Съобщение"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Съобщение"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Шрифт:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "Настройки"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "_Редактиране"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Файл"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Помощ"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Македония"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "Прозорец"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Ново"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Отваряне"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "Записване като..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "_Редактиране..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "Уганда"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "Червено:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Дата"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Изтрива всички"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Цветове за текста"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Изчистване на списъка"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Режим \"Редакция\""
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Номер"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Команда"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Забрана"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Того"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Номер"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "Скрит"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Версия"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Канада"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Графа"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Андора"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Изпращане на файлове..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Изкл."
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Измервател на забавянето:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Долу"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Прозореца за изпращане на файлове"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "_Относно"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Разглеждане..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Настройки"
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Изход"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Изчистване на списъка"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Изкл."
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Файл"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/de.po b/pd/po/de.po
new file mode 100644
index 00000000..0051c064
--- /dev/null
+++ b/pd/po/de.po
@@ -0,0 +1,1230 @@
+# German translation of Pure Data
+# This file is put in the public domain
+# Max Neupert <first_letter_of_name@maxneupert.de>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2009-09-22 13:00-0400\n"
+"Last-Translator: Max Neupert <first_letter_of_name@maxneupert.de>\n"
+"Language-Team: Deutsch <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Undo duplicate"
+msgstr "Duplizieren widerrufen"
+
+msgid "Undo paste"
+msgstr "Einfügen widerrufen"
+
+msgid "Undo motion"
+msgstr "Bewegen widerrufen"
+
+msgid "Undo cut"
+msgstr "Ausschneiden widerrufen"
+
+msgid "Undo disconnect"
+msgstr "Trennen widerrufen"
+
+msgid "Undo connect"
+msgstr "Verbinden widerrufen"
+
+msgid "Undo clear"
+msgstr "Löschen widerrufen"
+
+msgid "Undo typing"
+msgstr "Eingabe widerrufen"
+
+msgid "Discard changes to '%s'?"
+msgstr "Änderungen an '%s' verwerfen?"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "Änderungen in '%s' speichern?"
+
+#: ../src/dialog_array.tcl:115
+#: ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100
+#: ../src/pd_menus.tcl:101
+#: ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Kopieren"
+
+#: ../src/dialog_array.tcl:118
+#: ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102
+#: ../src/pd_menus.tcl:103
+#: ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr "Einfügen"
+
+#: ../src/dialog_array.tcl:264
+#: ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Feld-Eingenschaften"
+
+#: ../src/dialog_array.tcl:270
+#: ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Name:"
+
+#: ../src/dialog_array.tcl:276
+#: ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178
+#: ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619
+#: ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Größe:"
+
+#: ../src/dialog_array.tcl:280
+#: ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Inhalt speichern"
+
+#: ../src/dialog_array.tcl:284
+#: ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr "Zeichne als:"
+
+#: ../src/dialog_array.tcl:287
+#: ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Punkte"
+
+#: ../src/dialog_array.tcl:289
+#: ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Vieleck"
+
+#: ../src/dialog_array.tcl:291
+#: ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Bezier Kurve"
+
+#: ../src/dialog_array.tcl:297
+#: ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr "Feld einfügen in:"
+
+#: ../src/dialog_array.tcl:300
+#: ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr "Neue Kurve"
+
+#: ../src/dialog_array.tcl:302
+#: ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr "Letzte Kurve"
+
+#: ../src/dialog_array.tcl:306
+#: ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr "Feld löschen"
+
+#: ../src/dialog_array.tcl:312
+#: ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr "Öffne Listenanzeige..."
+
+#: ../src/dialog_array.tcl:319
+#: ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136
+#: ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51
+#: ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161
+#: ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: ../src/dialog_array.tcl:321
+#: ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138
+#: ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156
+#: ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745
+#: ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93
+#: ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Anwenden"
+
+#: ../src/dialog_array.tcl:323
+#: ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140
+#: ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53
+#: ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100
+#: ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159
+#: ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95
+#: ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr "OK"
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr "Audioeinstellungen"
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr "Einstellungen speichern"
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr "Samplingrate:"
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr "Verzögerung (msec):"
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr "Rückfragen verwenden"
+
+#: ../src/dialog_audio.tcl:166
+#: ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr "Eingabegerät 1:"
+
+#: ../src/dialog_audio.tcl:169
+#: ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198
+#: ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232
+#: ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265
+#: ../src/dialog_audio.tcl:280
+msgid "Channels:"
+msgstr "Kanäle:"
+
+#: ../src/dialog_audio.tcl:179
+#: ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr "Eingabegerät 2:"
+
+#: ../src/dialog_audio.tcl:194
+#: ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr "Eingabegerät 3:"
+
+#: ../src/dialog_audio.tcl:209
+#: ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr "Eingabegerät 4:"
+
+#: ../src/dialog_audio.tcl:223
+#: ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr "Ausgabegerät 1:"
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr "(wie Eingabegerät) .............. "
+
+#: ../src/dialog_audio.tcl:246
+#: ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr "Ausgabegerät 2:"
+
+#: ../src/dialog_audio.tcl:261
+#: ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr "Ausgabegerät 3:"
+
+#: ../src/dialog_audio.tcl:276
+#: ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr "Ausgabegerät 4:"
+
+#: ../src/dialog_audio.tcl:291
+#: ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr "Mehrere Geräte verwenden"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Arbeitsflächen-Eigenschaften"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Skalierung"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr "X Einheiten pro Pixel:"
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr "Y Einheiten pro Pixel:"
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr "Erscheinen auf dem übergeordneten Patch"
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr "Auf dem Übergeordneten Patch anzeigen"
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "Objektname und Argumente verbergen"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr "Spanne und Größe"
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr "X Spanne, von"
+
+#: ../src/dialog_canvas.tcl:176
+#: ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "bis"
+
+#: ../src/dialog_canvas.tcl:180
+#: ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Abstand:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr "Y Spanne, von"
+
+#: ../src/dialog_find.tcl:63
+#: ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79
+#: ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87
+#: ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105
+#: ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Finde"
+
+#: ../src/dialog_find.tcl:70
+#: ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87
+#: ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr "Suche in"
+
+#: ../src/dialog_find.tcl:72
+#: ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89
+#: ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr "für:"
+
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104
+#: ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110
+#: ../src/pd_menus.tcl:86
+#: ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132
+#: ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272
+#: ../src/pd_menus.tcl:295
+#: ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332
+#: ../src/pd_menus.tcl:345
+#: ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:392
+#: ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431
+#: ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Schließen"
+
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr "Ganzes Wort abgleichen"
+
+#: ../src/dialog_find.tcl:92
+#: ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50
+#: ../src/pd-gui.tcl:280
+#: ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286
+#: ../src/pd-gui.tcl:288
+#: ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212
+#: ../src/pd_menus.tcl:258
+#: ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr "Pd Fenster"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr "Zeichensatz-Einstellungen"
+
+#: ../src/dialog_font.tcl:46
+#: ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, tcl-format
+msgid "%s Font"
+msgstr "%s Zeichensatz"
+
+#: ../src/dialog_font.tcl:61
+#: ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104
+#: ../src/dialog_font.tcl:105
+msgid "Font Size"
+msgstr "Zeichensatzgröße"
+
+#: ../src/dialog_font.tcl:89
+#: ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116
+#: ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr "Dehnen"
+
+#: ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123
+#: ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr "X und Y"
+
+#: ../src/dialog_font.tcl:98
+#: ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125
+#: ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr "nur X"
+
+#: ../src/dialog_font.tcl:100
+#: ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127
+#: ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr "nur Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Atom Box Eigenschaften"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Breite:"
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr "Bereich"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Unterer:"
+
+#: ../src/dialog_gatom.tcl:112
+#: ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Oberer:"
+
+#: ../src/dialog_gatom.tcl:116
+#: ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600
+#: ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr "Etikett"
+
+#: ../src/dialog_gatom.tcl:124
+#: ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Links "
+
+#: ../src/dialog_gatom.tcl:126
+#: ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Rechts"
+
+#: ../src/dialog_gatom.tcl:128
+#: ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Oben"
+
+#: ../src/dialog_gatom.tcl:130
+#: ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Unten"
+
+#: ../src/dialog_gatom.tcl:137
+#: ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr "Nachrichten"
+
+#: ../src/dialog_gatom.tcl:141
+#: ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr "Sendesymbol:"
+
+#: ../src/dialog_gatom.tcl:147
+#: ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Empfangssymbol"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Hintergrundfarbe"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Vordergrundfarbe"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Etikettenfarbe"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr "Init"
+
+#: ../src/dialog_iemgui.tcl:275
+#: ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr "Kein Init"
+
+#: ../src/dialog_iemgui.tcl:287
+#: ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr "Sprung bei Klick"
+
+#: ../src/dialog_iemgui.tcl:290
+#: ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr "Gleichbleibend bei Klick"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "%s Eigenschaften"
+
+#: ../src/dialog_iemgui.tcl:550
+#: ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:288
+#: ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325
+#: ../src/pd_menus.tcl:338
+#: ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382
+#: ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422
+#: ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Speichern"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "X Verschiebung"
+
+#: ../src/dialog_iemgui.tcl:611
+#: ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr "Y Verschiebung"
+
+#: ../src/dialog_iemgui.tcl:642
+#: ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Farben"
+
+#: ../src/dialog_iemgui.tcl:648
+#: ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr "Hintergrund"
+
+#: ../src/dialog_iemgui.tcl:650
+#: ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr "Vordergrund"
+
+#: ../src/dialog_iemgui.tcl:662
+#: ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Farbe einstellen"
+
+#: ../src/dialog_iemgui.tcl:682
+#: ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr "Test Etikett"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr "MIDI Einstellungen"
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr "ALSA MIDI Einstellungen"
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr "Mehrere ALSA Geräte verwenden"
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr "Eingänge:"
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr "Ausgänge:"
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr "Änderungen an diesem Fenster verwerfen?"
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr "Wirklich Abbrechen?"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Dieses Fenster schließen?"
+
+#: ../src/pd-gui.tcl:185
+#: ../src/pd-gui.tcl:195
+#: ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206
+#: ../src/pd-gui.tcl:215
+#: ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr "Zugehörige Dateien"
+
+#: ../src/pd-gui.tcl:186
+#: ../src/pd-gui.tcl:196
+#: ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207
+#: ../src/pd-gui.tcl:216
+#: ../src/pd-gui.tcl:227
+msgid "Pd Files"
+msgstr "Pd Dateien"
+
+#: ../src/pd-gui.tcl:187
+#: ../src/pd-gui.tcl:205
+#: ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr "Max Patch Dateien"
+
+#: ../src/pd-gui.tcl:188
+#: ../src/pd-gui.tcl:206
+#: ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr "Max Textdateien"
+
+#: ../src/pd-gui.tcl:197
+#: ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr "Max Patch Dateien (.pat)"
+
+#: ../src/pd-gui.tcl:198
+#: ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr "Max Textdateien (.mxt)"
+
+#: ../src/pd-gui.tcl:270
+#: ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+"WARNUNG: Zeichensatzfamilie '%s' nicht gefunden, Standard wird verwendet (%s)"
+
+#: ../src/pd-gui.tcl:278
+#: ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+"WARNUNG: Zeichensatz Schnitt '%s' nicht gefunden, Standard wird verwendet (%"
+"s)"
+
+#: ../src/pd-gui.tcl:303
+#: ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr "FEHLER: %s failed to find font size (%s) that fits into %sx%s!"
+
+#: ../src/pd-gui.tcl:478
+#: ../src/pd-gui.tcl:483
+#: ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr "FEHLER: 'pd' startete nicht, 'pd-gui' beendet sich!"
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr "Unbenannt"
+
+#: ../src/pd_menucommands.tcl:78
+#: ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Nachricht senden..."
+
+#: ../src/pd_menucommands.tcl:82
+#: ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94
+#: ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192
+#: ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:292
+#: ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329
+#: ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387
+#: ../src/pd_menus.tcl:414
+#: ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453
+#: ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Nachricht"
+
+#: ../src/pd_menucommands.tcl:108
+#: ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112
+#: ../src/pd_menus.tcl:113
+#: ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118
+#: ../src/pd_menus.tcl:158
+#: ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163
+#: ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr "Zeichensatz"
+
+#: ../src/pd_menucommands.tcl:123
+#: ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:183
+#: ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr "Voreinstellungen"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Datei"
+
+#: ../src/pd_menus.tcl:45
+#: ../src/pdtk_canvas.tcl:48
+#: ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Hilfe"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Medien"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Einfügen"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Fenster"
+
+#: ../src/pd_menus.tcl:81
+#: ../src/pd_menus.tcl:82
+#: ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:255
+#: ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:298
+#: ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:349
+#: ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380
+#: ../src/pd_menus.tcl:407
+#: ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Neu"
+
+#: ../src/pd_menus.tcl:82
+#: ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:256
+#: ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286
+#: ../src/pd_menus.tcl:299
+#: ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336
+#: ../src/pd_menus.tcl:350
+#: ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:408
+#: ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447
+#: ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108
+#: ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128
+#: ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131
+#: ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Öffnen"
+
+#: ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:85
+#: ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131
+#: ../src/pd_menus.tcl:261
+#: ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289
+#: ../src/pd_menus.tcl:302
+#: ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339
+#: ../src/pd_menus.tcl:356
+#: ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384
+#: ../src/pd_menus.tcl:411
+#: ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Speichern als..."
+
+#: ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:89
+#: ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135
+#: ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293
+#: ../src/pd_menus.tcl:306
+#: ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343
+#: ../src/pd_menus.tcl:362
+#: ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389
+#: ../src/pd_menus.tcl:415
+#: ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr "Drucken"
+
+#: ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:94
+#: ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr "Widerrufen"
+
+#: ../src/pd_menus.tcl:95
+#: ../src/pd_menus.tcl:96
+#: ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr "Wiederholen"
+
+#: ../src/pd_menus.tcl:98
+#: ../src/pd_menus.tcl:99
+#: ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr "Ausschneiden"
+
+#: ../src/pd_menus.tcl:104
+#: ../src/pd_menus.tcl:105
+#: ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr "Duplizieren"
+
+#: ../src/pd_menus.tcl:106
+#: ../src/pd_menus.tcl:107
+#: ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr "Alles auswählen"
+
+#: ../src/pd_menus.tcl:110
+#: ../src/pd_menus.tcl:111
+#: ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116
+#: ../src/pd_menus.tcl:156
+#: ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161
+#: ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr "Texteditor"
+
+#: ../src/pd_menus.tcl:120
+#: ../src/pd_menus.tcl:121
+#: ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr "Aufräumen"
+
+#: ../src/pd_menus.tcl:122
+#: ../src/pd_menus.tcl:123
+#: ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr "Konsole Ein/Aus"
+
+#: ../src/pd_menus.tcl:124
+#: ../src/pd_menus.tcl:125
+#: ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr "Konsole löschen"
+
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr "Editiermodus"
+
+#: ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:190
+#: ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr "Objekt"
+
+#: ../src/pd_menus.tcl:149
+#: ../src/pd_menus.tcl:194
+#: ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr "Zahl"
+
+#: ../src/pd_menus.tcl:151
+#: ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr "Symbol"
+
+#: ../src/pd_menus.tcl:153
+#: ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr "Kommentar"
+
+#: ../src/pd_menus.tcl:156
+#: ../src/pd_menus.tcl:201
+#: ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr "Taster (Bang)"
+
+#: ../src/pd_menus.tcl:158
+#: ../src/pd_menus.tcl:203
+#: ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr "Schalter"
+
+#: ../src/pd_menus.tcl:160
+#: ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr "Zahl2"
+
+#: ../src/pd_menus.tcl:162
+#: ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr "Vertikaler Schieberegler"
+
+#: ../src/pd_menus.tcl:164
+#: ../src/pd_menus.tcl:209
+#: ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr "Horizontaler Schieberegler"
+
+#: ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:211
+#: ../src/pd_menus.tcl:212
+msgid "Vradio"
+msgstr "Vertikaler Radioknopf"
+
+#: ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:213
+#: ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr "Horizontaler Radioknopf"
+
+#: ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:215
+#: ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr "Aussteuerungsanzeige"
+
+#: ../src/pd_menus.tcl:172
+#: ../src/pd_menus.tcl:217
+#: ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr "Arbeitsfläche"
+
+#: ../src/pd_menus.tcl:175
+#: ../src/pd_menus.tcl:220
+#: ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Kurve"
+
+#: ../src/pd_menus.tcl:176
+#: ../src/pd_menus.tcl:221
+#: ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr "Feld"
+
+#: ../src/pd_menus.tcl:181
+#: ../src/pd_menus.tcl:226
+#: ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr "Finde..."
+
+#: ../src/pd_menus.tcl:183
+#: ../src/pd_menus.tcl:228
+#: ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr "Finde nochmal"
+
+#: ../src/pd_menus.tcl:185
+#: ../src/pd_menus.tcl:230
+#: ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr "Letzten Fehler finden"
+
+#: ../src/pd_menus.tcl:191
+#: ../src/pd_menus.tcl:236
+#: ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr "DSP An"
+
+#: ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:238
+#: ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr "DSP Aus"
+
+#: ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:242
+#: ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr "Teste Audio und MIDI..."
+
+#: ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:244
+#: ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr "Auslastungsanzeige"
+
+#: ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:251
+#: ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr "Minimieren"
+
+#: ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr "Zoom"
+
+#: ../src/pd_menus.tcl:210
+#: ../src/pd_menus.tcl:256
+#: ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr "Übergeordnetes Fenster"
+
+#: ../src/pd_menus.tcl:216
+#: ../src/pd_menus.tcl:262
+#: ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr "Alle nach vorne bringen"
+
+#: ../src/pd_menus.tcl:224
+#: ../src/pd_menus.tcl:241
+#: ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270
+#: ../src/pd_menus.tcl:297
+#: ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr "Über Pd"
+
+#: ../src/pd_menus.tcl:227
+#: ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr "HTML Anleitung"
+
+#: ../src/pd_menus.tcl:229
+#: ../src/pd_menus.tcl:275
+#: ../src/pd_menus.tcl:302
+msgid "Browser..."
+msgstr "Patch Browser..."
+
+#: ../src/pd_menus.tcl:248
+#: ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Voreinstellungen..."
+
+#: ../src/pd_menus.tcl:257
+#: ../src/pd_menus.tcl:270
+#: ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr "Letzte Dateien öffnen"
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr "Audioeinstellungen..."
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr "MIDI Einstellungen..."
+
+#: ../src/pd_menus.tcl:296
+#: ../src/pd_menus.tcl:309
+#: ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346
+#: ../src/pd_menus.tcl:393
+#: ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432
+#: ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Beenden"
+
+#: ../src/pd_menus.tcl:304
+#: ../src/pd_menus.tcl:331
+msgid "Clear Menu"
+msgstr "Menü löschen"
+
+#: ../src/pdtk_canvas.tcl:44
+#: ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109
+#: ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125
+#: ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr "Einstellungen"
+
+#, fuzzy
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr ""
+
+#, fuzzy
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr "Generatoren"
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr "Filter"
+
+#: ../startup/object_db.tcl:116
+#: ../startup/object_db.tcl:124
+msgid "Math"
+msgstr "Mathe"
+
+#, fuzzy
+#: ../startup/object_db.tcl:117
+#: ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#, fuzzy
+#: ../startup/object_db.tcl:118
+#: ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119
+#: ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr "Signalverlauf"
+
+#: ../startup/object_db.tcl:120
+#: ../startup/object_db.tcl:129
+msgid "Others"
+msgstr "Andere"
+
+#, fuzzy
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
+
+# iemgui
+msgid "left:"
+msgstr "links:"
+
+# iemgui
+msgid "right:"
+msgstr "rechts:"
+
+# iemgui
+msgid "----------dimensions(pix):-----------"
+msgstr "----------Rahmengröße(pix):-----------"
+
+# iemgui
+msgid "--------dimensions(pix)(pix):--------"
+msgstr "--------Rahmengröße(pix)(pix):--------"
+
+# iemgui
+msgid "-------dimensions(digits)(pix):-------"
+msgstr "------Rahmengröße(Zahlen)(pix):-------"
diff --git a/pd/po/el.po b/pd/po/el.po
new file mode 100644
index 00000000..40765415
--- /dev/null
+++ b/pd/po/el.po
@@ -0,0 +1,1152 @@
+# Greek translation of Pure Data
+# This file is put in the public domain
+# Γεώργιος Κερατζάκης <geokeratz@gmail.com>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-25 23:00-0400\n"
+"PO-Revision-Date: 2009-09-13 01:51+0200\n"
+"Last-Translator: Γεώργιος Κερατζάκης <geokeratz@gmail.com>\n"
+"Language-Team: Greek <pd-dev@iem.at>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Discard changes to '%s'?"
+msgstr "Απόρριψη αλλαγών σε '%s';"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "Αποθήκευση αλλαγών που έγιναν στο '%s';"
+
+#: ../src/dialog_array.tcl:115
+#: ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100
+#: ../src/pd_menus.tcl:101
+#: ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Αντιγραφή"
+
+#: ../src/dialog_array.tcl:118
+#: ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102
+#: ../src/pd_menus.tcl:103
+#: ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr "Επικόλληση"
+
+#: ../src/dialog_array.tcl:264
+#: ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Ιδιότητες Πίνακα"
+
+#: ../src/dialog_array.tcl:270
+#: ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Όνομα:"
+
+#: ../src/dialog_array.tcl:276
+#: ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178
+#: ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619
+#: ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Μέγεθος:"
+
+#: ../src/dialog_array.tcl:280
+#: ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Αποθήκευση περιεχομένων"
+
+#: ../src/dialog_array.tcl:284
+#: ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr "Σχεδίαση ως:"
+
+#: ../src/dialog_array.tcl:287
+#: ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Σημεία"
+
+#: ../src/dialog_array.tcl:289
+#: ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Πολύγωνο"
+
+#: ../src/dialog_array.tcl:291
+#: ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Καμπύλη Bezier"
+
+#: ../src/dialog_array.tcl:297
+#: ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr "Προσθήκη πίνακα σε:"
+
+#: ../src/dialog_array.tcl:300
+#: ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr "Νέο γράφημα"
+
+#: ../src/dialog_array.tcl:302
+#: ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr "Τελευταίο γράφημα"
+
+#: ../src/dialog_array.tcl:306
+#: ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr "Διαγραφή πίνακα"
+
+#: ../src/dialog_array.tcl:312
+#: ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr "Άνοιγμα Προβολής Λίστας..."
+
+#: ../src/dialog_array.tcl:319
+#: ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136
+#: ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51
+#: ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161
+#: ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Ακύρωση"
+
+#: ../src/dialog_array.tcl:321
+#: ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138
+#: ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156
+#: ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745
+#: ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93
+#: ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Εφαρμογή"
+
+#: ../src/dialog_array.tcl:323
+#: ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140
+#: ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53
+#: ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100
+#: ../src/dialog_gatom.tcl:159
+#: ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95
+#: ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr "ΟΚ"
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr "Ρυθμίσεις Ήχου"
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr "Αποθήκευση όλων των ρυθμίσεων"
+
+#: ../src/dialog_audio.tcl:151
+#, fuzzy
+msgid "Sample rate:"
+msgstr "Ταχύτητα δειγματοληψίας:"
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr "Καθυστέρηση (msec):"
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr "Χρήση επανακλήσεων"
+
+#: ../src/dialog_audio.tcl:166
+#: ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr "Συσκευή εισόδου 1:"
+
+#: ../src/dialog_audio.tcl:169
+#: ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198
+#: ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232
+#: ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265
+#: ../src/dialog_audio.tcl:280
+msgid "Channels:"
+msgstr "Κανάλια:"
+
+#: ../src/dialog_audio.tcl:179
+#: ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr "Συσκευή εισόδου 2:"
+
+#: ../src/dialog_audio.tcl:194
+#: ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr "Συσκευή εισόδου 3:"
+
+#: ../src/dialog_audio.tcl:209
+#: ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr "Συσκευή εισόδου 4:"
+
+#: ../src/dialog_audio.tcl:223
+#: ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr "Συσκευή εξόδου 1:"
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr "(ομοίως με συσκευή εισόδου) .............."
+
+#: ../src/dialog_audio.tcl:246
+#: ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr "Συσκευή εξόδου 2:"
+
+#: ../src/dialog_audio.tcl:261
+#: ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr "Συσκευή εξόδου 3:"
+
+#: ../src/dialog_audio.tcl:276
+#: ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr "Συσκευή εξόδου 4:"
+
+#: ../src/dialog_audio.tcl:291
+#: ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr "Χρήση πολλαπλών συσκευών"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Ιδιότητες Καμβά"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Κλίμακα"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr "Χ μονάδες ανά εικονοστοιχείο"
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr "Υ μονάδες ανά εικονοστοιχείο"
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr "Εμφάνιση στο γονεϊκό patch"
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "Απόκρυψη ονόματος και ορισμάτων του object"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr "Περιοχή και μέγεθος"
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr "περιοχή Χ, από"
+
+#: ../src/dialog_canvas.tcl:176
+#: ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "σε"
+
+#: ../src/dialog_canvas.tcl:180
+#: ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Περιθώριο:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr "περιοχή Y, από"
+
+#: ../src/dialog_find.tcl:63
+#: ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79
+#: ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87
+#: ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Εύρεση"
+
+#: ../src/dialog_find.tcl:70
+#: ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr "Αναζήτηση σε"
+
+#: ../src/dialog_find.tcl:72
+#: ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr "για:"
+
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104
+#: ../src/dialog_find.tcl:110
+#: ../src/pd_menus.tcl:86
+#: ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132
+#: ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272
+#: ../src/pd_menus.tcl:295
+#: ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332
+#: ../src/pd_menus.tcl:345
+#: ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:392
+#: ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431
+#: ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Κλείσιμο"
+
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr "Ταύτιση μόνο ολόκληρης λέξης"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr "Ιδιότητες Γραμματοσειράς"
+
+#: ../src/dialog_font.tcl:46
+#: ../src/dialog_font.tcl:54
+#, tcl-format
+msgid "%s Font"
+msgstr "Γραμματοσειρά %s"
+
+#: ../src/dialog_font.tcl:49
+#: ../src/pd-gui.tcl:280
+#: ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286
+#: ../src/pd-gui.tcl:288
+#: ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212
+#: ../src/pd_menus.tcl:258
+#: ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr "Παράθυρο Pd"
+
+#: ../src/dialog_font.tcl:61
+#: ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104
+msgid "Font Size"
+msgstr "Μέγεθος Γραμματοσειράς"
+
+#: ../src/dialog_font.tcl:89
+#: ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116
+msgid "Stretch"
+msgstr "Τέντωμα"
+
+#: ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123
+msgid "X and Y"
+msgstr "Χ και Y"
+
+#: ../src/dialog_font.tcl:98
+#: ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125
+msgid "X only"
+msgstr "Μόνο Χ"
+
+#: ../src/dialog_font.tcl:100
+#: ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127
+msgid "Y only"
+msgstr "Μόνο Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Ιδιότητες Atom Box"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Εύρος:"
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr "Όρια"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Κατώτερο:"
+
+#: ../src/dialog_gatom.tcl:112
+#: ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Ανώτερο:"
+
+#: ../src/dialog_gatom.tcl:116
+#: ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600
+#: ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr "Ετικέτα"
+
+#: ../src/dialog_gatom.tcl:124
+#: ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Αριστερά"
+
+#: ../src/dialog_gatom.tcl:126
+#: ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Δεξιά"
+
+#: ../src/dialog_gatom.tcl:128
+#: ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Κορυφή"
+
+#: ../src/dialog_gatom.tcl:130
+#: ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Κάτω"
+
+#: ../src/dialog_gatom.tcl:137
+#: ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr "Μηνύματα"
+
+#: ../src/dialog_gatom.tcl:141
+#: ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr "Αποστολή symbol:"
+
+#: ../src/dialog_gatom.tcl:147
+#: ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Λήψη συμβόλου:"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Χρώμα φόντου"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Χρώμα πρώτου πλάνου"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Χρώμα ετικέτας"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:275
+#: ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287
+#: ../src/dialog_iemgui.tcl:558
+#, fuzzy
+msgid "Jump on click"
+msgstr "Μεταπήδηση στο κλικ"
+
+#: ../src/dialog_iemgui.tcl:290
+#: ../src/dialog_iemgui.tcl:561
+#, fuzzy
+msgid "Steady on click"
+msgstr "Σταθερότητα στο κλικ"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "%s Ιδιότητες"
+
+#: ../src/dialog_iemgui.tcl:550
+#: ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:288
+#: ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325
+#: ../src/pd_menus.tcl:338
+#: ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382
+#: ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422
+#: ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Αποθήκευση"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "Παράθεση Χ"
+
+#: ../src/dialog_iemgui.tcl:611
+#: ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr "Παράθεση Υ"
+
+#: ../src/dialog_iemgui.tcl:642
+#: ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Χρώματα"
+
+#: ../src/dialog_iemgui.tcl:648
+#: ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr "Φόντο"
+
+#: ../src/dialog_iemgui.tcl:650
+#: ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr "Πρώτο Πλάνο"
+
+#: ../src/dialog_iemgui.tcl:662
+#: ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Σύνθεση χρώματος"
+
+#: ../src/dialog_iemgui.tcl:682
+#: ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr "Ρυθμίσεις MIDI"
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr "Ρυθμίσεις ALSA MIDI"
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr "Χρήση πολλαπλών συσκευών ALSA"
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr "Θύρες Εισόδου:"
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr "Θύρες Εξόδου:"
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr "Απόρριψη αλλαγών σε αυτό το παράθυρο;;"
+
+#: ../src/g_editor.c:1668
+#, fuzzy
+msgid "really quit?"
+msgstr "έξοδος οπωσδήποτε;"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Κλείσιμο αυτού του παραθύρου;;"
+
+#: ../src/pd-gui.tcl:185
+#: ../src/pd-gui.tcl:195
+#: ../src/pd-gui.tcl:206
+msgid "Associated Files"
+msgstr "Συνδεόμενα Αρχεία"
+
+#: ../src/pd-gui.tcl:186
+#: ../src/pd-gui.tcl:196
+#: ../src/pd-gui.tcl:207
+msgid "Pd Files"
+msgstr "Αρχεία Pd"
+
+#: ../src/pd-gui.tcl:187
+#: ../src/pd-gui.tcl:208
+msgid "Max Patch Files"
+msgstr "Αρχεία Patch από MAX"
+
+#: ../src/pd-gui.tcl:188
+#: ../src/pd-gui.tcl:209
+msgid "Max Text Files"
+msgstr "Αρχεία Κειμένου από MAX"
+
+#: ../src/pd-gui.tcl:197
+msgid "Max Patch Files (.pat)"
+msgstr "Αρχεία Patch από MAX (.pat)"
+
+#: ../src/pd-gui.tcl:198
+msgid "Max Text Files (.mxt)"
+msgstr "Αρχεία Κειμένου από MAX (.mxt)"
+
+#: ../src/pd-gui.tcl:270
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr "ΠΡΟΣΟΧΗ: Η οικογένεια γραμματοσειράς '%s' δεν βρέθηκε, χρήση προεπιλογής (%s)"
+
+#: ../src/pd-gui.tcl:278
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr "ΠΡΟΣΟΧΗ: Το βάρος γραμματοσειράς '%s' δεν βρέθηκε, χρήση προεπιλογής (%s)"
+
+#: ../src/pd-gui.tcl:303
+#, fuzzy, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr "ΣΦΑΛΜΑ: %s αποτυχία εύρεσης μεγέθους γραμματοσειράς (%s) που προσαρμόζεται στο %sx%s!"
+
+#: ../src/pd-gui.tcl:478
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr "ΣΦΑΛΜΑ: το 'pd' δεν εμφανίστηκε ποτέ, έξοδος του 'pd-gui'!"
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr "Ανώνυμο"
+
+#: ../src/pd_menucommands.tcl:78
+#: ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Αποστολή Μηνύματος..."
+
+#: ../src/pd_menucommands.tcl:82
+#: ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94
+#: ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192
+#: ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:292
+#: ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329
+#: ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387
+#: ../src/pd_menus.tcl:414
+#: ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453
+#: ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Μήνυμα"
+
+#: ../src/pd_menucommands.tcl:108
+#: ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112
+#: ../src/pd_menus.tcl:113
+#: ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118
+#: ../src/pd_menus.tcl:158
+#: ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163
+#: ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr "Γραμματοσειρά"
+
+#: ../src/pd_menucommands.tcl:123
+#: ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:183
+#: ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr "Προτιμήσεις"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Επεξεργασία"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Αρχείο"
+
+#: ../src/pd_menus.tcl:45
+#: ../src/pdtk_canvas.tcl:48
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Βοήθεια"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Μέσα"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Προσθήκη"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Παράθυρο"
+
+#: ../src/pd_menus.tcl:81
+#: ../src/pd_menus.tcl:82
+#: ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:255
+#: ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:298
+#: ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:349
+#: ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380
+#: ../src/pd_menus.tcl:407
+#: ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Νέο"
+
+#: ../src/pd_menus.tcl:82
+#: ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:256
+#: ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286
+#: ../src/pd_menus.tcl:299
+#: ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336
+#: ../src/pd_menus.tcl:350
+#: ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:408
+#: ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447
+#: ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:131
+#: ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Άνοιγμα"
+
+#: ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:85
+#: ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131
+#: ../src/pd_menus.tcl:261
+#: ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289
+#: ../src/pd_menus.tcl:302
+#: ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339
+#: ../src/pd_menus.tcl:356
+#: ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384
+#: ../src/pd_menus.tcl:411
+#: ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Αποθήκευση Ως..."
+
+#: ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:89
+#: ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135
+#: ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293
+#: ../src/pd_menus.tcl:306
+#: ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343
+#: ../src/pd_menus.tcl:362
+#: ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389
+#: ../src/pd_menus.tcl:415
+#: ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr "Εκτύπωση..."
+
+#: ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:94
+#: ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr "Αναίρεση"
+
+#: ../src/pd_menus.tcl:95
+#: ../src/pd_menus.tcl:96
+#: ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr "Ακύρωση Αναίρεσης"
+
+#: ../src/pd_menus.tcl:98
+#: ../src/pd_menus.tcl:99
+#: ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr "Αποκοπή"
+
+#: ../src/pd_menus.tcl:104
+#: ../src/pd_menus.tcl:105
+#: ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr "Αντίγραφο"
+
+#: ../src/pd_menus.tcl:106
+#: ../src/pd_menus.tcl:107
+#: ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr "Επιλογή Όλων"
+
+#: ../src/pd_menus.tcl:110
+#: ../src/pd_menus.tcl:111
+#: ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116
+#: ../src/pd_menus.tcl:156
+#: ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161
+#: ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr "Επεξεργαστής Κειμένου"
+
+#: ../src/pd_menus.tcl:120
+#: ../src/pd_menus.tcl:121
+#: ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr "Τακτοποίηση"
+
+#: ../src/pd_menus.tcl:122
+#: ../src/pd_menus.tcl:123
+#: ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr "Εναλλαγή Κονσόλας"
+
+#: ../src/pd_menus.tcl:124
+#: ../src/pd_menus.tcl:125
+#: ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr "Καθαρισμός Κονσόλας"
+
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr "Κατάσταση Επεξεργασίας"
+
+#: ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:190
+#: ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149
+#: ../src/pd_menus.tcl:194
+#: ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr ""
+
+#: ../src/pd_menus.tcl:151
+#: ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153
+#: ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr "Σχόλιο"
+
+#: ../src/pd_menus.tcl:156
+#: ../src/pd_menus.tcl:201
+#: ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr ""
+
+#: ../src/pd_menus.tcl:158
+#: ../src/pd_menus.tcl:203
+#: ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr ""
+
+#: ../src/pd_menus.tcl:160
+#: ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr ""
+
+#: ../src/pd_menus.tcl:162
+#: ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr "Κάθετο slider"
+
+#: ../src/pd_menus.tcl:164
+#: ../src/pd_menus.tcl:209
+#: ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr "Οριζόντιο slider"
+
+#: ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:211
+#: ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Κάθετο radio"
+
+#: ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:213
+#: ../src/pd_menus.tcl:214
+#, fuzzy
+msgid "Hradio"
+msgstr "Οριζόντιο radio"
+
+#: ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:215
+#: ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr "Μετρητής VU"
+
+#: ../src/pd_menus.tcl:172
+#: ../src/pd_menus.tcl:217
+#: ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr "Καμβάς"
+
+#: ../src/pd_menus.tcl:175
+#: ../src/pd_menus.tcl:220
+#: ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Γράφημα"
+
+#: ../src/pd_menus.tcl:176
+#: ../src/pd_menus.tcl:221
+#: ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr "Πίνακας"
+
+#: ../src/pd_menus.tcl:181
+#: ../src/pd_menus.tcl:226
+#: ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr "Εύρεση..."
+
+#: ../src/pd_menus.tcl:183
+#: ../src/pd_menus.tcl:228
+#: ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr "Εύρεση εκ νέου"
+
+#: ../src/pd_menus.tcl:185
+#: ../src/pd_menus.tcl:230
+#: ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr "Εύρεση Τελευταίου Σφάλματος"
+
+#: ../src/pd_menus.tcl:191
+#: ../src/pd_menus.tcl:236
+#: ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr "Ενεργοποίηση DSP"
+
+#: ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:238
+#: ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr "Απενεργοποίση DSP"
+
+#: ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:242
+#: ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr "Έλεγχος 'Ηχου και MIDI..."
+
+#: ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:244
+#: ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr "Φόρτωση Μετρητή"
+
+#: ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:251
+#: ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr "Ελαχιστοποιήση"
+
+#: ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr "Εστίαση"
+
+#: ../src/pd_menus.tcl:210
+#: ../src/pd_menus.tcl:256
+#: ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr "Γονεϊκό Παράθυρο"
+
+#: ../src/pd_menus.tcl:216
+#: ../src/pd_menus.tcl:262
+#: ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr "Μεταφορά Όλων σε Πρώτο Πλάνο"
+
+#: ../src/pd_menus.tcl:224
+#: ../src/pd_menus.tcl:241
+#: ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270
+#: ../src/pd_menus.tcl:297
+#: ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr "Περί..."
+
+#: ../src/pd_menus.tcl:227
+#: ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr "Εγχειρίδιο HTML..."
+
+#: ../src/pd_menus.tcl:229
+#: ../src/pd_menus.tcl:275
+#: ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Πλοήγηση..."
+
+#: ../src/pd_menus.tcl:248
+#: ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Προτιμήσεις..."
+
+#: ../src/pd_menus.tcl:257
+#: ../src/pd_menus.tcl:270
+#: ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr "Άνοιγμα Πρόσφατου"
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr "Ρυθμίσεις Ήχου..."
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr "Ρυθμίσεις MIDI..."
+
+#: ../src/pd_menus.tcl:296
+#: ../src/pd_menus.tcl:309
+#: ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346
+#: ../src/pd_menus.tcl:393
+#: ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432
+#: ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Έξοδος"
+
+#: ../src/pd_menus.tcl:304
+#: ../src/pd_menus.tcl:331
+msgid "Clear Menu"
+msgstr "Καθαρισμός Μενού"
+
+#: ../src/pdtk_canvas.tcl:44
+#: ../src/pdtk_canvas.tcl:109
+#: ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr "Ιδιότητες"
+
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr ""
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr "Σήμα"
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr "Γεννήτριες"
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr "Φίλτρα"
+
+#: ../startup/object_db.tcl:116
+#: ../startup/object_db.tcl:124
+msgid "Math"
+msgstr "Μαθηματικά"
+
+#: ../startup/object_db.tcl:117
+#: ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118
+#: ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr "Δειγματοληψία"
+
+#: ../startup/object_db.tcl:119
+#: ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr "Δρομολόγηση"
+
+#: ../startup/object_db.tcl:120
+#: ../startup/object_db.tcl:129
+msgid "Others"
+msgstr "Άλλα"
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
+
+#, fuzzy
+#~ msgid "Patch Font"
+#~ msgstr "Γραμματοσειρά του Patch"
+
diff --git a/pd/po/en_ca.po b/pd/po/en_ca.po
new file mode 100644
index 00000000..e474741d
--- /dev/null
+++ b/pd/po/en_ca.po
@@ -0,0 +1,887 @@
+# The Canadian English translation for Pure Data
+# This file is put in the public domain.
+# Ben Bogart <ben@ekran.org>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2009-08-25 18:19-0400\n"
+"Last-Translator: Ben Bogart <ben@ekran.org>\n"
+"Language-Team: Canadian English <pd-list@iem.at>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Undo duplicate"
+msgstr ""
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+msgid "Undo cut"
+msgstr ""
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr ""
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr ""
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr ""
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr ""
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr ""
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Béziercurve"
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr ""
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr ""
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr ""
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr ""
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+msgid "Channels:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr ""
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr ""
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr ""
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr ""
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr ""
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, tcl-format
+msgid "%s Font"
+msgstr ""
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+msgid "Font Size"
+msgstr ""
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr ""
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Background colour"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Foreground colour"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Label colour"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Colours"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Compose colour"
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr ""
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+msgid "Pd Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr ""
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr ""
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr ""
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr ""
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr ""
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr ""
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr ""
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr ""
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr ""
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr ""
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr ""
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr ""
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr ""
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr ""
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+msgid "Vradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr ""
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr ""
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr ""
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr ""
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr ""
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr ""
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr ""
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+msgid "Browser..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr ""
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+msgid "Clear Menu"
+msgstr ""
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr ""
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr ""
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/eu.po b/pd/po/eu.po
new file mode 100644
index 00000000..d064d4a6
--- /dev/null
+++ b/pd/po/eu.po
@@ -0,0 +1,953 @@
+# Basque translation of Pure Data.
+# This file is put in the public domain.
+# Mikel Olasagasti <hey_neken@euskal.org>, 2004, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-08-21 21:10+0200\n"
+"Last-Translator: Mikel Olasagasti <hey_neken@mundurat.net>\n"
+"Language-Team: Basque <translation-team-eu@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Data"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "Uganda"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Kopiatu"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Data"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Izena"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Tamainua:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "_Edukia"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Ataka"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Polonia"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Azken mezua:"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Ezabatu"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "Debekatuen zerrenda..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Utzi"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Aplikatu"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Utzi"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Gorde"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Marka lerroa:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Bilatu"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "Bilatu testua..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Ataka:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Itxi"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Bidalketa leihoa"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Letra-tipoa"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Tamainua:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "Hasiera:"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Zerrendak"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "Erabiltzailea:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "Ezkerrean"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Eskuinean"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Goian"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Behean"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "Mezua"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Jaso leihoa"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Atzeko planoa:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Aurreko planoa:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Aukeratu kolorea"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Gonbidatu"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Gorde"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Koloreak"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Atzeko planoa:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Letra-tipoa"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Egiaztatu denak"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "Fitxa/leiho hau itxitzen du"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Fitxategia"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "Mezua"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Mezua"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Letra-tipoa"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "Hobespenak..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "_Editatu"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Fitxategia"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Laguntza"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Macedonia"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "_Leihoa"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Berria"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Ireki"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "Gorde honela"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "_Editatu..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "Uganda"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "Gorria:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Data"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Ezabatu guztiak"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Testu koloreak"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Garbitu zerrenda"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Edizio modua"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Zenbakia"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Komandoa"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Debekatu"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Togo"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Zenbakia"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "Ezkutatu"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Bertsioa"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Kanada"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Grafikoa"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Andorra"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Bidali fitxategiak..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Off"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Atzerapen neurtzailea:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Behean"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Bidalketa leihoa"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "_Honi buruz"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Arakatu..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Hobespenak..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Irten"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Garbitu zerrenda"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Off"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Fitxategia"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/fr.po b/pd/po/fr.po
new file mode 100644
index 00000000..5d02d16f
--- /dev/null
+++ b/pd/po/fr.po
@@ -0,0 +1,542 @@
+# French translation for Pure Data
+# This file is put in the public domain.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-18 20:56-0400\n"
+"PO-Revision-Date: \n"
+"Last-Translator: Cyrille Henry\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/dialog_array.tcl:117 ../src/pd_menus.tcl:100
+msgid "Copy"
+msgstr "Copier"
+
+#: ../src/dialog_array.tcl:120 ../src/pd_menus.tcl:102
+msgid "Paste"
+msgstr "Coller"
+
+#: ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Propriétés du tableau"
+
+#: ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Nom:"
+
+#: ../src/dialog_array.tcl:278 ../src/dialog_canvas.tcl:178
+#: ../src/dialog_canvas.tcl:193 ../src/dialog_iemgui.tcl:619
+msgid "Size:"
+msgstr "Taille:"
+
+#: ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Sauver le contenu"
+
+#: ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Points"
+
+#: ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Polygone"
+
+#: ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "courbe de Bezier"
+
+#: ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr "Nouveau graphique"
+
+#: ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr "supprimer le tableau"
+
+#: ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr ""
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:161
+#: ../src/dialog_iemgui.tcl:742
+msgid "Cancel"
+msgstr "Annuler"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:164 ../src/dialog_iemgui.tcl:745
+msgid "Apply"
+msgstr "Appliquer"
+
+#: ../src/dialog_array.tcl:325 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748
+msgid "OK"
+msgstr "OK"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Propriétés du Canvas"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Echéle"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "cacher le nom et arguments de l'objet"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr "taille et échèle"
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "à"
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Marges"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:80 ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Rechercher"
+
+#: ../src/dialog_find.tcl:70
+msgid "Search in"
+msgstr "Rechercher dans"
+
+#: ../src/dialog_find.tcl:72
+msgid "for:"
+msgstr "pour:"
+
+#: ../src/dialog_find.tcl:83 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:332
+msgid "Close"
+msgstr "Fermer"
+
+#: ../src/dialog_font.tcl:45
+msgid "Patch Font"
+msgstr "Police du patch"
+
+#: ../src/dialog_font.tcl:61
+msgid "Font Size:"
+msgstr "taille de la police:"
+
+#: ../src/dialog_font.tcl:89
+msgid "Stretch:"
+msgstr "Étirer"
+
+#: ../src/dialog_font.tcl:96
+msgid "X and Y"
+msgstr "X et Y"
+
+#: ../src/dialog_font.tcl:98
+msgid "X only"
+msgstr "seulement X"
+
+#: ../src/dialog_font.tcl:100
+msgid "Y only"
+msgstr "seulement Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Propriétés du nombre"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Largeur:"
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr "Limites"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Inférieur:"
+
+#: ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Supérieur:"
+
+#: ../src/dialog_gatom.tcl:121 ../src/dialog_iemgui.tcl:600
+#: ../src/dialog_iemgui.tcl:652
+msgid "Label"
+msgstr "Label"
+
+#: ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Gauche"
+
+#: ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Droite"
+
+#: ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Haut"
+
+#: ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Bas"
+
+#: ../src/dialog_gatom.tcl:145 ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr "Messages"
+
+#: ../src/dialog_gatom.tcl:149 ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr "Envoyer au symbole:"
+
+#: ../src/dialog_gatom.tcl:155 ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Reçois du symbole"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Couleur du fond"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Couleur du premier plan"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr "Initialisation"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr "Pas d'initialisation"
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "%s Propriétés"
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:325
+msgid "Save"
+msgstr "Sauvegarder"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "Offset en X"
+
+#: ../src/dialog_iemgui.tcl:611
+msgid "Y offset"
+msgstr "Offset en Y"
+
+#: ../src/dialog_iemgui.tcl:642
+msgid "Colors"
+msgstr "Couleur"
+
+#: ../src/dialog_iemgui.tcl:648
+msgid "Background"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:650
+msgid "Front"
+msgstr "Police de caractére"
+
+#: ../src/dialog_iemgui.tcl:662
+msgid "Compose color"
+msgstr "créer la couleur"
+
+#: ../src/dialog_iemgui.tcl:682
+msgid "Test label"
+msgstr ""
+
+#: ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283 ../src/pd_menus.tcl:212
+msgid "Pd window"
+msgstr "Fenêtre Pd"
+
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Envoyer Message..."
+
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:147 ../src/pd_menus.tcl:265 ../src/pd_menus.tcl:292
+#: ../src/pd_menus.tcl:329
+msgid "Message"
+msgstr "Message"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:117
+msgid "Font"
+msgstr "Police"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138
+msgid "Preferences"
+msgstr "Préférences"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Édition"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Fichier"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48
+msgid "Help"
+msgstr "Aide"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Média"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Ajouter"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Fenêtre"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:322
+msgid "New"
+msgstr "Nouveau"
+""
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:286
+#: ../src/pd_menus.tcl:323 ../src/pdtk_canvas.tcl:46
+msgid "Open"
+msgstr "Ouvrir"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:289
+#: ../src/pd_menus.tcl:326
+msgid "Save As..."
+msgstr "Sauvegarder Sous..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:293
+#: ../src/pd_menus.tcl:330
+msgid "Print..."
+msgstr "Imprimer..."
+
+#: ../src/pd_menus.tcl:93
+msgid "Undo"
+msgstr "Défaire"
+
+#: ../src/pd_menus.tcl:95
+msgid "Redo"
+msgstr "Refaire"
+
+#: ../src/pd_menus.tcl:98
+msgid "Cut"
+msgstr "Couper"
+
+#: ../src/pd_menus.tcl:104
+msgid "Duplicate"
+msgstr "Dupliquer"
+
+#: ../src/pd_menus.tcl:106
+msgid "Select All"
+msgstr "Sélectionner tout"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:115
+msgid "Text Editor"
+msgstr "éditeur de texte..."
+
+#: ../src/pd_menus.tcl:120
+msgid "Tidy Up"
+msgstr "Aligner"
+
+#: ../src/pd_menus.tcl:122
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124
+msgid "Clear Console"
+msgstr "Effacer la console"
+
+#: ../src/pd_menus.tcl:128
+msgid "Edit Mode"
+msgstr "Mode d'édition"
+
+#: ../src/pd_menus.tcl:145
+msgid "Object"
+msgstr "Objet"
+
+#: ../src/pd_menus.tcl:149
+msgid "Number"
+msgstr "Nombre"
+
+#: ../src/pd_menus.tcl:151
+msgid "Symbol"
+msgstr "Symbole"
+
+#: ../src/pd_menus.tcl:153
+msgid "Comment"
+msgstr "Commentaire"
+
+#: ../src/pd_menus.tcl:156
+msgid "Bang"
+msgstr "Bang"
+
+#: ../src/pd_menus.tcl:158
+msgid "Toggle"
+msgstr "interrupteur"
+
+#: ../src/pd_menus.tcl:160
+msgid "Number2"
+msgstr "Nombre2"
+
+#: ../src/pd_menus.tcl:162
+msgid "Vslider"
+msgstr "slider_V"
+
+#: ../src/pd_menus.tcl:164
+msgid "Hslider"
+msgstr "Slider_H"
+
+#: ../src/pd_menus.tcl:166
+msgid "Vradio"
+msgstr "selecteur_V"
+
+#: ../src/pd_menus.tcl:168
+msgid "Hradio"
+msgstr "selecteur_H"
+
+#: ../src/pd_menus.tcl:170
+msgid "VU Meter"
+msgstr "VU-mètre"
+
+#: ../src/pd_menus.tcl:172
+msgid "Canvas"
+msgstr "Canvas"
+
+#: ../src/pd_menus.tcl:175
+msgid "Graph"
+msgstr "Graphique"
+
+#: ../src/pd_menus.tcl:176
+msgid "Array"
+msgstr "Tableau"
+
+#: ../src/pd_menus.tcl:181
+msgid "Find..."
+msgstr "Rechercher"
+
+#: ../src/pd_menus.tcl:183
+msgid "Find Again"
+msgstr "Rechercher encore"
+
+#: ../src/pd_menus.tcl:185
+msgid "Find Last Error"
+msgstr "Rechercher la dernière erreur"
+
+#: ../src/pd_menus.tcl:191
+msgid "DSP On"
+msgstr "DSP On"
+
+#: ../src/pd_menus.tcl:193
+msgid "DSP Off"
+msgstr "DSP off"
+
+#: ../src/pd_menus.tcl:196
+msgid "Test Audio and MIDI..."
+msgstr "Tester l'audio et le MIDI"
+
+#: ../src/pd_menus.tcl:198
+msgid "Load Meter"
+msgstr "CPU-mètre"
+
+#: ../src/pd_menus.tcl:205
+msgid "Minimize"
+msgstr "Minimiser"
+
+#: ../src/pd_menus.tcl:207
+msgid "Zoom"
+msgstr "Zoom"
+
+#: ../src/pd_menus.tcl:210
+msgid "Parent Window"
+msgstr "Fenêtre"
+
+#: ../src/pd_menus.tcl:216
+msgid "Bring All to Front"
+msgstr "Tout au premier plan"
+
+#: ../src/pd_menus.tcl:241
+msgid "About Pd"
+msgstr "À propos de Pd"
+
+#: ../src/pd_menus.tcl:248
+msgid "Preferences..."
+msgstr "Préférences..."
+
+#: ../src/pd_menus.tcl:257
+msgid "Open Recent"
+msgstr "ouvrir éléments récent"
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:333
+msgid "Quit"
+msgstr "Quitter"
+
+#: ../src/pdtk_canvas.tcl:44
+msgid "Properties"
+msgstr "Propriétés"
+
+#~ msgid "Audio OFF"
+#~ msgstr "Audio OFF"
+
+#~ msgid "Audio ON"
+#~ msgstr "Audio ON"
+
+#~ msgid "Paths"
+#~ msgstr "Chemins..."
diff --git a/pd/po/gu.po b/pd/po/gu.po
new file mode 100644
index 00000000..51388b84
--- /dev/null
+++ b/pd/po/gu.po
@@ -0,0 +1,956 @@
+# Translation of Pure Data-0.43.gu.po to Gujarati.
+# This file is put in the public domain.
+# Ankit Patel <ankit644@yahoo.com>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data-0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-09-14 12:49+0530\n"
+"Last-Translator: Ankit Patel <ankit644@yahoo.com>\n"
+"Language-Team: Gujarati <indianoss-gujarati@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "તારીખ"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "યુગાન્ડા"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "નકલ કરો"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "તારીખ"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "નામ"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "માપ:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "સમાવિષ્ટો (_C)"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "પોર્ટ"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "પોલેન્ડ"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "છેલ્લો સંદેશો:"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "દૂર કરો"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "બેન યાદી..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "રદ કરો"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "અમલમાં મૂકો"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "રદ કરો"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "સંગ્રહ કરો"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "માર્કર લાઈન:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "શોધો"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "લખાણ શોધો..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "પોર્ટ:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "બંધ કરો"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "મોકલો વિન્ડો"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "ફોન્ટ:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "માપ:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "શરૂ કરાયેલ:"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "વપરાશકર્તા મર્યાદા"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "વપરાશકર્તા:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "ડાબે"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "જમણુ"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "ઉપર"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "નીચે"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "સંદેશો"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "મેળવો વિન્ડો"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "પાશ્વ ભાગ:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "અગ્ર ભાગ:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "રંગ પસંદ કરો"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "આમંત્રણ આપો"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "સંગ્રહ કરો"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "રંગો"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "પાશ્વ ભાગ:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "ફોન્ટ:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "બધું ચકાસો"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "આ ટેબ/વિન્ડો બંધ કરો"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "ફાઇલ"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "સંદેશો"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "સંદેશો"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "ફોન્ટ:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "પસંદગીઓ..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "ફેરફાર કરો (_E)"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "ફાઇલ"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "મદદ"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "મેકેડોનિયા"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "વિન્ડો (_W)"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "નવું"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "ખોલો"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "આ રીતે સંગ્રહ કરો"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "ફેરફાર કરો (_E)..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "યુગાન્ડા"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "લાલ:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "તારીખ"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "રંગ પસંદ કરો"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "લખાણ રંગો"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "યાદી સાફ કરો"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "સ્થિતિ"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ નંબર"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "આદેશ"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "બેન"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "ટોગો"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ નંબર"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "છુપુ"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "આવૃત્તિ"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "કેનેડા"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "ગ્રાફ"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "અન્ડોરા"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "ફાઈલ મોકલો..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "બંધ"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "લેગ મીટર:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "નીચે"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "મોકલો વિન્ડો"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "વિશે (_A)"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "શોધો..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "પસંદગીઓ..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "બહાર નીકળો"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "યાદી સાફ કરો"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "બંધ"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "ફાઇલ"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/he.po b/pd/po/he.po
new file mode 100644
index 00000000..474686c7
--- /dev/null
+++ b/pd/po/he.po
@@ -0,0 +1,939 @@
+# Hebrew translation of Pure Data.
+# This file is put in the public domain
+# you can be the first! <pd-list@iem.at>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2001-10-03 15:48+02:00\n"
+"Last-Translator: xchat <pd-list@iem.at>\n"
+"Language-Team: Hebrew <pd-list@iem.at>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Undo duplicate"
+msgstr ""
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+msgid "Undo cut"
+msgstr ""
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr ""
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "פאנל"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "כתובת איי פי של שרת הפרוקסי:"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "הזדהות אוטומטית"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "פלאגין..."
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "טען"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr ""
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "חלון רשימת ערוצים.."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "ביטול"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "החל"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "ביטול"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr ""
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "חפש בבאפר.."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "גופן:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "סגור"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "_חלונות"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "גופן:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "גודל חלון"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr ""
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "רוחב:"
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "רשימת פייטון"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "תפריט משתמש"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+#, fuzzy
+msgid "Label"
+msgstr "פאנל"
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "שמאל"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "ימין"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "עליון"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "תחתון"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "הודעת יציאה:"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "קבצים שהתקבלו"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "XPM ברקע:"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "בחר גופן"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "בלתי נראה"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+#, fuzzy
+msgid "Colors"
+msgstr "סגור"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "XPM ברקע:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "גופן:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr ""
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+#, fuzzy
+msgid "Associated Files"
+msgstr "לאשר אוטומטית שליחות של דיסיסי"
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+msgid "Pd Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+#, fuzzy
+msgid "Untitled"
+msgstr "ללא סידור"
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "הודעת יציאה:"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+#, fuzzy
+msgid "Message"
+msgstr "הודעת יציאה:"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "גופן:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "איקס-צ'אט: הגדרות"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "עזרה"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "_חלונות"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr ""
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr ""
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "עריכת אירועי טקסט.."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr ""
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "אדום:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr ""
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "בחר גופן"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr ""
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "עריכת תפריט משתמש"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr ""
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "פקודה לניגון:"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "כפתורים"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr ""
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr ""
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "מוחבא"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "הסתר גירסה"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "איקס-צ'אט"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr ""
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "אוואי"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "חלון שליחות דיסיסי.."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr ""
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "טען"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "תחתון"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "חלון ראשי"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "אודות איקס-צ'אט"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "דפדף..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+#, fuzzy
+msgid "Preferences..."
+msgstr "איקס-צ'אט: הגדרות"
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "יציאה"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "תפריט משתמש"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr ""
+
+#: ../startup/object_db.tcl:113
+#, fuzzy
+msgid "Signal"
+msgstr "כללי"
+
+#: ../startup/object_db.tcl:114
+#, fuzzy
+msgid "Generators"
+msgstr "כללי"
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "פאלט.."
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+#, fuzzy
+msgid "Others"
+msgstr "אופציות אחרות של פריסה"
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/hi.po b/pd/po/hi.po
new file mode 100644
index 00000000..982c8f7f
--- /dev/null
+++ b/pd/po/hi.po
@@ -0,0 +1,953 @@
+# Translation of Pure Data 0.43.po to Hindi.
+# This file is put in the public domain.
+# Rajesh Ranjan <rranjan@redhat.com>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-05-04 12:50+0530\n"
+"Last-Translator: Rajesh Ranjan <rranjan@redhat.com>\n"
+"Language-Team: Hindi <fedora-trans-hi@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "तारीख़"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "यूगांडा"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "कॉपी"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "तारीख़"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "नाम"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#, fuzzy
+msgid "Size:"
+msgstr "आकार"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "विषय सूची (_C)"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "पोर्ट"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "पोलेंड"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "मिटाओ"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "प्रतिबंध सूची..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "रद्द"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "लागू करो"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "रद्द"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "सहेजें"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "मार्कर पंक्ति:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "ढूंढें"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "पाठ खोजें..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "पोर्टः"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "बन्द करो"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "भेजें विंडो"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "फ़ॉन्टः"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "फ़ॉन्टः"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr ""
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "उपयोक्ता सीमा"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "आपरेटर"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "बायाँ"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "दाहिना"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "ऊपर"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "नीचे"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "संदेश"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "विंडो पायें"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "पृष्ठभूमि:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "अग्रभूमि:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "रंग चुनें"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "निमंत्रित करें"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "सहेजें"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "रंग"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "पृष्ठभूमि:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "फ़ॉन्टः"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "सबको जांचें"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "इस tab/window बंद करें"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "फाइल"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "संदेश"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "संदेश"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "फ़ॉन्टः"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "प्राथमिकताएं..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "संपादन (_E)"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "फाइल"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "मदद"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "मेसीडोनिया"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "विंडो (_W)"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "नया"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "खोलें"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "इस रूप में सहेजें"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "संपादित करें (_E)..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "यूगांडा"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "लाल:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "तारीख़"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "रंग चुनें"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "पाठ रंग"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "सूची साफ करें"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "मोड"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ संख्या"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "कमांड"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "प्रतिबंध"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "टोगो"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ संख्या"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "छुपा हुआ"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "संस्करण"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "कनाडा"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "ग्राफ"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "अंडोरा"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "फाइल भेजें..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "बंद"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "लैग मीटर:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "नीचे"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "भेजें विंडो"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "के बारे में (_A)"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "ब्राउज़..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "प्राथमिकताएं..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "बाहर"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "सूची साफ करें"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "बंद"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "फाइल"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/hu.po b/pd/po/hu.po
new file mode 100644
index 00000000..10562306
--- /dev/null
+++ b/pd/po/hu.po
@@ -0,0 +1,895 @@
+# Hungarian translation of Pure Data.
+# This file is put in the public domain
+#
+# Andras Muranyi <muranyia@gmail.com>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2010-01-29 21:09+0100\n"
+"Last-Translator: Andras Muranyi <muranyia@gmail.com>\n"
+"Language-Team: Hungarian <hu@gnome.hu>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: "
+
+msgid "Undo duplicate"
+msgstr "Mégsem duplikál"
+
+msgid "Undo paste"
+msgstr "Mégsem illeszt be"
+
+msgid "Undo motion"
+msgstr "Mégsem mozgat"
+
+msgid "Undo cut"
+msgstr "Mégsem vág ki"
+
+msgid "Undo disconnect"
+msgstr "Mégsem törli a csatlakozást"
+
+msgid "Undo connect"
+msgstr "Mégsem csatlakoztat"
+
+msgid "Undo clear"
+msgstr "Mégsem töröl"
+
+msgid "Undo typing"
+msgstr "Mégsem ír"
+
+msgid "Discard changes to '%s'?"
+msgstr "Elveti '%s' változtatásait?"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "El akarja menteni '%s' változásait?"
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Másol"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr "Beilleszt"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Array tulajdonságai"
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Név:"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Méret:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Tartalom mentése"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr "Megjelenítés:"
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Pontok"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Sokszög"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Bezier görbe"
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr "Array helye:"
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr "Új graph"
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr "Legutóbbi graph"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr "Array-t töröl"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr "Lista nézet megnyitása..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Mégsem"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Alkalmaz"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr "OK"
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr "Hang beállítások"
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr "Minden bellítást ment"
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr "Mintavétel (Hz):"
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr "Késés (ms):"
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr "Callback-ek használata"
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr "1. bemeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+msgid "Channels:"
+msgstr "Csatornák:"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr "2. bemeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr "3. bemeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr "4. bemeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr "1. kimeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr "(ugyanaz mint a bemeneti eszköz) .............. "
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr "2. kimeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr "3. kimeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr "4. kimeneti eszköz:"
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr "Több eszköz használata"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Canvas tulajdonságai"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Méretarány"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr "X egység képpontonként:"
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr "Y egység képpontonként:"
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr "Megjelenés a szülő patch-en"
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr "Megjelenítés a szülőn (GOP)"
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "Elemnév és paraméterek elrejtése"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr "Tartomány és méret"
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr "X tartomány kezdete"
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "vége"
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Margó:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr "Y tartomány kezdete"
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Keres"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr "Keresés itt:"
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr "erre:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Bezár"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr "Csak egész szavas egyezés"
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr "Pd ablak"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr "Betű tulajdonságai"
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, tcl-format
+msgid "%s Font"
+msgstr "%s betűkészlet"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+msgid "Font Size"
+msgstr "Betűméret"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr "Nyújtás"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr "X és Y"
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr "csak X"
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr "csak Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Atom Box tulajdonságai"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Szélesség:"
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr "Korlátok"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Alsó:"
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Felső:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr "Címke"
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Bal"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Jobb"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Fent"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Lent"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr "Üzenetek"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr "Küldött symbol:"
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Fogadott symbol:"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Háttérszín"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Szín"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Címkeszín"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr "Kezdőérték"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr "Nincs kezdőérték"
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr "Kattintásra ugorjon"
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr "Kattintásra várjon"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "%s tulajdonságai"
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Ment"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "X offszet"
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr "Y offszet"
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Színek"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr "Háttér"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr "Előtér"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Színkeverés"
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr "Teszt címke"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr "MIDI beállítások"
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr "ALSA MIDI beállítások"
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr "Több ALSA eszköz használata"
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr "Bejövő portok:"
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr "Kimenő portok:"
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr "Elveti az ablak változtatásait?"
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr "tényleg kilép?"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Bezárja ezt az ablakot?"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr "Kapcsolódó fájlok"
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+msgid "Pd Files"
+msgstr "Pd fájlok"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr "Max patch fájlok"
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr "Max szövegfájlok"
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr "Max patch fájlok (.pat)"
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr "Max szövegfájlok (.mxt)"
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+"FIGYELEM: Nem található '%s' betűcsalád, az alapbeállítás (%s) érvényes"
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+"FIGYELEM: Nem található '%s' betűvastagság, az alapbeállítás (%s) érvényes"
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr "FIGYELEM: nem található %s betűkészlet %sx%s (%s) méretben!"
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr "HIBA: a 'pd' nem jelentkezett, a 'pd-gui' kilép!"
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr "Névtelen"
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Üzenet küldése..."
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Üzenet"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr "Betű"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr "Beállítások"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Szerkeszt"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Fájl"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Súgó"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Média"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Új"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Ablak"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Új"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Megnyit"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Ment új néven..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr "Nyomtat..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr "Mégsem!"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr "Mégis!"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr "Kivág"
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr "Duplikál"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr "Mindent kijelöl"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr "Szövegszerkesztő"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr "Elrendez"
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr "Konzol ki/be"
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr "Konzolt ürít"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr "Szerkesztő üzemmód"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr "Object"
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr "Number"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr "Symbol"
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr "Comment"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr "Bang"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr "Toggle"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr "Number2"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr "Vslider"
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr "Hslider"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+msgid "Vradio"
+msgstr "Vradio"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr "Hradio"
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr "VU meter"
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr "Canvas"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Graph"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr "Array"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr "Keres..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr "Újra keres"
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr "Legutóbbi hiba helye"
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr "DSP be"
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr "DSP ki"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr "Hang és MIDI tesztelése..."
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr "Terhelésmérő"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr "Kicsinyít"
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr "Nagyító"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr "Szülő ablak"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr "Mindent előtérbe hoz"
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr "A Pd-ről"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr "HTML kézikönyv..."
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+msgid "Browser..."
+msgstr "Beépített böngésző..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Beállítások..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr "Legutóbbi fájlok"
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr "Hang beállítások..."
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr "MIDI beállítások..."
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Kilép"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+msgid "Clear Menu"
+msgstr "Menüt ürít"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr "Tulajdonságok"
+
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr "DSP"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr "Jel"
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr "Generátorok"
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr "Szűrők"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr "Számítások"
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr "I/O"
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr "Mintavételezés"
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr "Egyéb"
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr "Kezelőfelület"
+
+#~ msgid "Patch Font"
+#~ msgstr "Patch betűkészlet"
+
+
diff --git a/pd/po/it.po b/pd/po/it.po
new file mode 100644
index 00000000..eea27597
--- /dev/null
+++ b/pd/po/it.po
@@ -0,0 +1,893 @@
+# Italian translation for Pure Data
+# This file is put in the public domain
+#
+# Lorenzo Sutton (lorenzosu) <lsutton@libero.it>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2009-10-27 21:07+0100\n"
+"Last-Translator: Lorenzo Sutton (lorenzosu) <lsutton@libero.it>\n"
+"Language-Team: American English <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "Undo duplicate"
+msgstr "Annulla duplica"
+
+msgid "Undo paste"
+msgstr "Annulla incolla"
+
+msgid "Undo motion"
+msgstr "Annulla spostamento "
+
+msgid "Undo cut"
+msgstr "Annulla taglia"
+
+msgid "Undo disconnect"
+msgstr "Annulla disconnetti"
+
+msgid "Undo connect"
+msgstr "Annulla connetti"
+
+msgid "Undo clear"
+msgstr "Annulla pulisci"
+
+msgid "Undo typing"
+msgstr "Annulla inserimento"
+
+msgid "Discard changes to '%s'?"
+msgstr "Cestinare le modifiche apportate a '%s'?"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "Salvare le modifiche apportate a '%s'?"
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Copia"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr "Incolla"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Proprietà Array"
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Nome:"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Dimensione:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Salva contenuto"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr "Disegna come:"
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Punti"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Poligono"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Curva bezier"
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr "Matty l'array in:"
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr "Nuovo grafico"
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr "Ultimo grafico"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr "Cancella array"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr "Apri visualizzazione lista..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Annulla"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Applica"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr "OK"
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr "Settaggi Audio"
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr "Salva tutti i settaggi"
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr "Frequenza di campionamento"
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr "Ritardo (msec):"
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr "Usa callback"
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr "Dispositivo di ingresso 1:"
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+msgid "Channels:"
+msgstr "Canali:"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr "Dispositivo di ingresso 2:"
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr "Dispositivo di ingresso 3:"
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr "Dispositivo di ingresso 4:"
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr "Dispositivo di uscita 1:"
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr "(lo stesso del dispositivo di ingresso)..........."
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr "Dispositivo di uscita 2:"
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr "Dispositivo di uscita 3:"
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr "Dispositivo di uscita 4:"
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr "Usa dispositivi multipli"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Proprietà Canvas"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Scala"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr "X unità per pixel"
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr "Y unità per pixel:"
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr "Aspetto sulla parent patch"
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr "Mostra sulla patent"
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "Nascondi il nome oggetto e gli argomenti"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr "Intervallo e dimensioni"
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr "Intervallo X, da"
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "a"
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Margine:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr "Intervallo Y, da"
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Trova"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr "Cerca in"
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr "per:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Chiudi"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr "Solo parole intere"
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr "Finestra Pd"
+
+#: ../src/dialog_font.tcl:45
+#, fuzzy
+msgid "Font Properties"
+msgstr "Proprietà"
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Carattere"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+msgid "Font Size"
+msgstr "Dimensione carattere:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+msgid "Stretch"
+msgstr "Allarga/riduci:"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr "X e Y"
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr "Solo X"
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr "Solo Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Proprietà Atom Box"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Larghezza:"
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr "Limiti"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Inferiore:"
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Superiore:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr "Etichetta"
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Sinistra "
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Destra"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Sopra"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Sotto"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr "Messaggi"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr "Invia simbolo:"
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Ricevi simbolo:"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Colore sfondo"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Colore primo piano"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Colore etichetta"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr "Click imposta il valore"
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr "Click incrementa/decrementa"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "%s Proprietà"
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Salva"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "Spostamento X"
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr "Spostamento Y"
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Colori"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr "Colore sfondo"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr "Primo piano"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Crea colore"
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr "Test etichetta"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr "Settaggi MIDI"
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr "Settaggi ALSA MIDI"
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr "Usa dispositivi ALSA multipli"
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr "Porte Ingresso:"
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr "Porte Uscita:"
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr "Cestinare le modifiche apportate in questa finestra?"
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr "Uscire veramente?"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Chiudere questa finestra??"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr "File associati"
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+msgid "Pd Files"
+msgstr "File Pd"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr "Patch Max"
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr "File di testo Max"
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr "Patch Max (.pat)"
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr "File di testo Max (.mxt)"
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+"ATTENZIONE: Famiglia di font '%s\" non trovata, uso quella di default (%s)"
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr "ATTENZIONE: Peso '%s' del font non trovato, uso quello di default (%s)"
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+"ERRORE: %s impossibile trovare la dimensione del font (%s) che entra in %sx%s!"
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr "ERRORE: 'pd' non è mai partito, chiudo 'pd-gui'!"
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Invia un Messaggio..."
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Messaggio"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr "Carattere"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr "Preferenze"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Modifica"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "File"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Aiuto"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Media"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Inserisci"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Finestra"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Nuovo File"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Apri File..."
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Salva con nome..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr "Stampa..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr "Annulla"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr "Ripristina"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr "Taglia"
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr "Duplica"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr "Seleziona tutto"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr "Editor di Testo..."
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr "Allinea elementi"
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr "Mostra/Nascondi console"
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr "Pulisci console"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr "Modalità modifica"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr "Oggetto"
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr "Numero"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr "Simbolo"
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr "Commento"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr "Bang"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr "Toggle"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr "Numero2"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr "Slider verticale"
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr "Slider orizzontale"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+msgid "Vradio"
+msgstr "Radio verticale"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr "Radio orizzontale"
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr "Indicatore VU"
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr "Tavolozza"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Grafico"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr "Array"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr "Trova"
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr "Cerca Ancora"
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr "Trova l'ultimo errore"
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr ""
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr "Test Audio e MIDI"
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr "Misura carico cpu"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr "Minimizza"
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr ""
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr "Finestra parent"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr "Porta tutto in primo piano"
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr "Informazioni su Pd..."
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr "Manuale HTML..."
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+msgid "Browser..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Preferenze..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr "Apri recenti"
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr "Settaggi audio..."
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr "Settaggi MIDI..."
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Esci"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+msgid "Clear Menu"
+msgstr "Pulisci menu"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr "Proprietà"
+
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr ""
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr "Segnali"
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr "Generatori"
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr "Filtri"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr "Matematica"
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr "Input/Output"
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr "Campionamento"
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr "Altri"
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
+
diff --git a/pd/po/pa.po b/pd/po/pa.po
new file mode 100644
index 00000000..d82cf9ac
--- /dev/null
+++ b/pd/po/pa.po
@@ -0,0 +1,955 @@
+# Translation of Pure Data 0.43.po to Punjabi.
+# This file is put in the public domain.
+#
+# Amanpreet Singh Alam <amanpreetalam@yahoo.com>, 2005.
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-11-04 08:04+0530\n"
+"Last-Translator: Amanpreet Singh Alam <amanpreetalam@yahoo.com>\n"
+"Language-Team: Punjabi <fedora-trans-pa@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "ਮਿਤੀ"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "ਯੂਗਾਂਡਾ"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "ਨਕਲ"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "ਮਿਤੀ"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "ਨਾਂ"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "ਅਕਾਰ:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "ਭਾਗ(_C)"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "ਪੋਰਟ"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "ਪੋਲੈਂਡ"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "ਆਖਰੀ ਸੁਨੇਹਾ:"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "ਹਟਾਓ"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "ਪਾਬੰਦੀ ਸੂਚੀ..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "ਰੱਦ"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "ਲਾਗੂ"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "ਰੱਦ"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "ਸੰਭਾਲੋ"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "ਨਿਸ਼ਾਨ ਰੇਖਾ:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "ਖੋਜ"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "ਪਾਠ ਖੋਜ..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "ਪੋਰਟ:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "ਬੰਦ ਕਰੋ"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "ਭੇਜਣ ਝਰੋਖਾ"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "ਫੋਂਟ:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "ਅਕਾਰ:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "ਸ਼ੁਰੂ:"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "ਉਪਭੋਗੀ ਸੀਮਾ"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "ਉਪਭੋਗੀ:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "ਖੱਬਾ"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "ਸੱਜਾ"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "ਉੱਪਰ"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "ਹੇਠਾਂ"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "ਸੁਨੇਹਾ"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "ਪ੍ਰਾਪਤੀ ਝਰੋਖਾ"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "ਪਿੱਠਭੂਮੀ:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "ਮੁੱਖ-ਭੂਮੀ:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "ਚੋਣ ਰੰਗ"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "ਸੱਦਾ"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "ਸੰਭਾਲੋ"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "ਰੰਗ"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "ਪਿੱਠਭੂਮੀ:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "ਫੋਂਟ:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "ਸਭ ਦੀ ਜਾਂਚ"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "ਝਰੋਖਾ ਬੰਦ(_C)"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "ਫਾਇਲ"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "ਸੁਨੇਹਾ"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "ਸੁਨੇਹਾ"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "ਫੋਂਟ:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "ਮੇਰੀ ਪਸੰਦ..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "ਸੋਧ(_E)"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "ਫਾਇਲ"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "ਸਹਾਇਤਾ"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "ਮੈਕਡੋਨੀਆ"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "ਝਰੋਖਾ(_W)"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+#, fuzzy
+msgid "New"
+msgstr "ਨਵਾਂ(_N)"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "ਖੋਲੋ"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "ਇੰਞ ਸੰਭਾਲੋ..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "ਸੋਧ(_E)..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "ਯੂਗਾਂਡਾ"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "ਲਾਲ:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "ਮਿਤੀ"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "ਚੋਣ ਰੰਗ"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "ਪਾਠ ਰੰਗ"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "ਸੂਚੀ ਸਾਫ਼"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "ਮੋਡ"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ ਅੰਕ"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "ਕਮਾਂਡ"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "ਪਾਬੰਦੀ"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "ਟੂਗੂ"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ ਅੰਕ"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "ਓਹਲੇ"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "ਵਰਜਨ"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "ਕੈਨੇਡਾ"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "ਗਰਾਫ਼"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "ਅਡੂਰਾ"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "ਖੋਜ"
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "ਬੰਦ"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "ਹੇਠਾਂ"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "ਭੇਜਣ ਝਰੋਖਾ"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "ਇਸ ਬਾਰੇ(_A)"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "ਝਲਕ..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "ਮੇਰੀ ਪਸੰਦ..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+#, fuzzy
+msgid "Quit"
+msgstr "ਬਾਹਰ(_Q)"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "ਸੂਚੀ ਸਾਫ਼"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "ਬੰਦ"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "ਫਾਇਲ"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/pt_br.po b/pd/po/pt_br.po
new file mode 100644
index 00000000..64706cbc
--- /dev/null
+++ b/pd/po/pt_br.po
@@ -0,0 +1,1342 @@
+# Brazilian Portuguese translation of Pure Data.
+# This file is put in the public domain
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2010-01-17 19:19-0500\n"
+"PO-Revision-Date: 2010-01-23 03:45-0200\n"
+"Last-Translator: Vilson Vieira <vilson@void.cc>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit"
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147 ../src/pd_menus.tcl:152 ../src/pd_menus.tcl:157
+msgid "Copy"
+msgstr "Copiar"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:154 ../src/pd_menus.tcl:159
+msgid "Paste"
+msgstr "Colar"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Propriedades do Vetor"
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#: ../src/dialog_array.tcl:274
+msgid "Name:"
+msgstr "Nome:"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_array.tcl:280 ../src/dialog_canvas.tcl:178
+#: ../src/dialog_canvas.tcl:182 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_canvas.tcl:197 ../src/dialog_iemgui.tcl:617
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#: ../src/dialog_iemgui.tcl:626
+msgid "Size:"
+msgstr "Tamanho:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#: ../src/dialog_array.tcl:284
+msgid "Save contents"
+msgstr "Salvar conteúdo"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+#: ../src/dialog_array.tcl:288
+msgid "Draw as:"
+msgstr "Desenhar como:"
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#: ../src/dialog_array.tcl:291
+msgid "Points"
+msgstr "Pontos"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#: ../src/dialog_array.tcl:293
+msgid "Polygon"
+msgstr "Polígono"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+#: ../src/dialog_array.tcl:295
+msgid "Bezier curve"
+msgstr "Curva de Bezier"
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+#: ../src/dialog_array.tcl:301
+msgid "Put array into:"
+msgstr "Inserir vetor em:"
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+#: ../src/dialog_array.tcl:304
+msgid "New graph"
+msgstr "Novo gráfico"
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#: ../src/dialog_array.tcl:306
+msgid "Last graph"
+msgstr "Último gráfico"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#: ../src/dialog_array.tcl:310
+msgid "Delete array"
+msgstr "Excluir vetor"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#: ../src/dialog_array.tcl:316
+msgid "Open List View..."
+msgstr "Abrir Visualização em Lista..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_array.tcl:323 ../src/dialog_audio.tcl:136
+#: ../src/dialog_audio.tcl:138 ../src/dialog_audio.tcl:144
+#: ../src/dialog_canvas.tcl:205 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_find.tcl:160 ../src/dialog_font.tcl:51
+#: ../src/dialog_gatom.tcl:153 ../src/dialog_gatom.tcl:157
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:738
+#: ../src/dialog_iemgui.tcl:742 ../src/dialog_iemgui.tcl:747
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:97
+#: ../src/dialog_midi.tcl:226 ../src/dialog_midi.tcl:228
+#: ../src/dialog_midi.tcl:232 ../src/scrollboxwindow.tcl:82
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_array.tcl:327 ../src/dialog_audio.tcl:138
+#: ../src/dialog_audio.tcl:140 ../src/dialog_audio.tcl:148
+#: ../src/dialog_canvas.tcl:207 ../src/dialog_canvas.tcl:213
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:161
+#: ../src/dialog_gatom.tcl:164 ../src/dialog_iemgui.tcl:741
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:95
+#: ../src/dialog_midi.tcl:99 ../src/dialog_midi.tcl:228
+#: ../src/dialog_midi.tcl:230 ../src/dialog_midi.tcl:234
+#: ../src/scrollboxwindow.tcl:84
+msgid "Apply"
+msgstr "Aplicar"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_array.tcl:331 ../src/dialog_audio.tcl:140
+#: ../src/dialog_audio.tcl:142 ../src/dialog_audio.tcl:152
+#: ../src/dialog_canvas.tcl:209 ../src/dialog_canvas.tcl:217
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_font.tcl:103 ../src/dialog_gatom.tcl:159
+#: ../src/dialog_gatom.tcl:165 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:744 ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_iemgui.tcl:754 ../src/dialog_iemgui.tcl:755
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:97
+#: ../src/dialog_midi.tcl:101 ../src/dialog_midi.tcl:230
+#: ../src/dialog_midi.tcl:232 ../src/dialog_midi.tcl:236
+#: ../src/dialog_startup.tcl:29 ../src/dialog_startup.tcl:30
+#: ../src/scrollboxwindow.tcl:86
+msgid "OK"
+msgstr "OK"
+
+#: ../src/dialog_audio.tcl:130 ../src/dialog_audio.tcl:132
+msgid "Audio Settings"
+msgstr "Configurações de Áudio"
+
+#: ../src/dialog_audio.tcl:142 ../src/dialog_audio.tcl:144
+#: ../src/dialog_audio.tcl:156
+msgid "Save all settings"
+msgstr "Salvar todas as configurações"
+
+#: ../src/dialog_audio.tcl:151 ../src/dialog_audio.tcl:153
+#: ../src/dialog_audio.tcl:164
+msgid "Sample rate:"
+msgstr "Taxa de amostragem:"
+
+#: ../src/dialog_audio.tcl:153 ../src/dialog_audio.tcl:155
+#: ../src/dialog_audio.tcl:166
+msgid "Delay (msec):"
+msgstr "Delay (ms):"
+
+#: ../src/dialog_audio.tcl:158 ../src/dialog_audio.tcl:160
+#: ../src/dialog_audio.tcl:172
+msgid "Use callbacks"
+msgstr "Usar callbacks"
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_audio.tcl:168
+#: ../src/dialog_audio.tcl:180 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:107 ../src/dialog_midi.tcl:111
+#: ../src/dialog_midi.tcl:241 ../src/dialog_midi.tcl:243
+#: ../src/dialog_midi.tcl:247
+msgid "Input device 1:"
+msgstr "Dispositivo de entrada 1:"
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:171
+#: ../src/dialog_audio.tcl:183 ../src/dialog_audio.tcl:185
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:200
+#: ../src/dialog_audio.tcl:213 ../src/dialog_audio.tcl:214
+#: ../src/dialog_audio.tcl:215 ../src/dialog_audio.tcl:229
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:234
+#: ../src/dialog_audio.tcl:249 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:252 ../src/dialog_audio.tcl:265
+#: ../src/dialog_audio.tcl:267 ../src/dialog_audio.tcl:268
+#: ../src/dialog_audio.tcl:280 ../src/dialog_audio.tcl:282
+#: ../src/dialog_audio.tcl:284 ../src/dialog_audio.tcl:300
+msgid "Channels:"
+msgstr "Canais:"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_audio.tcl:181
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:117 ../src/dialog_midi.tcl:121
+#: ../src/dialog_midi.tcl:251 ../src/dialog_midi.tcl:253
+#: ../src/dialog_midi.tcl:257
+msgid "Input device 2:"
+msgstr "Dispositivo de entrada 2:"
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_audio.tcl:196
+#: ../src/dialog_audio.tcl:210 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:129 ../src/dialog_midi.tcl:133
+#: ../src/dialog_midi.tcl:263 ../src/dialog_midi.tcl:265
+#: ../src/dialog_midi.tcl:269
+msgid "Input device 3:"
+msgstr "Dispositivo de entrada 3:"
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_audio.tcl:211
+#: ../src/dialog_audio.tcl:225 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:141 ../src/dialog_midi.tcl:145
+#: ../src/dialog_midi.tcl:275 ../src/dialog_midi.tcl:277
+#: ../src/dialog_midi.tcl:281
+msgid "Input device 4:"
+msgstr "Dispositivo de entrada 4:"
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_audio.tcl:225
+#: ../src/dialog_audio.tcl:240 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:152 ../src/dialog_midi.tcl:156
+#: ../src/dialog_midi.tcl:286 ../src/dialog_midi.tcl:288
+#: ../src/dialog_midi.tcl:292
+msgid "Output device 1:"
+msgstr "Dispositivo de saída 1:"
+
+#: ../src/dialog_audio.tcl:226 ../src/dialog_audio.tcl:228
+#: ../src/dialog_audio.tcl:243
+msgid "(same as input device) .............. "
+msgstr "(mesmo que o dispositivo de entrada) .............. "
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_audio.tcl:248
+#: ../src/dialog_audio.tcl:264 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:162 ../src/dialog_midi.tcl:166
+#: ../src/dialog_midi.tcl:296 ../src/dialog_midi.tcl:298
+#: ../src/dialog_midi.tcl:302
+msgid "Output device 2:"
+msgstr "Dispositivo de saída 2:"
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_audio.tcl:263
+#: ../src/dialog_audio.tcl:280 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:173 ../src/dialog_midi.tcl:177
+#: ../src/dialog_midi.tcl:307 ../src/dialog_midi.tcl:309
+#: ../src/dialog_midi.tcl:313
+msgid "Output device 3:"
+msgstr "Dispositivo de saída 3:"
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_audio.tcl:278
+#: ../src/dialog_audio.tcl:296 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:184 ../src/dialog_midi.tcl:188
+#: ../src/dialog_midi.tcl:318 ../src/dialog_midi.tcl:320
+#: ../src/dialog_midi.tcl:324
+msgid "Output device 4:"
+msgstr "Dispositivo de saída 4:"
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_audio.tcl:293
+#: ../src/dialog_audio.tcl:312 ../src/dialog_midi.tcl:195
+#: ../src/dialog_midi.tcl:197 ../src/dialog_midi.tcl:201
+msgid "Use multiple devices"
+msgstr "Usar múltiplos dispositivos"
+
+#: ../src/dialog_canvas.tcl:122
+msgid "WARNING: unknown graphme flags received in pdtk_canvas_dialog"
+msgstr "AVISO: flags graphme desconhecidas recebidas em pdtk_canvas_dialog"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Propriedades da Tela"
+
+#: ../src/dialog_canvas.tcl:146 ../src/dialog_canvas.tcl:150
+msgid "Scale"
+msgstr "Escala"
+
+#: ../src/dialog_canvas.tcl:150 ../src/dialog_canvas.tcl:154
+msgid "X units per pixel:"
+msgstr "Unidades X por pixel:"
+
+#: ../src/dialog_canvas.tcl:155 ../src/dialog_canvas.tcl:159
+msgid "Y units per pixel:"
+msgstr "Unidades Y por pixel:"
+
+#: ../src/dialog_canvas.tcl:159 ../src/dialog_canvas.tcl:163
+msgid "Appearance on parent patch"
+msgstr "Aparência no patch pai"
+
+#: ../src/dialog_canvas.tcl:161 ../src/dialog_canvas.tcl:165
+msgid "Graph-On-Parent"
+msgstr "Desenhar-No-Pai"
+
+#: ../src/dialog_canvas.tcl:165 ../src/dialog_canvas.tcl:169
+msgid "Hide object name and arguments"
+msgstr "Esconder nome e argumentos do objeto"
+
+#: ../src/dialog_canvas.tcl:170 ../src/dialog_canvas.tcl:174
+msgid "Range and size"
+msgstr "Registro de valores e tamanho"
+
+#: ../src/dialog_canvas.tcl:174 ../src/dialog_canvas.tcl:178
+msgid "X range, from"
+msgstr "Registro de X, de"
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:180
+#: ../src/dialog_canvas.tcl:191 ../src/dialog_canvas.tcl:195
+msgid "to"
+msgstr "a"
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:184
+#: ../src/dialog_canvas.tcl:195 ../src/dialog_canvas.tcl:199
+msgid "Margin:"
+msgstr "Margem:"
+
+#: ../src/dialog_canvas.tcl:189 ../src/dialog_canvas.tcl:193
+msgid "Y range, from"
+msgstr "Registro de Y, de"
+
+#: ../src/dialog_data.tcl:29
+msgid "Data Properties"
+msgstr "Propriedades dos Dados"
+
+#: ../src/dialog_data.tcl:37
+msgid "Send (Ctrl s)"
+msgstr "Enviar (Ctrl s)"
+
+#: ../src/dialog_data.tcl:39
+msgid "OK (Ctrl t)"
+msgstr "OK (Ctrl t)"
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:105
+#: ../src/dialog_find.tcl:107 ../src/dialog_find.tcl:115
+#: ../src/dialog_find.tcl:123 ../src/dialog_find.tcl:164
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Procurar"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:142
+msgid "Search in"
+msgstr "Procurar em"
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95 ../src/dialog_find.tcl:103
+#: ../src/dialog_find.tcl:144
+msgid "for:"
+msgstr "por:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/dialog_find.tcl:118
+#: ../src/dialog_find.tcl:168 ../src/pd_menus.tcl:63 ../src/pd_menus.tcl:74
+#: ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:118
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:143 ../src/pd_menus.tcl:259 ../src/pd_menus.tcl:272
+#: ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308 ../src/pd_menus.tcl:332
+#: ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354 ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:410 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:448 ../src/pd_menus.tcl:458
+#: ../src/pd_menus.tcl:489 ../src/pd_menus.tcl:496 ../src/pd_menus.tcl:527
+#: ../src/pd_menus.tcl:574
+msgid "Close"
+msgstr "Fechar"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+#: ../src/dialog_find.tcl:111 ../src/dialog_find.tcl:154
+msgid "Match whole word only"
+msgstr "Casar somente palavra inteira"
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_find.tcl:102
+#: ../src/dialog_find.tcl:143 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:296 ../src/pdwindow.tcl:33
+#: ../src/pdwindow.tcl:128 ../src/pdwindow.tcl:277 ../src/pdwindow.tcl:278
+msgid "Pd window"
+msgstr "Janela do PD"
+
+#: ../src/dialog_find.tcl:105
+#, tcl-format
+msgid "Couldn't find '%s' in %s"
+msgstr "Não foi possível encontrar '%s' em %s"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr "Propriedades da Fonte"
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:54 ../src/dialog_font.tcl:55
+#, tcl-format
+msgid "%s Font"
+msgstr "Fonte %s"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#: ../src/dialog_font.tcl:107
+msgid "Font Size"
+msgstr "Tamanho da Fonte"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:119
+msgid "Stretch"
+msgstr "Esticar"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+#: ../src/dialog_font.tcl:126
+msgid "X and Y"
+msgstr "X e Y"
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+#: ../src/dialog_font.tcl:128
+msgid "X only"
+msgstr "Somente X"
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+#: ../src/dialog_font.tcl:130
+msgid "Y only"
+msgstr "Somente Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Propriedades de Caixa de Átomos"
+
+#: ../src/dialog_gatom.tcl:99 ../src/dialog_gatom.tcl:103
+msgid "Width:"
+msgstr "Largura:"
+
+#: ../src/dialog_gatom.tcl:103 ../src/dialog_gatom.tcl:107
+msgid "Limits"
+msgstr "Limites"
+
+#: ../src/dialog_gatom.tcl:107 ../src/dialog_gatom.tcl:111
+msgid "Lower:"
+msgstr "Menor:"
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#: ../src/dialog_gatom.tcl:116
+msgid "Upper:"
+msgstr "Maior:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:120
+#: ../src/dialog_gatom.tcl:121 ../src/dialog_iemgui.tcl:598
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:606
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657 ../src/dialog_iemgui.tcl:659
+msgid "Label"
+msgstr "Etiqueta"
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:128
+#: ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Esquerda "
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:130
+#: ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Direita"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:132
+#: ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Topo"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:134
+#: ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Fundo"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:141
+#: ../src/dialog_gatom.tcl:145 ../src/dialog_iemgui.tcl:572
+#: ../src/dialog_iemgui.tcl:574 ../src/dialog_iemgui.tcl:576
+msgid "Messages"
+msgstr "Mensagens"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_gatom.tcl:149 ../src/dialog_iemgui.tcl:576
+#: ../src/dialog_iemgui.tcl:578 ../src/dialog_iemgui.tcl:580
+msgid "Send symbol:"
+msgstr "Símbolo de 'send':"
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:151
+#: ../src/dialog_gatom.tcl:155 ../src/dialog_iemgui.tcl:583
+#: ../src/dialog_iemgui.tcl:585 ../src/dialog_iemgui.tcl:589
+msgid "Receive symbol:"
+msgstr "Símbolo de 'receive':"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Cor de plano de fundo"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Cor de plano de frente"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Cor da etiqueta"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr "Inicialização"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+#: ../src/dialog_iemgui.tcl:550
+msgid "No init"
+msgstr "Sem inicialização"
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:556
+#: ../src/dialog_iemgui.tcl:558 ../src/dialog_iemgui.tcl:560
+msgid "Jump on click"
+msgstr "Pular ao clicar"
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:559
+#: ../src/dialog_iemgui.tcl:561 ../src/dialog_iemgui.tcl:563
+msgid "Steady on click"
+msgstr "Fixo ao clicar"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "Propriedades de %s"
+
+#: ../src/dialog_iemgui.tcl:549 ../src/dialog_iemgui.tcl:550
+#: ../src/dialog_iemgui.tcl:553 ../src/pd_menus.tcl:60 ../src/pd_menus.tcl:71
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:92 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:135
+#: ../src/pd_menus.tcl:140 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301 ../src/pd_menus.tcl:325
+#: ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355 ../src/pd_menus.tcl:382
+#: ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410 ../src/pd_menus.tcl:411
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:439 ../src/pd_menus.tcl:449
+#: ../src/pd_menus.tcl:487 ../src/pd_menus.tcl:490 ../src/pd_menus.tcl:518
+#: ../src/pd_menus.tcl:563
+msgid "Save"
+msgstr "Salvar"
+
+#: ../src/dialog_iemgui.tcl:606 ../src/dialog_iemgui.tcl:608
+#: ../src/dialog_iemgui.tcl:614
+msgid "X offset"
+msgstr "Deslocamento X"
+
+#: ../src/dialog_iemgui.tcl:609 ../src/dialog_iemgui.tcl:611
+#: ../src/dialog_iemgui.tcl:612 ../src/dialog_iemgui.tcl:617
+msgid "Y offset"
+msgstr "Deslocamento Y"
+
+#: ../src/dialog_iemgui.tcl:640 ../src/dialog_iemgui.tcl:642
+#: ../src/dialog_iemgui.tcl:645 ../src/dialog_iemgui.tcl:649
+msgid "Colors"
+msgstr "Cores"
+
+#: ../src/dialog_iemgui.tcl:646 ../src/dialog_iemgui.tcl:648
+#: ../src/dialog_iemgui.tcl:651 ../src/dialog_iemgui.tcl:655
+msgid "Background"
+msgstr "Plano de fundo"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:650
+#: ../src/dialog_iemgui.tcl:654 ../src/dialog_iemgui.tcl:657
+msgid "Front"
+msgstr "Frente"
+
+#: ../src/dialog_iemgui.tcl:660 ../src/dialog_iemgui.tcl:662
+#: ../src/dialog_iemgui.tcl:668 ../src/dialog_iemgui.tcl:669
+msgid "Compose color"
+msgstr "Compor cor"
+
+#: ../src/dialog_iemgui.tcl:679 ../src/dialog_iemgui.tcl:682
+#: ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr "Etiqueta de teste"
+
+#: ../src/dialog_message.tcl:61
+msgid "Send a Pd message"
+msgstr "Enviar uma mensagem PD"
+
+#: ../src/dialog_message.tcl:80
+msgid "(use arrow keys for history)"
+msgstr "(use as setas do teclado para histórico)"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr "Configurações de MIDI"
+
+#: ../src/dialog_midi.tcl:220 ../src/dialog_midi.tcl:222
+#: ../src/dialog_midi.tcl:226
+msgid "ALSA MIDI Settings"
+msgstr "Configurações de ALSA MIDI"
+
+#: ../src/dialog_midi.tcl:331 ../src/dialog_midi.tcl:333
+#: ../src/dialog_midi.tcl:337
+msgid "Use multiple ALSA devices"
+msgstr "Usar múltiplos dispositivos ALSA"
+
+#: ../src/dialog_midi.tcl:337 ../src/dialog_midi.tcl:339
+#: ../src/dialog_midi.tcl:343
+msgid "In Ports:"
+msgstr "Portas de Entrada:"
+
+#: ../src/dialog_midi.tcl:340 ../src/dialog_midi.tcl:342
+#: ../src/dialog_midi.tcl:346
+msgid "Out Ports:"
+msgstr "Portas de Saída:"
+
+#: ../src/dialog_path.tcl:30
+msgid "Pd search path for objects, help, fonts, and other files"
+msgstr "Caminho de busca do PD para objetos, arquivos de ajuda, fontes e outros"
+
+#: ../src/dialog_path.tcl:35
+msgid "Use standard extensions"
+msgstr "Usar extensões padrões"
+
+#: ../src/dialog_path.tcl:37
+msgid "Verbose"
+msgstr "Informativo"
+
+#: ../src/dialog_startup.tcl:49
+msgid "Add new library"
+msgstr "Adicionar nova biblioteca"
+
+#: ../src/dialog_startup.tcl:53
+msgid "Edit library"
+msgstr "Editar biblioteca"
+
+#: ../src/dialog_startup.tcl:79
+msgid "Pd libraries to load on startup"
+msgstr "Bibliotecas PD para carregar na inicialização"
+
+#: ../src/dialog_startup.tcl:82
+msgid "Startup flags:"
+msgstr "Flags de inicialização:"
+
+#: ../src/dialog_startup.tcl:91
+msgid "Defeat real-time scheduling"
+msgstr "Anular agendamento em tempo real"
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr "Descartar mudanças feitas nessa janela??"
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr "deseja realmente sair?"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Fechar esta janela??"
+
+#: ../src/helpbrowser.tcl:25
+msgid "Help Browser"
+msgstr "Navegador da Ajuda"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:218
+#: ../src/pd-gui.tcl:226 ../src/pd-gui.tcl:230 ../src/pd-gui.tcl:241
+#: ../src/pd-gui.tcl:259 ../src/pd-gui.tcl:277 ../src/pd-gui.tcl:296
+msgid "Associated Files"
+msgstr "Arquivos Associados"
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:219
+#: ../src/pd-gui.tcl:227 ../src/pd-gui.tcl:231 ../src/pd-gui.tcl:242
+#: ../src/pd-gui.tcl:260 ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:297
+msgid "Pd Files"
+msgstr "Arquivos PD"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:220 ../src/pd-gui.tcl:228 ../src/pd-gui.tcl:243
+#: ../src/pd-gui.tcl:261 ../src/pd-gui.tcl:298
+msgid "Max Patch Files"
+msgstr "Arquivos de Patch Max"
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:221 ../src/pd-gui.tcl:229 ../src/pd-gui.tcl:244
+#: ../src/pd-gui.tcl:262 ../src/pd-gui.tcl:299
+msgid "Max Text Files"
+msgstr "Arquivos de Texto Max"
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217 ../src/pd-gui.tcl:232
+#: ../src/pd-gui.tcl:279
+msgid "Max Patch Files (.pat)"
+msgstr "Arquivos de Patch Max (.pat)"
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218 ../src/pd-gui.tcl:233
+#: ../src/pd-gui.tcl:280
+msgid "Max Text Files (.mxt)"
+msgstr "Arquivos de Texto Max (.mxt)"
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290 ../src/pd-gui.tcl:305
+#: ../src/pd-gui.tcl:374
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr "AVISO: Fonte '%s' não encontrada, usando a padrão (%s)"
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298 ../src/pd-gui.tcl:313
+#: ../src/pd-gui.tcl:382
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr "AVISO: Tamanho de fonte '%s' não encontrado, usando o padrão (%s)"
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr "ERRO: %s Falha ao procurar o tamanho de fonte (%s) que caiba em %sx%s!"
+
+#: ../src/pd-gui.tcl:338 ../src/pd-gui.tcl:407
+#, tcl-format
+msgid "WARNING: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr "AVISO: %s Falha ao procurar o tamanho de fonte (%s) que caiba em %sx%s!"
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+#: ../src/pd-gui.tcl:518 ../src/pd-gui.tcl:620
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr "ERRO: 'pd' não apareceu, 'pd-gui' saindo!"
+
+#: ../src/pd_connect.tcl:76 ../src/pd_connect.tcl:85 ../src/pdwindow.tcl:90
+#: ../src/pdwindow.tcl:239
+msgid "(Tcl) INVALID COMMAND NAME: "
+msgstr "(Tcl) NOME DE COMANDO INVÁLIDO: "
+
+#: ../src/pd_connect.tcl:78 ../src/pd_connect.tcl:87 ../src/pdwindow.tcl:92
+#: ../src/pdwindow.tcl:241
+msgid "(Tcl) UNHANDLED ERROR: "
+msgstr "(Tcl) ERRO NÃO TRATADO:"
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr "Sem título"
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:83 ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Enviar Mensagem..."
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:87 ../src/pd_menucommands.tcl:94
+#: ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:144 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:265 ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305 ../src/pd_menus.tcl:329
+#: ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360 ../src/pd_menus.tcl:387
+#: ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:416 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:443 ../src/pd_menus.tcl:453 ../src/pd_menus.tcl:491
+#: ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Mensagem"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:169
+#: ../src/pd_menus.tcl:174
+msgid "Font"
+msgstr "Fonte"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#: ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:475
+#: ../src/pd_menus.tcl:569
+msgid "Preferences"
+msgstr "Preferências"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Editar"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Arquivo"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113 ../src/pdtk_canvas.tcl:160
+msgid "Help"
+msgstr "Ajuda"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Mídia"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Inserir"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Janela"
+
+#: ../src/pd_menus.tcl:61 ../src/pd_menus.tcl:72 ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:108 ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:136 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274 ../src/pd_menus.tcl:289
+#: ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326 ../src/pd_menus.tcl:339
+#: ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:384
+#: ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:412 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:440 ../src/pd_menus.tcl:450 ../src/pd_menus.tcl:488
+#: ../src/pd_menus.tcl:491 ../src/pd_menus.tcl:519 ../src/pd_menus.tcl:564
+msgid "Save As..."
+msgstr "Salvar Como..."
+
+#: ../src/pd_menus.tcl:62 ../src/pd_menus.tcl:73 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:94
+#: ../src/pd_menus.tcl:109 ../src/pd_menus.tcl:117 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:140 ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280 ../src/pd_menus.tcl:293
+#: ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330 ../src/pd_menus.tcl:343
+#: ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388 ../src/pd_menus.tcl:389
+#: ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:418 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:444 ../src/pd_menus.tcl:454 ../src/pd_menus.tcl:492
+#: ../src/pd_menus.tcl:497 ../src/pd_menus.tcl:523 ../src/pd_menus.tcl:570
+msgid "Print..."
+msgstr "Imprimir..."
+
+#: ../src/pd_menus.tcl:65 ../src/pd_menus.tcl:76 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:97 ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105
+#: ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:161
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: ../src/pd_menus.tcl:66 ../src/pd_menus.tcl:77 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:114 ../src/pd_menus.tcl:120
+#: ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:167
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:177
+msgid "Tidy Up"
+msgstr "Organizar"
+
+#: ../src/pd_menus.tcl:67 ../src/pd_menus.tcl:78 ../src/pd_menus.tcl:89
+#: ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:115 ../src/pd_menus.tcl:122
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:178 ../src/pd_menus.tcl:185
+#: ../src/pd_menus.tcl:551 ../src/pdtk_canvas.tcl:224
+#: ../src/pdtk_canvas.tcl:226
+msgid "Edit Mode"
+msgstr "Modo de Edição"
+
+#: ../src/pd_menus.tcl:70 ../src/pd_menus.tcl:80 ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:124
+#: ../src/pd_menus.tcl:139 ../src/pd_menus.tcl:140 ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:150 ../src/pd_menus.tcl:320 ../src/pd_menus.tcl:326
+msgid "Undo"
+msgstr "Desfazer"
+
+#: ../src/pd_menus.tcl:71 ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:95
+#: ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:119 ../src/pd_menus.tcl:125
+#: ../src/pd_menus.tcl:141 ../src/pd_menus.tcl:142 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:152 ../src/pd_menus.tcl:326 ../src/pd_menus.tcl:332
+msgid "Redo"
+msgstr "Refazer"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376 ../src/pd_menus.tcl:380
+#: ../src/pd_menus.tcl:405 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:436 ../src/pd_menus.tcl:446 ../src/pd_menus.tcl:484
+#: ../src/pd_menus.tcl:515 ../src/pd_menus.tcl:560
+msgid "New"
+msgstr "Novo"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268 ../src/pd_menus.tcl:286
+#: ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323 ../src/pd_menus.tcl:336
+#: ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377 ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:406 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:437 ../src/pd_menus.tcl:447 ../src/pd_menus.tcl:485
+#: ../src/pd_menus.tcl:516 ../src/pd_menus.tcl:561 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+#: ../src/pdtk_canvas.tcl:158 ../src/pdtk_canvas.tcl:178
+#: ../src/pdtk_canvas.tcl:180
+msgid "Open"
+msgstr "Abrir"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:150 ../src/pd_menus.tcl:155
+msgid "Cut"
+msgstr "Cortar"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:163
+msgid "Select All"
+msgstr "Selecionar Tudo"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:167
+#: ../src/pd_menus.tcl:172
+msgid "Text Editor"
+msgstr "Editor de Texto"
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169 ../src/pd_menus.tcl:179
+msgid "Toggle Console"
+msgstr "Ativar Console"
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171 ../src/pd_menus.tcl:174 ../src/pd_menus.tcl:181
+msgid "Clear Console"
+msgstr "Limpar Console"
+
+#: ../src/pd_menus.tcl:139 ../src/pd_menus.tcl:495 ../src/pd_menus.tcl:522
+#: ../src/pd_menus.tcl:567
+msgid "Message..."
+msgstr "Mensagem..."
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:188 ../src/pd_menus.tcl:190
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:201
+msgid "Object"
+msgstr "Objeto"
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:194
+#: ../src/pd_menus.tcl:195 ../src/pd_menus.tcl:205
+msgid "Number"
+msgstr "Número"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:197 ../src/pd_menus.tcl:207
+msgid "Symbol"
+msgstr "Símbolo"
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:199 ../src/pd_menus.tcl:209
+msgid "Comment"
+msgstr "Comentário"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:199 ../src/pd_menus.tcl:201
+#: ../src/pd_menus.tcl:202 ../src/pd_menus.tcl:212
+msgid "Bang"
+msgstr "Bang"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:203
+#: ../src/pd_menus.tcl:204 ../src/pd_menus.tcl:214
+msgid "Toggle"
+msgstr "Toggle"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:206 ../src/pd_menus.tcl:216
+msgid "Number2"
+msgstr "Número2"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:208 ../src/pd_menus.tcl:218
+msgid "Vslider"
+msgstr "Slider Vertical"
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:209
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:220
+msgid "Hslider"
+msgstr "Slider Horizontal"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:211
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:222
+msgid "Vradio"
+msgstr "Seleção Vertical"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:213
+#: ../src/pd_menus.tcl:214 ../src/pd_menus.tcl:224
+msgid "Hradio"
+msgstr "Seleção Horizontal"
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:215
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:226
+msgid "VU Meter"
+msgstr "Medidor de VU"
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:217
+#: ../src/pd_menus.tcl:218 ../src/pd_menus.tcl:228
+msgid "Canvas"
+msgstr "Tela"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:218 ../src/pd_menus.tcl:220
+#: ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:231
+msgid "Graph"
+msgstr "Gráfico"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:219 ../src/pd_menus.tcl:221
+#: ../src/pd_menus.tcl:222 ../src/pd_menus.tcl:232
+msgid "Array"
+msgstr "Vetor"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:226
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:237
+msgid "Find..."
+msgstr "Procurar..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:228
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:239
+msgid "Find Again"
+msgstr "Procurar Novamente"
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:230
+#: ../src/pd_menus.tcl:231 ../src/pd_menus.tcl:241
+msgid "Find Last Error"
+msgstr "Procurar Último Erro"
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:234 ../src/pd_menus.tcl:236
+#: ../src/pd_menus.tcl:237 ../src/pd_menus.tcl:247
+msgid "DSP On"
+msgstr "DSP Ligado"
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:238
+#: ../src/pd_menus.tcl:239 ../src/pd_menus.tcl:249
+msgid "DSP Off"
+msgstr "DSP Desligado"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:240 ../src/pd_menus.tcl:242
+#: ../src/pd_menus.tcl:269 ../src/pd_menus.tcl:280
+msgid "Test Audio and MIDI..."
+msgstr "Testar Áudio e MIDI..."
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:244
+#: ../src/pd_menus.tcl:271 ../src/pd_menus.tcl:282
+msgid "Load Meter"
+msgstr "Medidor de Carga de CPU"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:289
+msgid "Minimize"
+msgstr "Minimizar"
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:276
+#: ../src/pd_menus.tcl:280 ../src/pd_menus.tcl:291
+msgid "Zoom"
+msgstr "Ampliar"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#: ../src/pd_menus.tcl:291 ../src/pd_menus.tcl:294
+msgid "Parent Window"
+msgstr "Janela Mãe"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:300
+msgid "Bring All to Front"
+msgstr "Trazer Tudo para Frente"
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:298
+#: ../src/pd_menus.tcl:308 ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:362
+#: ../src/pd_menus.tcl:390 ../src/pd_menus.tcl:472
+msgid "About Pd"
+msgstr "Sobre PD"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+#: ../src/pd_menus.tcl:311
+msgid "HTML Manual..."
+msgstr "Manual HTML..."
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#: ../src/pd_menus.tcl:313
+msgid "Browser..."
+msgstr "Navegador..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369 ../src/pd_menus.tcl:395
+msgid "Preferences..."
+msgstr "Preferências..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:487
+msgid "Open Recent"
+msgstr "Abrir Recente"
+
+#: ../src/pd_menus.tcl:263 ../src/pd_menus.tcl:274
+msgid "Audio settings..."
+msgstr "Configurações de Áudio..."
+
+#: ../src/pd_menus.tcl:265 ../src/pd_menus.tcl:276 ../src/pd_menus.tcl:461
+msgid "MIDI settings..."
+msgstr "Configurações de MIDI..."
+
+#: ../src/pd_menus.tcl:281
+msgid "Next Window"
+msgstr "Próxima Janela"
+
+#: ../src/pd_menus.tcl:284
+msgid "Previous Window"
+msgstr "Janela Anterior"
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:449 ../src/pd_menus.tcl:459
+#: ../src/pd_menus.tcl:497 ../src/pd_menus.tcl:528 ../src/pd_menus.tcl:575
+msgid "Quit"
+msgstr "Sair"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331 ../src/pd_menus.tcl:350
+#: ../src/pd_menus.tcl:356
+msgid "Clear Menu"
+msgstr "Limpar Menu"
+
+#: ../src/pd_menus.tcl:305
+msgid "puredata.info"
+msgstr "puredata.info"
+
+#: ../src/pd_menus.tcl:307
+msgid "Report a bug"
+msgstr "Reportar um bug"
+
+#: ../src/pd_menus.tcl:455
+msgid "Path..."
+msgstr "Caminho..."
+
+#: ../src/pd_menus.tcl:457
+msgid "Startup..."
+msgstr "Inicialização..."
+
+#: ../src/pd_menus.tcl:459
+msgid "Audio Settings..."
+msgstr "Configurações de Áudio..."
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:156
+#: ../src/pdtk_canvas.tcl:173 ../src/pdtk_canvas.tcl:175
+msgid "Properties"
+msgstr "Propriedades"
+
+#: ../src/pdwindow.tcl:43 ../src/pdwindow.tcl:164 ../src/pdwindow.tcl:309
+msgid "DSP"
+msgstr "DSP"
+
+#: ../src/pdwindow.tcl:86 ../src/pdwindow.tcl:235
+msgid "(Tcl) MISSING CLOSE-BRACE '}': "
+msgstr "(Tcl) FALTANDO FECHA CHAVES '}': "
+
+#: ../src/pdwindow.tcl:88 ../src/pdwindow.tcl:237
+msgid "(Tcl) MISSING CLOSE-BRACKET ']': "
+msgstr "(Tcl) FALTANDO FECHA COLCHETES ']': "
+
+#: ../src/pdwindow.tcl:161 ../src/pdwindow.tcl:306
+msgid "IN"
+msgstr "ENTRADA"
+
+#: ../src/pdwindow.tcl:162 ../src/pdwindow.tcl:307
+msgid "OUT"
+msgstr "SAÍDA"
+
+#: ../src/pdwindow.tcl:168 ../src/pdwindow.tcl:314
+msgid "DIO"
+msgstr "DIO"
+
+#: ../src/pdwindow.tcl:177 ../src/pdwindow.tcl:324
+msgid "Tcl:"
+msgstr "Tcl:"
+
+#: ../src/wheredoesthisgo.tcl:19
+#, tcl-format
+msgid "Ignoring '%s': doesn't look like a Pd-file"
+msgstr "Ignorando '%s': não parece ser um arquivo PD válido"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr "Sinal"
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr "Geradores"
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr "Filtros"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr "Matemática"
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr "E/S"
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr "Amostragem"
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr "Roteamento"
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr "Outros"
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr "GUI"
+
+# iemgui
+msgid "-------dimensions(digits)(pix):-------"
+msgstr "------dimensões(dígitos)(pix):-------"
+
+# iemgui
+msgid "--------dimensions(pix)(pix):--------"
+msgstr "--------dimensões(pix)(pix):--------"
+
+# iemgui
+msgid "----------dimensions(pix):-----------"
+msgstr "----------dimensões(pix):-----------"
+
+# iemgui
+# iemgui
+msgid "------selectable_dimensions(pix):------"
+msgstr "----dimensões_selecionáveis(pix):-----"
+
+# iemgui
+msgid "------visible_rectangle(pix)(pix):------"
+msgstr "-----retângulo_visível(pix)(pix):------"
+
+# iemgui
+msgid "-----------output-range:-----------"
+msgstr "---------registro-de-saída:---------"
+
+# iemgui
+msgid "--------flash-time(ms)(ms):---------"
+msgstr "-----tempo-de-flash(ms)(ms):-------"
+
+# iemgui
+msgid "log-height:"
+msgstr "altura-do-log:"
+
+# iemgui
+msgid "log"
+msgstr "log"
+
+# iemgui
+msgid "lin"
+msgstr "lin"
+
+# iemgui
+msgid "top:"
+msgstr "topo:"
+
+# iemgui
+msgid "bottom:"
+msgstr "fundo:"
+
+# iemgui
+msgid "value:"
+msgstr "valor:"
+
+# iemgui
+msgid "max:"
+msgstr "máx:"
+
+# iemgui
+msgid "min:"
+msgstr "min:"
+
+# iemgui
+msgid "right:"
+msgstr "direita:"
+
+# iemgui
+msgid "left:"
+msgstr "esquerda:"
+
+# iemgui
+msgid "hold:"
+msgstr "segurar:"
+
+# iemgui
+msgid "intrrpt:"
+msgstr "interromper:"
+
+# iemgui
+msgid "size:"
+msgstr "tamanho:"
+
+# iemgui
+msgid "width:"
+msgstr "largura:"
+
+# iemgui
+msgid "height:"
+msgstr "altura:"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "Você deseja salvar as alterações feitas em '%s'?"
+
+msgid "Discard changes to '%s'?"
+msgstr "Descartar as mudanças em '%s'?"
+
+msgid "Undo typing"
+msgstr "Desfazer digitação"
+
+msgid "Undo clear"
+msgstr "Desfazer limpar"
+
+msgid "Undo connect"
+msgstr "Desfazer conectar"
+
+msgid "Undo disconnect"
+msgstr "Desfazer desconectar"
+
+msgid "Undo cut"
+msgstr "Desfazer cortar"
+
+msgid "Undo motion"
+msgstr "Desfazer movimentar"
+
+msgid "Undo paste"
+msgstr "Desfazer colar"
+
+msgid "Undo duplicate"
+msgstr "Desfazer duplicar"
+
+msgid "Redo typing"
+msgstr "Refazer digitação"
+
+msgid "Redo clear"
+msgstr "Refazer limpar"
+
+msgid "Redo connect"
+msgstr "Refazer conectar"
+
+msgid "Redo disconnect"
+msgstr "Refazer desconectar"
+
+msgid "Redo cut"
+msgstr "Refazer cortar"
+
+msgid "Redo motion"
+msgstr "Refazer movimentar"
+
+msgid "Redo paste"
+msgstr "Refazer colar"
+
+msgid "Redo duplicate"
+msgstr "Refazer duplicar"
+
+
+
diff --git a/pd/po/pt_pt.po b/pd/po/pt_pt.po
new file mode 100644
index 00000000..1d95ffb0
--- /dev/null
+++ b/pd/po/pt_pt.po
@@ -0,0 +1,1144 @@
+# Portugal Portugeuse translation for Pure Data
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-25 23:00-0400\n"
+"PO-Revision-Date: \n"
+"Last-Translator: João Pais <jmmmpais@googlemail.com>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Portuguese\n"
+"X-Poedit-Country: PORTUGAL\n"
+
+msgid "Discard changes to '%s'?"
+msgstr "Rejeitar modificações em '%s'?"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "Quer gravar as modificações feitas em '%s'?"
+
+#: ../src/dialog_array.tcl:115
+#: ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100
+#: ../src/pd_menus.tcl:101
+#: ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Copiar"
+
+#: ../src/dialog_array.tcl:118
+#: ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102
+#: ../src/pd_menus.tcl:103
+#: ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr "Colar"
+
+#: ../src/dialog_array.tcl:264
+#: ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr "Propriedades do array"
+
+#: ../src/dialog_array.tcl:270
+#: ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Nome:"
+
+#: ../src/dialog_array.tcl:276
+#: ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178
+#: ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619
+#: ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Tamanho:"
+
+#: ../src/dialog_array.tcl:280
+#: ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Guardar conteúdo"
+
+#: ../src/dialog_array.tcl:284
+#: ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr "Desenhar como:"
+
+#: ../src/dialog_array.tcl:287
+#: ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Pontos"
+
+#: ../src/dialog_array.tcl:289
+#: ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Polígono"
+
+#: ../src/dialog_array.tcl:291
+#: ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Curva de Bézier"
+
+#: ../src/dialog_array.tcl:297
+#: ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr "Pôr array em:"
+
+#: ../src/dialog_array.tcl:300
+#: ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr "Gráfico novo"
+
+#: ../src/dialog_array.tcl:302
+#: ../src/dialog_array.tcl:304
+msgid "Last graph"
+msgstr "Gráfico precedente"
+
+#: ../src/dialog_array.tcl:306
+#: ../src/dialog_array.tcl:308
+msgid "Delete array"
+msgstr "Apagar array"
+
+#: ../src/dialog_array.tcl:312
+#: ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr "Ver lista"
+
+#: ../src/dialog_array.tcl:319
+#: ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136
+#: ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51
+#: ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161
+#: ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: ../src/dialog_array.tcl:321
+#: ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138
+#: ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156
+#: ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745
+#: ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93
+#: ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Aplicar"
+
+#: ../src/dialog_array.tcl:323
+#: ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140
+#: ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53
+#: ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100
+#: ../src/dialog_gatom.tcl:159
+#: ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95
+#: ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr "OK"
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr "Configuração audio"
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr "Gravar a configuração"
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr "Sample rate:"
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr "Delay (mseg):"
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr "Usar callbacks"
+
+#: ../src/dialog_audio.tcl:166
+#: ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr "Dispositivo de entrada 1:"
+
+#: ../src/dialog_audio.tcl:169
+#: ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198
+#: ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232
+#: ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265
+#: ../src/dialog_audio.tcl:280
+msgid "Channels:"
+msgstr "Canais:"
+
+#: ../src/dialog_audio.tcl:179
+#: ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr "Dispositivo de entrada 2:"
+
+#: ../src/dialog_audio.tcl:194
+#: ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr "Dispositivo de entrada 3:"
+
+#: ../src/dialog_audio.tcl:209
+#: ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr "Dispositivo de entrada 4:"
+
+#: ../src/dialog_audio.tcl:223
+#: ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr "Dispositivo de saída 1:"
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr "(igual ao dispositivo de entrada) .............."
+
+#: ../src/dialog_audio.tcl:246
+#: ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr "Dispositivo de saída 2:"
+
+#: ../src/dialog_audio.tcl:261
+#: ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr "Dispositivo de saída 3:"
+
+#: ../src/dialog_audio.tcl:276
+#: ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr "Dispositivo de saída 4:"
+
+#: ../src/dialog_audio.tcl:291
+#: ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr "Usar vários dispositivos"
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr "Propriedades da tela"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Escala"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr "Unidades de X por pixel"
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr "Unidades de Y por pixel"
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr "Mostrar na janela superior"
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "Esconder nome e variáveis do objecto"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr "Faixa X, de"
+
+#: ../src/dialog_canvas.tcl:176
+#: ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "a"
+
+#: ../src/dialog_canvas.tcl:180
+#: ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Margem:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr "Faixa Y, de"
+
+#: ../src/dialog_find.tcl:63
+#: ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79
+#: ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87
+#: ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Localizar"
+
+#: ../src/dialog_find.tcl:70
+#: ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr "Procurar em"
+
+#: ../src/dialog_find.tcl:72
+#: ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr "por:"
+
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104
+#: ../src/dialog_find.tcl:110
+#: ../src/pd_menus.tcl:86
+#: ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132
+#: ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272
+#: ../src/pd_menus.tcl:295
+#: ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332
+#: ../src/pd_menus.tcl:345
+#: ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:392
+#: ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431
+#: ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Fechar"
+
+#: ../src/dialog_find.tcl:83
+#: ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr "Propriedades do tipo de letra"
+
+#: ../src/dialog_font.tcl:46
+#: ../src/dialog_font.tcl:54
+#, tcl-format
+msgid "%s Font"
+msgstr ""
+
+#: ../src/dialog_font.tcl:49
+#: ../src/pd-gui.tcl:280
+#: ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286
+#: ../src/pd-gui.tcl:288
+#: ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212
+#: ../src/pd_menus.tcl:258
+#: ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr "Janela Pd"
+
+#: ../src/dialog_font.tcl:61
+#: ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104
+msgid "Font Size"
+msgstr "Tamanho do tipo de letra"
+
+#: ../src/dialog_font.tcl:89
+#: ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116
+msgid "Stretch"
+msgstr "Expandir"
+
+#: ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123
+msgid "X and Y"
+msgstr "X e Y"
+
+#: ../src/dialog_font.tcl:98
+#: ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125
+msgid "X only"
+msgstr "Apenas X"
+
+#: ../src/dialog_font.tcl:100
+#: ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127
+msgid "Y only"
+msgstr "Apenas Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Propriedades da atom box"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Largura:"
+
+#: ../src/dialog_gatom.tcl:103
+msgid "Limits"
+msgstr "Limites"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Inferior:"
+
+#: ../src/dialog_gatom.tcl:112
+#: ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Superior:"
+
+#: ../src/dialog_gatom.tcl:116
+#: ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600
+#: ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr "Legenda"
+
+#: ../src/dialog_gatom.tcl:124
+#: ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Esquerda"
+
+#: ../src/dialog_gatom.tcl:126
+#: ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Direita"
+
+#: ../src/dialog_gatom.tcl:128
+#: ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Acima"
+
+#: ../src/dialog_gatom.tcl:130
+#: ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Abaixo"
+
+#: ../src/dialog_gatom.tcl:137
+#: ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:141
+#: ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr "Símbolo para enviar:"
+
+#: ../src/dialog_gatom.tcl:147
+#: ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Símbolo para receber:"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Cor de fundo"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Cor frontal"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Cor da legenda"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr "Iniciar"
+
+#: ../src/dialog_iemgui.tcl:275
+#: ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr "Não iniciar"
+
+#: ../src/dialog_iemgui.tcl:287
+#: ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr "Saltar no clique"
+
+#: ../src/dialog_iemgui.tcl:290
+#: ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr "Manter no clique"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "Propriedades de %s"
+
+#: ../src/dialog_iemgui.tcl:550
+#: ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:288
+#: ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325
+#: ../src/pd_menus.tcl:338
+#: ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382
+#: ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422
+#: ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Guardar"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "Posição X"
+
+#: ../src/dialog_iemgui.tcl:611
+#: ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr "Posição Y"
+
+#: ../src/dialog_iemgui.tcl:642
+#: ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Cores"
+
+#: ../src/dialog_iemgui.tcl:648
+#: ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr "Fundo"
+
+#: ../src/dialog_iemgui.tcl:650
+#: ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr "Fachada"
+
+#: ../src/dialog_iemgui.tcl:662
+#: ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Criar uma cor"
+
+#: ../src/dialog_iemgui.tcl:682
+#: ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr "teste"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr "Configuração MIDI"
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr "Configuração MIDI ALSA"
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr "Usar vários dispositivos ALSA"
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr "Ports de entrada:"
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr "Ports de saída:"
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr "Rejeitar mudanças "
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr "Fechar mesmo?"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Fechar esta janela?"
+
+#: ../src/pd-gui.tcl:185
+#: ../src/pd-gui.tcl:195
+#: ../src/pd-gui.tcl:206
+msgid "Associated Files"
+msgstr "Ficheiros associados"
+
+#: ../src/pd-gui.tcl:186
+#: ../src/pd-gui.tcl:196
+#: ../src/pd-gui.tcl:207
+msgid "Pd Files"
+msgstr "Ficheiros Pd"
+
+#: ../src/pd-gui.tcl:187
+#: ../src/pd-gui.tcl:208
+msgid "Max Patch Files"
+msgstr "Ficheiros Max-Patches"
+
+#: ../src/pd-gui.tcl:188
+#: ../src/pd-gui.tcl:209
+msgid "Max Text Files"
+msgstr "Ficheiros Max-Texto"
+
+#: ../src/pd-gui.tcl:197
+msgid "Max Patch Files (.pat)"
+msgstr "Ficheiros Max-Patches (.pat)"
+
+#: ../src/pd-gui.tcl:198
+msgid "Max Text Files (.mxt)"
+msgstr "Ficheiros Max-Texto (.mxt)"
+
+#: ../src/pd-gui.tcl:270
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr "AVISO: O tipo de letra '%s' não foi encontrado, usando o padrão (%s)"
+
+#: ../src/pd-gui.tcl:278
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr "AVISO: O formato de letra '%s' não foi encontrado, usando o padrão (%s)"
+
+#: ../src/pd-gui.tcl:303
+#, tcl-format
+#, fuzzy
+# this is broken, its missing all of the formats
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr "AVISO: O tamanho de letra '%s' não foi encontrado, usando o padrão (%s)"
+
+#: ../src/pd-gui.tcl:478
+#, fuzzy
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr "ERRO: 'pd' não apareceu, 'pd-gui' vai desligar-se!"
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr "Sem título"
+
+#: ../src/pd_menucommands.tcl:78
+#: ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Enviar mensagem..."
+
+#: ../src/pd_menucommands.tcl:82
+#: ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94
+#: ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192
+#: ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:292
+#: ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329
+#: ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387
+#: ../src/pd_menus.tcl:414
+#: ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453
+#: ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Mensagem"
+
+#: ../src/pd_menucommands.tcl:108
+#: ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112
+#: ../src/pd_menus.tcl:113
+#: ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118
+#: ../src/pd_menus.tcl:158
+#: ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163
+#: ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr "Tipo de letra"
+
+#: ../src/pd_menucommands.tcl:123
+#: ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:183
+#: ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr "Preferências"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Editar"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Ficheiro"
+
+#: ../src/pd_menus.tcl:45
+#: ../src/pdtk_canvas.tcl:48
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Ajuda"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Put"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Janela"
+
+#: ../src/pd_menus.tcl:81
+#: ../src/pd_menus.tcl:82
+#: ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:255
+#: ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:298
+#: ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:349
+#: ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380
+#: ../src/pd_menus.tcl:407
+#: ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Novo"
+
+#: ../src/pd_menus.tcl:82
+#: ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:256
+#: ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286
+#: ../src/pd_menus.tcl:299
+#: ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336
+#: ../src/pd_menus.tcl:350
+#: ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:408
+#: ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447
+#: ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:131
+#: ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Abrir"
+
+#: ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:85
+#: ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131
+#: ../src/pd_menus.tcl:261
+#: ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289
+#: ../src/pd_menus.tcl:302
+#: ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339
+#: ../src/pd_menus.tcl:356
+#: ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384
+#: ../src/pd_menus.tcl:411
+#: ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Guardar como..."
+
+#: ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:89
+#: ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135
+#: ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293
+#: ../src/pd_menus.tcl:306
+#: ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343
+#: ../src/pd_menus.tcl:362
+#: ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389
+#: ../src/pd_menus.tcl:415
+#: ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr "Imprimir"
+
+#: ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:94
+#: ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr "Anular"
+
+#: ../src/pd_menus.tcl:95
+#: ../src/pd_menus.tcl:96
+#: ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr "Restaurar"
+
+#: ../src/pd_menus.tcl:98
+#: ../src/pd_menus.tcl:99
+#: ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr "Cortar"
+
+#: ../src/pd_menus.tcl:104
+#: ../src/pd_menus.tcl:105
+#: ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: ../src/pd_menus.tcl:106
+#: ../src/pd_menus.tcl:107
+#: ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr "Escolher tudo"
+
+#: ../src/pd_menus.tcl:110
+#: ../src/pd_menus.tcl:111
+#: ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116
+#: ../src/pd_menus.tcl:156
+#: ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161
+#: ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr "Editor de texto"
+
+#: ../src/pd_menus.tcl:120
+#: ../src/pd_menus.tcl:121
+#: ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr "Arrumar"
+
+#: ../src/pd_menus.tcl:122
+#: ../src/pd_menus.tcl:123
+#: ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr "Mostrar consola"
+
+#: ../src/pd_menus.tcl:124
+#: ../src/pd_menus.tcl:125
+#: ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+msgid "Clear Console"
+msgstr "Limpar consola"
+
+#: ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129
+#: ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr "Modo de edição"
+
+#: ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:190
+#: ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr "Object"
+
+#: ../src/pd_menus.tcl:149
+#: ../src/pd_menus.tcl:194
+#: ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr "Número"
+
+#: ../src/pd_menus.tcl:151
+#: ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr "Symbol"
+
+#: ../src/pd_menus.tcl:153
+#: ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr "Comment"
+
+#: ../src/pd_menus.tcl:156
+#: ../src/pd_menus.tcl:201
+#: ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr "Bang"
+
+#: ../src/pd_menus.tcl:158
+#: ../src/pd_menus.tcl:203
+#: ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr "Toggle"
+
+#: ../src/pd_menus.tcl:160
+#: ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr "Number2"
+
+#: ../src/pd_menus.tcl:162
+#: ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr "Vslider"
+
+#: ../src/pd_menus.tcl:164
+#: ../src/pd_menus.tcl:209
+#: ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr "Hslider"
+
+#: ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:211
+#: ../src/pd_menus.tcl:212
+msgid "Vradio"
+msgstr "Vradio"
+
+#: ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:213
+#: ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr "Hradio"
+
+#: ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:215
+#: ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr "VU Meter"
+
+#: ../src/pd_menus.tcl:172
+#: ../src/pd_menus.tcl:217
+#: ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr "Canvas"
+
+#: ../src/pd_menus.tcl:175
+#: ../src/pd_menus.tcl:220
+#: ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Graph"
+
+#: ../src/pd_menus.tcl:176
+#: ../src/pd_menus.tcl:221
+#: ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr "Array"
+
+#: ../src/pd_menus.tcl:181
+#: ../src/pd_menus.tcl:226
+#: ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr "Localizar..."
+
+#: ../src/pd_menus.tcl:183
+#: ../src/pd_menus.tcl:228
+#: ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr "Localizar de novo"
+
+#: ../src/pd_menus.tcl:185
+#: ../src/pd_menus.tcl:230
+#: ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr "Localizar último erro"
+
+#: ../src/pd_menus.tcl:191
+#: ../src/pd_menus.tcl:236
+#: ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr "DSP Ligado"
+
+#: ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:238
+#: ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr "DSP Desligado"
+
+#: ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:242
+#: ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr "Testar audio e MIDI..."
+
+#: ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:244
+#: ../src/pd_menus.tcl:271
+msgid "Load Meter"
+msgstr "Carregar medidor"
+
+#: ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:251
+#: ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr "Minimizar"
+
+#: ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr "Zoom"
+
+#: ../src/pd_menus.tcl:210
+#: ../src/pd_menus.tcl:256
+#: ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr "Janela superior"
+
+#: ../src/pd_menus.tcl:216
+#: ../src/pd_menus.tcl:262
+#: ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224
+#: ../src/pd_menus.tcl:241
+#: ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270
+#: ../src/pd_menus.tcl:297
+#: ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr "Sobre o Pd"
+
+#: ../src/pd_menus.tcl:227
+#: ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr "Manual HTML"
+
+#: ../src/pd_menus.tcl:229
+#: ../src/pd_menus.tcl:275
+#: ../src/pd_menus.tcl:302
+msgid "Browser..."
+msgstr "Navegador"
+
+#: ../src/pd_menus.tcl:248
+#: ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Preferências..."
+
+#: ../src/pd_menus.tcl:257
+#: ../src/pd_menus.tcl:270
+#: ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr "Abrir recente"
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr "Configuração audio..."
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr "Configuração MIDI..."
+
+#: ../src/pd_menus.tcl:296
+#: ../src/pd_menus.tcl:309
+#: ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346
+#: ../src/pd_menus.tcl:393
+#: ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432
+#: ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Sair"
+
+#: ../src/pd_menus.tcl:304
+#: ../src/pd_menus.tcl:331
+msgid "Clear Menu"
+msgstr "Limpar menu"
+
+#: ../src/pdtk_canvas.tcl:44
+#: ../src/pdtk_canvas.tcl:109
+#: ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr "Propriedades"
+
+#: ../src/pdwindow.tcl:43
+msgid "DSP"
+msgstr "DSP"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr "Sinal"
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr "Geradores"
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr "Filtros"
+
+#: ../startup/object_db.tcl:116
+#: ../startup/object_db.tcl:124
+msgid "Math"
+msgstr "Matemática"
+
+#: ../startup/object_db.tcl:117
+#: ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr "Entrada/Saída"
+
+#: ../startup/object_db.tcl:118
+#: ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119
+#: ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120
+#: ../startup/object_db.tcl:129
+msgid "Others"
+msgstr "Outros"
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr "GUI"
+
diff --git a/pd/po/sq.po b/pd/po/sq.po
new file mode 100644
index 00000000..6db87566
--- /dev/null
+++ b/pd/po/sq.po
@@ -0,0 +1,954 @@
+# translation of Pure Data to Albanian
+# This file is put in the public domain.
+# Besnik Bleta <besnik@spymac.com>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-03-07 11:12+0200\n"
+"Last-Translator: Besnik Bleta <besnik@spymac.com>\n"
+"Language-Team: Albanian <translation-team-sq@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Datë"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "Uganda"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Kopjo"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Datë"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Emër"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#, fuzzy
+msgid "Size:"
+msgstr "Madhësi"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "_Përmbajtje"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Portë"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Poloni"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Msz i Fundit: %s"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Fshij"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "Listë Ndalimesh..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Anulo"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Zbato"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Anulo"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Ruaj"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Vijë shënimi"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Gjej"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "Kërko Tekst..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Portë:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Mbyll"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Dritare dërgimesh"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Gërma:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Madhësi"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "KohëFillim"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Kufi Përdoruesi"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "Përdorues"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "Majtas"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Djathtas"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Sipër"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Poshtë"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "Mesazh"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Dritare marrjesh"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Sfond:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Përpara:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Përzgjidhni ngjyrë"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Fto"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Ruaj"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Ngjyra"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Sfond:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Gërma:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Testo Tërë"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "Mbyll këtë skedë/dritare"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Kartelë"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "Mesazh"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Mesazh"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Gërma:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "Parapëlqime..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "_Përpuno"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Kartelë"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Ndihmë"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Maqedonia"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "_Dritare"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "E re"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Hap"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "Ruaj Si"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "_Përpuno..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "Uganda"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "E kuqe:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Datë"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Fshij Tërë"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Ngjyra Teksti"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Fshij listë"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Mënyrë"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Numër"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Urdhër"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Ndalo"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Togo"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Numër"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "Fshehur"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Version"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Kanada"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Grafik"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Andorra"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Dërgo Kartelë..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Asnjë"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Matës vonese:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Poshtë"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Dritare dërgimesh"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "_Rreth"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Shfleto..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Parapëlqime..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Lër"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Fshij listë"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Asnjë"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Kartelë"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/po/sv.po b/pd/po/sv.po
new file mode 100644
index 00000000..327ec101
--- /dev/null
+++ b/pd/po/sv.po
@@ -0,0 +1,921 @@
+# Swedish translation of Pure Data.
+# This file is put in the public domain
+# Johannes Burström <johannes@ljud.org>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2009-08-22 11:20+0100\n"
+"Last-Translator: Johannes Burström <johannes@ljud.org>\n"
+"Language-Team: Johannes Burström <johannes@ljud.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Swedish\n"
+"X-Poedit-Country: Sweden\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Duplicera"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "Ångra"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr "Förkasta ändringar i '%s'?"
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr "Vill du spara dina ändringar i '%s'?"
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Kopiera"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+msgid "Paste"
+msgstr "Klistra in"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+#, fuzzy
+msgid "Array Properties"
+msgstr "Egenskaper för Array"
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+msgid "Name:"
+msgstr "Namn:"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Storlek:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+msgid "Save contents"
+msgstr "Spara innehåll"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr "Rita som:"
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+msgid "Points"
+msgstr "Punkter"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+msgid "Polygon"
+msgstr "Polygon"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr "Bezier-kurva"
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+#, fuzzy
+msgid "Put array into:"
+msgstr "Rita array i:"
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+#, fuzzy
+msgid "New graph"
+msgstr "Ny graf"
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Senaste graf"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Radera array"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+msgid "Open List View..."
+msgstr "Öppna listvy..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Ångra"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Verkställ"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr "Ok"
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Ångra"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+#, fuzzy
+msgid "Canvas Properties"
+msgstr "Egenskaper för canvas"
+
+#: ../src/dialog_canvas.tcl:146
+msgid "Scale"
+msgstr "Skala"
+
+#: ../src/dialog_canvas.tcl:150
+#, fuzzy
+msgid "X units per pixel:"
+msgstr "X enheter per pixel:"
+
+#: ../src/dialog_canvas.tcl:155
+#, fuzzy
+msgid "Y units per pixel:"
+msgstr "Y enheter per pixel:"
+
+#: ../src/dialog_canvas.tcl:159
+#, fuzzy
+msgid "Appearance on parent patch"
+msgstr "Utseende på föräldrapatchen"
+
+#: ../src/dialog_canvas.tcl:161
+#, fuzzy
+msgid "Graph-On-Parent"
+msgstr "Graph-On-Parent"
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr "Göm objektnamn och argument"
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr "Omfång och storlek"
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr "Omfång (x), från"
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr "till"
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+msgid "Margin:"
+msgstr "Marginal:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr "Omfång (y), från:"
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Sök"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+msgid "Search in"
+msgstr "Sök i"
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+msgid "for:"
+msgstr "efter:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Stäng"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr "Endast hela ord"
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+msgid "Pd window"
+msgstr "Huvudfönster"
+
+#: ../src/dialog_font.tcl:45
+#, fuzzy
+msgid "Font Properties"
+msgstr "Egenskaper"
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Typsnitt"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Typsnittsstorlek:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "Sträck:"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr "X och Y"
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr "Bara X"
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr "Bara Y"
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr "Egenskaper för Atom"
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr "Bredd:"
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Gränser"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr "Lägre:"
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+msgid "Upper:"
+msgstr "Övre"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+#, fuzzy
+msgid "Label"
+msgstr "Text"
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr "Vänster"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Höger"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Överkant"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Underkant"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+msgid "Messages"
+msgstr "Meddelanden"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+#, fuzzy
+msgid "Send symbol:"
+msgstr "Sändsymbol:"
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+msgid "Receive symbol:"
+msgstr "Mottagarsymbol:"
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr "Bakgrundsfärg"
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr "Förgrundsfärg"
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr "Textfärg"
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr "Initiera"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr "Initiera inte"
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr "Ändra värde vid klick"
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr "Behåll värde vid klick"
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr "Egenskaper för %s"
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Spara"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr "x-position"
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr "y-position"
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Färger"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+msgid "Background"
+msgstr "Bakgrund"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+msgid "Front"
+msgstr "Förgrund"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr "Skapa ny färg"
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr "Testtext"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+#, fuzzy
+msgid "Discard changes to this window??"
+msgstr "Ignorera ändringar i detta fönster?"
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr "Vill du avsluta?"
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr "Stäng fönstret?"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Fil"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr "Sänd meddelande"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Meddelande"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+msgid "Font"
+msgstr "Typsnitt"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+msgid "Preferences"
+msgstr "Inställningar"
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr "Redigera"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Fil"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Hjälp"
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr "Media"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr "Placera"
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr "Fönster"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Ny"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Öppna"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+msgid "Save As..."
+msgstr "Spara som..."
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+msgid "Print..."
+msgstr "Skriv ut..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+msgid "Undo"
+msgstr "Ångra"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+msgid "Redo"
+msgstr "Gör om"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr "Klipp ut"
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+msgid "Duplicate"
+msgstr "Duplicera"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+msgid "Select All"
+msgstr "Markera allt"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+msgid "Text Editor"
+msgstr "Textredigerare"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr "Städa upp"
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+#, fuzzy
+msgid "Toggle Console"
+msgstr "Växla visning av konsoll"
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Rensa konsoll"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+msgid "Edit Mode"
+msgstr "Redigeringsläge"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr "Objekt"
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+msgid "Number"
+msgstr "Number"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr "Symbol"
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+msgid "Comment"
+msgstr "Kommentar"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+msgid "Bang"
+msgstr "Bang"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+msgid "Toggle"
+msgstr "Toggle"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+msgid "Number2"
+msgstr "Number2"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr "Vslider"
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+msgid "Hslider"
+msgstr "Hslider"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+msgid "Vradio"
+msgstr "Vradio"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr "Hradio"
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr "VU-mätare"
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+msgid "Canvas"
+msgstr "Canvas"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Graf"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+msgid "Array"
+msgstr "Array"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+msgid "Find..."
+msgstr "Sök..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr "Sök igen"
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr "Sök senaste fel"
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr "DSP på"
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+msgid "DSP Off"
+msgstr "DSP av"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr "Testa ljud och MIDI..."
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Belastningsmätare"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr "Minimera"
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+msgid "Zoom"
+msgstr "Zooma"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+msgid "Parent Window"
+msgstr "Föräldrafönster"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+#, fuzzy
+msgid "Bring All to Front"
+msgstr "Lägg alla överst"
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+msgid "About Pd"
+msgstr "Om Pd"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr "HTML-manual..."
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+msgid "Browser..."
+msgstr "Bläddra..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Inställningar..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr "Öppna senaste"
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Avsluta"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Rensa konsoll"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr "Egenskaper"
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "DSP på"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Fil"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
+
+#~ msgid "Patch Font"
+#~ msgstr "Patchtypsnitt"
diff --git a/pd/po/template.pot b/pd/po/template.pot
new file mode 100644
index 00000000..8ee2d377
--- /dev/null
+++ b/pd/po/template.pot
@@ -0,0 +1,1338 @@
+# SOME DESCRIPTIVE TITLE.
+# This file is put in the public domain
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2010-01-17 19:19-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147 ../src/pd_menus.tcl:152 ../src/pd_menus.tcl:157
+msgid "Copy"
+msgstr ""
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:154 ../src/pd_menus.tcl:159
+msgid "Paste"
+msgstr ""
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#: ../src/dialog_array.tcl:274
+msgid "Name:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_array.tcl:280 ../src/dialog_canvas.tcl:178
+#: ../src/dialog_canvas.tcl:182 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_canvas.tcl:197 ../src/dialog_iemgui.tcl:617
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+#: ../src/dialog_iemgui.tcl:626
+msgid "Size:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#: ../src/dialog_array.tcl:284
+msgid "Save contents"
+msgstr ""
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+#: ../src/dialog_array.tcl:288
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#: ../src/dialog_array.tcl:291
+msgid "Points"
+msgstr ""
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#: ../src/dialog_array.tcl:293
+msgid "Polygon"
+msgstr ""
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+#: ../src/dialog_array.tcl:295
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+#: ../src/dialog_array.tcl:301
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+#: ../src/dialog_array.tcl:304
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#: ../src/dialog_array.tcl:306
+msgid "Last graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#: ../src/dialog_array.tcl:310
+msgid "Delete array"
+msgstr ""
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#: ../src/dialog_array.tcl:316
+msgid "Open List View..."
+msgstr ""
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_array.tcl:323 ../src/dialog_audio.tcl:136
+#: ../src/dialog_audio.tcl:138 ../src/dialog_audio.tcl:144
+#: ../src/dialog_canvas.tcl:205 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_find.tcl:160 ../src/dialog_font.tcl:51
+#: ../src/dialog_gatom.tcl:153 ../src/dialog_gatom.tcl:157
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:738
+#: ../src/dialog_iemgui.tcl:742 ../src/dialog_iemgui.tcl:747
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:97
+#: ../src/dialog_midi.tcl:226 ../src/dialog_midi.tcl:228
+#: ../src/dialog_midi.tcl:232 ../src/scrollboxwindow.tcl:82
+msgid "Cancel"
+msgstr ""
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_array.tcl:327 ../src/dialog_audio.tcl:138
+#: ../src/dialog_audio.tcl:140 ../src/dialog_audio.tcl:148
+#: ../src/dialog_canvas.tcl:207 ../src/dialog_canvas.tcl:213
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:161
+#: ../src/dialog_gatom.tcl:164 ../src/dialog_iemgui.tcl:741
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:95
+#: ../src/dialog_midi.tcl:99 ../src/dialog_midi.tcl:228
+#: ../src/dialog_midi.tcl:230 ../src/dialog_midi.tcl:234
+#: ../src/scrollboxwindow.tcl:84
+msgid "Apply"
+msgstr ""
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_array.tcl:331 ../src/dialog_audio.tcl:140
+#: ../src/dialog_audio.tcl:142 ../src/dialog_audio.tcl:152
+#: ../src/dialog_canvas.tcl:209 ../src/dialog_canvas.tcl:217
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_font.tcl:103 ../src/dialog_gatom.tcl:159
+#: ../src/dialog_gatom.tcl:165 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:744 ../src/dialog_iemgui.tcl:748
+#: ../src/dialog_iemgui.tcl:754 ../src/dialog_iemgui.tcl:755
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:97
+#: ../src/dialog_midi.tcl:101 ../src/dialog_midi.tcl:230
+#: ../src/dialog_midi.tcl:232 ../src/dialog_midi.tcl:236
+#: ../src/dialog_startup.tcl:29 ../src/dialog_startup.tcl:30
+#: ../src/scrollboxwindow.tcl:86
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130 ../src/dialog_audio.tcl:132
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142 ../src/dialog_audio.tcl:144
+#: ../src/dialog_audio.tcl:156
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151 ../src/dialog_audio.tcl:153
+#: ../src/dialog_audio.tcl:164
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153 ../src/dialog_audio.tcl:155
+#: ../src/dialog_audio.tcl:166
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158 ../src/dialog_audio.tcl:160
+#: ../src/dialog_audio.tcl:172
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_audio.tcl:168
+#: ../src/dialog_audio.tcl:180 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:107 ../src/dialog_midi.tcl:111
+#: ../src/dialog_midi.tcl:241 ../src/dialog_midi.tcl:243
+#: ../src/dialog_midi.tcl:247
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:171
+#: ../src/dialog_audio.tcl:183 ../src/dialog_audio.tcl:185
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:200
+#: ../src/dialog_audio.tcl:213 ../src/dialog_audio.tcl:214
+#: ../src/dialog_audio.tcl:215 ../src/dialog_audio.tcl:229
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:234
+#: ../src/dialog_audio.tcl:249 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:252 ../src/dialog_audio.tcl:265
+#: ../src/dialog_audio.tcl:267 ../src/dialog_audio.tcl:268
+#: ../src/dialog_audio.tcl:280 ../src/dialog_audio.tcl:282
+#: ../src/dialog_audio.tcl:284 ../src/dialog_audio.tcl:300
+msgid "Channels:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_audio.tcl:181
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:117 ../src/dialog_midi.tcl:121
+#: ../src/dialog_midi.tcl:251 ../src/dialog_midi.tcl:253
+#: ../src/dialog_midi.tcl:257
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_audio.tcl:196
+#: ../src/dialog_audio.tcl:210 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:129 ../src/dialog_midi.tcl:133
+#: ../src/dialog_midi.tcl:263 ../src/dialog_midi.tcl:265
+#: ../src/dialog_midi.tcl:269
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_audio.tcl:211
+#: ../src/dialog_audio.tcl:225 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:141 ../src/dialog_midi.tcl:145
+#: ../src/dialog_midi.tcl:275 ../src/dialog_midi.tcl:277
+#: ../src/dialog_midi.tcl:281
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_audio.tcl:225
+#: ../src/dialog_audio.tcl:240 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:152 ../src/dialog_midi.tcl:156
+#: ../src/dialog_midi.tcl:286 ../src/dialog_midi.tcl:288
+#: ../src/dialog_midi.tcl:292
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226 ../src/dialog_audio.tcl:228
+#: ../src/dialog_audio.tcl:243
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_audio.tcl:248
+#: ../src/dialog_audio.tcl:264 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:162 ../src/dialog_midi.tcl:166
+#: ../src/dialog_midi.tcl:296 ../src/dialog_midi.tcl:298
+#: ../src/dialog_midi.tcl:302
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_audio.tcl:263
+#: ../src/dialog_audio.tcl:280 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:173 ../src/dialog_midi.tcl:177
+#: ../src/dialog_midi.tcl:307 ../src/dialog_midi.tcl:309
+#: ../src/dialog_midi.tcl:313
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_audio.tcl:278
+#: ../src/dialog_audio.tcl:296 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:184 ../src/dialog_midi.tcl:188
+#: ../src/dialog_midi.tcl:318 ../src/dialog_midi.tcl:320
+#: ../src/dialog_midi.tcl:324
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_audio.tcl:293
+#: ../src/dialog_audio.tcl:312 ../src/dialog_midi.tcl:195
+#: ../src/dialog_midi.tcl:197 ../src/dialog_midi.tcl:201
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:122
+msgid "WARNING: unknown graphme flags received in pdtk_canvas_dialog"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146 ../src/dialog_canvas.tcl:150
+msgid "Scale"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:150 ../src/dialog_canvas.tcl:154
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155 ../src/dialog_canvas.tcl:159
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159 ../src/dialog_canvas.tcl:163
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161 ../src/dialog_canvas.tcl:165
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165 ../src/dialog_canvas.tcl:169
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170 ../src/dialog_canvas.tcl:174
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174 ../src/dialog_canvas.tcl:178
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:180
+#: ../src/dialog_canvas.tcl:191 ../src/dialog_canvas.tcl:195
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:184
+#: ../src/dialog_canvas.tcl:195 ../src/dialog_canvas.tcl:199
+msgid "Margin:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:189 ../src/dialog_canvas.tcl:193
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_data.tcl:29
+msgid "Data Properties"
+msgstr ""
+
+#: ../src/dialog_data.tcl:37
+msgid "Send (Ctrl s)"
+msgstr ""
+
+#: ../src/dialog_data.tcl:39
+msgid "OK (Ctrl t)"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:105
+#: ../src/dialog_find.tcl:107 ../src/dialog_find.tcl:115
+#: ../src/dialog_find.tcl:123 ../src/dialog_find.tcl:164
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr ""
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:142
+msgid "Search in"
+msgstr ""
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95 ../src/dialog_find.tcl:103
+#: ../src/dialog_find.tcl:144
+msgid "for:"
+msgstr ""
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/dialog_find.tcl:118
+#: ../src/dialog_find.tcl:168 ../src/pd_menus.tcl:63 ../src/pd_menus.tcl:74
+#: ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:118
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:143 ../src/pd_menus.tcl:259 ../src/pd_menus.tcl:272
+#: ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308 ../src/pd_menus.tcl:332
+#: ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354 ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:410 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:448 ../src/pd_menus.tcl:458
+#: ../src/pd_menus.tcl:489 ../src/pd_menus.tcl:496 ../src/pd_menus.tcl:527
+#: ../src/pd_menus.tcl:574
+msgid "Close"
+msgstr ""
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+#: ../src/dialog_find.tcl:111 ../src/dialog_find.tcl:154
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_find.tcl:102
+#: ../src/dialog_find.tcl:143 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:296 ../src/pdwindow.tcl:33
+#: ../src/pdwindow.tcl:128 ../src/pdwindow.tcl:277 ../src/pdwindow.tcl:278
+msgid "Pd window"
+msgstr ""
+
+#: ../src/dialog_find.tcl:105
+#, tcl-format
+msgid "Couldn't find '%s' in %s"
+msgstr ""
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:54 ../src/dialog_font.tcl:55
+#, tcl-format
+msgid "%s Font"
+msgstr ""
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#: ../src/dialog_font.tcl:107
+msgid "Font Size"
+msgstr ""
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:119
+msgid "Stretch"
+msgstr ""
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+#: ../src/dialog_font.tcl:126
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+#: ../src/dialog_font.tcl:128
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+#: ../src/dialog_font.tcl:130
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99 ../src/dialog_gatom.tcl:103
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103 ../src/dialog_gatom.tcl:107
+msgid "Limits"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:107 ../src/dialog_gatom.tcl:111
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#: ../src/dialog_gatom.tcl:116
+msgid "Upper:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:120
+#: ../src/dialog_gatom.tcl:121 ../src/dialog_iemgui.tcl:598
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:606
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657 ../src/dialog_iemgui.tcl:659
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:128
+#: ../src/dialog_gatom.tcl:129
+msgid "Left "
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:130
+#: ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:132
+#: ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:134
+#: ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:141
+#: ../src/dialog_gatom.tcl:145 ../src/dialog_iemgui.tcl:572
+#: ../src/dialog_iemgui.tcl:574 ../src/dialog_iemgui.tcl:576
+msgid "Messages"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_gatom.tcl:149 ../src/dialog_iemgui.tcl:576
+#: ../src/dialog_iemgui.tcl:578 ../src/dialog_iemgui.tcl:580
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:151
+#: ../src/dialog_gatom.tcl:155 ../src/dialog_iemgui.tcl:583
+#: ../src/dialog_iemgui.tcl:585 ../src/dialog_iemgui.tcl:589
+msgid "Receive symbol:"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:197
+msgid "Background color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:204
+msgid "Foreground color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:211
+msgid "Label color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:272
+msgid "Init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+#: ../src/dialog_iemgui.tcl:550
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:556
+#: ../src/dialog_iemgui.tcl:558 ../src/dialog_iemgui.tcl:560
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:559
+#: ../src/dialog_iemgui.tcl:561 ../src/dialog_iemgui.tcl:563
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:549 ../src/dialog_iemgui.tcl:550
+#: ../src/dialog_iemgui.tcl:553 ../src/pd_menus.tcl:60 ../src/pd_menus.tcl:71
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:92 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:135
+#: ../src/pd_menus.tcl:140 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:273
+#: ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301 ../src/pd_menus.tcl:325
+#: ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355 ../src/pd_menus.tcl:382
+#: ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410 ../src/pd_menus.tcl:411
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:439 ../src/pd_menus.tcl:449
+#: ../src/pd_menus.tcl:487 ../src/pd_menus.tcl:490 ../src/pd_menus.tcl:518
+#: ../src/pd_menus.tcl:563
+msgid "Save"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:606 ../src/dialog_iemgui.tcl:608
+#: ../src/dialog_iemgui.tcl:614
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:609 ../src/dialog_iemgui.tcl:611
+#: ../src/dialog_iemgui.tcl:612 ../src/dialog_iemgui.tcl:617
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:640 ../src/dialog_iemgui.tcl:642
+#: ../src/dialog_iemgui.tcl:645 ../src/dialog_iemgui.tcl:649
+msgid "Colors"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:646 ../src/dialog_iemgui.tcl:648
+#: ../src/dialog_iemgui.tcl:651 ../src/dialog_iemgui.tcl:655
+msgid "Background"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:650
+#: ../src/dialog_iemgui.tcl:654 ../src/dialog_iemgui.tcl:657
+msgid "Front"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:660 ../src/dialog_iemgui.tcl:662
+#: ../src/dialog_iemgui.tcl:668 ../src/dialog_iemgui.tcl:669
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:679 ../src/dialog_iemgui.tcl:682
+#: ../src/dialog_iemgui.tcl:688
+msgid "Test label"
+msgstr ""
+
+#: ../src/dialog_message.tcl:61
+msgid "Send a Pd message"
+msgstr ""
+
+#: ../src/dialog_message.tcl:80
+msgid "(use arrow keys for history)"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220 ../src/dialog_midi.tcl:222
+#: ../src/dialog_midi.tcl:226
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331 ../src/dialog_midi.tcl:333
+#: ../src/dialog_midi.tcl:337
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337 ../src/dialog_midi.tcl:339
+#: ../src/dialog_midi.tcl:343
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340 ../src/dialog_midi.tcl:342
+#: ../src/dialog_midi.tcl:346
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/dialog_path.tcl:30
+msgid "Pd search path for objects, help, fonts, and other files"
+msgstr ""
+
+#: ../src/dialog_path.tcl:35
+msgid "Use standard extensions"
+msgstr ""
+
+#: ../src/dialog_path.tcl:37
+msgid "Verbose"
+msgstr ""
+
+#: ../src/dialog_startup.tcl:49
+msgid "Add new library"
+msgstr ""
+
+#: ../src/dialog_startup.tcl:53
+msgid "Edit library"
+msgstr ""
+
+#: ../src/dialog_startup.tcl:79
+msgid "Pd libraries to load on startup"
+msgstr ""
+
+#: ../src/dialog_startup.tcl:82
+msgid "Startup flags:"
+msgstr ""
+
+#: ../src/dialog_startup.tcl:91
+msgid "Defeat real-time scheduling"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+msgid "Close this window??"
+msgstr ""
+
+#: ../src/helpbrowser.tcl:25
+msgid "Help Browser"
+msgstr ""
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:218
+#: ../src/pd-gui.tcl:226 ../src/pd-gui.tcl:230 ../src/pd-gui.tcl:241
+#: ../src/pd-gui.tcl:259 ../src/pd-gui.tcl:277 ../src/pd-gui.tcl:296
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:219
+#: ../src/pd-gui.tcl:227 ../src/pd-gui.tcl:231 ../src/pd-gui.tcl:242
+#: ../src/pd-gui.tcl:260 ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:297
+msgid "Pd Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:220 ../src/pd-gui.tcl:228 ../src/pd-gui.tcl:243
+#: ../src/pd-gui.tcl:261 ../src/pd-gui.tcl:298
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:221 ../src/pd-gui.tcl:229 ../src/pd-gui.tcl:244
+#: ../src/pd-gui.tcl:262 ../src/pd-gui.tcl:299
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217 ../src/pd-gui.tcl:232
+#: ../src/pd-gui.tcl:279
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218 ../src/pd-gui.tcl:233
+#: ../src/pd-gui.tcl:280
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290 ../src/pd-gui.tcl:305
+#: ../src/pd-gui.tcl:374
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298 ../src/pd-gui.tcl:313
+#: ../src/pd-gui.tcl:382
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:338 ../src/pd-gui.tcl:407
+#, tcl-format
+msgid "WARNING: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+#: ../src/pd-gui.tcl:518 ../src/pd-gui.tcl:620
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_connect.tcl:76 ../src/pd_connect.tcl:85 ../src/pdwindow.tcl:90
+#: ../src/pdwindow.tcl:239
+msgid "(Tcl) INVALID COMMAND NAME: "
+msgstr ""
+
+#: ../src/pd_connect.tcl:78 ../src/pd_connect.tcl:87 ../src/pdwindow.tcl:92
+#: ../src/pdwindow.tcl:241
+msgid "(Tcl) UNHANDLED ERROR: "
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:83 ../src/pd_menucommands.tcl:90
+msgid "Send Message..."
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:87 ../src/pd_menucommands.tcl:94
+#: ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:133
+#: ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:144 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193
+#: ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:265 ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305 ../src/pd_menus.tcl:329
+#: ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360 ../src/pd_menus.tcl:387
+#: ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:416 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:443 ../src/pd_menus.tcl:453 ../src/pd_menus.tcl:491
+#: ../startup/object_db.tcl:123
+msgid "Message"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:169
+#: ../src/pd_menus.tcl:174
+msgid "Font"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#: ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:475
+#: ../src/pd_menus.tcl:569
+msgid "Preferences"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Edit"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113 ../src/pdtk_canvas.tcl:160
+msgid "Help"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Media"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+msgid "Window"
+msgstr ""
+
+#: ../src/pd_menus.tcl:61 ../src/pd_menus.tcl:72 ../src/pd_menus.tcl:83
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:108 ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:136 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274 ../src/pd_menus.tcl:289
+#: ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326 ../src/pd_menus.tcl:339
+#: ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:384
+#: ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:412 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:440 ../src/pd_menus.tcl:450 ../src/pd_menus.tcl:488
+#: ../src/pd_menus.tcl:491 ../src/pd_menus.tcl:519 ../src/pd_menus.tcl:564
+msgid "Save As..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:62 ../src/pd_menus.tcl:73 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:94
+#: ../src/pd_menus.tcl:109 ../src/pd_menus.tcl:117 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:140 ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280 ../src/pd_menus.tcl:293
+#: ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330 ../src/pd_menus.tcl:343
+#: ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388 ../src/pd_menus.tcl:389
+#: ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:418 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:444 ../src/pd_menus.tcl:454 ../src/pd_menus.tcl:492
+#: ../src/pd_menus.tcl:497 ../src/pd_menus.tcl:523 ../src/pd_menus.tcl:570
+msgid "Print..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:65 ../src/pd_menus.tcl:76 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:97 ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105
+#: ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:161
+msgid "Duplicate"
+msgstr ""
+
+#: ../src/pd_menus.tcl:66 ../src/pd_menus.tcl:77 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:114 ../src/pd_menus.tcl:120
+#: ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:167
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:177
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:67 ../src/pd_menus.tcl:78 ../src/pd_menus.tcl:89
+#: ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:115 ../src/pd_menus.tcl:122
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:178 ../src/pd_menus.tcl:185
+#: ../src/pd_menus.tcl:551 ../src/pdtk_canvas.tcl:224
+#: ../src/pdtk_canvas.tcl:226
+msgid "Edit Mode"
+msgstr ""
+
+#: ../src/pd_menus.tcl:70 ../src/pd_menus.tcl:80 ../src/pd_menus.tcl:93
+#: ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:124
+#: ../src/pd_menus.tcl:139 ../src/pd_menus.tcl:140 ../src/pd_menus.tcl:145
+#: ../src/pd_menus.tcl:150 ../src/pd_menus.tcl:320 ../src/pd_menus.tcl:326
+msgid "Undo"
+msgstr ""
+
+#: ../src/pd_menus.tcl:71 ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:95
+#: ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:119 ../src/pd_menus.tcl:125
+#: ../src/pd_menus.tcl:141 ../src/pd_menus.tcl:142 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:152 ../src/pd_menus.tcl:326 ../src/pd_menus.tcl:332
+msgid "Redo"
+msgstr ""
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:138
+#: ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:285
+#: ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376 ../src/pd_menus.tcl:380
+#: ../src/pd_menus.tcl:405 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:436 ../src/pd_menus.tcl:446 ../src/pd_menus.tcl:484
+#: ../src/pd_menus.tcl:515 ../src/pd_menus.tcl:560
+msgid "New"
+msgstr ""
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268 ../src/pd_menus.tcl:286
+#: ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323 ../src/pd_menus.tcl:336
+#: ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377 ../src/pd_menus.tcl:381
+#: ../src/pd_menus.tcl:406 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:437 ../src/pd_menus.tcl:447 ../src/pd_menus.tcl:485
+#: ../src/pd_menus.tcl:516 ../src/pd_menus.tcl:561 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+#: ../src/pdtk_canvas.tcl:158 ../src/pdtk_canvas.tcl:178
+#: ../src/pdtk_canvas.tcl:180
+msgid "Open"
+msgstr ""
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:150 ../src/pd_menus.tcl:155
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:163
+msgid "Select All"
+msgstr ""
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:167
+#: ../src/pd_menus.tcl:172
+msgid "Text Editor"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169 ../src/pd_menus.tcl:179
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171 ../src/pd_menus.tcl:174 ../src/pd_menus.tcl:181
+msgid "Clear Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:139 ../src/pd_menus.tcl:495 ../src/pd_menus.tcl:522
+#: ../src/pd_menus.tcl:567
+msgid "Message..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:188 ../src/pd_menus.tcl:190
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:201
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:194
+#: ../src/pd_menus.tcl:195 ../src/pd_menus.tcl:205
+msgid "Number"
+msgstr ""
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:196
+#: ../src/pd_menus.tcl:197 ../src/pd_menus.tcl:207
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:198
+#: ../src/pd_menus.tcl:199 ../src/pd_menus.tcl:209
+msgid "Comment"
+msgstr ""
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:199 ../src/pd_menus.tcl:201
+#: ../src/pd_menus.tcl:202 ../src/pd_menus.tcl:212
+msgid "Bang"
+msgstr ""
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:203
+#: ../src/pd_menus.tcl:204 ../src/pd_menus.tcl:214
+msgid "Toggle"
+msgstr ""
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:205
+#: ../src/pd_menus.tcl:206 ../src/pd_menus.tcl:216
+msgid "Number2"
+msgstr ""
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:207
+#: ../src/pd_menus.tcl:208 ../src/pd_menus.tcl:218
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:209
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:220
+msgid "Hslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:211
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:222
+msgid "Vradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:213
+#: ../src/pd_menus.tcl:214 ../src/pd_menus.tcl:224
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:215
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:226
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:217
+#: ../src/pd_menus.tcl:218 ../src/pd_menus.tcl:228
+msgid "Canvas"
+msgstr ""
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:218 ../src/pd_menus.tcl:220
+#: ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:231
+msgid "Graph"
+msgstr ""
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:219 ../src/pd_menus.tcl:221
+#: ../src/pd_menus.tcl:222 ../src/pd_menus.tcl:232
+msgid "Array"
+msgstr ""
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:226
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:237
+msgid "Find..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:228
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:239
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:230
+#: ../src/pd_menus.tcl:231 ../src/pd_menus.tcl:241
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:234 ../src/pd_menus.tcl:236
+#: ../src/pd_menus.tcl:237 ../src/pd_menus.tcl:247
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:238
+#: ../src/pd_menus.tcl:239 ../src/pd_menus.tcl:249
+msgid "DSP Off"
+msgstr ""
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:240 ../src/pd_menus.tcl:242
+#: ../src/pd_menus.tcl:269 ../src/pd_menus.tcl:280
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:244
+#: ../src/pd_menus.tcl:271 ../src/pd_menus.tcl:282
+msgid "Load Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:289
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:276
+#: ../src/pd_menus.tcl:280 ../src/pd_menus.tcl:291
+msgid "Zoom"
+msgstr ""
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#: ../src/pd_menus.tcl:291 ../src/pd_menus.tcl:294
+msgid "Parent Window"
+msgstr ""
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:278
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:300
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:298
+#: ../src/pd_menus.tcl:308 ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:362
+#: ../src/pd_menus.tcl:390 ../src/pd_menus.tcl:472
+msgid "About Pd"
+msgstr ""
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+#: ../src/pd_menus.tcl:311
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#: ../src/pd_menus.tcl:313
+msgid "Browser..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369 ../src/pd_menus.tcl:395
+msgid "Preferences..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:487
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263 ../src/pd_menus.tcl:274
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265 ../src/pd_menus.tcl:276 ../src/pd_menus.tcl:461
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:281
+msgid "Next Window"
+msgstr ""
+
+#: ../src/pd_menus.tcl:284
+msgid "Previous Window"
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:449 ../src/pd_menus.tcl:459
+#: ../src/pd_menus.tcl:497 ../src/pd_menus.tcl:528 ../src/pd_menus.tcl:575
+msgid "Quit"
+msgstr ""
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331 ../src/pd_menus.tcl:350
+#: ../src/pd_menus.tcl:356
+msgid "Clear Menu"
+msgstr ""
+
+#: ../src/pd_menus.tcl:305
+msgid "puredata.info"
+msgstr ""
+
+#: ../src/pd_menus.tcl:307
+msgid "Report a bug"
+msgstr ""
+
+#: ../src/pd_menus.tcl:455
+msgid "Path..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:457
+msgid "Startup..."
+msgstr ""
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:156
+#: ../src/pdtk_canvas.tcl:173 ../src/pdtk_canvas.tcl:175
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43 ../src/pdwindow.tcl:164 ../src/pdwindow.tcl:309
+msgid "DSP"
+msgstr ""
+
+#: ../src/pdwindow.tcl:86 ../src/pdwindow.tcl:235
+msgid "(Tcl) MISSING CLOSE-BRACE '}': "
+msgstr ""
+
+#: ../src/pdwindow.tcl:88 ../src/pdwindow.tcl:237
+msgid "(Tcl) MISSING CLOSE-BRACKET ']': "
+msgstr ""
+
+#: ../src/pdwindow.tcl:161 ../src/pdwindow.tcl:306
+msgid "IN"
+msgstr ""
+
+#: ../src/pdwindow.tcl:162 ../src/pdwindow.tcl:307
+msgid "OUT"
+msgstr ""
+
+#: ../src/pdwindow.tcl:168 ../src/pdwindow.tcl:314
+msgid "DIO"
+msgstr ""
+
+#: ../src/pdwindow.tcl:177 ../src/pdwindow.tcl:324
+msgid "Tcl:"
+msgstr ""
+
+#: ../src/wheredoesthisgo.tcl:19
+#, tcl-format
+msgid "Ignoring '%s': doesn't look like a Pd-file"
+msgstr ""
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+msgid "Filters"
+msgstr ""
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
+
+# iemgui
+msgid "-------dimensions(digits)(pix):-------"
+msgstr ""
+
+# iemgui
+msgid "--------dimensions(pix)(pix):--------"
+msgstr ""
+
+# iemgui
+msgid "----------dimensions(pix):-----------"
+msgstr ""
+
+# iemgui
+# iemgui
+msgid "------selectable_dimensions(pix):------"
+msgstr ""
+
+# iemgui
+msgid "------visible_rectangle(pix)(pix):------"
+msgstr ""
+
+# iemgui
+msgid "-----------output-range:-----------"
+msgstr ""
+
+# iemgui
+msgid "--------flash-time(ms)(ms):---------"
+msgstr ""
+
+# iemgui
+msgid "log-height:"
+msgstr ""
+
+# iemgui
+msgid "log"
+msgstr ""
+
+# iemgui
+msgid "lin"
+msgstr ""
+
+# iemgui
+msgid "top:"
+msgstr ""
+
+# iemgui
+msgid "bottom:"
+msgstr ""
+
+# iemgui
+msgid "value:"
+msgstr ""
+
+# iemgui
+msgid "max:"
+msgstr ""
+
+# iemgui
+msgid "min:"
+msgstr ""
+
+# iemgui
+msgid "right:"
+msgstr ""
+
+# iemgui
+msgid "left:"
+msgstr ""
+
+# iemgui
+msgid "hold:"
+msgstr ""
+
+# iemgui
+msgid "intrrpt:"
+msgstr ""
+
+# iemgui
+msgid "size:"
+msgstr ""
+
+# iemgui
+msgid "width:"
+msgstr ""
+
+# iemgui
+msgid "height:"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo cut"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo duplicate"
+msgstr ""
+
+msgid "Redo typing"
+msgstr ""
+
+msgid "Redo clear"
+msgstr ""
+
+msgid "Redo connect"
+msgstr ""
+
+msgid "Redo disconnect"
+msgstr ""
+
+msgid "Redo cut"
+msgstr ""
+
+msgid "Redo motion"
+msgstr ""
+
+msgid "Redo paste"
+msgstr ""
+
+msgid "Redo duplicate"
+msgstr ""
+
diff --git a/pd/po/vi.po b/pd/po/vi.po
new file mode 100644
index 00000000..9a26c50d
--- /dev/null
+++ b/pd/po/vi.po
@@ -0,0 +1,954 @@
+# Vietnamese translation for Pure Data-0.43.
+# This file is put in the public domain.
+# Clytie Siddall <clytie@riverland.net.au>, 2005.
+msgid ""
+msgstr ""
+"Project-Id-Version: Pure Data 0.43\n"
+"Report-Msgid-Bugs-To: pd-dev@iem.at\n"
+"POT-Creation-Date: 2009-08-27 10:01-0400\n"
+"PO-Revision-Date: 2005-07-28 17:29+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <gnomevi-list@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"X-Generator: LocFactoryEditor 1.2.2\n"
+
+#, fuzzy
+msgid "Undo duplicate"
+msgstr "Ngày"
+
+msgid "Undo paste"
+msgstr ""
+
+msgid "Undo motion"
+msgstr ""
+
+#, fuzzy
+msgid "Undo cut"
+msgstr "U-gan-đa"
+
+msgid "Undo disconnect"
+msgstr ""
+
+msgid "Undo connect"
+msgstr ""
+
+msgid "Undo clear"
+msgstr ""
+
+msgid "Undo typing"
+msgstr ""
+
+msgid "Discard changes to '%s'?"
+msgstr ""
+
+msgid "Do you want to save the changes you made in '%s'?"
+msgstr ""
+
+#: ../src/dialog_array.tcl:115 ../src/dialog_array.tcl:117
+#: ../src/pd_menus.tcl:100 ../src/pd_menus.tcl:101 ../src/pd_menus.tcl:146
+#: ../src/pd_menus.tcl:147
+msgid "Copy"
+msgstr "Chép"
+
+#: ../src/dialog_array.tcl:118 ../src/dialog_array.tcl:120
+#: ../src/pd_menus.tcl:102 ../src/pd_menus.tcl:103 ../src/pd_menus.tcl:148
+#: ../src/pd_menus.tcl:149
+#, fuzzy
+msgid "Paste"
+msgstr "Ngày"
+
+#: ../src/dialog_array.tcl:264 ../src/dialog_array.tcl:266
+msgid "Array Properties"
+msgstr ""
+
+#: ../src/dialog_array.tcl:270 ../src/dialog_array.tcl:272
+#, fuzzy
+msgid "Name:"
+msgstr "Tên"
+
+#: ../src/dialog_array.tcl:276 ../src/dialog_array.tcl:278
+#: ../src/dialog_canvas.tcl:178 ../src/dialog_canvas.tcl:193
+#: ../src/dialog_iemgui.tcl:619 ../src/dialog_iemgui.tcl:621
+msgid "Size:"
+msgstr "Cỡ:"
+
+#: ../src/dialog_array.tcl:280 ../src/dialog_array.tcl:282
+#, fuzzy
+msgid "Save contents"
+msgstr "_Nội dụng"
+
+#: ../src/dialog_array.tcl:284 ../src/dialog_array.tcl:286
+msgid "Draw as:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:287 ../src/dialog_array.tcl:289
+#, fuzzy
+msgid "Points"
+msgstr "Cổng"
+
+#: ../src/dialog_array.tcl:289 ../src/dialog_array.tcl:291
+#, fuzzy
+msgid "Polygon"
+msgstr "Ba-lan"
+
+#: ../src/dialog_array.tcl:291 ../src/dialog_array.tcl:293
+msgid "Bezier curve"
+msgstr ""
+
+#: ../src/dialog_array.tcl:297 ../src/dialog_array.tcl:299
+msgid "Put array into:"
+msgstr ""
+
+#: ../src/dialog_array.tcl:300 ../src/dialog_array.tcl:302
+msgid "New graph"
+msgstr ""
+
+#: ../src/dialog_array.tcl:302 ../src/dialog_array.tcl:304
+#, fuzzy
+msgid "Last graph"
+msgstr "Tin nhẳn trước:"
+
+#: ../src/dialog_array.tcl:306 ../src/dialog_array.tcl:308
+#, fuzzy
+msgid "Delete array"
+msgstr "Xóa bỏ"
+
+#: ../src/dialog_array.tcl:312 ../src/dialog_array.tcl:314
+#, fuzzy
+msgid "Open List View..."
+msgstr "Danh sách đuổi ra..."
+
+#: ../src/dialog_array.tcl:319 ../src/dialog_array.tcl:321
+#: ../src/dialog_audio.tcl:136 ../src/dialog_canvas.tcl:205
+#: ../src/dialog_font.tcl:51 ../src/dialog_gatom.tcl:153
+#: ../src/dialog_gatom.tcl:161 ../src/dialog_iemgui.tcl:742
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_midi.tcl:91
+#: ../src/dialog_midi.tcl:226
+msgid "Cancel"
+msgstr "Thôi"
+
+#: ../src/dialog_array.tcl:321 ../src/dialog_array.tcl:323
+#: ../src/dialog_audio.tcl:138 ../src/dialog_canvas.tcl:207
+#: ../src/dialog_gatom.tcl:156 ../src/dialog_gatom.tcl:164
+#: ../src/dialog_iemgui.tcl:745 ../src/dialog_iemgui.tcl:751
+#: ../src/dialog_midi.tcl:93 ../src/dialog_midi.tcl:228
+msgid "Apply"
+msgstr "Áp dụng"
+
+#: ../src/dialog_array.tcl:323 ../src/dialog_array.tcl:325
+#: ../src/dialog_audio.tcl:140 ../src/dialog_canvas.tcl:209
+#: ../src/dialog_font.tcl:53 ../src/dialog_font.tcl:92
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:101
+#: ../src/dialog_gatom.tcl:159 ../src/dialog_gatom.tcl:167
+#: ../src/dialog_iemgui.tcl:748 ../src/dialog_iemgui.tcl:754
+#: ../src/dialog_midi.tcl:95 ../src/dialog_midi.tcl:230
+msgid "OK"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:130
+msgid "Audio Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:142
+msgid "Save All Settings"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:151
+msgid "Sample rate:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:153
+msgid "Delay (msec):"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:158
+msgid "Use callbacks"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:166 ../src/dialog_midi.tcl:105
+#: ../src/dialog_midi.tcl:241
+msgid "Input device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:169 ../src/dialog_audio.tcl:183
+#: ../src/dialog_audio.tcl:198 ../src/dialog_audio.tcl:213
+#: ../src/dialog_audio.tcl:232 ../src/dialog_audio.tcl:250
+#: ../src/dialog_audio.tcl:265 ../src/dialog_audio.tcl:280
+#, fuzzy
+msgid "Channels:"
+msgstr "Thôi"
+
+#: ../src/dialog_audio.tcl:179 ../src/dialog_midi.tcl:115
+#: ../src/dialog_midi.tcl:251
+msgid "Input device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:194 ../src/dialog_midi.tcl:127
+#: ../src/dialog_midi.tcl:263
+msgid "Input device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:209 ../src/dialog_midi.tcl:139
+#: ../src/dialog_midi.tcl:275
+msgid "Input device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:223 ../src/dialog_midi.tcl:150
+#: ../src/dialog_midi.tcl:286
+msgid "Output device 1:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:226
+msgid "(same as input device) .............. "
+msgstr ""
+
+#: ../src/dialog_audio.tcl:246 ../src/dialog_midi.tcl:160
+#: ../src/dialog_midi.tcl:296
+msgid "Output device 2:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:261 ../src/dialog_midi.tcl:171
+#: ../src/dialog_midi.tcl:307
+msgid "Output device 3:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:276 ../src/dialog_midi.tcl:182
+#: ../src/dialog_midi.tcl:318
+msgid "Output device 4:"
+msgstr ""
+
+#: ../src/dialog_audio.tcl:291 ../src/dialog_midi.tcl:195
+msgid "Use multiple devices"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:142
+msgid "Canvas Properties"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:146
+#, fuzzy
+msgid "Scale"
+msgstr "Lưu"
+
+#: ../src/dialog_canvas.tcl:150
+msgid "X units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:155
+msgid "Y units per pixel:"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:159
+msgid "Appearance on parent patch"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:161
+msgid "Graph-On-Parent"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:165
+msgid "Hide object name and arguments"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:170
+msgid "Range and size"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:174
+msgid "X range, from"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:176 ../src/dialog_canvas.tcl:191
+msgid "to"
+msgstr ""
+
+#: ../src/dialog_canvas.tcl:180 ../src/dialog_canvas.tcl:195
+#, fuzzy
+msgid "Margin:"
+msgstr "Dòng đánh dấu:"
+
+#: ../src/dialog_canvas.tcl:189
+msgid "Y range, from"
+msgstr ""
+
+#: ../src/dialog_find.tcl:63 ../src/dialog_find.tcl:66
+#: ../src/dialog_find.tcl:79 ../src/dialog_find.tcl:80
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:85
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:101
+#: ../src/dialog_find.tcl:105 ../src/dialog_find.tcl:107
+#: ../src/pd_menus.tcl:45
+msgid "Find"
+msgstr "Tìm"
+
+#: ../src/dialog_find.tcl:70 ../src/dialog_find.tcl:73
+#: ../src/dialog_find.tcl:87 ../src/dialog_find.tcl:91
+#: ../src/dialog_find.tcl:93
+#, fuzzy
+msgid "Search in"
+msgstr "Tìm kiếm trong văn bản..."
+
+#: ../src/dialog_find.tcl:72 ../src/dialog_find.tcl:75
+#: ../src/dialog_find.tcl:89 ../src/dialog_find.tcl:93
+#: ../src/dialog_find.tcl:95
+#, fuzzy
+msgid "for:"
+msgstr "Cổng:"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:90
+#: ../src/dialog_find.tcl:104 ../src/dialog_find.tcl:108
+#: ../src/dialog_find.tcl:110 ../src/pd_menus.tcl:86 ../src/pd_menus.tcl:87
+#: ../src/pd_menus.tcl:132 ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:259
+#: ../src/pd_menus.tcl:272 ../src/pd_menus.tcl:295 ../src/pd_menus.tcl:308
+#: ../src/pd_menus.tcl:332 ../src/pd_menus.tcl:345 ../src/pd_menus.tcl:354
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:392 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:431 ../src/pd_menus.tcl:458
+msgid "Close"
+msgstr "Đóng"
+
+#: ../src/dialog_find.tcl:83 ../src/dialog_find.tcl:97
+#: ../src/dialog_find.tcl:101 ../src/dialog_find.tcl:103
+msgid "Match whole word only"
+msgstr ""
+
+#: ../src/dialog_find.tcl:92 ../src/dialog_font.tcl:49
+#: ../src/dialog_font.tcl:50 ../src/pd-gui.tcl:280 ../src/pd-gui.tcl:283
+#: ../src/pd-gui.tcl:286 ../src/pd-gui.tcl:288 ../src/pd-gui.tcl:291
+#: ../src/pd_menus.tcl:212 ../src/pd_menus.tcl:258 ../src/pd_menus.tcl:285
+#: ../src/pdwindow.tcl:33
+#, fuzzy
+msgid "Pd window"
+msgstr "Cửa sô Gởi"
+
+#: ../src/dialog_font.tcl:45
+msgid "Font Properties"
+msgstr ""
+
+#: ../src/dialog_font.tcl:46 ../src/dialog_font.tcl:54
+#: ../src/dialog_font.tcl:55
+#, fuzzy, tcl-format
+msgid "%s Font"
+msgstr "Phông chữ:"
+
+#: ../src/dialog_font.tcl:61 ../src/dialog_font.tcl:96
+#: ../src/dialog_font.tcl:104 ../src/dialog_font.tcl:105
+#, fuzzy
+msgid "Font Size"
+msgstr "Cỡ:"
+
+#: ../src/dialog_font.tcl:89 ../src/dialog_font.tcl:108
+#: ../src/dialog_font.tcl:116 ../src/dialog_font.tcl:117
+#, fuzzy
+msgid "Stretch"
+msgstr "Bắt đầu:"
+
+#: ../src/dialog_font.tcl:96 ../src/dialog_font.tcl:115
+#: ../src/dialog_font.tcl:123 ../src/dialog_font.tcl:124
+msgid "X and Y"
+msgstr ""
+
+#: ../src/dialog_font.tcl:98 ../src/dialog_font.tcl:117
+#: ../src/dialog_font.tcl:125 ../src/dialog_font.tcl:126
+msgid "X only"
+msgstr ""
+
+#: ../src/dialog_font.tcl:100 ../src/dialog_font.tcl:119
+#: ../src/dialog_font.tcl:127 ../src/dialog_font.tcl:128
+msgid "Y only"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:93
+msgid "Atom Box Properties"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:99
+msgid "Width:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:103
+#, fuzzy
+msgid "Limits"
+msgstr "Giới hạn người dùng"
+
+#: ../src/dialog_gatom.tcl:107
+msgid "Lower:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:112 ../src/dialog_gatom.tcl:113
+#, fuzzy
+msgid "Upper:"
+msgstr "Người dùng:"
+
+#: ../src/dialog_gatom.tcl:116 ../src/dialog_gatom.tcl:121
+#: ../src/dialog_iemgui.tcl:600 ../src/dialog_iemgui.tcl:652
+#: ../src/dialog_iemgui.tcl:657
+msgid "Label"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:124 ../src/dialog_gatom.tcl:129
+#, fuzzy
+msgid "Left "
+msgstr "Bên trái"
+
+#: ../src/dialog_gatom.tcl:126 ../src/dialog_gatom.tcl:131
+msgid "Right"
+msgstr "Bên phải"
+
+#: ../src/dialog_gatom.tcl:128 ../src/dialog_gatom.tcl:133
+msgid "Top"
+msgstr "Đầu"
+
+#: ../src/dialog_gatom.tcl:130 ../src/dialog_gatom.tcl:135
+msgid "Bottom"
+msgstr "Đáy"
+
+#: ../src/dialog_gatom.tcl:137 ../src/dialog_gatom.tcl:145
+#: ../src/dialog_iemgui.tcl:574
+#, fuzzy
+msgid "Messages"
+msgstr "Tin nhẳn"
+
+#: ../src/dialog_gatom.tcl:141 ../src/dialog_gatom.tcl:149
+#: ../src/dialog_iemgui.tcl:578
+msgid "Send symbol:"
+msgstr ""
+
+#: ../src/dialog_gatom.tcl:147 ../src/dialog_gatom.tcl:155
+#: ../src/dialog_iemgui.tcl:585
+#, fuzzy
+msgid "Receive symbol:"
+msgstr "Cửa sổ Nhận"
+
+#: ../src/dialog_iemgui.tcl:197
+#, fuzzy
+msgid "Background color"
+msgstr "Nền:"
+
+#: ../src/dialog_iemgui.tcl:204
+#, fuzzy
+msgid "Foreground color"
+msgstr "Tiền cảnh:"
+
+#: ../src/dialog_iemgui.tcl:211
+#, fuzzy
+msgid "Label color"
+msgstr "Chọn màu"
+
+#: ../src/dialog_iemgui.tcl:272
+#, fuzzy
+msgid "Init"
+msgstr "Mời"
+
+#: ../src/dialog_iemgui.tcl:275 ../src/dialog_iemgui.tcl:546
+msgid "No init"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:287 ../src/dialog_iemgui.tcl:558
+msgid "Jump on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:290 ../src/dialog_iemgui.tcl:561
+msgid "Steady on click"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:498
+#, tcl-format
+msgid "%s Properties"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:550 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:84
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:130 ../src/pd_menus.tcl:260
+#: ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:288 ../src/pd_menus.tcl:301
+#: ../src/pd_menus.tcl:325 ../src/pd_menus.tcl:338 ../src/pd_menus.tcl:355
+#: ../src/pd_menus.tcl:382 ../src/pd_menus.tcl:383 ../src/pd_menus.tcl:410
+#: ../src/pd_menus.tcl:422 ../src/pd_menus.tcl:449
+msgid "Save"
+msgstr "Lưu"
+
+#: ../src/dialog_iemgui.tcl:608
+msgid "X offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:611 ../src/dialog_iemgui.tcl:612
+msgid "Y offset"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:642 ../src/dialog_iemgui.tcl:645
+msgid "Colors"
+msgstr "Màu"
+
+#: ../src/dialog_iemgui.tcl:648 ../src/dialog_iemgui.tcl:651
+#, fuzzy
+msgid "Background"
+msgstr "Nền:"
+
+#: ../src/dialog_iemgui.tcl:650 ../src/dialog_iemgui.tcl:654
+#, fuzzy
+msgid "Front"
+msgstr "Phông chữ:"
+
+#: ../src/dialog_iemgui.tcl:662 ../src/dialog_iemgui.tcl:668
+msgid "Compose color"
+msgstr ""
+
+#: ../src/dialog_iemgui.tcl:682 ../src/dialog_iemgui.tcl:688
+#, fuzzy
+msgid "Test label"
+msgstr "Kiểm tra tất cả"
+
+#: ../src/dialog_midi.tcl:85
+msgid "MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:220
+msgid "ALSA MIDI Settings"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:331
+msgid "Use multiple ALSA devices"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:337
+msgid "In Ports:"
+msgstr ""
+
+#: ../src/dialog_midi.tcl:340
+msgid "Out Ports:"
+msgstr ""
+
+#: ../src/g_editor.c:1663
+msgid "Discard changes to this window??"
+msgstr ""
+
+#: ../src/g_editor.c:1668
+msgid "really quit?"
+msgstr ""
+
+#: ../src/g_editor.c:1699
+#, fuzzy
+msgid "Close this window??"
+msgstr "Đóng thanh/cửa sổ này"
+
+#: ../src/pd-gui.tcl:185 ../src/pd-gui.tcl:195 ../src/pd-gui.tcl:203
+#: ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:215 ../src/pd-gui.tcl:226
+msgid "Associated Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:186 ../src/pd-gui.tcl:196 ../src/pd-gui.tcl:204
+#: ../src/pd-gui.tcl:207 ../src/pd-gui.tcl:216 ../src/pd-gui.tcl:227
+#, fuzzy
+msgid "Pd Files"
+msgstr "Tập tin"
+
+#: ../src/pd-gui.tcl:187 ../src/pd-gui.tcl:205 ../src/pd-gui.tcl:208
+#: ../src/pd-gui.tcl:228
+msgid "Max Patch Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:188 ../src/pd-gui.tcl:206 ../src/pd-gui.tcl:209
+#: ../src/pd-gui.tcl:229
+msgid "Max Text Files"
+msgstr ""
+
+#: ../src/pd-gui.tcl:197 ../src/pd-gui.tcl:217
+msgid "Max Patch Files (.pat)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:198 ../src/pd-gui.tcl:218
+msgid "Max Text Files (.mxt)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:270 ../src/pd-gui.tcl:290
+#, tcl-format
+msgid "WARNING: Font family '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:278 ../src/pd-gui.tcl:298
+#, tcl-format
+msgid "WARNING: Font weight '%s' not found, using default (%s)"
+msgstr ""
+
+#: ../src/pd-gui.tcl:303 ../src/pd-gui.tcl:323
+#, tcl-format
+msgid "ERROR: %s failed to find font size (%s) that fits into %sx%s!"
+msgstr ""
+
+#: ../src/pd-gui.tcl:478 ../src/pd-gui.tcl:483 ../src/pd-gui.tcl:501
+msgid "ERROR: 'pd' never showed up, 'pd-gui' quitting!"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:19
+msgid "Untitled"
+msgstr ""
+
+#: ../src/pd_menucommands.tcl:78 ../src/pd_menucommands.tcl:79
+#: ../src/pd_menucommands.tcl:90
+#, fuzzy
+msgid "Send Message..."
+msgstr "Tin nhẳn"
+
+#: ../src/pd_menucommands.tcl:82 ../src/pd_menucommands.tcl:83
+#: ../src/pd_menucommands.tcl:94 ../src/pd_menus.tcl:87 ../src/pd_menus.tcl:88
+#: ../src/pd_menus.tcl:133 ../src/pd_menus.tcl:134 ../src/pd_menus.tcl:147
+#: ../src/pd_menus.tcl:192 ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:265
+#: ../src/pd_menus.tcl:278 ../src/pd_menus.tcl:292 ../src/pd_menus.tcl:305
+#: ../src/pd_menus.tcl:329 ../src/pd_menus.tcl:342 ../src/pd_menus.tcl:360
+#: ../src/pd_menus.tcl:387 ../src/pd_menus.tcl:414 ../src/pd_menus.tcl:426
+#: ../src/pd_menus.tcl:453 ../startup/object_db.tcl:123
+msgid "Message"
+msgstr "Tin nhẳn"
+
+#: ../src/pd_menucommands.tcl:108 ../src/pd_menucommands.tcl:111
+#: ../src/pd_menus.tcl:112 ../src/pd_menus.tcl:113 ../src/pd_menus.tcl:117
+#: ../src/pd_menus.tcl:118 ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:159
+#: ../src/pd_menus.tcl:163 ../src/pd_menus.tcl:164
+#, fuzzy
+msgid "Font"
+msgstr "Phông chữ:"
+
+#: ../src/pd_menucommands.tcl:123 ../src/pd_menucommands.tcl:126
+#: ../src/pd_menus.tcl:138 ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:184
+#, fuzzy
+msgid "Preferences"
+msgstr "Sở thích..."
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Edit"
+msgstr "_Hiệu chỉnh"
+
+#: ../src/pd_menus.tcl:45
+msgid "File"
+msgstr "Tập tin"
+
+#: ../src/pd_menus.tcl:45 ../src/pdtk_canvas.tcl:48 ../src/pdtk_canvas.tcl:110
+#: ../src/pdtk_canvas.tcl:113
+msgid "Help"
+msgstr "Trợ giúp"
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Media"
+msgstr "Maxêđôni"
+
+#: ../src/pd_menus.tcl:45
+msgid "Put"
+msgstr ""
+
+#: ../src/pd_menus.tcl:45
+#, fuzzy
+msgid "Window"
+msgstr "_Cửa sổ"
+
+#: ../src/pd_menus.tcl:81 ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:127
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:255 ../src/pd_menus.tcl:267
+#: ../src/pd_menus.tcl:285 ../src/pd_menus.tcl:298 ../src/pd_menus.tcl:322
+#: ../src/pd_menus.tcl:335 ../src/pd_menus.tcl:349 ../src/pd_menus.tcl:376
+#: ../src/pd_menus.tcl:380 ../src/pd_menus.tcl:407 ../src/pd_menus.tcl:419
+#: ../src/pd_menus.tcl:446
+msgid "New"
+msgstr "Mới"
+
+#: ../src/pd_menus.tcl:82 ../src/pd_menus.tcl:83 ../src/pd_menus.tcl:128
+#: ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:268
+#: ../src/pd_menus.tcl:286 ../src/pd_menus.tcl:299 ../src/pd_menus.tcl:323
+#: ../src/pd_menus.tcl:336 ../src/pd_menus.tcl:350 ../src/pd_menus.tcl:377
+#: ../src/pd_menus.tcl:381 ../src/pd_menus.tcl:408 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:447 ../src/pdtk_canvas.tcl:46
+#: ../src/pdtk_canvas.tcl:108 ../src/pdtk_canvas.tcl:111
+#: ../src/pdtk_canvas.tcl:128 ../src/pdtk_canvas.tcl:130
+#: ../src/pdtk_canvas.tcl:131 ../src/pdtk_canvas.tcl:133
+msgid "Open"
+msgstr "Mở"
+
+#: ../src/pd_menus.tcl:84 ../src/pd_menus.tcl:85 ../src/pd_menus.tcl:130
+#: ../src/pd_menus.tcl:131 ../src/pd_menus.tcl:261 ../src/pd_menus.tcl:274
+#: ../src/pd_menus.tcl:289 ../src/pd_menus.tcl:302 ../src/pd_menus.tcl:326
+#: ../src/pd_menus.tcl:339 ../src/pd_menus.tcl:356 ../src/pd_menus.tcl:383
+#: ../src/pd_menus.tcl:384 ../src/pd_menus.tcl:411 ../src/pd_menus.tcl:423
+#: ../src/pd_menus.tcl:450
+#, fuzzy
+msgid "Save As..."
+msgstr "Lưu là"
+
+#: ../src/pd_menus.tcl:88 ../src/pd_menus.tcl:89 ../src/pd_menus.tcl:134
+#: ../src/pd_menus.tcl:135 ../src/pd_menus.tcl:267 ../src/pd_menus.tcl:280
+#: ../src/pd_menus.tcl:293 ../src/pd_menus.tcl:306 ../src/pd_menus.tcl:330
+#: ../src/pd_menus.tcl:343 ../src/pd_menus.tcl:362 ../src/pd_menus.tcl:388
+#: ../src/pd_menus.tcl:389 ../src/pd_menus.tcl:415 ../src/pd_menus.tcl:427
+#: ../src/pd_menus.tcl:454
+#, fuzzy
+msgid "Print..."
+msgstr "_Hiệu chỉnh..."
+
+#: ../src/pd_menus.tcl:93 ../src/pd_menus.tcl:94 ../src/pd_menus.tcl:139
+#: ../src/pd_menus.tcl:140
+#, fuzzy
+msgid "Undo"
+msgstr "U-gan-đa"
+
+#: ../src/pd_menus.tcl:95 ../src/pd_menus.tcl:96 ../src/pd_menus.tcl:141
+#: ../src/pd_menus.tcl:142
+#, fuzzy
+msgid "Redo"
+msgstr "Màu đỏ:"
+
+#: ../src/pd_menus.tcl:98 ../src/pd_menus.tcl:99 ../src/pd_menus.tcl:144
+#: ../src/pd_menus.tcl:145
+msgid "Cut"
+msgstr ""
+
+#: ../src/pd_menus.tcl:104 ../src/pd_menus.tcl:105 ../src/pd_menus.tcl:150
+#: ../src/pd_menus.tcl:151
+#, fuzzy
+msgid "Duplicate"
+msgstr "Ngày"
+
+#: ../src/pd_menus.tcl:106 ../src/pd_menus.tcl:107 ../src/pd_menus.tcl:152
+#: ../src/pd_menus.tcl:153
+#, fuzzy
+msgid "Select All"
+msgstr "Chọn màu"
+
+#: ../src/pd_menus.tcl:110 ../src/pd_menus.tcl:111 ../src/pd_menus.tcl:115
+#: ../src/pd_menus.tcl:116 ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:157
+#: ../src/pd_menus.tcl:161 ../src/pd_menus.tcl:162
+#, fuzzy
+msgid "Text Editor"
+msgstr "Màu chữ"
+
+#: ../src/pd_menus.tcl:120 ../src/pd_menus.tcl:121 ../src/pd_menus.tcl:166
+#: ../src/pd_menus.tcl:167
+msgid "Tidy Up"
+msgstr ""
+
+#: ../src/pd_menus.tcl:122 ../src/pd_menus.tcl:123 ../src/pd_menus.tcl:168
+#: ../src/pd_menus.tcl:169
+msgid "Toggle Console"
+msgstr ""
+
+#: ../src/pd_menus.tcl:124 ../src/pd_menus.tcl:125 ../src/pd_menus.tcl:170
+#: ../src/pd_menus.tcl:171
+#, fuzzy
+msgid "Clear Console"
+msgstr "Xóa danh sách"
+
+#: ../src/pd_menus.tcl:128 ../src/pd_menus.tcl:129 ../src/pd_menus.tcl:174
+#: ../src/pd_menus.tcl:175
+#, fuzzy
+msgid "Edit Mode"
+msgstr "Chế độ"
+
+#: ../src/pd_menus.tcl:145 ../src/pd_menus.tcl:190 ../src/pd_menus.tcl:191
+msgid "Object"
+msgstr ""
+
+#: ../src/pd_menus.tcl:149 ../src/pd_menus.tcl:194 ../src/pd_menus.tcl:195
+#, fuzzy
+msgid "Number"
+msgstr "$ Số"
+
+#: ../src/pd_menus.tcl:151 ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:197
+msgid "Symbol"
+msgstr ""
+
+#: ../src/pd_menus.tcl:153 ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:199
+#, fuzzy
+msgid "Comment"
+msgstr "Lệnh"
+
+#: ../src/pd_menus.tcl:156 ../src/pd_menus.tcl:201 ../src/pd_menus.tcl:202
+#, fuzzy
+msgid "Bang"
+msgstr "Đuổi"
+
+#: ../src/pd_menus.tcl:158 ../src/pd_menus.tcl:203 ../src/pd_menus.tcl:204
+#, fuzzy
+msgid "Toggle"
+msgstr "Tô-gô"
+
+#: ../src/pd_menus.tcl:160 ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:206
+#, fuzzy
+msgid "Number2"
+msgstr "$ Số"
+
+#: ../src/pd_menus.tcl:162 ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:208
+msgid "Vslider"
+msgstr ""
+
+#: ../src/pd_menus.tcl:164 ../src/pd_menus.tcl:209 ../src/pd_menus.tcl:210
+#, fuzzy
+msgid "Hslider"
+msgstr "Bị ẩn"
+
+#: ../src/pd_menus.tcl:166 ../src/pd_menus.tcl:211 ../src/pd_menus.tcl:212
+#, fuzzy
+msgid "Vradio"
+msgstr "Phiên bản"
+
+#: ../src/pd_menus.tcl:168 ../src/pd_menus.tcl:213 ../src/pd_menus.tcl:214
+msgid "Hradio"
+msgstr ""
+
+#: ../src/pd_menus.tcl:170 ../src/pd_menus.tcl:215 ../src/pd_menus.tcl:216
+msgid "VU Meter"
+msgstr ""
+
+#: ../src/pd_menus.tcl:172 ../src/pd_menus.tcl:217 ../src/pd_menus.tcl:218
+#, fuzzy
+msgid "Canvas"
+msgstr "Ca-na-đa"
+
+#: ../src/pd_menus.tcl:175 ../src/pd_menus.tcl:220 ../src/pd_menus.tcl:221
+msgid "Graph"
+msgstr "Đồ thị"
+
+#: ../src/pd_menus.tcl:176 ../src/pd_menus.tcl:221 ../src/pd_menus.tcl:222
+#, fuzzy
+msgid "Array"
+msgstr "Ăn-đoa-râ"
+
+#: ../src/pd_menus.tcl:181 ../src/pd_menus.tcl:226 ../src/pd_menus.tcl:227
+#, fuzzy
+msgid "Find..."
+msgstr "Gởi tâp tin..."
+
+#: ../src/pd_menus.tcl:183 ../src/pd_menus.tcl:228 ../src/pd_menus.tcl:229
+msgid "Find Again"
+msgstr ""
+
+#: ../src/pd_menus.tcl:185 ../src/pd_menus.tcl:230 ../src/pd_menus.tcl:231
+msgid "Find Last Error"
+msgstr ""
+
+#: ../src/pd_menus.tcl:191 ../src/pd_menus.tcl:236 ../src/pd_menus.tcl:237
+msgid "DSP On"
+msgstr ""
+
+#: ../src/pd_menus.tcl:193 ../src/pd_menus.tcl:238 ../src/pd_menus.tcl:239
+#, fuzzy
+msgid "DSP Off"
+msgstr "Tất"
+
+#: ../src/pd_menus.tcl:196 ../src/pd_menus.tcl:242 ../src/pd_menus.tcl:269
+msgid "Test Audio and MIDI..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:198 ../src/pd_menus.tcl:244 ../src/pd_menus.tcl:271
+#, fuzzy
+msgid "Load Meter"
+msgstr "Bộ đo trễ:"
+
+#: ../src/pd_menus.tcl:205 ../src/pd_menus.tcl:251 ../src/pd_menus.tcl:278
+msgid "Minimize"
+msgstr ""
+
+#: ../src/pd_menus.tcl:207 ../src/pd_menus.tcl:253 ../src/pd_menus.tcl:280
+#, fuzzy
+msgid "Zoom"
+msgstr "Đáy"
+
+#: ../src/pd_menus.tcl:210 ../src/pd_menus.tcl:256 ../src/pd_menus.tcl:283
+#, fuzzy
+msgid "Parent Window"
+msgstr "Cửa sô Gởi"
+
+#: ../src/pd_menus.tcl:216 ../src/pd_menus.tcl:262 ../src/pd_menus.tcl:289
+msgid "Bring All to Front"
+msgstr ""
+
+#: ../src/pd_menus.tcl:224 ../src/pd_menus.tcl:241 ../src/pd_menus.tcl:253
+#: ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:297 ../src/pd_menus.tcl:335
+#: ../src/pd_menus.tcl:362
+#, fuzzy
+msgid "About Pd"
+msgstr "_Giới thiệu"
+
+#: ../src/pd_menus.tcl:227 ../src/pd_menus.tcl:273 ../src/pd_menus.tcl:300
+msgid "HTML Manual..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:229 ../src/pd_menus.tcl:275 ../src/pd_menus.tcl:302
+#, fuzzy
+msgid "Browser..."
+msgstr "Duyệt..."
+
+#: ../src/pd_menus.tcl:248 ../src/pd_menus.tcl:260 ../src/pd_menus.tcl:342
+#: ../src/pd_menus.tcl:369
+msgid "Preferences..."
+msgstr "Sở thích..."
+
+#: ../src/pd_menus.tcl:257 ../src/pd_menus.tcl:270 ../src/pd_menus.tcl:352
+#: ../src/pd_menus.tcl:379
+msgid "Open Recent"
+msgstr ""
+
+#: ../src/pd_menus.tcl:263
+msgid "Audio Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:265
+msgid "MIDI Settings..."
+msgstr ""
+
+#: ../src/pd_menus.tcl:296 ../src/pd_menus.tcl:309 ../src/pd_menus.tcl:333
+#: ../src/pd_menus.tcl:346 ../src/pd_menus.tcl:393 ../src/pd_menus.tcl:420
+#: ../src/pd_menus.tcl:432 ../src/pd_menus.tcl:459
+msgid "Quit"
+msgstr "Thoát"
+
+#: ../src/pd_menus.tcl:304 ../src/pd_menus.tcl:331
+#, fuzzy
+msgid "Clear Menu"
+msgstr "Xóa danh sách"
+
+#: ../src/pdtk_canvas.tcl:44 ../src/pdtk_canvas.tcl:106
+#: ../src/pdtk_canvas.tcl:109 ../src/pdtk_canvas.tcl:123
+#: ../src/pdtk_canvas.tcl:125 ../src/pdtk_canvas.tcl:126
+#: ../src/pdtk_canvas.tcl:128
+msgid "Properties"
+msgstr ""
+
+#: ../src/pdwindow.tcl:43
+#, fuzzy
+msgid "DSP"
+msgstr "Tất"
+
+#: ../startup/object_db.tcl:113
+msgid "Signal"
+msgstr ""
+
+#: ../startup/object_db.tcl:114
+msgid "Generators"
+msgstr ""
+
+#: ../startup/object_db.tcl:115
+#, fuzzy
+msgid "Filters"
+msgstr "Tập tin"
+
+#: ../startup/object_db.tcl:116 ../startup/object_db.tcl:124
+msgid "Math"
+msgstr ""
+
+#: ../startup/object_db.tcl:117 ../startup/object_db.tcl:125
+msgid "I/O"
+msgstr ""
+
+#: ../startup/object_db.tcl:118 ../startup/object_db.tcl:126
+msgid "Sampling"
+msgstr ""
+
+#: ../startup/object_db.tcl:119 ../startup/object_db.tcl:128
+msgid "Routing"
+msgstr ""
+
+#: ../startup/object_db.tcl:120 ../startup/object_db.tcl:129
+msgid "Others"
+msgstr ""
+
+#: ../startup/object_db.tcl:127
+msgid "GUI"
+msgstr ""
diff --git a/pd/portaudio/LICENSE.txt b/pd/portaudio/LICENSE.txt
new file mode 100644
index 00000000..e0ac4e8a
--- /dev/null
+++ b/pd/portaudio/LICENSE.txt
@@ -0,0 +1,81 @@
+Portable header file to contain:
+>>>>>
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * PortAudio API Header File
+ * Latest version available at: http://www.portaudio.com
+ *
+ * Copyright (c) 1999-2006 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+<<<<<
+
+
+Implementation files to contain:
+>>>>>
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Latest version at: http://www.portaudio.com
+ * <platform> Implementation
+ * Copyright (c) 1999-2000 <author(s)>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+<<<<< \ No newline at end of file
diff --git a/pd/portaudio/Makefile.am b/pd/portaudio/Makefile.am
new file mode 100644
index 00000000..961b1b11
--- /dev/null
+++ b/pd/portaudio/Makefile.am
@@ -0,0 +1,99 @@
+# this is built as a "libtool convenience library"
+# http://sources.redhat.com/automake/automake.html#Libtool-Convenience-Libraries
+AUTOMAKE_OPTIONS = foreign
+AM_CFLAGS =
+INCLUDES = -Iinclude -Isrc/common
+
+noinst_LTLIBRARIES = libportaudio.la
+
+libportaudio_la_SOURCES = src/common/pa_allocation.c \
+ src/common/pa_converters.c \
+ src/common/pa_cpuload.c \
+ src/common/pa_dither.c \
+ src/common/pa_front.c \
+ src/common/pa_process.c \
+ src/common/pa_skeleton.c \
+ src/common/pa_stream.c \
+ src/common/pa_trace.c \
+ src/common/pa_debugprint.c \
+ src/common/pa_ringbuffer.c
+
+
+if ALSA
+AM_CFLAGS += -DPA_USE_ALSA
+libportaudio_la_SOURCES += src/hostapi/alsa/pa_linux_alsa.c
+endif
+
+if ASIO
+libportaudio_la_CPPFLAGS = -DWINVER=0x0501 #kludge to work around Portaudio/ASIO bug
+libportaudio_la_SOURCES += src/hostapi/asio/pa_asio.cpp \
+ src/hostapi/asio/iasiothiscallresolver.cpp
+INCLUDES += -I../asio/ASIOSDK2/host -I../asio/ASIOSDK2/host/pc -I../asio/ASIOSDK2/common
+else
+AM_CFLAGS += -DPA_NO_ASIO
+endif
+
+if COREAUDIO
+AM_CFLAGS += -DPA_USE_COREAUDIO
+INCLUDES += -Isrc/os/mac_osx
+libportaudio_la_SOURCES += src/os/unix/pa_unix_util.c \
+ src/os/mac_osx/pa_mac_hostapis.c \
+ src/hostapi/coreaudio/pa_mac_core.c \
+ src/hostapi/coreaudio/pa_mac_core_blocking.c \
+ src/hostapi/coreaudio/pa_mac_core_utilities.c
+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
+libportaudio_la_SOURCES += src/hostapi/oss/pa_unix_oss.c
+endif
+endif
+
+if LINUX
+INCLUDES += -Isrc/os/unix
+libportaudio_la_SOURCES += src/os/unix/pa_unix_hostapis.c \
+ src/os/unix/pa_unix_util.c
+endif
+
+if WINDOWS
+AM_CFLAGS += -DPA_NO_DS -DPA19 -DPA_LITTLE_ENDIAN
+INCLUDES += -Isrc/os/win
+libportaudio_la_SOURCES += src/os/win/pa_win_hostapis.c \
+ src/os/win/pa_win_util.c \
+ src/os/win/pa_win_waveformat.c \
+ src/hostapi/wmme/pa_win_wmme.c
+endif
+
+# include the headers in the dist so you can build
+nobase_noinst_HEADERS = \
+ include/pa_asio.h \
+ include/pa_jack.h \
+ include/pa_linux_alsa.h \
+ include/pa_mac_core.h \
+ include/pa_win_waveformat.h \
+ include/pa_win_wmme.h \
+ include/portaudio.h \
+ src/common/pa_allocation.h \
+ src/common/pa_converters.h \
+ src/common/pa_cpuload.h \
+ src/common/pa_debugprint.h \
+ src/common/pa_dither.h \
+ src/common/pa_endianness.h \
+ src/common/pa_hostapi.h \
+ src/common/pa_process.h \
+ src/common/pa_ringbuffer.h \
+ src/common/pa_memorybarrier.h \
+ src/common/pa_stream.h \
+ src/common/pa_trace.h \
+ src/common/pa_types.h \
+ src/common/pa_util.h \
+ src/hostapi/asio/iasiothiscallresolver.h \
+ src/hostapi/coreaudio/pa_mac_core_blocking.h \
+ src/hostapi/coreaudio/pa_mac_core_internal.h \
+ src/hostapi/coreaudio/pa_mac_core_utilities.h \
+ src/os/unix/pa_unix_util.h \
+ src/os/win/pa_win_wdmks_utils.h \
+ src/os/win/pa_x86_plain_converters.h
+
diff --git a/pd/portaudio/include/pa_asio.h b/pd/portaudio/include/pa_asio.h
index 21f50dda..64d1bd4e 100644
--- a/pd/portaudio/include/pa_asio.h
+++ b/pd/portaudio/include/pa_asio.h
@@ -1,7 +1,7 @@
#ifndef PA_ASIO_H
#define PA_ASIO_H
/*
- * $Id: pa_asio.h 1083 2006-08-23 07:30:49Z rossb $
+ * $Id: pa_asio.h 1400 2009-01-21 10:20:42Z rossb $
* PortAudio Portable Real-Time Audio Library
* ASIO specific extensions
*
@@ -40,6 +40,7 @@
/** @file
+ @ingroup public_header
@brief ASIO-specific PortAudio API extension header file.
*/
@@ -99,6 +100,19 @@ PaError PaAsio_GetOutputChannelName( PaDeviceIndex device, int channelIndex,
const char** channelName );
+/** Set the sample rate of an open paASIO stream.
+
+ @param stream The stream to operate on.
+ @param sampleRate The new sample rate.
+
+ Note that this function may fail if the stream is alredy running and the
+ ASIO driver does not support switching the sample rate of a running stream.
+
+ Returns paIncompatibleStreamHostApi if stream is not a paASIO stream.
+*/
+PaError PaAsio_SetStreamSampleRate( PaStream* stream, double sampleRate );
+
+
#define paAsioUseChannelSelectors (0x01)
typedef struct PaAsioStreamInfo{
diff --git a/pd/portaudio/include/pa_jack.h b/pd/portaudio/include/pa_jack.h
index c4eca1d6..ba2aeb9c 100644
--- a/pd/portaudio/include/pa_jack.h
+++ b/pd/portaudio/include/pa_jack.h
@@ -40,7 +40,8 @@
*/
/** @file
- * JACK-specific PortAudio API extension header file.
+ * @ingroup public_header
+ * @brief JACK-specific PortAudio API extension header file.
*/
#include "portaudio.h"
diff --git a/pd/portaudio/include/pa_linux_alsa.h b/pd/portaudio/include/pa_linux_alsa.h
index 7db633ae..de89ae9b 100644
--- a/pd/portaudio/include/pa_linux_alsa.h
+++ b/pd/portaudio/include/pa_linux_alsa.h
@@ -2,7 +2,7 @@
#define PA_LINUX_ALSA_H
/*
- * $Id: pa_linux_alsa.h 1236 2007-06-24 20:39:26Z aknudsen $
+ * $Id: pa_linux_alsa.h 1414 2009-05-24 17:02:10Z aknudsen $
* PortAudio Portable Real-Time Audio Library
* ALSA-specific extensions
*
@@ -40,7 +40,8 @@
*/
/** @file
- * ALSA-specific PortAudio API extension header file.
+ * @ingroup public_header
+ * @brief ALSA-specific PortAudio API extension header file.
*/
#include "portaudio.h"
@@ -86,6 +87,11 @@ PaError PaAlsa_GetStreamOutputCard( PaStream *s, int *card );
*/
PaError PaAlsa_SetNumPeriods( int numPeriods );
+/** Set the maximum number of times to retry opening busy device (sleeping for a
+ * short interval inbetween).
+ */
+PaError PaAlsa_SetRetriesBusy( int retries );
+
#ifdef __cplusplus
}
#endif
diff --git a/pd/portaudio/include/pa_mac_core.h b/pd/portaudio/include/pa_mac_core.h
index 783e3bc9..b0921b3c 100644
--- a/pd/portaudio/include/pa_mac_core.h
+++ b/pd/portaudio/include/pa_mac_core.h
@@ -38,6 +38,11 @@
* license above.
*/
+/** @file
+ * @ingroup public_header
+ * @brief CoreAudio-specific PortAudio API extension header file.
+ */
+
#include <AudioUnit/AudioUnit.h>
//#include <AudioToolbox/AudioToolbox.h>
diff --git a/pd/portaudio/include/pa_win_waveformat.h b/pd/portaudio/include/pa_win_waveformat.h
new file mode 100644
index 00000000..b9cca698
--- /dev/null
+++ b/pd/portaudio/include/pa_win_waveformat.h
@@ -0,0 +1,199 @@
+#ifndef PA_WIN_WAVEFORMAT_H
+#define PA_WIN_WAVEFORMAT_H
+
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Windows WAVEFORMAT* data structure utilities
+ * portaudio.h should be included before this file.
+ *
+ * Copyright (c) 2007 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/** @file
+ @ingroup public_header
+ @brief Windows specific PortAudio API extension and utilities header file.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ The following #defines for speaker channel masks are the same
+ as those in ksmedia.h, except with PAWIN_ prepended, KSAUDIO_ removed
+ in some cases, and casts to PaWinWaveFormatChannelMask added.
+*/
+
+typedef unsigned long PaWinWaveFormatChannelMask;
+
+/* Speaker Positions: */
+#define PAWIN_SPEAKER_FRONT_LEFT ((PaWinWaveFormatChannelMask)0x1)
+#define PAWIN_SPEAKER_FRONT_RIGHT ((PaWinWaveFormatChannelMask)0x2)
+#define PAWIN_SPEAKER_FRONT_CENTER ((PaWinWaveFormatChannelMask)0x4)
+#define PAWIN_SPEAKER_LOW_FREQUENCY ((PaWinWaveFormatChannelMask)0x8)
+#define PAWIN_SPEAKER_BACK_LEFT ((PaWinWaveFormatChannelMask)0x10)
+#define PAWIN_SPEAKER_BACK_RIGHT ((PaWinWaveFormatChannelMask)0x20)
+#define PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER ((PaWinWaveFormatChannelMask)0x40)
+#define PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER ((PaWinWaveFormatChannelMask)0x80)
+#define PAWIN_SPEAKER_BACK_CENTER ((PaWinWaveFormatChannelMask)0x100)
+#define PAWIN_SPEAKER_SIDE_LEFT ((PaWinWaveFormatChannelMask)0x200)
+#define PAWIN_SPEAKER_SIDE_RIGHT ((PaWinWaveFormatChannelMask)0x400)
+#define PAWIN_SPEAKER_TOP_CENTER ((PaWinWaveFormatChannelMask)0x800)
+#define PAWIN_SPEAKER_TOP_FRONT_LEFT ((PaWinWaveFormatChannelMask)0x1000)
+#define PAWIN_SPEAKER_TOP_FRONT_CENTER ((PaWinWaveFormatChannelMask)0x2000)
+#define PAWIN_SPEAKER_TOP_FRONT_RIGHT ((PaWinWaveFormatChannelMask)0x4000)
+#define PAWIN_SPEAKER_TOP_BACK_LEFT ((PaWinWaveFormatChannelMask)0x8000)
+#define PAWIN_SPEAKER_TOP_BACK_CENTER ((PaWinWaveFormatChannelMask)0x10000)
+#define PAWIN_SPEAKER_TOP_BACK_RIGHT ((PaWinWaveFormatChannelMask)0x20000)
+
+/* Bit mask locations reserved for future use */
+#define PAWIN_SPEAKER_RESERVED ((PaWinWaveFormatChannelMask)0x7FFC0000)
+
+/* Used to specify that any possible permutation of speaker configurations */
+#define PAWIN_SPEAKER_ALL ((PaWinWaveFormatChannelMask)0x80000000)
+
+/* DirectSound Speaker Config */
+#define PAWIN_SPEAKER_DIRECTOUT 0
+#define PAWIN_SPEAKER_MONO (PAWIN_SPEAKER_FRONT_CENTER)
+#define PAWIN_SPEAKER_STEREO (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT)
+#define PAWIN_SPEAKER_QUAD (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+ PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT)
+#define PAWIN_SPEAKER_SURROUND (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+ PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_BACK_CENTER)
+#define PAWIN_SPEAKER_5POINT1 (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+ PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+ PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT)
+#define PAWIN_SPEAKER_7POINT1 (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+ PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+ PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT | \
+ PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER | PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER)
+#define PAWIN_SPEAKER_5POINT1_SURROUND (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+ PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+ PAWIN_SPEAKER_SIDE_LEFT | PAWIN_SPEAKER_SIDE_RIGHT)
+#define PAWIN_SPEAKER_7POINT1_SURROUND (PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+ PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+ PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT | \
+ PAWIN_SPEAKER_SIDE_LEFT | PAWIN_SPEAKER_SIDE_RIGHT)
+/*
+ According to the Microsoft documentation:
+ The following are obsolete 5.1 and 7.1 settings (they lack side speakers). Note this means
+ that the default 5.1 and 7.1 settings (KSAUDIO_SPEAKER_5POINT1 and KSAUDIO_SPEAKER_7POINT1 are
+ similarly obsolete but are unchanged for compatibility reasons).
+*/
+#define PAWIN_SPEAKER_5POINT1_BACK PAWIN_SPEAKER_5POINT1
+#define PAWIN_SPEAKER_7POINT1_WIDE PAWIN_SPEAKER_7POINT1
+
+/* DVD Speaker Positions */
+#define PAWIN_SPEAKER_GROUND_FRONT_LEFT PAWIN_SPEAKER_FRONT_LEFT
+#define PAWIN_SPEAKER_GROUND_FRONT_CENTER PAWIN_SPEAKER_FRONT_CENTER
+#define PAWIN_SPEAKER_GROUND_FRONT_RIGHT PAWIN_SPEAKER_FRONT_RIGHT
+#define PAWIN_SPEAKER_GROUND_REAR_LEFT PAWIN_SPEAKER_BACK_LEFT
+#define PAWIN_SPEAKER_GROUND_REAR_RIGHT PAWIN_SPEAKER_BACK_RIGHT
+#define PAWIN_SPEAKER_TOP_MIDDLE PAWIN_SPEAKER_TOP_CENTER
+#define PAWIN_SPEAKER_SUPER_WOOFER PAWIN_SPEAKER_LOW_FREQUENCY
+
+
+/*
+ PaWinWaveFormat is defined here to provide compatibility with
+ compilation environments which don't have headers defining
+ WAVEFORMATEXTENSIBLE (e.g. older versions of MSVC, Borland C++ etc.
+
+ The fields for WAVEFORMATEX and WAVEFORMATEXTENSIBLE are declared as an
+ unsigned char array here to avoid clients who include this file having
+ a dependency on windows.h and mmsystem.h, and also to to avoid having
+ to write separate packing pragmas for each compiler.
+*/
+#define PAWIN_SIZEOF_WAVEFORMATEX 18
+#define PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE (PAWIN_SIZEOF_WAVEFORMATEX + 22)
+
+typedef struct{
+ unsigned char fields[ PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE ];
+ unsigned long extraLongForAlignment; /* ensure that compiler aligns struct to DWORD */
+} PaWinWaveFormat;
+
+/*
+ WAVEFORMATEXTENSIBLE fields:
+
+ union {
+ WORD wValidBitsPerSample;
+ WORD wSamplesPerBlock;
+ WORD wReserved;
+ } Samples;
+ DWORD dwChannelMask;
+ GUID SubFormat;
+*/
+
+#define PAWIN_INDEXOF_WVALIDBITSPERSAMPLE (PAWIN_SIZEOF_WAVEFORMATEX+0)
+#define PAWIN_INDEXOF_DWCHANNELMASK (PAWIN_SIZEOF_WAVEFORMATEX+2)
+#define PAWIN_INDEXOF_SUBFORMAT (PAWIN_SIZEOF_WAVEFORMATEX+6)
+
+
+/*
+ Valid values to pass for the waveFormatTag PaWin_InitializeWaveFormatEx and
+ PaWin_InitializeWaveFormatExtensible functions below. These must match
+ the standard Windows WAVE_FORMAT_* values.
+*/
+#define PAWIN_WAVE_FORMAT_PCM (1)
+#define PAWIN_WAVE_FORMAT_IEEE_FLOAT (3)
+#define PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092)
+#define PAWIN_WAVE_FORMAT_WMA_SPDIF (0x0164)
+
+
+/*
+ returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT
+ depending on the sampleFormat parameter.
+*/
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat );
+
+/*
+ Use the following two functions to initialize the waveformat structure.
+*/
+
+void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate );
+
+
+void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,
+ PaWinWaveFormatChannelMask channelMask );
+
+
+/* Map a channel count to a speaker channel mask */
+PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_WIN_WAVEFORMAT_H */
diff --git a/pd/portaudio/include/pa_win_wmme.h b/pd/portaudio/include/pa_win_wmme.h
index 2e90233a..deffd100 100644
--- a/pd/portaudio/include/pa_win_wmme.h
+++ b/pd/portaudio/include/pa_win_wmme.h
@@ -1,7 +1,7 @@
#ifndef PA_WIN_WMME_H
#define PA_WIN_WMME_H
/*
- * $Id: pa_win_wmme.h 1115 2006-09-06 15:39:48Z rossb $
+ * $Id: pa_win_wmme.h 1405 2009-03-08 08:10:55Z rossb $
* PortAudio Portable Real-Time Audio Library
* MME specific extensions
*
@@ -39,11 +39,13 @@
*/
/** @file
+ @ingroup public_header
@brief WMME-specific PortAudio API extension header file.
*/
#include "portaudio.h"
+#include "pa_win_waveformat.h"
#ifdef __cplusplus
extern "C"
@@ -51,9 +53,13 @@ extern "C"
#endif /* __cplusplus */
+/* The following are flags which can be set in
+ PaWinMmeStreamInfo's flags field.
+*/
+
#define paWinMmeUseLowLevelLatencyParameters (0x01)
#define paWinMmeUseMultipleDevices (0x02) /* use mme specific multiple device feature */
-
+#define paWinMmeUseChannelMask (0x04)
/* By default, the mme implementation drops the processing thread's priority
to THREAD_PRIORITY_NORMAL and sleeps the thread if the CPU load exceeds 100%
@@ -62,6 +68,11 @@ extern "C"
*/
#define paWinMmeDontThrottleOverloadedProcessingThread (0x08)
+/* Flags for non-PCM spdif passthrough.
+*/
+#define paWinMmeWaveFormatDolbyAc3Spdif (0x10)
+#define paWinMmeWaveFormatWmaSpdif (0x20)
+
typedef struct PaWinMmeDeviceAndChannelCount{
PaDeviceIndex device;
@@ -106,6 +117,15 @@ typedef struct PaWinMmeStreamInfo{
PaWinMmeDeviceAndChannelCount *devices;
unsigned long deviceCount;
+ /*
+ support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
+ paWinMmeUseChannelMask this allows you to specify which speakers
+ to address in a multichannel stream. Constants for channelMask
+ are specified in pa_win_waveformat.h
+
+ */
+ PaWinWaveFormatChannelMask channelMask;
+
}PaWinMmeStreamInfo;
diff --git a/pd/portaudio/include/portaudio.h b/pd/portaudio/include/portaudio.h
index 67fa2ea4..89964ab3 100644
--- a/pd/portaudio/include/portaudio.h
+++ b/pd/portaudio/include/portaudio.h
@@ -1,8 +1,7 @@
-
#ifndef PORTAUDIO_H
#define PORTAUDIO_H
/*
- * $Id: portaudio.h 1195 2007-04-22 17:34:45Z aknudsen $
+ * $Id: portaudio.h 1337 2008-02-15 07:32:09Z rossb $
* PortAudio Portable Real-Time Audio Library
* PortAudio API Header File
* Latest version available at: http://www.portaudio.com/
@@ -41,7 +40,8 @@
*/
/** @file
- @brief The PortAudio API.
+ @ingroup public_header
+ @brief The portable PortAudio API.
*/
diff --git a/pd/portaudio/src/common/pa_allocation.h b/pd/portaudio/src/common/pa_allocation.h
index b265b016..811dd72e 100644
--- a/pd/portaudio/src/common/pa_allocation.h
+++ b/pd/portaudio/src/common/pa_allocation.h
@@ -1,12 +1,12 @@
#ifndef PA_ALLOCATION_H
#define PA_ALLOCATION_H
/*
- * $Id: pa_allocation.h 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_allocation.h 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library allocation context header
* memory allocation context for tracking allocation groups
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -43,12 +43,12 @@
@ingroup common_src
@brief Allocation Group prototypes. An Allocation Group makes it easy to
- allocate multiple blocks of memory and free them all simultanously.
+ allocate multiple blocks of memory and free them all at once.
An allocation group is useful for keeping track of multiple blocks
of memory which are allocated at the same time (such as during initialization)
and need to be deallocated at the same time. The allocation group maintains
- a list of allocated blocks, and can deallocate them all simultaneously which
+ a list of allocated blocks, and can free all allocations at once. This
can be usefull for cleaning up after a partially initialized object fails.
The allocation group implementation is built on top of the lower
diff --git a/pd/portaudio/src/common/pa_converters.c b/pd/portaudio/src/common/pa_converters.c
index 3b98c858..965c1460 100644
--- a/pd/portaudio/src/common/pa_converters.c
+++ b/pd/portaudio/src/common/pa_converters.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_converters.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_converters.c 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library sample conversion mechanism
*
* Based on the Open Source API proposed by Ross Bencina
@@ -39,7 +39,7 @@
/** @file
@ingroup common_src
- @brief Conversion functions implementations.
+ @brief Conversion function implementations.
If the C9x function lrintf() is available, define PA_USE_C99_LRINTF to use it
diff --git a/pd/portaudio/src/common/pa_debugprint.c b/pd/portaudio/src/common/pa_debugprint.c
index 33fcf32e..a878028c 100644
--- a/pd/portaudio/src/common/pa_debugprint.c
+++ b/pd/portaudio/src/common/pa_debugprint.c
@@ -74,8 +74,11 @@ void PaUtil_SetDebugPrintFunction(PaUtilLogCallback cb)
VERY dangerous alternative, vsprintf (with no n)
*/
-#if (_MSC_VER) && (_MSC_VER < 1400)
-#define VSNPRINTF _vsnprintf
+#if _MSC_VER
+/* Some Windows Mobile SDKs don't define vsnprintf but all define _vsnprintf (hopefully).
+ According to MSDN "vsnprintf is identical to _vsnprintf". So we use _vsnprintf with MSC.
+*/
+#define VSNPRINTF _vsnprintf
#else
#define VSNPRINTF vsnprintf
#endif
diff --git a/pd/portaudio/src/common/pa_dither.c b/pd/portaudio/src/common/pa_dither.c
index 6f6c9a1a..7a1b1312 100644
--- a/pd/portaudio/src/common/pa_dither.c
+++ b/pd/portaudio/src/common/pa_dither.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_dither.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_dither.c 1418 2009-10-12 21:00:53Z philburk $
* Portable Audio I/O Library triangular dither generator
*
* Based on the Open Source API proposed by Ross Bencina
@@ -42,9 +42,14 @@
@brief Functions for generating dither noise
*/
-
-#include "pa_dither.h"
#include "pa_types.h"
+#include "pa_dither.h"
+
+
+/* Note that the linear congruential algorithm requires 32 bit integers
+ * because it uses arithmetic overflow. So use PaUint32 instead of
+ * unsigned long so it will work on 64 bit systems.
+ */
#define PA_DITHER_BITS_ (15)
@@ -57,9 +62,9 @@ void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *st
}
-signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *state )
+PaInt32 PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *state )
{
- signed long current, highPass;
+ PaInt32 current, highPass;
/* Generate two random numbers. */
state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
@@ -69,9 +74,10 @@ signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerato
* Shift before adding to prevent overflow which would skew the distribution.
* Also shift an extra bit for the high pass filter.
*/
-#define DITHER_SHIFT_ ((SIZEOF_LONG*8 - PA_DITHER_BITS_) + 1)
- current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
- (((signed long)state->randSeed2)>>DITHER_SHIFT_);
+#define DITHER_SHIFT_ ((sizeof(PaInt32)*8 - PA_DITHER_BITS_) + 1)
+
+ current = (((PaInt32)state->randSeed1)>>DITHER_SHIFT_) +
+ (((PaInt32)state->randSeed2)>>DITHER_SHIFT_);
/* High pass filter to reduce audibility. */
highPass = current - state->previous;
@@ -86,7 +92,7 @@ static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *state )
{
- signed long current, highPass;
+ PaInt32 current, highPass;
/* Generate two random numbers. */
state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
@@ -96,9 +102,8 @@ float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *sta
* Shift before adding to prevent overflow which would skew the distribution.
* Also shift an extra bit for the high pass filter.
*/
-#define DITHER_SHIFT_ ((SIZEOF_LONG*8 - PA_DITHER_BITS_) + 1)
- current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
- (((signed long)state->randSeed2)>>DITHER_SHIFT_);
+ current = (((PaInt32)state->randSeed1)>>DITHER_SHIFT_) +
+ (((PaInt32)state->randSeed2)>>DITHER_SHIFT_);
/* High pass filter to reduce audibility. */
highPass = current - state->previous;
diff --git a/pd/portaudio/src/common/pa_dither.h b/pd/portaudio/src/common/pa_dither.h
index e77ce470..a5131b27 100644
--- a/pd/portaudio/src/common/pa_dither.h
+++ b/pd/portaudio/src/common/pa_dither.h
@@ -1,7 +1,7 @@
#ifndef PA_DITHER_H
#define PA_DITHER_H
/*
- * $Id: pa_dither.h 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_dither.h 1418 2009-10-12 21:00:53Z philburk $
* Portable Audio I/O Library triangular dither generator
*
* Based on the Open Source API proposed by Ross Bencina
@@ -44,18 +44,24 @@
@brief Functions for generating dither noise
*/
+#include "pa_types.h"
+
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
+/* Note that the linear congruential algorithm requires 32 bit integers
+ * because it uses arithmetic overflow. So use PaUint32 instead of
+ * unsigned long so it will work on 64 bit systems.
+ */
/** @brief State needed to generate a dither signal */
typedef struct PaUtilTriangularDitherGenerator{
- unsigned long previous;
- unsigned long randSeed1;
- unsigned long randSeed2;
+ PaUint32 previous;
+ PaUint32 randSeed1;
+ PaUint32 randSeed2;
} PaUtilTriangularDitherGenerator;
@@ -73,9 +79,9 @@ void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *di
signed short out = (signed short)(((in>>1) + dither) >> 15);
</pre>
@return
- A signed long with a range of +32767 to -32768
+ A signed 32-bit integer with a range of +32767 to -32768
*/
-signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
+PaInt32 PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
/**
diff --git a/pd/portaudio/src/common/pa_endianness.h b/pd/portaudio/src/common/pa_endianness.h
index bdcc74f7..84e904ca 100644
--- a/pd/portaudio/src/common/pa_endianness.h
+++ b/pd/portaudio/src/common/pa_endianness.h
@@ -1,7 +1,7 @@
#ifndef PA_ENDIANNESS_H
#define PA_ENDIANNESS_H
/*
- * $Id: pa_endianness.h 1216 2007-06-10 09:26:00Z aknudsen $
+ * $Id: pa_endianness.h 1324 2008-01-27 02:03:30Z bjornroche $
* Portable Audio I/O Library current platform endianness macros
*
* Based on the Open Source API proposed by Ross Bencina
@@ -120,18 +120,22 @@ extern "C"
and raises an assertion if they don't match. <assert.h> must be included in
the context in which this macro is used.
*/
-#if defined(PA_LITTLE_ENDIAN)
- #define PA_VALIDATE_ENDIANNESS \
- { \
- const long nativeOne = 1; \
- assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 1 ); \
- }
-#elif defined(PA_BIG_ENDIAN)
- #define PA_VALIDATE_ENDIANNESS \
- { \
- const long nativeOne = 1; \
- assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 0 ); \
- }
+#if defined(NDEBUG)
+ #define PA_VALIDATE_ENDIANNESS
+#else
+ #if defined(PA_LITTLE_ENDIAN)
+ #define PA_VALIDATE_ENDIANNESS \
+ { \
+ const long nativeOne = 1; \
+ assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 1 ); \
+ }
+ #elif defined(PA_BIG_ENDIAN)
+ #define PA_VALIDATE_ENDIANNESS \
+ { \
+ const long nativeOne = 1; \
+ assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 0 ); \
+ }
+ #endif
#endif
diff --git a/pd/portaudio/src/common/pa_front.c b/pd/portaudio/src/common/pa_front.c
index 5af90d45..28f0c60e 100644
--- a/pd/portaudio/src/common/pa_front.c
+++ b/pd/portaudio/src/common/pa_front.c
@@ -1,10 +1,10 @@
/*
- * $Id: pa_front.c 1229 2007-06-15 16:11:11Z rossb $
+ * $Id: pa_front.c 1396 2008-11-03 19:31:30Z philburk $
* Portable Audio I/O Library Multi-Host API front end
* Validate function parameters and manage multiple host APIs.
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -40,17 +40,20 @@
/** @file
@ingroup common_src
- @brief Implements public PortAudio API, checks some errors, forwards to
- host API implementations.
+ @brief Implements PortAudio API functions defined in portaudio.h, checks
+ some errors, delegates platform-specific behavior to host API implementations.
- Implements the functions defined in the PortAudio API, checks for
- some parameter and state inconsistencies and forwards API requests to
- specific Host API implementations (via the interface declared in
- pa_hostapi.h), and Streams (via the interface declared in pa_stream.h).
+ Implements the functions defined in the PortAudio API (portaudio.h),
+ validates some parameters and checks for state inconsistencies before
+ forwarding API requests to specific Host API implementations (via the
+ interface declared in pa_hostapi.h), and Streams (via the interface
+ declared in pa_stream.h).
- This file handles initialization and termination of Host API
- implementations via initializers stored in the paHostApiInitializers
- global variable.
+ This file manages initialization and termination of Host API
+ implementations via initializer functions stored in the paHostApiInitializers
+ global array (usually defined in an os-specific pa_[os]_hostapis.c file).
+
+ This file maintains a list of all open streams and closes them at Pa_Terminate().
Some utility functions declared in pa_util.h are implemented in this file.
@@ -87,7 +90,7 @@
#define PA_VERSION_ 1899
-#define PA_VERSION_TEXT_ "PortAudio V19-devel (built " __DATE__ ")"
+#define PA_VERSION_TEXT_ "PortAudio V19-devel (built " __DATE__ " " __TIME__ ")"
@@ -405,6 +408,8 @@ const char *Pa_GetErrorText( PaError errorCode )
case paCanNotWriteToACallbackStream: result = "Can't write to a callback stream"; break;
case paCanNotReadFromAnOutputOnlyStream: result = "Can't read from an output only stream"; break;
case paCanNotWriteToAnInputOnlyStream: result = "Can't write to an input only stream"; break;
+ case paIncompatibleStreamHostApi: result = "Incompatible stream host API"; break;
+ case paBadBufferPtr: result = "Bad buffer pointer"; break;
default:
if( errorCode > 0 )
result = "Invalid error code (value greater than zero)";
@@ -1501,7 +1506,7 @@ const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream )
result = 0;
PA_LOGAPI(("Pa_GetStreamInfo returned:\n" ));
- PA_LOGAPI(("\tconst PaStreamInfo*: 0 [PaError error:%d ( %s )]\n", result, error, Pa_GetErrorText( error ) ));
+ PA_LOGAPI(("\tconst PaStreamInfo*: 0 [PaError error:%d ( %s )]\n", error, Pa_GetErrorText( error ) ));
}
else
diff --git a/pd/portaudio/src/common/pa_hostapi.h b/pd/portaudio/src/common/pa_hostapi.h
index 5a86d4e9..5462d443 100644
--- a/pd/portaudio/src/common/pa_hostapi.h
+++ b/pd/portaudio/src/common/pa_hostapi.h
@@ -1,12 +1,12 @@
#ifndef PA_HOSTAPI_H
#define PA_HOSTAPI_H
/*
- * $Id: pa_hostapi.h 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_hostapi.h 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library
* host api representation
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -42,8 +42,8 @@
/** @file
@ingroup common_src
- @brief Interface used by pa_front to virtualize functions which operate on
- host APIs.
+ @brief Interfaces and representation structures used by pa_front.c
+ to manage and communicate with host API implementations.
*/
@@ -224,13 +224,19 @@ typedef struct PaUtilHostApiRepresentation {
/** Prototype for the initialization function which must be implemented by every
host API.
+ This function should only return an error other than paNoError if it encounters
+ an unexpected and fatal error (memory allocation error for example). In general,
+ there may be conditions under which it returns a NULL interface pointer and also
+ returns paNoError. For example, if the ASIO implementation detects that ASIO is
+ not installed, it should return a NULL interface, and paNoError.
+
@see paHostApiInitializers
*/
typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostApiIndex );
/** paHostApiInitializers is a NULL-terminated array of host API initialization
- functions. These functions are called by pa_front to initialize the host APIs
+ functions. These functions are called by pa_front.c to initialize the host APIs
when the client calls Pa_Initialize().
There is a platform specific file which defines paHostApiInitializers for that
diff --git a/pd/portaudio/src/common/pa_memorybarrier.h b/pd/portaudio/src/common/pa_memorybarrier.h
new file mode 100644
index 00000000..5efeed24
--- /dev/null
+++ b/pd/portaudio/src/common/pa_memorybarrier.h
@@ -0,0 +1,123 @@
+/*
+ * $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
+ * Portable Audio I/O Library
+ * Memory barrier utilities
+ *
+ * Author: Bjorn Roche, XO Audio, LLC
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/**
+ @file pa_memorybarrier.h
+ @ingroup common_src
+*/
+
+/****************
+ * Some memory barrier primitives based on the system.
+ * right now only OS X, FreeBSD, and Linux are supported. In addition to providing
+ * memory barriers, these functions should ensure that data cached in registers
+ * is written out to cache where it can be snooped by other CPUs. (ie, the volatile
+ * keyword should not be required)
+ *
+ * the primitives that must be defined are:
+ *
+ * PaUtil_FullMemoryBarrier()
+ * PaUtil_ReadMemoryBarrier()
+ * PaUtil_WriteMemoryBarrier()
+ *
+ ****************/
+
+#if defined(__APPLE__)
+# include <libkern/OSAtomic.h>
+ /* Here are the memory barrier functions. Mac OS X only provides
+ full memory barriers, so the three types of barriers are the same,
+ however, these barriers are superior to compiler-based ones. */
+# define PaUtil_FullMemoryBarrier() OSMemoryBarrier()
+# define PaUtil_ReadMemoryBarrier() OSMemoryBarrier()
+# define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
+#elif defined(__GNUC__)
+ /* GCC >= 4.1 has built-in intrinsics. We'll use those */
+# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+# define PaUtil_FullMemoryBarrier() __sync_synchronize()
+# define PaUtil_ReadMemoryBarrier() __sync_synchronize()
+# define PaUtil_WriteMemoryBarrier() __sync_synchronize()
+ /* as a fallback, GCC understands volatile asm and "memory" to mean it
+ * should not reorder memory read/writes */
+ /* Note that it is not clear that any compiler actually defines __PPC__,
+ * it can probably removed safely. */
+# elif defined( __ppc__ ) || defined( __powerpc__) || defined( __PPC__ )
+# define PaUtil_FullMemoryBarrier() asm volatile("sync":::"memory")
+# define PaUtil_ReadMemoryBarrier() asm volatile("sync":::"memory")
+# define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory")
+# elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || \
+ defined( __i686__ ) || defined( __x86_64__ )
+# define PaUtil_FullMemoryBarrier() asm volatile("mfence":::"memory")
+# define PaUtil_ReadMemoryBarrier() asm volatile("lfence":::"memory")
+# define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory")
+# else
+# ifdef ALLOW_SMP_DANGERS
+# warning Memory barriers not defined on this system or system unknown
+# warning For SMP safety, you should fix this.
+# define PaUtil_FullMemoryBarrier()
+# define PaUtil_ReadMemoryBarrier()
+# define PaUtil_WriteMemoryBarrier()
+# else
+# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+# endif
+# endif
+#elif (_MSC_VER >= 1400)
+# include <intrin.h>
+# pragma intrinsic(_ReadWriteBarrier)
+# pragma intrinsic(_ReadBarrier)
+# pragma intrinsic(_WriteBarrier)
+# define PaUtil_FullMemoryBarrier() _ReadWriteBarrier()
+# define PaUtil_ReadMemoryBarrier() _ReadBarrier()
+# define PaUtil_WriteMemoryBarrier() _WriteBarrier()
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+# define PaUtil_FullMemoryBarrier() _asm { lock add [esp], 0 }
+# define PaUtil_ReadMemoryBarrier() _asm { lock add [esp], 0 }
+# define PaUtil_WriteMemoryBarrier() _asm { lock add [esp], 0 }
+#else
+# ifdef ALLOW_SMP_DANGERS
+# warning Memory barriers not defined on this system or system unknown
+# warning For SMP safety, you should fix this.
+# define PaUtil_FullMemoryBarrier()
+# define PaUtil_ReadMemoryBarrier()
+# define PaUtil_WriteMemoryBarrier()
+# else
+# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+# endif
+#endif
diff --git a/pd/portaudio/src/common/pa_process.c b/pd/portaudio/src/common/pa_process.c
index fac474d5..4770610b 100644
--- a/pd/portaudio/src/common/pa_process.c
+++ b/pd/portaudio/src/common/pa_process.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_process.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_process.c 1408 2009-03-13 16:41:39Z rossb $
* Portable Audio I/O Library
* streamCallback <-> host buffer processing adapter
*
@@ -56,8 +56,6 @@
@todo Consider cache tilings for intereave<->deinterleave.
- @todo implement timeInfo->currentTime int PaUtil_BeginBufferProcessing()
-
@todo specify and implement some kind of logical policy for handling the
underflow and overflow stream flags when the underflow/overflow overlaps
multiple user buffers/callbacks.
@@ -683,7 +681,9 @@ void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bp,
bp->timeInfo->inputBufferAdcTime -= bp->framesInTempInputBuffer * bp->samplePeriod;
- bp->timeInfo->currentTime = 0; /** FIXME: @todo time info currentTime not implemented */
+ /* We just pass through timeInfo->currentTime provided by the caller. This is
+ not strictly conformant to the word of the spec, since the buffer processor
+ might call the callback multiple times, and we never refresh currentTime. */
/* the first streamCallback will be called to generate samples which will be
outputted after the frames currently in the output buffer have been
@@ -997,7 +997,7 @@ static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp,
bp->framesPerUserBuffer, bp->timeInfo,
bp->callbackStatusFlags, bp->userData );
- bp->timeInfo->inputBufferAdcTime += frameCount * bp->samplePeriod;
+ bp->timeInfo->inputBufferAdcTime += bp->framesPerUserBuffer * bp->samplePeriod;
}
bp->framesInTempInputBuffer = 0;
diff --git a/pd/portaudio/src/common/pa_ringbuffer.c b/pd/portaudio/src/common/pa_ringbuffer.c
index f4e1201a..ad9e2ae5 100644
--- a/pd/portaudio/src/common/pa_ringbuffer.c
+++ b/pd/portaudio/src/common/pa_ringbuffer.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_ringbuffer.c 1240 2007-07-17 13:05:07Z bjornroche $
+ * $Id: pa_ringbuffer.c 1346 2008-02-20 10:09:20Z rossb $
* Portable Audio I/O Library
* Ring Buffer utility.
*
@@ -7,6 +7,8 @@
* modified for SMP safety on Mac OS X by Bjorn Roche
* modified for SMP safety on Linux by Leland Lucius
* also, allowed for const where possible
+ * modified for multiple-byte-sized data elements by Sven Fischer
+ *
* Note that this is safe only for a single-thread reader and a
* single-thread writer.
*
@@ -55,93 +57,33 @@
#include <math.h>
#include "pa_ringbuffer.h"
#include <string.h>
-
-/****************
- * First, we'll define some memory barrier primitives based on the system.
- * right now only OS X, FreeBSD, and Linux are supported. In addition to providing
- * memory barriers, these functions should ensure that data cached in registers
- * is written out to cache where it can be snooped by other CPUs. (ie, the volatile
- * keyword should not be required)
- *
- * the primitives that must be defined are:
- *
- * PaUtil_FullMemoryBarrier()
- * PaUtil_ReadMemoryBarrier()
- * PaUtil_WriteMemoryBarrier()
- *
- ****************/
-
-#if defined(__APPLE__)
-# include <libkern/OSAtomic.h>
- /* Here are the memory barrier functions. Mac OS X only provides
- full memory barriers, so the three types of barriers are the same,
- however, these barriers are superior to compiler-based ones. */
-# define PaUtil_FullMemoryBarrier() OSMemoryBarrier()
-# define PaUtil_ReadMemoryBarrier() OSMemoryBarrier()
-# define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
-#elif defined(__GNUC__)
- /* GCC >= 4.1 has built-in intrinsics. We'll use those */
-# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
-# define PaUtil_FullMemoryBarrier() __sync_synchronize()
-# define PaUtil_ReadMemoryBarrier() __sync_synchronize()
-# define PaUtil_WriteMemoryBarrier() __sync_synchronize()
- /* as a fallback, GCC understands volatile asm and "memory" to mean it
- * should not reorder memory read/writes */
-# elif defined( __PPC__ )
-# define PaUtil_FullMemoryBarrier() asm volatile("sync":::"memory")
-# define PaUtil_ReadMemoryBarrier() asm volatile("sync":::"memory")
-# define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory")
-# elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || defined( __i686__ ) || defined( __x86_64__ )
-# define PaUtil_FullMemoryBarrier() asm volatile("mfence":::"memory")
-# define PaUtil_ReadMemoryBarrier() asm volatile("lfence":::"memory")
-# define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory")
-# else
-# ifdef ALLOW_SMP_DANGERS
-# warning Memory barriers not defined on this system or system unknown
-# warning For SMP safety, you should fix this.
-# define PaUtil_FullMemoryBarrier()
-# define PaUtil_ReadMemoryBarrier()
-# define PaUtil_WriteMemoryBarrier()
-# else
-# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
-# endif
-# endif
-#else
-# ifdef ALLOW_SMP_DANGERS
-# warning Memory barriers not defined on this system or system unknown
-# warning For SMP safety, you should fix this.
-# define PaUtil_FullMemoryBarrier()
-# define PaUtil_ReadMemoryBarrier()
-# define PaUtil_WriteMemoryBarrier()
-# else
-# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
-# endif
-#endif
+#include "pa_memorybarrier.h"
/***************************************************************************
* Initialize FIFO.
- * numBytes must be power of 2, returns -1 if not.
+ * elementCount must be power of 2, returns -1 if not.
*/
-long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *dataPtr )
+long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long elementSizeBytes, long elementCount, void *dataPtr )
{
- if( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
- rbuf->bufferSize = numBytes;
+ if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */
+ rbuf->bufferSize = elementCount;
rbuf->buffer = (char *)dataPtr;
PaUtil_FlushRingBuffer( rbuf );
- rbuf->bigMask = (numBytes*2)-1;
- rbuf->smallMask = (numBytes)-1;
+ rbuf->bigMask = (elementCount*2)-1;
+ rbuf->smallMask = (elementCount)-1;
+ rbuf->elementSizeBytes = elementSizeBytes;
return 0;
}
/***************************************************************************
-** Return number of bytes available for reading. */
+** Return number of elements available for reading. */
long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf )
{
PaUtil_ReadMemoryBarrier();
return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
}
/***************************************************************************
-** Return number of bytes available for writing. */
+** Return number of elements available for writing. */
long PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
{
/* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
@@ -159,126 +101,126 @@ void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
-** Returns room available to be written or numBytes, whichever is smaller.
+** Returns room available to be written or elementCount, whichever is smaller.
*/
-long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
+long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long elementCount,
void **dataPtr1, long *sizePtr1,
void **dataPtr2, long *sizePtr2 )
{
long index;
long available = PaUtil_GetRingBufferWriteAvailable( rbuf );
- if( numBytes > available ) numBytes = available;
+ if( elementCount > available ) elementCount = available;
/* Check to see if write is not contiguous. */
index = rbuf->writeIndex & rbuf->smallMask;
- if( (index + numBytes) > rbuf->bufferSize )
+ if( (index + elementCount) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index;
- *dataPtr1 = &rbuf->buffer[index];
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0];
- *sizePtr2 = numBytes - firstHalf;
+ *sizePtr2 = elementCount - firstHalf;
}
else
{
- *dataPtr1 = &rbuf->buffer[index];
- *sizePtr1 = numBytes;
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+ *sizePtr1 = elementCount;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
- return numBytes;
+ return elementCount;
}
/***************************************************************************
*/
-long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes )
+long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long elementCount )
{
/* we need to ensure that previous writes are seen before we update the write index */
PaUtil_WriteMemoryBarrier();
- return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
+ return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
}
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
-** Returns room available to be written or numBytes, whichever is smaller.
+** Returns room available to be written or elementCount, whichever is smaller.
*/
-long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
+long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long elementCount,
void **dataPtr1, long *sizePtr1,
void **dataPtr2, long *sizePtr2 )
{
long index;
long available = PaUtil_GetRingBufferReadAvailable( rbuf );
- if( numBytes > available ) numBytes = available;
+ if( elementCount > available ) elementCount = available;
/* Check to see if read is not contiguous. */
index = rbuf->readIndex & rbuf->smallMask;
- if( (index + numBytes) > rbuf->bufferSize )
+ if( (index + elementCount) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index;
- *dataPtr1 = &rbuf->buffer[index];
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0];
- *sizePtr2 = numBytes - firstHalf;
+ *sizePtr2 = elementCount - firstHalf;
}
else
{
- *dataPtr1 = &rbuf->buffer[index];
- *sizePtr1 = numBytes;
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+ *sizePtr1 = elementCount;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
- return numBytes;
+ return elementCount;
}
/***************************************************************************
*/
-long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes )
+long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long elementCount )
{
/* we need to ensure that previous writes are always seen before updating the index. */
PaUtil_WriteMemoryBarrier();
- return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
+ return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
}
/***************************************************************************
-** Return bytes written. */
-long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes )
+** Return elements written. */
+long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long elementCount )
{
long size1, size2, numWritten;
void *data1, *data2;
- numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+ numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
if( size2 > 0 )
{
- memcpy( data1, data, size1 );
- data = ((char *)data) + size1;
- memcpy( data2, data, size2 );
+ memcpy( data1, data, size1*rbuf->elementSizeBytes );
+ data = ((char *)data) + size1*rbuf->elementSizeBytes;
+ memcpy( data2, data, size2*rbuf->elementSizeBytes );
}
else
{
- memcpy( data1, data, size1 );
+ memcpy( data1, data, size1*rbuf->elementSizeBytes );
}
PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
return numWritten;
}
/***************************************************************************
-** Return bytes read. */
-long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes )
+** Return elements read. */
+long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long elementCount )
{
long size1, size2, numRead;
void *data1, *data2;
- numRead = PaUtil_GetRingBufferReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+ numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
if( size2 > 0 )
{
- memcpy( data, data1, size1 );
- data = ((char *)data) + size1;
- memcpy( data, data2, size2 );
+ memcpy( data, data1, size1*rbuf->elementSizeBytes );
+ data = ((char *)data) + size1*rbuf->elementSizeBytes;
+ memcpy( data, data2, size2*rbuf->elementSizeBytes );
}
else
{
- memcpy( data, data1, size1 );
+ memcpy( data, data1, size1*rbuf->elementSizeBytes );
}
PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
return numRead;
diff --git a/pd/portaudio/src/common/pa_ringbuffer.h b/pd/portaudio/src/common/pa_ringbuffer.h
index b3808898..fd92882a 100644
--- a/pd/portaudio/src/common/pa_ringbuffer.h
+++ b/pd/portaudio/src/common/pa_ringbuffer.h
@@ -1,13 +1,15 @@
#ifndef PA_RINGBUFFER_H
#define PA_RINGBUFFER_H
/*
- * $Id: pa_ringbuffer.h 1151 2006-11-29 02:11:16Z leland_lucius $
+ * $Id: pa_ringbuffer.h 1347 2008-02-21 04:54:36Z rossb $
* Portable Audio I/O Library
* Ring Buffer utility.
*
* Author: Phil Burk, http://www.softsynth.com
* modified for SMP safety on OS X by Bjorn Roche.
* also allowed for const where possible.
+ * modified for multiple-byte-sized data elements by Sven Fischer
+ *
* Note that this is safe only for a single-thread reader
* and a single-thread writer.
*
@@ -48,6 +50,21 @@
/** @file
@ingroup common_src
+ @brief Single-reader single-writer lock-free ring buffer
+
+ PaUtilRingBuffer is a ring buffer used to transport samples between
+ different execution contexts (threads, OS callbacks, interrupt handlers)
+ without requiring the use of any locks. This only works when there is
+ a single reader and a single writer (ie. one thread or callback writes
+ to the ring buffer, another thread or callback reads from it).
+
+ The PaUtilRingBuffer structure manages a ring buffer containing N
+ elements, where N must be a power of two. An element may be any size
+ (specified in bytes).
+
+ The memory area used to store the buffer elements must be allocated by
+ the client prior to calling PaUtil_InitializeRingBuffer() and must outlive
+ the use of the ring buffer.
*/
#ifdef __cplusplus
@@ -57,26 +74,29 @@ extern "C"
typedef struct PaUtilRingBuffer
{
- long bufferSize; /* Number of bytes in FIFO. Power of 2. Set by PaUtil_InitRingBuffer. */
- long writeIndex; /* Index of next writable byte. Set by PaUtil_AdvanceRingBufferWriteIndex. */
- long readIndex; /* Index of next readable byte. Set by PaUtil_AdvanceRingBufferReadIndex. */
- long bigMask; /* Used for wrapping indices with extra bit to distinguish full/empty. */
- long smallMask; /* Used for fitting indices to buffer. */
- char *buffer;
+ long bufferSize; /**< Number of elements in FIFO. Power of 2. Set by PaUtil_InitRingBuffer. */
+ long writeIndex; /**< Index of next writable element. Set by PaUtil_AdvanceRingBufferWriteIndex. */
+ long readIndex; /**< Index of next readable element. Set by PaUtil_AdvanceRingBufferReadIndex. */
+ long bigMask; /**< Used for wrapping indices with extra bit to distinguish full/empty. */
+ long smallMask; /**< Used for fitting indices to buffer. */
+ long elementSizeBytes; /**< Number of bytes per element. */
+ char *buffer; /**< Pointer to the buffer containing the actual data. */
}PaUtilRingBuffer;
/** Initialize Ring Buffer.
@param rbuf The ring buffer.
- @param numBytes The number of bytes in the buffer and must be power of 2.
+ @param elementSizeBytes The size of a single data element in bytes.
+
+ @param elementCount The number of elements in the buffer (must be power of 2).
@param dataPtr A pointer to a previously allocated area where the data
- will be maintained. It must be numBytes long.
+ will be maintained. It must be elementCount*elementSizeBytes long.
- @return -1 if numBytes is not a power of 2, otherwise 0.
+ @return -1 if elementCount is not a power of 2, otherwise 0.
*/
-long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *dataPtr );
+long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long elementSizeBytes, long elementCount, void *dataPtr );
/** Clear buffer. Should only be called when buffer is NOT being read.
@@ -84,19 +104,19 @@ long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *d
*/
void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf );
-/** Retrieve the number of bytes available in the ring buffer for writing.
+/** Retrieve the number of elements available in the ring buffer for writing.
@param rbuf The ring buffer.
- @return The number of bytes available for writing.
+ @return The number of elements available for writing.
*/
long PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf );
-/** Retrieve the number of bytes available in the ring buffer for reading.
+/** Retrieve the number of elements available in the ring buffer for reading.
@param rbuf The ring buffer.
- @return The number of bytes available for reading.
+ @return The number of elements available for reading.
*/
long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf );
@@ -106,11 +126,11 @@ long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf );
@param data The address of new data to write to the buffer.
- @param numBytes The number of bytes to be written.
+ @param elementCount The number of elements to be written.
- @return The number of bytes written.
+ @return The number of elements written.
*/
-long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes );
+long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long elementCount );
/** Read data from the ring buffer.
@@ -118,17 +138,17 @@ long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numB
@param data The address where the data should be stored.
- @param numBytes The number of bytes to be read.
+ @param elementCount The number of elements to be read.
- @return The number of bytes read.
+ @return The number of elements read.
*/
-long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes );
+long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long elementCount );
/** Get address of region(s) to which we can write data.
@param rbuf The ring buffer.
- @param numBytes The number of bytes desired.
+ @param elementCount The number of elements desired.
@param dataPtr1 The address where the first (or only) region pointer will be
stored.
@@ -137,14 +157,14 @@ long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes );
stored.
@param dataPtr2 The address where the second region pointer will be stored if
- the first region is too small to satisfy numBytes.
+ the first region is too small to satisfy elementCount.
@param sizePtr2 The address where the second region length will be stored if
- the first region is too small to satisfy numBytes.
+ the first region is too small to satisfy elementCount.
- @return The room available to be written or numBytes, whichever is smaller.
+ @return The room available to be written or elementCount, whichever is smaller.
*/
-long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
+long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long elementCount,
void **dataPtr1, long *sizePtr1,
void **dataPtr2, long *sizePtr2 );
@@ -152,17 +172,17 @@ long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
@param rbuf The ring buffer.
- @param numBytes The number of bytes to advance.
+ @param elementCount The number of elements to advance.
@return The new position.
*/
-long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes );
+long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long elementCount );
/** Get address of region(s) from which we can write data.
@param rbuf The ring buffer.
- @param numBytes The number of bytes desired.
+ @param elementCount The number of elements desired.
@param dataPtr1 The address where the first (or only) region pointer will be
stored.
@@ -171,14 +191,14 @@ long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes )
stored.
@param dataPtr2 The address where the second region pointer will be stored if
- the first region is too small to satisfy numBytes.
+ the first region is too small to satisfy elementCount.
@param sizePtr2 The address where the second region length will be stored if
- the first region is too small to satisfy numBytes.
+ the first region is too small to satisfy elementCount.
- @return The number of bytes available for reading.
+ @return The number of elements available for reading.
*/
-long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
+long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long elementCount,
void **dataPtr1, long *sizePtr1,
void **dataPtr2, long *sizePtr2 );
@@ -186,11 +206,11 @@ long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
@param rbuf The ring buffer.
- @param numBytes The number of bytes to advance.
+ @param elementCount The number of elements to advance.
@return The new position.
*/
-long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes );
+long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long elementCount );
#ifdef __cplusplus
}
diff --git a/pd/portaudio/src/common/pa_skeleton.c b/pd/portaudio/src/common/pa_skeleton.c
index e229b07b..d5cb52d8 100644
--- a/pd/portaudio/src/common/pa_skeleton.c
+++ b/pd/portaudio/src/common/pa_skeleton.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_skeleton.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_skeleton.c 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library skeleton implementation
* demonstrates how to use the common functions to implement support
* for a host API
@@ -43,8 +43,10 @@
@brief Skeleton implementation of support for a host API.
- @note This file is provided as a starting point for implementing support for
- a new host API. IMPLEMENT ME comments are used to indicate functionality
+ This file is provided as a starting point for implementing support for
+ a new host API. It provides examples of how the common code can be used.
+
+ @note IMPLEMENT ME comments are used to indicate functionality
which much be customised for each implementation.
*/
diff --git a/pd/portaudio/src/common/pa_stream.c b/pd/portaudio/src/common/pa_stream.c
index 172e7d26..ea91821f 100644
--- a/pd/portaudio/src/common/pa_stream.c
+++ b/pd/portaudio/src/common/pa_stream.c
@@ -1,10 +1,10 @@
/*
- * $Id: pa_stream.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_stream.c 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library
- *
+ * stream interface
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 2002 Ross Bencina
+ * Copyright (c) 2008 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -40,8 +40,8 @@
/** @file
@ingroup common_src
- @brief Interface used by pa_front to virtualize functions which operate on
- streams.
+ @brief Stream interfaces, representation structures and helper functions
+ used to interface between pa_front.c host API implementations.
*/
diff --git a/pd/portaudio/src/common/pa_stream.h b/pd/portaudio/src/common/pa_stream.h
index f5363b3e..8d707b79 100644
--- a/pd/portaudio/src/common/pa_stream.h
+++ b/pd/portaudio/src/common/pa_stream.h
@@ -1,12 +1,12 @@
#ifndef PA_STREAM_H
#define PA_STREAM_H
/*
- * $Id: pa_stream.h 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_stream.h 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library
* stream interface
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -42,8 +42,8 @@
/** @file
@ingroup common_src
- @brief Interface used by pa_front to virtualize functions which operate on
- streams.
+ @brief Stream interfaces, representation structures and helper functions
+ used to interface between pa_front.c host API implementations.
*/
diff --git a/pd/portaudio/src/common/pa_trace.c b/pd/portaudio/src/common/pa_trace.c
index 583d3ae9..24305003 100644
--- a/pd/portaudio/src/common/pa_trace.c
+++ b/pd/portaudio/src/common/pa_trace.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_trace.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_trace.c 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library Trace Facility
* Store trace information in real-time for later printing.
*
@@ -40,7 +40,7 @@
/** @file
@ingroup common_src
- @brief Event trace mechanism for debugging.
+ @brief Real-time safe event trace logging facility for debugging.
*/
diff --git a/pd/portaudio/src/common/pa_trace.h b/pd/portaudio/src/common/pa_trace.h
index a4d2a331..b11509e0 100644
--- a/pd/portaudio/src/common/pa_trace.h
+++ b/pd/portaudio/src/common/pa_trace.h
@@ -1,7 +1,7 @@
#ifndef PA_TRACE_H
#define PA_TRACE_H
/*
- * $Id: pa_trace.h 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_trace.h 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library Trace Facility
* Store trace information in real-time for later printing.
*
@@ -42,14 +42,36 @@
/** @file
@ingroup common_src
- @brief Event trace mechanism for debugging.
+ @brief Real-time safe event trace logging facility for debugging.
- Allows data to be written to the buffer at interrupt time and dumped later.
+ Allows data to be logged to a fixed size trace buffer in a real-time
+ execution context (such as at interrupt time). Each log entry consists
+ of a message comprising a string pointer and an int. The trace buffer
+ may be dumped to stdout later.
+
+ This facility is only active if PA_TRACE_REALTIME_EVENTS is set to 1,
+ otherwise the trace functions expand to no-ops.
+
+ @fn PaUtil_ResetTraceMessages
+ @brief Clear the trace buffer.
+
+ @fn PaUtil_AddTraceMessage
+ @brief Add a message to the trace buffer. A message consists of string and an int.
+ @param msg The string pointer must remain valid until PaUtil_DumpTraceMessages
+ is called. As a result, usually only string literals should be passed as
+ the msg parameter.
+
+ @fn PaUtil_DumpTraceMessages
+ @brief Print all messages in the trace buffer to stdout and clear the trace buffer.
*/
+#ifndef PA_TRACE_REALTIME_EVENTS
+#define PA_TRACE_REALTIME_EVENTS (0) /**< Set to 1 to enable logging using the trace functions defined below */
+#endif
-#define PA_TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */
-#define PA_MAX_TRACE_RECORDS (2048)
+#ifndef PA_MAX_TRACE_RECORDS
+#define PA_MAX_TRACE_RECORDS (2048) /**< Maximum number of records stored in trace buffer */
+#endif
#ifdef __cplusplus
extern "C"
diff --git a/pd/portaudio/src/common/pa_util.h b/pd/portaudio/src/common/pa_util.h
index 55eaa138..95ea6789 100644
--- a/pd/portaudio/src/common/pa_util.h
+++ b/pd/portaudio/src/common/pa_util.h
@@ -1,12 +1,12 @@
#ifndef PA_UTIL_H
#define PA_UTIL_H
/*
- * $Id: pa_util.h 1229 2007-06-15 16:11:11Z rossb $
+ * $Id: pa_util.h 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library implementation utilities header
* common implementation utilities and interfaces
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -44,6 +44,9 @@
@brief Prototypes for utility functions used by PortAudio implementations.
+ Some functions declared here are defined in pa_front.c while others
+ are implemented separately for each platform.
+
@todo Document and adhere to the alignment guarantees provided by
PaUtil_AllocateMemory().
*/
diff --git a/pd/portaudio/src/hostapi/alsa/pa_linux_alsa.c b/pd/portaudio/src/hostapi/alsa/pa_linux_alsa.c
index 06b17ac1..6b4a7b9f 100644
--- a/pd/portaudio/src/hostapi/alsa/pa_linux_alsa.c
+++ b/pd/portaudio/src/hostapi/alsa/pa_linux_alsa.c
@@ -1,11 +1,12 @@
/*
- * $Id: pa_linux_alsa.c 1236 2007-06-24 20:39:26Z aknudsen $
+ * $Id: pa_linux_alsa.c 1415 2009-06-03 18:57:56Z aknudsen $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* ALSA implementation by Joshua Haberman and Arve Knudsen
*
* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
- * Copyright (c) 2005-2006 Arve Knudsen <aknuds-1@broadpark.no>
+ * Copyright (c) 2005-2009 Arve Knudsen <arve.knudsen@gmail.com>
+ * Copyright (c) 2008 Kevin Kofler <kevin.kofler@chello.at>
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
@@ -62,6 +63,7 @@
#include <sys/mman.h>
#include <signal.h> /* For sig_atomic_t */
+#include "portaudio.h"
#include "pa_util.h"
#include "pa_unix_util.h"
#include "pa_allocation.h"
@@ -98,6 +100,7 @@
static int aErr_; /* Used with ENSURE_ */
static int numPeriods_ = 4;
+static int busyRetries_ = 100;
int PaAlsa_SetNumPeriods( int numPeriods )
{
@@ -117,6 +120,8 @@ typedef struct
unsigned long framesPerBuffer;
int numUserChannels, numHostChannels;
int userInterleaved, hostInterleaved;
+ int canMmap;
+ void *nonMmapBuffer;
PaDeviceIndex device; /* Keep the device index */
snd_pcm_t *pcm;
@@ -320,7 +325,7 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
* and a suitable result returned. The device is closed before returning.
*/
static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, int openBlocking,
- PaAlsaDeviceInfo* devInfo, int* canMmap )
+ PaAlsaDeviceInfo* devInfo )
{
PaError result = paNoError;
snd_pcm_hw_params_t *hwParams;
@@ -353,9 +358,6 @@ static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, in
snd_pcm_hw_params_alloca( &hwParams );
snd_pcm_hw_params_any( pcm, hwParams );
- *canMmap = snd_pcm_hw_params_test_access( pcm, hwParams, SND_PCM_ACCESS_MMAP_INTERLEAVED ) >= 0 ||
- snd_pcm_hw_params_test_access( pcm, hwParams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED ) >= 0;
-
if( defaultSr >= 0 )
{
/* Could be that the device opened in one mode supports samplerates that the other mode wont have,
@@ -538,7 +540,7 @@ static int IgnorePlugin( const char *pluginId )
**/
static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode, int waitOnBusy )
{
- int tries = 0, maxTries = waitOnBusy ? 100 : 0;
+ int tries = 0, maxTries = waitOnBusy ? busyRetries_ : 0;
int ret = snd_pcm_open( pcmp, name, stream, mode );
for( tries = 0; tries < maxTries && -EBUSY == ret; ++tries )
{
@@ -565,7 +567,6 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
PaError result = 0;
PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo;
snd_pcm_t *pcm;
- int canMmap = -1;
PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;
/* Zero fields */
@@ -579,8 +580,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE, blocking, 0 )
>= 0 )
{
- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, blocking, devInfo,
- &canMmap ) != paNoError )
+ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, blocking, devInfo ) != paNoError )
{
/* Error */
PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__, deviceName->alsaName));
@@ -593,8 +593,7 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK, blocking, 0 )
>= 0 )
{
- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, blocking, devInfo,
- &canMmap ) != paNoError )
+ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, blocking, devInfo ) != paNoError )
{
/* Error */
PA_DEBUG(("%s: Failed groping %s for playback\n", __FUNCTION__, deviceName->alsaName));
@@ -602,12 +601,6 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
}
}
- if( 0 == canMmap )
- {
- PA_DEBUG(("%s: Device %s doesn't support mmap\n", __FUNCTION__, deviceName->alsaName));
- goto end;
- }
-
baseDeviceInfo->structVersion = 2;
baseDeviceInfo->hostApi = alsaApi->hostApiIndex;
baseDeviceInfo->name = deviceName->name;
@@ -620,8 +613,12 @@ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* d
if( baseDeviceInfo->maxInputChannels > 0 || baseDeviceInfo->maxOutputChannels > 0 )
{
/* Make device default if there isn't already one or it is the ALSA "default" device */
- if( baseApi->info.defaultInputDevice == paNoDevice && baseDeviceInfo->maxInputChannels > 0 )
+ if( (baseApi->info.defaultInputDevice == paNoDevice || !strcmp(deviceName->alsaName,
+ "default" )) && baseDeviceInfo->maxInputChannels > 0 )
+ {
baseApi->info.defaultInputDevice = *devIdx;
+ PA_DEBUG(("Default input device: %s\n", deviceName->name));
+ }
if( (baseApi->info.defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName,
"default" )) && baseDeviceInfo->maxOutputChannels > 0 )
{
@@ -1192,6 +1189,8 @@ static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, Pa
self->hostInterleaved = self->userInterleaved = !(userSampleFormat & paNonInterleaved);
self->numUserChannels = params->channelCount;
self->streamDir = streamDir;
+ self->canMmap = 0;
+ self->nonMmapBuffer = NULL;
if( !callbackMode && !self->userInterleaved )
{
@@ -1234,6 +1233,7 @@ static PaError PaAlsaStreamComponent_InitialConfigure( PaAlsaStreamComponent *se
PaError result = paNoError;
snd_pcm_access_t accessMode, alternateAccessMode;
+ snd_pcm_access_t rwAccessMode, alternateRwAccessMode;
int dir = 0;
snd_pcm_t *pcm = self->pcm;
double sr = *sampleRate;
@@ -1253,32 +1253,40 @@ static PaError PaAlsaStreamComponent_InitialConfigure( PaAlsaStreamComponent *se
if( self->userInterleaved )
{
accessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ rwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED;
alternateAccessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ alternateRwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED;
}
else
{
accessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ rwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED;
alternateAccessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ alternateRwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED;
}
/* If requested access mode fails, try alternate mode */
+ self->canMmap = 1;
if( snd_pcm_hw_params_set_access( pcm, hwParams, accessMode ) < 0 )
{
- int err = 0;
- if( (err = snd_pcm_hw_params_set_access( pcm, hwParams, alternateAccessMode )) < 0)
+ if( snd_pcm_hw_params_set_access( pcm, hwParams, rwAccessMode ) >= 0 )
+ self->canMmap = 0;
+ else
{
- result = paUnanticipatedHostError;
- if( -EINVAL == err )
- {
- PaUtil_SetLastHostErrorInfo( paALSA, err, "PA ALSA requires that a device supports mmap access" );
- }
- else
+ if( snd_pcm_hw_params_set_access( pcm, hwParams, alternateAccessMode ) < 0 )
{
- PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror( err ) );
+ int err = 0;
+ if( (err = snd_pcm_hw_params_set_access( pcm, hwParams, alternateRwAccessMode )) >= 0)
+ self->canMmap = 0;
+ else
+ {
+ result = paUnanticipatedHostError;
+ PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror( err ) );
+ goto error;
+ }
}
- goto error;
+ /* Flip mode */
+ self->hostInterleaved = !self->userInterleaved;
}
- /* Flip mode */
- self->hostInterleaved = !self->userInterleaved;
}
ENSURE_( snd_pcm_hw_params_set_format( pcm, hwParams, self->nativeFormat ), paUnanticipatedHostError );
@@ -1356,7 +1364,10 @@ static PaError PaAlsaStreamComponent_FinishConfigure( PaAlsaStreamComponent *sel
ENSURE_( snd_pcm_sw_params_set_avail_min( self->pcm, swParams, self->framesPerBuffer ), paUnanticipatedHostError );
ENSURE_( snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ), paUnanticipatedHostError );
- ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_MMAP ), paUnanticipatedHostError );
+#ifndef SND_PCM_TSTAMP_ENABLE /* old versions of ALSA called this something different */
+#define SND_PCM_TSTAMP_ENABLE SND_PCM_TSTAMP_MMAP
+#endif
+ ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
/* Set the parameters! */
ENSURE_( snd_pcm_sw_params( self->pcm, swParams ), paUnanticipatedHostError );
@@ -1584,6 +1595,10 @@ static PaError PaAlsaStreamComponent_DetermineFramesPerBuffer( PaAlsaStreamCompo
}
}
+ /* non-mmap mode needs a reasonably-sized buffer or it'll stutter */
+ if( !self->canMmap && framesPerHostBuffer < 2048 )
+ framesPerHostBuffer = 2048;
+
assert( framesPerHostBuffer > 0 );
{
snd_pcm_uframes_t min = 0, max = 0;
@@ -1725,12 +1740,15 @@ static PaError PaAlsaStream_DetermineFramesPerBuffer( PaAlsaStream* self, double
while( optimalPeriodSize >= periodSize )
{
- if( snd_pcm_hw_params_test_period_size( self->capture.pcm, hwParamsCapture, optimalPeriodSize, 0 ) < 0 )
- continue;
- if( snd_pcm_hw_params_test_period_size( self->playback.pcm, hwParamsPlayback, optimalPeriodSize, 0 ) >= 0 )
+ if( snd_pcm_hw_params_test_period_size( self->capture.pcm, hwParamsCapture, optimalPeriodSize, 0 )
+ >= 0 && snd_pcm_hw_params_test_period_size( self->playback.pcm, hwParamsPlayback,
+ optimalPeriodSize, 0 ) >= 0 )
+ {
break;
+ }
optimalPeriodSize /= 2;
}
+
if( optimalPeriodSize > periodSize )
periodSize = optimalPeriodSize;
@@ -1823,12 +1841,13 @@ static PaError PaAlsaStream_DetermineFramesPerBuffer( PaAlsaStream* self, double
PA_UNLESS( framesPerHostBuffer != 0, paInternalError );
self->maxFramesPerHostBuffer = framesPerHostBuffer;
- if( !accurate )
+ if( !self->playback.canMmap || !accurate )
{
/* Don't know the exact size per host buffer */
*hostBufferSizeMode = paUtilBoundedHostBufferSize;
/* Raise upper bound */
- ++self->maxFramesPerHostBuffer;
+ if( !accurate )
+ ++self->maxFramesPerHostBuffer;
}
error:
@@ -1987,11 +2006,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* Ok, buffer processor is initialized, now we can deduce it's latency */
if( numInputChannels > 0 )
- stream->streamRepresentation.streamInfo.inputLatency = inputLatency + PaUtil_GetBufferProcessorInputLatency(
- &stream->bufferProcessor );
+ stream->streamRepresentation.streamInfo.inputLatency = inputLatency + (PaTime)(
+ PaUtil_GetBufferProcessorInputLatency( &stream->bufferProcessor ) / sampleRate);
if( numOutputChannels > 0 )
- stream->streamRepresentation.streamInfo.outputLatency = outputLatency + PaUtil_GetBufferProcessorOutputLatency(
- &stream->bufferProcessor );
+ stream->streamRepresentation.streamInfo.outputLatency = outputLatency + (PaTime)(
+ PaUtil_GetBufferProcessorOutputLatency( &stream->bufferProcessor ) / sampleRate);
*s = (PaStream*)stream;
@@ -2051,9 +2070,11 @@ static PaError AlsaStart( PaAlsaStream *stream, int priming )
{
/* Buffer isn't primed, so prepare and silence */
ENSURE_( snd_pcm_prepare( stream->playback.pcm ), paUnanticipatedHostError );
- SilenceBuffer( stream );
+ if( stream->playback.canMmap )
+ SilenceBuffer( stream );
}
- ENSURE_( snd_pcm_start( stream->playback.pcm ), paUnanticipatedHostError );
+ if( stream->playback.canMmap )
+ ENSURE_( snd_pcm_start( stream->playback.pcm ), paUnanticipatedHostError );
}
else
ENSURE_( snd_pcm_prepare( stream->playback.pcm ), paUnanticipatedHostError );
@@ -2151,7 +2172,9 @@ error:
static PaError AlsaStop( PaAlsaStream *stream, int abort )
{
PaError result = paNoError;
- /* XXX: Seems that draining the dmix device may trigger a race condition in ALSA */
+ /* XXX: snd_pcm_drain tends to lock up, avoid it until we find out more */
+ abort = 1;
+ /*
if( stream->capture.pcm && !strcmp( Pa_GetDeviceInfo( stream->capture.device )->name,
"dmix" ) )
{
@@ -2162,6 +2185,7 @@ static PaError AlsaStop( PaAlsaStream *stream, int abort )
{
abort = 1;
}
+ */
if( abort )
{
@@ -2379,6 +2403,7 @@ static PaError PaAlsaStream_HandleXrun( PaAlsaStream *self )
snd_pcm_status_t *st;
PaTime now = PaUtil_GetTime();
snd_timestamp_t t;
+ int errplayback = 0, errcapture = 0;
snd_pcm_status_alloca( &st );
@@ -2389,6 +2414,7 @@ static PaError PaAlsaStream_HandleXrun( PaAlsaStream *self )
{
snd_pcm_status_get_trigger_tstamp( st, &t );
self->underrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime) t.tv_usec / 1000);
+ errplayback = snd_pcm_recover( self->playback.pcm, -EPIPE, 0 );
}
}
if( self->capture.pcm )
@@ -2398,10 +2424,12 @@ static PaError PaAlsaStream_HandleXrun( PaAlsaStream *self )
{
snd_pcm_status_get_trigger_tstamp( st, &t );
self->overrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime) t.tv_usec / 1000);
+ errcapture = snd_pcm_recover( self->capture.pcm, -EPIPE, 0 );
}
}
- PA_ENSURE( AlsaRestart( self ) );
+ if( errplayback || errcapture )
+ PA_ENSURE( AlsaRestart( self ) );
end:
return result;
@@ -2552,7 +2580,7 @@ static void CalculateTimeInfo( PaAlsaStream *stream, PaStreamCallbackTimeInfo *t
static PaError PaAlsaStreamComponent_EndProcessing( PaAlsaStreamComponent *self, unsigned long numFrames, int *xrun )
{
PaError result = paNoError;
- int res;
+ int res = 0;
/* @concern FullDuplex It is possible that only one direction is marked ready after polling, and processed
* afterwards
@@ -2560,7 +2588,34 @@ static PaError PaAlsaStreamComponent_EndProcessing( PaAlsaStreamComponent *self,
if( !self->ready )
goto end;
- res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames );
+ if( !self->canMmap && StreamDirection_Out == self->streamDir )
+ {
+ /* Play sound */
+ if( self->hostInterleaved )
+ res = snd_pcm_writei( self->pcm, self->nonMmapBuffer, numFrames );
+ else
+ {
+ void *bufs[self->numHostChannels];
+ int bufsize = snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 );
+ unsigned char *buffer = self->nonMmapBuffer;
+ int i;
+ for( i = 0; i < self->numHostChannels; ++i )
+ {
+ bufs[i] = buffer;
+ buffer += bufsize;
+ }
+ res = snd_pcm_writen( self->pcm, bufs, numFrames );
+ }
+ }
+
+ if( self->canMmap )
+ res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames );
+ else
+ {
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = NULL;
+ }
+
if( res == -EPIPE || res == -ESTRPIPE )
{
*xrun = 1;
@@ -2600,7 +2655,7 @@ static PaError PaAlsaStreamComponent_DoChannelAdaption( PaAlsaStreamComponent *s
if( self->hostInterleaved )
{
int swidth = snd_pcm_format_size( self->nativeFormat, 1 );
- unsigned char *buffer = ExtractAddress( self->channelAreas, self->offset );
+ unsigned char *buffer = self->canMmap ? ExtractAddress( self->channelAreas, self->offset ) : self->nonMmapBuffer;
/* Start after the last user channel */
p = buffer + self->numUserChannels * swidth;
@@ -2980,13 +3035,23 @@ static PaError PaAlsaStreamComponent_RegisterChannels( PaAlsaStreamComponent* se
goto end;
}
- ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset, numFrames ), paUnanticipatedHostError );
+ if( self->canMmap )
+ {
+ ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset, numFrames ), paUnanticipatedHostError );
+ /* @concern ChannelAdaption Buffer address is recorded so we can do some channel adaption later */
+ self->channelAreas = (snd_pcm_channel_area_t *)areas;
+ }
+ else
+ {
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = calloc( self->numHostChannels, snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ) );
+ }
if( self->hostInterleaved )
{
int swidth = snd_pcm_format_size( self->nativeFormat, 1 );
- p = buffer = ExtractAddress( areas, self->offset );
+ p = buffer = self->canMmap ? ExtractAddress( areas, self->offset ) : self->nonMmapBuffer;
for( i = 0; i < self->numUserChannels; ++i )
{
/* We're setting the channels up to userChannels, but the stride will be hostChannels samples */
@@ -2996,16 +3061,52 @@ static PaError PaAlsaStreamComponent_RegisterChannels( PaAlsaStreamComponent* se
}
else
{
- for( i = 0; i < self->numUserChannels; ++i )
+ if( self->canMmap )
+ for( i = 0; i < self->numUserChannels; ++i )
+ {
+ area = areas + i;
+ buffer = ExtractAddress( area, self->offset );
+ setChannel( bp, i, buffer, 1 );
+ }
+ else
{
- area = areas + i;
- buffer = ExtractAddress( area, self->offset );
- setChannel( bp, i, buffer, 1 );
+ int bufsize = snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 );
+ buffer = self->nonMmapBuffer;
+ for( i = 0; i < self->numUserChannels; ++i )
+ {
+ setChannel( bp, i, buffer, 1 );
+ buffer += bufsize;
+ }
}
}
- /* @concern ChannelAdaption Buffer address is recorded so we can do some channel adaption later */
- self->channelAreas = (snd_pcm_channel_area_t *)areas;
+ if( !self->canMmap && StreamDirection_In == self->streamDir )
+ {
+ /* Read sound */
+ int res;
+ if( self->hostInterleaved )
+ res = snd_pcm_readi( self->pcm, self->nonMmapBuffer, *numFrames );
+ else
+ {
+ void *bufs[self->numHostChannels];
+ int bufsize = snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 );
+ unsigned char *buffer = self->nonMmapBuffer;
+ int i;
+ for( i = 0; i < self->numHostChannels; ++i )
+ {
+ bufs[i] = buffer;
+ buffer += bufsize;
+ }
+ res = snd_pcm_readn( self->pcm, bufs, *numFrames );
+ }
+ if( res == -EPIPE || res == -ESTRPIPE )
+ {
+ *xrun = 1;
+ *numFrames = 0;
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = NULL;
+ }
+ }
end:
error:
@@ -3519,10 +3620,31 @@ void PaAlsa_EnableWatchdog( PaStream *s, int enable )
}
#endif
+static PaError GetAlsaStreamPointer( PaStream* s, PaAlsaStream** stream )
+{
+ PaError result = paNoError;
+ PaUtilHostApiRepresentation* hostApi;
+ PaAlsaHostApiRepresentation* alsaHostApi;
+
+ PA_ENSURE( PaUtil_ValidateStreamPointer( s ) );
+ PA_ENSURE( PaUtil_GetHostApiRepresentation( &hostApi, paALSA ) );
+ alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
+
+ PA_UNLESS( PA_STREAM_REP( s )->streamInterface == &alsaHostApi->callbackStreamInterface
+ || PA_STREAM_REP( s )->streamInterface == &alsaHostApi->blockingStreamInterface,
+ paIncompatibleStreamHostApi );
+
+ *stream = (PaAlsaStream*)s;
+error:
+ return paNoError;
+}
+
PaError PaAlsa_GetStreamInputCard(PaStream* s, int* card) {
- PaAlsaStream *stream = (PaAlsaStream *) s;
- snd_pcm_info_t* pcmInfo;
+ PaAlsaStream *stream;
PaError result = paNoError;
+ snd_pcm_info_t* pcmInfo;
+
+ PA_ENSURE( GetAlsaStreamPointer( s, &stream ) );
/* XXX: More descriptive error? */
PA_UNLESS( stream->capture.pcm, paDeviceUnavailable );
@@ -3536,9 +3658,11 @@ error:
}
PaError PaAlsa_GetStreamOutputCard(PaStream* s, int* card) {
- PaAlsaStream *stream = (PaAlsaStream *) s;
- snd_pcm_info_t* pcmInfo;
+ PaAlsaStream *stream;
PaError result = paNoError;
+ snd_pcm_info_t* pcmInfo;
+
+ PA_ENSURE( GetAlsaStreamPointer( s, &stream ) );
/* XXX: More descriptive error? */
PA_UNLESS( stream->playback.pcm, paDeviceUnavailable );
@@ -3550,3 +3674,9 @@ PaError PaAlsa_GetStreamOutputCard(PaStream* s, int* card) {
error:
return result;
}
+
+PaError PaAlsa_SetRetriesBusy( int retries )
+{
+ busyRetries_ = retries;
+ return paNoError;
+}
diff --git a/pd/portaudio/src/hostapi/asio/pa_asio.cpp b/pd/portaudio/src/hostapi/asio/pa_asio.cpp
index 4b3fb68e..84d1c511 100644
--- a/pd/portaudio/src/hostapi/asio/pa_asio.cpp
+++ b/pd/portaudio/src/hostapi/asio/pa_asio.cpp
@@ -1,10 +1,12 @@
/*
- * $Id: pa_asio.cpp 1230 2007-06-15 16:16:33Z rossb $
+ * $Id: pa_asio.cpp 1416 2009-06-16 16:12:41Z rossb $
* Portable Audio I/O Library for ASIO Drivers
*
* Author: Stephane Letz
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 2000-2002 Stephane Letz, Phil Burk, Ross Bencina
+ * Blocking i/o implementation by Sven Fischer, Institute of Hearing
+ * Technology and Audiology (www.hoertechnik-audiologie.de)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -71,18 +73,18 @@
*/
/** @file
- @ingroup hostapi_src
+ @ingroup hostapi_src
Note that specific support for paInputUnderflow, paOutputOverflow and
paNeverDropInput is not necessary or possible with this driver due to the
synchronous full duplex double-buffered architecture of ASIO.
- @todo check that CoInitialize()/CoUninitialize() are always correctly
- paired, even in error cases.
-
@todo implement host api specific extension to set i/o buffer sizes in frames
- @todo implement ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable
+ @todo review ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable
+
+ @todo review Blocking i/o latency computations in OpenStream(), changing ring
+ buffer to a non-power-of-two structure could reduce blocking i/o latency.
@todo implement IsFormatSupported
@@ -120,6 +122,7 @@
#include <assert.h>
#include <string.h>
//#include <values.h>
+#include <new>
#include <windows.h>
#include <mmsystem.h>
@@ -133,6 +136,7 @@
#include "pa_cpuload.h"
#include "pa_process.h"
#include "pa_debugprint.h"
+#include "pa_ringbuffer.h"
/* This version of pa_asio.cpp is currently only targetted at Win32,
It would require a few tweaks to work with pre-OS X Macintosh.
@@ -164,16 +168,24 @@
#endif
*/
-/* external references */
-extern AsioDrivers* asioDrivers ;
-bool loadAsioDriver(char *name);
+/* external reference to ASIO SDK's asioDrivers.
-/* We are trying to be compatible with CARBON but this has not been thoroughly tested. */
-/* not tested at all since new code was introduced. */
-#define CARBON_COMPATIBLE (0)
+ This is a bit messy because we want to explicitly manage
+ allocation/deallocation of this structure, but some layers of the SDK
+ which we currently use (eg the implementation in asio.cpp) still
+ use this global version.
+
+ For now we keep it in sync with our local instance in the host
+ API representation structure, but later we should be able to remove
+ all dependence on it.
+*/
+extern AsioDrivers* asioDrivers;
+/* We are trying to be compatible with CARBON but this has not been thoroughly tested. */
+/* not tested at all since new V19 code was introduced. */
+#define CARBON_COMPATIBLE (0)
/* prototypes for functions declared in this file */
@@ -206,6 +218,14 @@ static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long
static signed long GetStreamReadAvailable( PaStream* stream );
static signed long GetStreamWriteAvailable( PaStream* stream );
+/* Blocking i/o callback function. */
+static int BlockingIoPaCallback(const void *inputBuffer ,
+ void *outputBuffer ,
+ unsigned long framesPerBuffer,
+ const PaStreamCallbackTimeInfo *timeInfo ,
+ PaStreamCallbackFlags statusFlags ,
+ void *userData );
+
/* our ASIO callback functions */
static void bufferSwitch(long index, ASIOBool processNow);
@@ -270,12 +290,12 @@ static const char* PaAsio_GetAsioErrorText( ASIOError asioError )
// Atomic increment and decrement operations
#if MAC
- /* need to be implemented on Mac */
- inline long PaAsio_AtomicIncrement(volatile long* v) {return ++(*const_cast<long*>(v));}
- inline long PaAsio_AtomicDecrement(volatile long* v) {return --(*const_cast<long*>(v));}
+ /* need to be implemented on Mac */
+ inline long PaAsio_AtomicIncrement(volatile long* v) {return ++(*const_cast<long*>(v));}
+ inline long PaAsio_AtomicDecrement(volatile long* v) {return --(*const_cast<long*>(v));}
#elif WINDOWS
- inline long PaAsio_AtomicIncrement(volatile long* v) {return InterlockedIncrement(const_cast<long*>(v));}
- inline long PaAsio_AtomicDecrement(volatile long* v) {return InterlockedDecrement(const_cast<long*>(v));}
+ inline long PaAsio_AtomicIncrement(volatile long* v) {return InterlockedIncrement(const_cast<long*>(v));}
+ inline long PaAsio_AtomicDecrement(volatile long* v) {return InterlockedDecrement(const_cast<long*>(v));}
#endif
@@ -300,6 +320,7 @@ typedef struct
PaUtilAllocationGroup *allocations;
+ AsioDrivers *asioDrivers;
void *systemSpecific;
/* the ASIO C API only allows one ASIO driver to be open at a time,
@@ -323,7 +344,7 @@ PaAsioHostApiRepresentation;
Retrieve <driverCount> driver names from ASIO, returned in a char**
allocated in <group>.
*/
-static char **GetAsioDriverNames( PaUtilAllocationGroup *group, long driverCount )
+static char **GetAsioDriverNames( PaAsioHostApiRepresentation *asioHostApi, PaUtilAllocationGroup *group, long driverCount )
{
char **result = 0;
int i;
@@ -341,7 +362,7 @@ static char **GetAsioDriverNames( PaUtilAllocationGroup *group, long driverCount
for( i=0; i<driverCount; ++i )
result[i] = result[0] + (32 * i);
- asioDrivers->getDriverNames( result, driverCount );
+ asioHostApi->asioDrivers->getDriverNames( result, driverCount );
error:
return result;
@@ -917,7 +938,7 @@ PaAsioDeviceInfo;
PaError PaAsio_GetAvailableLatencyValues( PaDeviceIndex device,
- long *minLatency, long *maxLatency, long *preferredLatency, long *granularity )
+ long *minLatency, long *maxLatency, long *preferredLatency, long *granularity )
{
PaError result;
PaUtilHostApiRepresentation *hostApi;
@@ -944,23 +965,45 @@ PaError PaAsio_GetAvailableLatencyValues( PaDeviceIndex device,
return result;
}
-
+/* Unload whatever we loaded in LoadAsioDriver().
+ Also balance the call to CoInitialize(0).
+*/
+static void UnloadAsioDriver( void )
+{
+ ASIOExit();
+ CoUninitialize();
+}
/*
load the asio driver named by <driverName> and return statistics about
the driver in info. If no error occurred, the driver will remain open
- and must be closed by the called by calling ASIOExit() - if an error
- is returned the driver will already be closed.
+ and must be closed by the called by calling UnloadAsioDriver() - if an error
+ is returned the driver will already be unloaded.
*/
-static PaError LoadAsioDriver( const char *driverName,
+static PaError LoadAsioDriver( PaAsioHostApiRepresentation *asioHostApi, const char *driverName,
PaAsioDriverInfo *driverInfo, void *systemSpecific )
{
PaError result = paNoError;
ASIOError asioError;
int asioIsInitialized = 0;
- if( !loadAsioDriver( const_cast<char*>(driverName) ) )
+ /*
+ ASIO uses CoCreateInstance() to load a driver. That requires that
+ CoInitialize(0) be called for every thread that loads a driver.
+ It is OK to call CoInitialize(0) multiple times form one thread as long
+ as it is balanced by a call to CoUninitialize(). See UnloadAsioDriver().
+
+ The V18 version called CoInitialize() starting on 2/19/02.
+ That was removed from PA V19 for unknown reasons.
+ Phil Burk added it back on 6/27/08 so that JSyn would work.
+ */
+ CoInitialize( 0 );
+
+ if( !asioHostApi->asioDrivers->loadDriver( const_cast<char*>(driverName) ) )
{
+ /* If this returns an error then it might be because CoInitialize(0) was removed.
+ It should be called right before this.
+ */
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_HOST_ERROR( 0, "Failed to load ASIO driver" );
goto error;
@@ -1006,8 +1049,10 @@ static PaError LoadAsioDriver( const char *driverName,
error:
if( asioIsInitialized )
- ASIOExit();
-
+ {
+ ASIOExit();
+ }
+ CoUninitialize();
return result;
}
@@ -1039,6 +1084,8 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
goto error;
}
+ asioHostApi->asioDrivers = 0; /* avoid surprises in our error handler below */
+
asioHostApi->allocations = PaUtil_CreateAllocationGroup();
if( !asioHostApi->allocations )
{
@@ -1046,6 +1093,25 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
goto error;
}
+ /* Allocate the AsioDrivers() driver list (class from ASIO SDK) */
+ try
+ {
+ asioHostApi->asioDrivers = new AsioDrivers(); /* calls CoInitialize(0) */
+ }
+ catch (std::bad_alloc)
+ {
+ asioHostApi->asioDrivers = 0;
+ }
+ /* some implementations of new (ie MSVC, see http://support.microsoft.com/?kbid=167733)
+ don't throw std::bad_alloc, so we also explicitly test for a null return. */
+ if( asioHostApi->asioDrivers == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ asioDrivers = asioHostApi->asioDrivers; /* keep SDK global in sync until we stop depending on it */
+
asioHostApi->systemSpecific = 0;
asioHostApi->openAsioDeviceIndex = paNoDevice;
@@ -1059,23 +1125,19 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
#ifdef WINDOWS
/* use desktop window as system specific ptr */
asioHostApi->systemSpecific = GetDesktopWindow();
- CoInitialize(NULL);
#endif
- /* MUST BE CHECKED : to force fragments loading on Mac */
- loadAsioDriver( "dummy" );
-
/* driverCount is the number of installed drivers - not necessarily
the number of installed physical devices. */
#if MAC
- driverCount = asioDrivers->getNumFragments();
+ driverCount = asioHostApi->asioDrivers->getNumFragments();
#elif WINDOWS
- driverCount = asioDrivers->asioGetNumDev();
+ driverCount = asioHostApi->asioDrivers->asioGetNumDev();
#endif
if( driverCount > 0 )
{
- names = GetAsioDriverNames( asioHostApi->allocations, driverCount );
+ names = GetAsioDriverNames( asioHostApi, asioHostApi->allocations, driverCount );
if( !names )
{
result = paInsufficientMemory;
@@ -1102,7 +1164,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
goto error;
}
- IsDebuggerPresent_ = GetProcAddress( LoadLibrary( "Kernel32.dll" ), "IsDebuggerPresent" );
+ IsDebuggerPresent_ = GetProcAddress( LoadLibrary( "Kernel32.dll" ), "IsDebuggerPresent" );
for( i=0; i < driverCount; ++i )
{
@@ -1120,7 +1182,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
|| strcmp (names[i],"ASIO Multimedia Driver") == 0
|| strncmp(names[i],"Premiere",8) == 0 //"Premiere Elements Windows Sound 1.0"
|| strncmp(names[i],"Adobe",5) == 0 //"Adobe Default Windows Sound 1.5"
- || strncmp(names[i],"ReaRoute ASIO",13) == 0 //Reaper www.reaper.fm <- fix your stuff man.
)
{
PA_DEBUG(("BLACKLISTED!!!\n"));
@@ -1141,7 +1202,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
/* Attempt to load the asio driver... */
- if( LoadAsioDriver( names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError )
+ if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError )
{
PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo;
@@ -1233,7 +1294,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
if( !asioDeviceInfo->asioChannelInfos )
{
result = paInsufficientMemory;
- goto error;
+ goto error_unload;
}
int a;
@@ -1246,7 +1307,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
- goto error;
+ goto error_unload;
}
}
@@ -1259,13 +1320,13 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
- goto error;
+ goto error_unload;
}
}
/* unload the driver */
- ASIOExit();
+ UnloadAsioDriver();
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
++(*hostApi)->info.deviceCount;
@@ -1302,6 +1363,9 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
return result;
+error_unload:
+ UnloadAsioDriver();
+
error:
if( asioHostApi )
{
@@ -1311,6 +1375,9 @@ error:
PaUtil_DestroyAllocationGroup( asioHostApi->allocations );
}
+ delete asioHostApi->asioDrivers;
+ asioDrivers = 0; /* keep SDK global in sync until we stop depending on it */
+
PaUtil_FreeMemory( asioHostApi );
}
return result;
@@ -1323,7 +1390,7 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
/*
IMPLEMENT ME:
- - clean up any resources not handled by the allocation group
+ - clean up any resources not handled by the allocation group (need to review if there are any)
*/
if( asioHostApi->allocations )
@@ -1332,6 +1399,9 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
PaUtil_DestroyAllocationGroup( asioHostApi->allocations );
}
+ delete asioHostApi->asioDrivers; /* calls CoUninitialize() */
+ asioDrivers = 0; /* keep SDK global in sync until we stop depending on it */
+
PaUtil_FreeMemory( asioHostApi );
}
@@ -1418,7 +1488,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
/* if an ASIO device is open we can only get format information for the currently open device */
if( asioHostApi->openAsioDeviceIndex != paNoDevice
- && asioHostApi->openAsioDeviceIndex != asioDeviceIndex )
+ && asioHostApi->openAsioDeviceIndex != asioDeviceIndex )
{
return paDeviceUnavailable;
}
@@ -1430,7 +1500,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
/* open the device if it's not already open */
if( asioHostApi->openAsioDeviceIndex == paNoDevice )
{
- result = LoadAsioDriver( asioHostApi->inheritedHostApiRep.deviceInfos[ asioDeviceIndex ]->name,
+ result = LoadAsioDriver( asioHostApi, asioHostApi->inheritedHostApiRep.deviceInfos[ asioDeviceIndex ]->name,
driverInfo, asioHostApi->systemSpecific );
if( result != paNoError )
return result;
@@ -1468,7 +1538,7 @@ done:
/* close the device if it wasn't already open */
if( asioHostApi->openAsioDeviceIndex == paNoDevice )
{
- ASIOExit(); /* not sure if we should check for errors here */
+ UnloadAsioDriver(); /* not sure if we should check for errors here */
}
if( result == paNoError )
@@ -1479,6 +1549,40 @@ done:
+/** A data structure specifically for storing blocking i/o related data. */
+typedef struct PaAsioStreamBlockingState
+{
+ int stopFlag; /**< Flag indicating that block processing is to be stopped. */
+
+ unsigned long writeBuffersRequested; /**< The number of available output buffers, requested by the #WriteStream() function. */
+ unsigned long readFramesRequested; /**< The number of available input frames, requested by the #ReadStream() function. */
+
+ int writeBuffersRequestedFlag; /**< Flag to indicate that #WriteStream() has requested more output buffers to be available. */
+ int readFramesRequestedFlag; /**< Flag to indicate that #ReadStream() requires more input frames to be available. */
+
+ HANDLE writeBuffersReadyEvent; /**< Event to signal that requested output buffers are available. */
+ HANDLE readFramesReadyEvent; /**< Event to signal that requested input frames are available. */
+
+ void *writeRingBufferData; /**< The actual ring buffer memory, used by the output ring buffer. */
+ void *readRingBufferData; /**< The actual ring buffer memory, used by the input ring buffer. */
+
+ PaUtilRingBuffer writeRingBuffer; /**< Frame-aligned blocking i/o ring buffer to store output data (interleaved user format). */
+ PaUtilRingBuffer readRingBuffer; /**< Frame-aligned blocking i/o ring buffer to store input data (interleaved user format). */
+
+ long writeRingBufferInitialFrames; /**< The initial number of silent frames within the output ring buffer. */
+
+ const void **writeStreamBuffer; /**< Temp buffer, used by #WriteStream() for handling non-interleaved data. */
+ void **readStreamBuffer; /**< Temp buffer, used by #ReadStream() for handling non-interleaved data. */
+
+ PaUtilBufferProcessor bufferProcessor; /**< Buffer processor, used to handle the blocking i/o ring buffers. */
+
+ int outputUnderflowFlag; /**< Flag to signal an output underflow from within the callback function. */
+ int inputOverflowFlag; /**< Flag to signal an input overflow from within the callback function. */
+}
+PaAsioStreamBlockingState;
+
+
+
/* PaAsioStream - a stream data structure specifically for this implementation */
typedef struct PaAsioStream
@@ -1515,6 +1619,7 @@ typedef struct PaAsioStream
HANDLE completedBuffersPlayedEvent;
bool streamFinishedCallbackCalled;
+ int isStopped;
volatile int isActive;
volatile bool zeroOutput; /* all future calls to the callback will output silence */
@@ -1522,6 +1627,8 @@ typedef struct PaAsioStream
volatile long reenterError;
PaStreamCallbackFlags callbackFlags;
+
+ PaAsioStreamBlockingState *blockingState; /**< Blocking i/o data struct, or NULL when using callback interface. */
}
PaAsioStream;
@@ -1621,15 +1728,15 @@ static PaError ValidateAsioSpecificStreamInfo(
int deviceChannelCount,
int **channelSelectors )
{
- if( streamInfo )
- {
- if( streamInfo->size != sizeof( PaAsioStreamInfo )
- || streamInfo->version != 1 )
- {
- return paIncompatibleHostApiSpecificStreamInfo;
- }
+ if( streamInfo )
+ {
+ if( streamInfo->size != sizeof( PaAsioStreamInfo )
+ || streamInfo->version != 1 )
+ {
+ return paIncompatibleHostApiSpecificStreamInfo;
+ }
- if( streamInfo->flags & paAsioUseChannelSelectors )
+ if( streamInfo->flags & paAsioUseChannelSelectors )
*channelSelectors = streamInfo->channelSelectors;
if( !(*channelSelectors) )
@@ -1641,9 +1748,101 @@ static PaError ValidateAsioSpecificStreamInfo(
return paInvalidChannelCount;
}
}
- }
+ }
+
+ return paNoError;
+}
+
+
+static bool IsUsingExternalClockSource()
+{
+ bool result = false;
+ ASIOError asioError;
+ ASIOClockSource clocks[32];
+ long numSources=32;
- return paNoError;
+ /* davidv: listing ASIO Clock sources. there is an ongoing investigation by
+ me about whether or not to call ASIOSetSampleRate if an external Clock is
+ used. A few drivers expected different things here */
+
+ asioError = ASIOGetClockSources(clocks, &numSources);
+ if( asioError != ASE_OK ){
+ PA_DEBUG(("ERROR: ASIOGetClockSources: %s\n", PaAsio_GetAsioErrorText(asioError) ));
+ }else{
+ PA_DEBUG(("INFO ASIOGetClockSources listing %d clocks\n", numSources ));
+ for (int i=0;i<numSources;++i){
+ PA_DEBUG(("ASIOClockSource%d %s current:%d\n", i, clocks[i].name, clocks[i].isCurrentSource ));
+
+ if (clocks[i].isCurrentSource)
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+
+static PaError ValidateAndSetSampleRate( double sampleRate )
+{
+ PaError result = paNoError;
+ ASIOError asioError;
+
+ // check that the device supports the requested sample rate
+
+ asioError = ASIOCanSampleRate( sampleRate );
+ PA_DEBUG(("ASIOCanSampleRate(%f):%d\n", sampleRate, asioError ));
+
+ if( asioError != ASE_OK )
+ {
+ result = paInvalidSampleRate;
+ PA_DEBUG(("ERROR: ASIOCanSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) ));
+ goto error;
+ }
+
+ // retrieve the current sample rate, we only change to the requested
+ // sample rate if the device is not already in that rate.
+
+ ASIOSampleRate oldRate;
+ asioError = ASIOGetSampleRate(&oldRate);
+ if( asioError != ASE_OK )
+ {
+ result = paInvalidSampleRate;
+ PA_DEBUG(("ERROR: ASIOGetSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) ));
+ goto error;
+ }
+ PA_DEBUG(("ASIOGetSampleRate:%f\n",oldRate));
+
+ if (oldRate != sampleRate){
+ /* Set sample rate */
+
+ PA_DEBUG(("before ASIOSetSampleRate(%f)\n",sampleRate));
+
+ /*
+ If you have problems with some drivers when externally clocked,
+ try switching on the following line and commenting out the one after it.
+ See IsUsingExternalClockSource() for more info.
+ */
+ //if( IsUsingExternalClockSource() ){
+ if( false ){
+ asioError = ASIOSetSampleRate( 0 );
+ }else{
+ asioError = ASIOSetSampleRate( sampleRate );
+ }
+ if( asioError != ASE_OK )
+ {
+ result = paInvalidSampleRate;
+ PA_DEBUG(("ERROR: ASIOSetSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) ));
+ goto error;
+ }
+ PA_DEBUG(("after ASIOSetSampleRate(%f)\n",sampleRate));
+ }
+ else
+ {
+ PA_DEBUG(("No Need to change SR\n"));
+ }
+
+error:
+ return result;
}
@@ -1678,23 +1877,38 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
PaAsioDriverInfo *driverInfo;
int *inputChannelSelectors = 0;
int *outputChannelSelectors = 0;
- bool isExternal = false;
+
+ /* Are we using blocking i/o interface? */
+ int usingBlockingIo = ( !streamCallback ) ? TRUE : FALSE;
+ /* Blocking i/o stuff */
+ long lBlockingBufferSize = 0; /* Desired ring buffer size in samples. */
+ long lBlockingBufferSizePow2 = 0; /* Power-of-2 rounded ring buffer size. */
+ long lBytesPerFrame = 0; /* Number of bytes per input/output frame. */
+ int blockingWriteBuffersReadyEventInitialized = 0; /* Event init flag. */
+ int blockingReadFramesReadyEventInitialized = 0; /* Event init flag. */
+
+ int callbackBufferProcessorInited = FALSE;
+ int blockingBufferProcessorInited = FALSE;
/* unless we move to using lower level ASIO calls, we can only have
one device open at a time */
- if( asioHostApi->openAsioDeviceIndex != paNoDevice ){
+ if( asioHostApi->openAsioDeviceIndex != paNoDevice )
+ {
PA_DEBUG(("OpenStream paDeviceUnavailable\n"));
return paDeviceUnavailable;
}
+ assert( theAsioStream == 0 );
+
if( inputParameters && outputParameters )
{
/* full duplex ASIO stream must use the same device for input and output */
- if( inputParameters->device != outputParameters->device ){
+ if( inputParameters->device != outputParameters->device )
+ {
PA_DEBUG(("OpenStream paBadIODeviceCombination\n"));
return paBadIODeviceCombination;
- }
+ }
}
if( inputParameters )
@@ -1762,12 +1976,12 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* NOTE: we load the driver and use its current settings
rather than the ones in our device info structure which may be stale */
- result = LoadAsioDriver( asioHostApi->inheritedHostApiRep.deviceInfos[ asioDeviceIndex ]->name,
+ result = LoadAsioDriver( asioHostApi, asioHostApi->inheritedHostApiRep.deviceInfos[ asioDeviceIndex ]->name,
driverInfo, asioHostApi->systemSpecific );
if( result == paNoError )
asioIsInitialized = 1;
else{
- PA_DEBUG(("OpenStream ERROR1\n"));
+ PA_DEBUG(("OpenStream ERROR1 - LoadAsioDriver returned %d\n", result));
goto error;
}
@@ -1793,76 +2007,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
}
-
- /* davidv: listing ASIO Clock sources, there is an ongoing investigation by
- me about whether or not call ASIOSetSampleRate if an external Clock is
- used. A few drivers expected different things here */
- {
- ASIOClockSource clocks[32];
- long numSources=32;
- asioError = ASIOGetClockSources(clocks, &numSources);
- if( asioError != ASE_OK ){
- PA_DEBUG(("ERROR: ASIOGetClockSources: %s\n", PaAsio_GetAsioErrorText(asioError) ));
- }else{
- PA_DEBUG(("INFO ASIOGetClockSources listing %d clocks\n", numSources ));
- for (int i=0;i<numSources;++i){
- PA_DEBUG(("ASIOClockSource%d %s current:%d\n", i,clocks[i].name, clocks[i].isCurrentSource ));
-
- /*
- If you have problems with some drivers when externally clocked,
- uncomment the next two lines
- */
- //if (clocks[i].isCurrentSource)
- // isExternal = true;
- }
- }
- }
-
- // check that the device supports the requested sample rate
-
- asioError = ASIOCanSampleRate( sampleRate );
- PA_DEBUG(("ASIOCanSampleRate(%f):%d\n",sampleRate, asioError ));
-
- if( asioError != ASE_OK )
- {
- result = paInvalidSampleRate;
- PA_DEBUG(("ERROR: ASIOCanSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) ));
- goto error;
- }
-
-
- // retrieve the current sample rate, we only change to the requested
- // sample rate if the device is not already in that rate.
-
- ASIOSampleRate oldRate;
- asioError = ASIOGetSampleRate(&oldRate);
- if( asioError != ASE_OK )
- {
- result = paInvalidSampleRate;
- PA_DEBUG(("ERROR: ASIOGetSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) ));
+ result = ValidateAndSetSampleRate( sampleRate );
+ if( result != paNoError )
goto error;
- }
- PA_DEBUG(("ASIOGetSampleRate:%f\n",oldRate));
-
- if (oldRate != sampleRate){
-
- PA_DEBUG(("before ASIOSetSampleRate(%f)\n",sampleRate));
-
- asioError = ASIOSetSampleRate( isExternal?0:sampleRate );
- /* Set sample rate */
- if( asioError != ASE_OK )
- {
- result = paInvalidSampleRate;
- PA_DEBUG(("ERROR: ASIOSetSampleRate: %s\n", PaAsio_GetAsioErrorText(asioError) ));
- goto error;
- }
- PA_DEBUG(("after ASIOSetSampleRate(%f)\n",sampleRate));
- }
- else
- {
- PA_DEBUG(("No Need to change SR\n"));
- }
-
/*
IMPLEMENT ME:
@@ -1884,6 +2031,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
PA_DEBUG(("OpenStream ERROR5\n"));
goto error;
}
+ stream->blockingState = NULL; /* Blocking i/o not initialized, yet. */
+
stream->completedBuffersPlayedEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if( stream->completedBuffersPlayedEvent == NULL )
@@ -1900,15 +2049,19 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->asioChannelInfos = 0; /* for deallocation in error */
stream->bufferPtrs = 0; /* for deallocation in error */
- if( streamCallback )
+ /* Using blocking i/o interface... */
+ if( usingBlockingIo )
{
+ /* Blocking i/o is implemented by running callback mode, using a special blocking i/o callback. */
+ streamCallback = BlockingIoPaCallback; /* Setup PA to use the ASIO blocking i/o callback. */
+ userData = &theAsioStream; /* The callback user data will be the PA ASIO stream. */
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
- &asioHostApi->callbackStreamInterface, streamCallback, userData );
+ &asioHostApi->blockingStreamInterface, streamCallback, userData );
}
- else
+ else /* Using callback interface... */
{
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
- &asioHostApi->blockingStreamInterface, streamCallback, userData );
+ &asioHostApi->callbackStreamInterface, streamCallback, userData );
}
@@ -1959,13 +2112,24 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
- framesPerHostBuffer = SelectHostBufferSize(
- (( suggestedInputLatencyFrames > suggestedOutputLatencyFrames )
- ? suggestedInputLatencyFrames : suggestedOutputLatencyFrames),
- driverInfo );
+ /* Using blocking i/o interface... */
+ if( usingBlockingIo )
+ {
+/** @todo REVIEW selection of host buffer size for blocking i/o */
+ /* Use default host latency for blocking i/o. */
+ framesPerHostBuffer = SelectHostBufferSize( 0, driverInfo );
+
+ }
+ else /* Using callback interface... */
+ {
+ framesPerHostBuffer = SelectHostBufferSize(
+ (( suggestedInputLatencyFrames > suggestedOutputLatencyFrames )
+ ? suggestedInputLatencyFrames : suggestedOutputLatencyFrames),
+ driverInfo );
+ }
- PA_DEBUG(("PaAsioOpenStream: framesPerHostBuffer :%d\n", framesPerHostBuffer));
+ PA_DEBUG(("PaAsioOpenStream: framesPerHostBuffer :%d\n", framesPerHostBuffer));
asioError = ASIOCreateBuffers( stream->asioBufferInfos,
inputChannelCount+outputChannelCount,
@@ -2103,43 +2267,302 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->outputBufferConverter = 0;
}
- result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
- inputChannelCount, inputSampleFormat, hostInputSampleFormat,
- outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
- sampleRate, streamFlags, framesPerBuffer,
- framesPerHostBuffer, paUtilFixedHostBufferSize,
- streamCallback, userData );
- if( result != paNoError ){
- PA_DEBUG(("OpenStream ERROR13\n"));
- goto error;
- }
-
ASIOGetLatencies( &stream->inputLatency, &stream->outputLatency );
- stream->streamRepresentation.streamInfo.inputLatency =
- (double)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)
- + stream->inputLatency) / sampleRate; // seconds
- stream->streamRepresentation.streamInfo.outputLatency =
- (double)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)
- + stream->outputLatency) / sampleRate; // seconds
- stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
-
- // the code below prints the ASIO latency which doesn't include the
- // buffer processor latency. it reports the added latency separately
- PA_DEBUG(("PaAsio : ASIO InputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
- stream->inputLatency,
- (long)((stream->inputLatency*1000)/ sampleRate),
- PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor),
- (long)((PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)*1000)/ sampleRate)
- ));
-
- PA_DEBUG(("PaAsio : ASIO OuputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
- stream->outputLatency,
- (long)((stream->outputLatency*1000)/ sampleRate),
- PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor),
- (long)((PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)*1000)/ sampleRate)
- ));
+
+ /* Using blocking i/o interface... */
+ if( usingBlockingIo )
+ {
+ /* Allocate the blocking i/o input ring buffer memory. */
+ stream->blockingState = (PaAsioStreamBlockingState*)PaUtil_AllocateMemory( sizeof(PaAsioStreamBlockingState) );
+ if( !stream->blockingState )
+ {
+ result = paInsufficientMemory;
+ PA_DEBUG(("ERROR! Blocking i/o interface struct allocation failed in OpenStream()\n"));
+ goto error;
+ }
+
+ /* Initialize blocking i/o interface struct. */
+ stream->blockingState->readFramesReadyEvent = NULL; /* Uninitialized, yet. */
+ stream->blockingState->writeBuffersReadyEvent = NULL; /* Uninitialized, yet. */
+ stream->blockingState->readRingBufferData = NULL; /* Uninitialized, yet. */
+ stream->blockingState->writeRingBufferData = NULL; /* Uninitialized, yet. */
+ stream->blockingState->readStreamBuffer = NULL; /* Uninitialized, yet. */
+ stream->blockingState->writeStreamBuffer = NULL; /* Uninitialized, yet. */
+ stream->blockingState->stopFlag = TRUE; /* Not started, yet. */
+
+
+ /* If the user buffer is unspecified */
+ if( framesPerBuffer == paFramesPerBufferUnspecified )
+ {
+ /* Make the user buffer the same size as the host buffer. */
+ framesPerBuffer = framesPerHostBuffer;
+ }
+
+
+ /* Initialize callback buffer processor. */
+ result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor ,
+ inputChannelCount ,
+ inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
+ hostInputSampleFormat , /* Host format. */
+ outputChannelCount ,
+ outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
+ hostOutputSampleFormat , /* Host format. */
+ sampleRate ,
+ streamFlags ,
+ framesPerBuffer , /* Frames per ring buffer block. */
+ framesPerHostBuffer , /* Frames per asio buffer. */
+ paUtilFixedHostBufferSize ,
+ streamCallback ,
+ userData );
+ if( result != paNoError ){
+ PA_DEBUG(("OpenStream ERROR13\n"));
+ goto error;
+ }
+ callbackBufferProcessorInited = TRUE;
+
+ /* Initialize the blocking i/o buffer processor. */
+ result = PaUtil_InitializeBufferProcessor(&stream->blockingState->bufferProcessor,
+ inputChannelCount ,
+ inputSampleFormat , /* User format. */
+ inputSampleFormat & ~paNonInterleaved , /* Ring buffer. */
+ outputChannelCount ,
+ outputSampleFormat , /* User format. */
+ outputSampleFormat & ~paNonInterleaved, /* Ring buffer. */
+ sampleRate ,
+ paClipOff | paDitherOff , /* Don't use dither nor clipping. */
+ framesPerBuffer , /* Frames per user buffer. */
+ framesPerBuffer , /* Frames per ring buffer block. */
+ paUtilBoundedHostBufferSize ,
+ NULL, NULL );/* No callback! */
+ if( result != paNoError ){
+ PA_DEBUG(("ERROR! Blocking i/o buffer processor initialization failed in OpenStream()\n"));
+ goto error;
+ }
+ blockingBufferProcessorInited = TRUE;
+
+ /* If input is requested. */
+ if( inputChannelCount )
+ {
+ /* Create the callback sync-event. */
+ stream->blockingState->readFramesReadyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( stream->blockingState->readFramesReadyEvent == NULL )
+ {
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ PA_DEBUG(("ERROR! Blocking i/o \"read frames ready\" event creation failed in OpenStream()\n"));
+ goto error;
+ }
+ blockingReadFramesReadyEventInitialized = 1;
+
+
+ /* Create pointer buffer to access non-interleaved data in ReadStream() */
+ stream->blockingState->readStreamBuffer = (void**)PaUtil_AllocateMemory( sizeof(void*) * inputChannelCount );
+ if( !stream->blockingState->readStreamBuffer )
+ {
+ result = paInsufficientMemory;
+ PA_DEBUG(("ERROR! Blocking i/o read stream buffer allocation failed in OpenStream()\n"));
+ goto error;
+ }
+
+ /* The ring buffer should store as many data blocks as needed
+ to achieve the requested latency. Whereas it must be large
+ enough to store at least two complete data blocks.
+
+ 1) Determine the amount of latency to be added to the
+ prefered ASIO latency.
+ 2) Make sure we have at lest one additional latency frame.
+ 3) Divide the number of frames by the desired block size to
+ get the number (rounded up to pure integer) of blocks to
+ be stored in the buffer.
+ 4) Add one additional block for block processing and convert
+ to samples frames.
+ 5) Get the next larger (or equal) power-of-two buffer size.
+ */
+ lBlockingBufferSize = suggestedInputLatencyFrames - stream->inputLatency;
+ lBlockingBufferSize = (lBlockingBufferSize > 0) ? lBlockingBufferSize : 1;
+ lBlockingBufferSize = (lBlockingBufferSize + framesPerBuffer - 1) / framesPerBuffer;
+ lBlockingBufferSize = (lBlockingBufferSize + 1) * framesPerBuffer;
+
+ /* Get the next larger or equal power-of-two buffersize. */
+ lBlockingBufferSizePow2 = 1;
+ while( lBlockingBufferSize > (lBlockingBufferSizePow2<<=1) );
+ lBlockingBufferSize = lBlockingBufferSizePow2;
+
+ /* Compute total intput latency in seconds */
+ stream->streamRepresentation.streamInfo.inputLatency =
+ (double)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor )
+ + PaUtil_GetBufferProcessorInputLatency(&stream->blockingState->bufferProcessor)
+ + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer
+ + stream->inputLatency )
+ / sampleRate;
+
+ /* The code below prints the ASIO latency which doesn't include
+ the buffer processor latency nor the blocking i/o latency. It
+ reports the added latency separately.
+ */
+ PA_DEBUG(("PaAsio : ASIO InputLatency = %ld (%ld ms),\n added buffProc:%ld (%ld ms),\n added blocking:%ld (%ld ms)\n",
+ stream->inputLatency,
+ (long)( stream->inputLatency * (1000.0 / sampleRate) ),
+ PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor),
+ (long)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor) * (1000.0 / sampleRate) ),
+ PaUtil_GetBufferProcessorInputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer,
+ (long)( (PaUtil_GetBufferProcessorInputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer) * (1000.0 / sampleRate) )
+ ));
+
+ /* Determine the size of ring buffer in bytes. */
+ lBytesPerFrame = inputChannelCount * Pa_GetSampleSize(inputSampleFormat );
+
+ /* Allocate the blocking i/o input ring buffer memory. */
+ stream->blockingState->readRingBufferData = (void*)PaUtil_AllocateMemory( lBlockingBufferSize * lBytesPerFrame );
+ if( !stream->blockingState->readRingBufferData )
+ {
+ result = paInsufficientMemory;
+ PA_DEBUG(("ERROR! Blocking i/o input ring buffer allocation failed in OpenStream()\n"));
+ goto error;
+ }
+
+ /* Initialize the input ring buffer struct. */
+ PaUtil_InitializeRingBuffer( &stream->blockingState->readRingBuffer ,
+ lBytesPerFrame ,
+ lBlockingBufferSize ,
+ stream->blockingState->readRingBufferData );
+ }
+
+ /* If output is requested. */
+ if( outputChannelCount )
+ {
+ stream->blockingState->writeBuffersReadyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( stream->blockingState->writeBuffersReadyEvent == NULL )
+ {
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ PA_DEBUG(("ERROR! Blocking i/o \"write buffers ready\" event creation failed in OpenStream()\n"));
+ goto error;
+ }
+ blockingWriteBuffersReadyEventInitialized = 1;
+
+ /* Create pointer buffer to access non-interleaved data in WriteStream() */
+ stream->blockingState->writeStreamBuffer = (const void**)PaUtil_AllocateMemory( sizeof(const void*) * outputChannelCount );
+ if( !stream->blockingState->writeStreamBuffer )
+ {
+ result = paInsufficientMemory;
+ PA_DEBUG(("ERROR! Blocking i/o write stream buffer allocation failed in OpenStream()\n"));
+ goto error;
+ }
+
+ /* The ring buffer should store as many data blocks as needed
+ to achieve the requested latency. Whereas it must be large
+ enough to store at least two complete data blocks.
+
+ 1) Determine the amount of latency to be added to the
+ prefered ASIO latency.
+ 2) Make sure we have at lest one additional latency frame.
+ 3) Divide the number of frames by the desired block size to
+ get the number (rounded up to pure integer) of blocks to
+ be stored in the buffer.
+ 4) Add one additional block for block processing and convert
+ to samples frames.
+ 5) Get the next larger (or equal) power-of-two buffer size.
+ */
+ lBlockingBufferSize = suggestedOutputLatencyFrames - stream->outputLatency;
+ lBlockingBufferSize = (lBlockingBufferSize > 0) ? lBlockingBufferSize : 1;
+ lBlockingBufferSize = (lBlockingBufferSize + framesPerBuffer - 1) / framesPerBuffer;
+ lBlockingBufferSize = (lBlockingBufferSize + 1) * framesPerBuffer;
+
+ /* The buffer size (without the additional block) corresponds
+ to the initial number of silent samples in the output ring
+ buffer. */
+ stream->blockingState->writeRingBufferInitialFrames = lBlockingBufferSize - framesPerBuffer;
+
+ /* Get the next larger or equal power-of-two buffersize. */
+ lBlockingBufferSizePow2 = 1;
+ while( lBlockingBufferSize > (lBlockingBufferSizePow2<<=1) );
+ lBlockingBufferSize = lBlockingBufferSizePow2;
+
+ /* Compute total output latency in seconds */
+ stream->streamRepresentation.streamInfo.outputLatency =
+ (double)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor )
+ + PaUtil_GetBufferProcessorOutputLatency(&stream->blockingState->bufferProcessor)
+ + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer
+ + stream->outputLatency )
+ / sampleRate;
+
+ /* The code below prints the ASIO latency which doesn't include
+ the buffer processor latency nor the blocking i/o latency. It
+ reports the added latency separately.
+ */
+ PA_DEBUG(("PaAsio : ASIO OutputLatency = %ld (%ld ms),\n added buffProc:%ld (%ld ms),\n added blocking:%ld (%ld ms)\n",
+ stream->outputLatency,
+ (long)( stream->inputLatency * (1000.0 / sampleRate) ),
+ PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor),
+ (long)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor) * (1000.0 / sampleRate) ),
+ PaUtil_GetBufferProcessorOutputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer,
+ (long)( (PaUtil_GetBufferProcessorOutputLatency(&stream->blockingState->bufferProcessor) + (lBlockingBufferSize / framesPerBuffer - 1) * framesPerBuffer) * (1000.0 / sampleRate) )
+ ));
+
+ /* Determine the size of ring buffer in bytes. */
+ lBytesPerFrame = outputChannelCount * Pa_GetSampleSize(outputSampleFormat);
+
+ /* Allocate the blocking i/o output ring buffer memory. */
+ stream->blockingState->writeRingBufferData = (void*)PaUtil_AllocateMemory( lBlockingBufferSize * lBytesPerFrame );
+ if( !stream->blockingState->writeRingBufferData )
+ {
+ result = paInsufficientMemory;
+ PA_DEBUG(("ERROR! Blocking i/o output ring buffer allocation failed in OpenStream()\n"));
+ goto error;
+ }
+
+ /* Initialize the output ring buffer struct. */
+ PaUtil_InitializeRingBuffer( &stream->blockingState->writeRingBuffer ,
+ lBytesPerFrame ,
+ lBlockingBufferSize ,
+ stream->blockingState->writeRingBufferData );
+ }
+
+ stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
+
+
+ }
+ else /* Using callback interface... */
+ {
+ result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
+ inputChannelCount, inputSampleFormat, hostInputSampleFormat,
+ outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
+ sampleRate, streamFlags, framesPerBuffer,
+ framesPerHostBuffer, paUtilFixedHostBufferSize,
+ streamCallback, userData );
+ if( result != paNoError ){
+ PA_DEBUG(("OpenStream ERROR13\n"));
+ goto error;
+ }
+ callbackBufferProcessorInited = TRUE;
+
+ stream->streamRepresentation.streamInfo.inputLatency =
+ (double)( PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)
+ + stream->inputLatency) / sampleRate; // seconds
+ stream->streamRepresentation.streamInfo.outputLatency =
+ (double)( PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)
+ + stream->outputLatency) / sampleRate; // seconds
+ stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
+
+ // the code below prints the ASIO latency which doesn't include the
+ // buffer processor latency. it reports the added latency separately
+ PA_DEBUG(("PaAsio : ASIO InputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
+ stream->inputLatency,
+ (long)((stream->inputLatency*1000)/ sampleRate),
+ PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor),
+ (long)((PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)*1000)/ sampleRate)
+ ));
+
+ PA_DEBUG(("PaAsio : ASIO OuputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n",
+ stream->outputLatency,
+ (long)((stream->outputLatency*1000)/ sampleRate),
+ PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor),
+ (long)((PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)*1000)/ sampleRate)
+ ));
+ }
stream->asioHostApi = asioHostApi;
stream->framesPerHostCallback = framesPerHostBuffer;
@@ -2147,10 +2570,12 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream->inputChannelCount = inputChannelCount;
stream->outputChannelCount = outputChannelCount;
stream->postOutput = driverInfo->postOutput;
+ stream->isStopped = 1;
stream->isActive = 0;
-
+
asioHostApi->openAsioDeviceIndex = asioDeviceIndex;
+ theAsioStream = stream;
*s = (PaStream*)stream;
return result;
@@ -2159,6 +2584,31 @@ error:
PA_DEBUG(("goto errored\n"));
if( stream )
{
+ if( stream->blockingState )
+ {
+ if( blockingBufferProcessorInited )
+ PaUtil_TerminateBufferProcessor( &stream->blockingState->bufferProcessor );
+
+ if( stream->blockingState->writeRingBufferData )
+ PaUtil_FreeMemory( stream->blockingState->writeRingBufferData );
+ if( stream->blockingState->writeStreamBuffer )
+ PaUtil_FreeMemory( stream->blockingState->writeStreamBuffer );
+ if( blockingWriteBuffersReadyEventInitialized )
+ CloseHandle( stream->blockingState->writeBuffersReadyEvent );
+
+ if( stream->blockingState->readRingBufferData )
+ PaUtil_FreeMemory( stream->blockingState->readRingBufferData );
+ if( stream->blockingState->readStreamBuffer )
+ PaUtil_FreeMemory( stream->blockingState->readStreamBuffer );
+ if( blockingReadFramesReadyEventInitialized )
+ CloseHandle( stream->blockingState->readFramesReadyEvent );
+
+ PaUtil_FreeMemory( stream->blockingState );
+ }
+
+ if( callbackBufferProcessorInited )
+ PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
+
if( completedBuffersPlayedEventInited )
CloseHandle( stream->completedBuffersPlayedEvent );
@@ -2178,8 +2628,9 @@ error:
ASIODisposeBuffers();
if( asioIsInitialized )
- ASIOExit();
-
+ {
+ UnloadAsioDriver();
+ }
return result;
}
@@ -2205,13 +2656,34 @@ static PaError CloseStream( PaStream* s )
CloseHandle( stream->completedBuffersPlayedEvent );
+ /* Using blocking i/o interface... */
+ if( stream->blockingState )
+ {
+ PaUtil_TerminateBufferProcessor( &stream->blockingState->bufferProcessor );
+
+ if( stream->inputChannelCount ) {
+ PaUtil_FreeMemory( stream->blockingState->readRingBufferData );
+ PaUtil_FreeMemory( stream->blockingState->readStreamBuffer );
+ CloseHandle( stream->blockingState->readFramesReadyEvent );
+ }
+ if( stream->outputChannelCount ) {
+ PaUtil_FreeMemory( stream->blockingState->writeRingBufferData );
+ PaUtil_FreeMemory( stream->blockingState->writeStreamBuffer );
+ CloseHandle( stream->blockingState->writeBuffersReadyEvent );
+ }
+
+ PaUtil_FreeMemory( stream->blockingState );
+ }
+
PaUtil_FreeMemory( stream->asioBufferInfos );
PaUtil_FreeMemory( stream->asioChannelInfos );
PaUtil_FreeMemory( stream->bufferPtrs );
PaUtil_FreeMemory( stream );
ASIODisposeBuffers();
- ASIOExit();
+ UnloadAsioDriver();
+
+ theAsioStream = 0;
return result;
}
@@ -2245,10 +2717,10 @@ static void bufferSwitch(long index, ASIOBool directProcess)
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
- #define ASIO64toDouble(a) (a)
+ #define ASIO64toDouble(a) (a)
#else
- const double twoRaisedTo32 = 4294967296.;
- #define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
+ const double twoRaisedTo32 = 4294967296.;
+ #define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
#endif
static ASIOTime *bufferSwitchTimeInfo( ASIOTime *timeInfo, long index, ASIOBool directProcess )
@@ -2430,7 +2902,9 @@ previousIndex = index;
paTimeInfo.inputBufferAdcTime = paTimeInfo.currentTime - theAsioStream->streamRepresentation.streamInfo.inputLatency;
paTimeInfo.outputBufferDacTime = paTimeInfo.currentTime + theAsioStream->streamRepresentation.streamInfo.outputLatency;
*/
-#if 1
+
+/* Disabled! Stopping and re-starting the stream causes an input overflow / output undeflow. S.Fischer */
+#if 0
// detect underflows by checking inter-callback time > 2 buffer period
static double previousTime = -1;
if( previousTime > 0 ){
@@ -2634,6 +3108,7 @@ static PaError StartStream( PaStream *s )
{
PaError result = paNoError;
PaAsioStream *stream = (PaAsioStream*)s;
+ PaAsioStreamBlockingState *blockingState = stream->blockingState;
ASIOError asioError;
if( stream->outputChannelCount > 0 )
@@ -2658,18 +3133,72 @@ static PaError StartStream( PaStream *s )
PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
}
- if( result == paNoError )
+
+ /* Using blocking i/o interface... */
+ if( blockingState )
{
- theAsioStream = stream;
- asioError = ASIOStart();
- if( asioError == ASE_OK )
+ /* Reset blocking i/o buffer processor. */
+ PaUtil_ResetBufferProcessor( &blockingState->bufferProcessor );
+
+ /* If we're about to process some input data. */
+ if( stream->inputChannelCount )
{
- stream->isActive = 1;
- stream->streamFinishedCallbackCalled = false;
+ /* Reset callback-ReadStream sync event. */
+ if( ResetEvent( blockingState->readFramesReadyEvent ) == 0 )
+ {
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ }
+
+ /* Flush blocking i/o ring buffer. */
+ PaUtil_FlushRingBuffer( &blockingState->readRingBuffer );
+ (*blockingState->bufferProcessor.inputZeroer)( blockingState->readRingBuffer.buffer, 1, blockingState->bufferProcessor.inputChannelCount * blockingState->readRingBuffer.bufferSize );
}
- else
+
+ /* If we're about to process some output data. */
+ if( stream->outputChannelCount )
+ {
+ /* Reset callback-WriteStream sync event. */
+ if( ResetEvent( blockingState->writeBuffersReadyEvent ) == 0 )
+ {
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ }
+
+ /* Flush blocking i/o ring buffer. */
+ PaUtil_FlushRingBuffer( &blockingState->writeRingBuffer );
+ (*blockingState->bufferProcessor.outputZeroer)( blockingState->writeRingBuffer.buffer, 1, blockingState->bufferProcessor.outputChannelCount * blockingState->writeRingBuffer.bufferSize );
+
+ /* Initialize the output ring buffer to "silence". */
+ PaUtil_AdvanceRingBufferWriteIndex( &blockingState->writeRingBuffer, blockingState->writeRingBufferInitialFrames );
+ }
+
+ /* Clear requested frames / buffers count. */
+ blockingState->writeBuffersRequested = 0;
+ blockingState->readFramesRequested = 0;
+ blockingState->writeBuffersRequestedFlag = FALSE;
+ blockingState->readFramesRequestedFlag = FALSE;
+ blockingState->outputUnderflowFlag = FALSE;
+ blockingState->inputOverflowFlag = FALSE;
+ blockingState->stopFlag = FALSE;
+ }
+
+
+ if( result == paNoError )
+ {
+ assert( theAsioStream == stream ); /* theAsioStream should be set correctly in OpenStream */
+
+ /* initialize these variables before the callback has a chance to be invoked */
+ stream->isStopped = 0;
+ stream->isActive = 1;
+ stream->streamFinishedCallbackCalled = false;
+
+ asioError = ASIOStart();
+ if( asioError != ASE_OK )
{
- theAsioStream = 0;
+ stream->isStopped = 1;
+ stream->isActive = 0;
+
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
}
@@ -2678,15 +3207,59 @@ static PaError StartStream( PaStream *s )
return result;
}
+static void EnsureCallbackHasCompleted( PaAsioStream *stream )
+{
+ // make sure that the callback is not still in-flight after ASIOStop()
+ // returns. This has been observed to happen on the Hoontech DSP24 for
+ // example.
+ int count = 2000; // only wait for 2 seconds, rather than hanging.
+ while( stream->reenterCount != -1 && count > 0 )
+ {
+ Sleep(1);
+ --count;
+ }
+}
static PaError StopStream( PaStream *s )
{
PaError result = paNoError;
PaAsioStream *stream = (PaAsioStream*)s;
+ PaAsioStreamBlockingState *blockingState = stream->blockingState;
ASIOError asioError;
if( stream->isActive )
{
+ /* If blocking i/o output is in use */
+ if( blockingState && stream->outputChannelCount )
+ {
+ /* Request the whole output buffer to be available. */
+ blockingState->writeBuffersRequested = blockingState->writeRingBuffer.bufferSize;
+ /* Signalize that additional buffers are need. */
+ blockingState->writeBuffersRequestedFlag = TRUE;
+ /* Set flag to indicate the playback is to be stopped. */
+ blockingState->stopFlag = TRUE;
+
+ /* Wait until requested number of buffers has been freed. Time
+ out after twice the blocking i/o ouput buffer could have
+ been consumed. */
+ DWORD timeout = (DWORD)( 2 * blockingState->writeRingBuffer.bufferSize * 1000
+ / stream->streamRepresentation.streamInfo.sampleRate );
+ DWORD waitResult = WaitForSingleObject( blockingState->writeBuffersReadyEvent, timeout );
+
+ /* If something seriously went wrong... */
+ if( waitResult == WAIT_FAILED )
+ {
+ PA_DEBUG(("WaitForSingleObject() failed in StopStream()\n"));
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ }
+ else if( waitResult == WAIT_TIMEOUT )
+ {
+ PA_DEBUG(("WaitForSingleObject() timed out in StopStream()\n"));
+ result = paTimedOut;
+ }
+ }
+
stream->stopProcessing = true;
/* wait for the stream to finish playing out enqueued buffers.
@@ -2696,22 +3269,26 @@ static PaError StopStream( PaStream *s )
length is longer than the asio buffer size then that should
be taken into account.
*/
- if( WaitForSingleObject( theAsioStream->completedBuffersPlayedEvent,
+ if( WaitForSingleObject( stream->completedBuffersPlayedEvent,
(DWORD)(stream->streamRepresentation.streamInfo.outputLatency * 1000. * 4.) )
- == WAIT_TIMEOUT )
+ == WAIT_TIMEOUT )
{
PA_DEBUG(("WaitForSingleObject() timed out in StopStream()\n" ));
}
}
asioError = ASIOStop();
- if( asioError != ASE_OK )
+ if( asioError == ASE_OK )
+ {
+ EnsureCallbackHasCompleted( stream );
+ }
+ else
{
result = paUnanticipatedHostError;
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
}
- theAsioStream = 0;
+ stream->isStopped = 1;
stream->isActive = 0;
if( !stream->streamFinishedCallbackCalled )
@@ -2723,7 +3300,6 @@ static PaError StopStream( PaStream *s )
return result;
}
-
static PaError AbortStream( PaStream *s )
{
PaError result = paNoError;
@@ -2733,31 +3309,17 @@ static PaError AbortStream( PaStream *s )
stream->zeroOutput = true;
asioError = ASIOStop();
- if( asioError != ASE_OK )
+ if( asioError == ASE_OK )
{
- result = paUnanticipatedHostError;
- PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
+ EnsureCallbackHasCompleted( stream );
}
else
{
- // make sure that the callback is not still in-flight when ASIOStop()
- // returns. This has been observed to happen on the Hoontech DSP24 for
- // example.
- int count = 2000; // only wait for 2 seconds, rather than hanging.
- while( theAsioStream->reenterCount != -1 && count > 0 )
- {
- Sleep(1);
- --count;
- }
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
}
- /* it is questionable whether we should zero theAsioStream if ASIOStop()
- returns an error, because the callback could still be active. We assume
- not - this is based on the fact that ASIOStop is unlikely to fail
- if the callback is running - it's more likely to fail because the
- callback is not running. */
-
- theAsioStream = 0;
+ stream->isStopped = 1;
stream->isActive = 0;
if( !stream->streamFinishedCallbackCalled )
@@ -2772,9 +3334,9 @@ static PaError AbortStream( PaStream *s )
static PaError IsStreamStopped( PaStream *s )
{
- //PaAsioStream *stream = (PaAsioStream*)s;
- (void) s; /* unused parameter */
- return theAsioStream == 0;
+ PaAsioStream *stream = (PaAsioStream*)s;
+
+ return stream->isStopped;
}
@@ -2807,33 +3369,348 @@ static double GetStreamCpuLoad( PaStream* s )
for blocking streams.
*/
-static PaError ReadStream( PaStream* s,
- void *buffer,
- unsigned long frames )
+static PaError ReadStream( PaStream *s ,
+ void *buffer,
+ unsigned long frames )
{
- PaAsioStream *stream = (PaAsioStream*)s;
+ PaError result = paNoError; /* Initial return value. */
+ PaAsioStream *stream = (PaAsioStream*)s; /* The PA ASIO stream. */
- /* IMPLEMENT ME, see portaudio.h for required behavior*/
- (void) stream; /* unused parameters */
- (void) buffer;
- (void) frames;
+ /* Pointer to the blocking i/o data struct. */
+ PaAsioStreamBlockingState *blockingState = stream->blockingState;
- return paNoError;
-}
+ /* Get blocking i/o buffer processor and ring buffer pointers. */
+ PaUtilBufferProcessor *pBp = &blockingState->bufferProcessor;
+ PaUtilRingBuffer *pRb = &blockingState->readRingBuffer;
+
+ /* Ring buffer segment(s) used for writing. */
+ void *pRingBufferData1st = NULL; /* First segment. (Mandatory) */
+ void *pRingBufferData2nd = NULL; /* Second segment. (Optional) */
+
+ /* Number of frames per ring buffer segment. */
+ long lRingBufferSize1st = 0; /* First segment. (Mandatory) */
+ long lRingBufferSize2nd = 0; /* Second segment. (Optional) */
+
+ /* Get number of frames to be processed per data block. */
+ unsigned long lFramesPerBlock = stream->bufferProcessor.framesPerUserBuffer;
+ /* Actual number of frames that has been copied into the ring buffer. */
+ unsigned long lFramesCopied = 0;
+ /* The number of remaining unprocessed dtat frames. */
+ unsigned long lFramesRemaining = frames;
+ /* Copy the input argument to avoid pointer increment! */
+ const void *userBuffer;
+ unsigned int i; /* Just a counter. */
+
+ /* About the time, needed to process 8 data blocks. */
+ DWORD timeout = (DWORD)( 8 * lFramesPerBlock * 1000 / stream->streamRepresentation.streamInfo.sampleRate );
+ DWORD waitResult = 0;
+
+
+ /* Check if the stream is still available ready to gather new data. */
+ if( blockingState->stopFlag || !stream->isActive )
+ {
+ PA_DEBUG(("Warning! Stream no longer available for reading in ReadStream()\n"));
+ result = paStreamIsStopped;
+ return result;
+ }
+
+ /* If the stream is a input stream. */
+ if( stream->inputChannelCount )
+ {
+ /* Prepare buffer access. */
+ if( !pBp->userOutputIsInterleaved )
+ {
+ userBuffer = blockingState->readStreamBuffer;
+ for( i = 0; i<pBp->inputChannelCount; ++i )
+ {
+ ((void**)userBuffer)[i] = ((void**)buffer)[i];
+ }
+ } /* Use the unchanged buffer. */
+ else { userBuffer = buffer; }
-static PaError WriteStream( PaStream* s,
- const void *buffer,
- unsigned long frames )
+ do /* Internal block processing for too large user data buffers. */
+ {
+ /* Get the size of the current data block to be processed. */
+ lFramesPerBlock =(lFramesPerBlock < lFramesRemaining)
+ ? lFramesPerBlock : lFramesRemaining;
+ /* Use predefined block size for as long there are enough
+ buffers available, thereafter reduce the processing block
+ size to match the number of remaining buffers. So the final
+ data block is processed although it may be incomplete. */
+
+ /* If the available amount of data frames is insufficient. */
+ if( PaUtil_GetRingBufferReadAvailable(pRb) < (long) lFramesPerBlock )
+ {
+ /* Make sure, the event isn't already set! */
+ /* ResetEvent( blockingState->readFramesReadyEvent ); */
+
+ /* Set the number of requested buffers. */
+ blockingState->readFramesRequested = lFramesPerBlock;
+
+ /* Signalize that additional buffers are need. */
+ blockingState->readFramesRequestedFlag = TRUE;
+
+ /* Wait until requested number of buffers has been freed. */
+ waitResult = WaitForSingleObject( blockingState->readFramesReadyEvent, timeout );
+
+ /* If something seriously went wrong... */
+ if( waitResult == WAIT_FAILED )
+ {
+ PA_DEBUG(("WaitForSingleObject() failed in ReadStream()\n"));
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ return result;
+ }
+ else if( waitResult == WAIT_TIMEOUT )
+ {
+ PA_DEBUG(("WaitForSingleObject() timed out in ReadStream()\n"));
+
+ /* If block processing has stopped, abort! */
+ if( blockingState->stopFlag ) { return result = paStreamIsStopped; }
+
+ /* If a timeout is encountered, give up eventually. */
+ return result = paTimedOut;
+ }
+ }
+ /* Now, the ring buffer contains the required amount of data
+ frames.
+ (Therefor we don't need to check the return argument of
+ PaUtil_GetRingBufferReadRegions(). ;-) )
+ */
+
+ /* Retrieve pointer(s) to the ring buffer's current write
+ position(s). If the first buffer segment is too small to
+ store the requested number of bytes, an additional second
+ segment is returned. Otherwise, i.e. if the first segment
+ is large enough, the second segment's pointer will be NULL.
+ */
+ PaUtil_GetRingBufferReadRegions(pRb ,
+ lFramesPerBlock ,
+ &pRingBufferData1st,
+ &lRingBufferSize1st,
+ &pRingBufferData2nd,
+ &lRingBufferSize2nd);
+
+ /* Set number of frames to be copied from the ring buffer. */
+ PaUtil_SetInputFrameCount( pBp, lRingBufferSize1st );
+ /* Setup ring buffer access. */
+ PaUtil_SetInterleavedInputChannels(pBp , /* Buffer processor. */
+ 0 , /* The first channel's index. */
+ pRingBufferData1st, /* First ring buffer segment. */
+ 0 ); /* Use all available channels. */
+
+ /* If a second ring buffer segment is required. */
+ if( lRingBufferSize2nd ) {
+ /* Set number of frames to be copied from the ring buffer. */
+ PaUtil_Set2ndInputFrameCount( pBp, lRingBufferSize2nd );
+ /* Setup ring buffer access. */
+ PaUtil_Set2ndInterleavedInputChannels(pBp , /* Buffer processor. */
+ 0 , /* The first channel's index. */
+ pRingBufferData2nd, /* Second ring buffer segment. */
+ 0 ); /* Use all available channels. */
+ }
+
+ /* Let the buffer processor handle "copy and conversion" and
+ update the ring buffer indices manually. */
+ lFramesCopied = PaUtil_CopyInput( pBp, &buffer, lFramesPerBlock );
+ PaUtil_AdvanceRingBufferReadIndex( pRb, lFramesCopied );
+
+ /* Decrease number of unprocessed frames. */
+ lFramesRemaining -= lFramesCopied;
+
+ } /* Continue with the next data chunk. */
+ while( lFramesRemaining );
+
+
+ /* If there has been an input overflow within the callback */
+ if( blockingState->inputOverflowFlag )
+ {
+ blockingState->inputOverflowFlag = FALSE;
+
+ /* Return the corresponding error code. */
+ result = paInputOverflowed;
+ }
+
+ } /* If this is not an input stream. */
+ else {
+ result = paCanNotReadFromAnOutputOnlyStream;
+ }
+
+ return result;
+}
+
+static PaError WriteStream( PaStream *s ,
+ const void *buffer,
+ unsigned long frames )
{
- PaAsioStream *stream = (PaAsioStream*)s;
+ PaError result = paNoError; /* Initial return value. */
+ PaAsioStream *stream = (PaAsioStream*)s; /* The PA ASIO stream. */
- /* IMPLEMENT ME, see portaudio.h for required behavior*/
- (void) stream; /* unused parameters */
- (void) buffer;
- (void) frames;
+ /* Pointer to the blocking i/o data struct. */
+ PaAsioStreamBlockingState *blockingState = stream->blockingState;
- return paNoError;
+ /* Get blocking i/o buffer processor and ring buffer pointers. */
+ PaUtilBufferProcessor *pBp = &blockingState->bufferProcessor;
+ PaUtilRingBuffer *pRb = &blockingState->writeRingBuffer;
+
+ /* Ring buffer segment(s) used for writing. */
+ void *pRingBufferData1st = NULL; /* First segment. (Mandatory) */
+ void *pRingBufferData2nd = NULL; /* Second segment. (Optional) */
+
+ /* Number of frames per ring buffer segment. */
+ long lRingBufferSize1st = 0; /* First segment. (Mandatory) */
+ long lRingBufferSize2nd = 0; /* Second segment. (Optional) */
+
+ /* Get number of frames to be processed per data block. */
+ unsigned long lFramesPerBlock = stream->bufferProcessor.framesPerUserBuffer;
+ /* Actual number of frames that has been copied into the ring buffer. */
+ unsigned long lFramesCopied = 0;
+ /* The number of remaining unprocessed dtat frames. */
+ unsigned long lFramesRemaining = frames;
+
+ /* About the time, needed to process 8 data blocks. */
+ DWORD timeout = (DWORD)( 8 * lFramesPerBlock * 1000 / stream->streamRepresentation.streamInfo.sampleRate );
+ DWORD waitResult = 0;
+
+ /* Copy the input argument to avoid pointer increment! */
+ const void *userBuffer;
+ unsigned int i; /* Just a counter. */
+
+
+ /* Check if the stream ist still available ready to recieve new data. */
+ if( blockingState->stopFlag || !stream->isActive )
+ {
+ PA_DEBUG(("Warning! Stream no longer available for writing in WriteStream()\n"));
+ result = paStreamIsStopped;
+ return result;
+ }
+
+ /* If the stream is a output stream. */
+ if( stream->outputChannelCount )
+ {
+ /* Prepare buffer access. */
+ if( !pBp->userOutputIsInterleaved )
+ {
+ userBuffer = blockingState->writeStreamBuffer;
+ for( i = 0; i<pBp->outputChannelCount; ++i )
+ {
+ ((const void**)userBuffer)[i] = ((const void**)buffer)[i];
+ }
+ } /* Use the unchanged buffer. */
+ else { userBuffer = buffer; }
+
+
+ do /* Internal block processing for too large user data buffers. */
+ {
+ /* Get the size of the current data block to be processed. */
+ lFramesPerBlock =(lFramesPerBlock < lFramesRemaining)
+ ? lFramesPerBlock : lFramesRemaining;
+ /* Use predefined block size for as long there are enough
+ frames available, thereafter reduce the processing block
+ size to match the number of remaining frames. So the final
+ data block is processed although it may be incomplete. */
+
+ /* If the available amount of buffers is insufficient. */
+ if( PaUtil_GetRingBufferWriteAvailable(pRb) < (long) lFramesPerBlock )
+ {
+ /* Make sure, the event isn't already set! */
+ /* ResetEvent( blockingState->writeBuffersReadyEvent ); */
+
+ /* Set the number of requested buffers. */
+ blockingState->writeBuffersRequested = lFramesPerBlock;
+
+ /* Signalize that additional buffers are need. */
+ blockingState->writeBuffersRequestedFlag = TRUE;
+
+ /* Wait until requested number of buffers has been freed. */
+ waitResult = WaitForSingleObject( blockingState->writeBuffersReadyEvent, timeout );
+
+ /* If something seriously went wrong... */
+ if( waitResult == WAIT_FAILED )
+ {
+ PA_DEBUG(("WaitForSingleObject() failed in WriteStream()\n"));
+ result = paUnanticipatedHostError;
+ PA_ASIO_SET_LAST_SYSTEM_ERROR( GetLastError() );
+ return result;
+ }
+ else if( waitResult == WAIT_TIMEOUT )
+ {
+ PA_DEBUG(("WaitForSingleObject() timed out in WriteStream()\n"));
+
+ /* If block processing has stopped, abort! */
+ if( blockingState->stopFlag ) { return result = paStreamIsStopped; }
+
+ /* If a timeout is encountered, give up eventually. */
+ return result = paTimedOut;
+ }
+ }
+ /* Now, the ring buffer contains the required amount of free
+ space to store the provided number of data frames.
+ (Therefor we don't need to check the return argument of
+ PaUtil_GetRingBufferWriteRegions(). ;-) )
+ */
+
+ /* Retrieve pointer(s) to the ring buffer's current write
+ position(s). If the first buffer segment is too small to
+ store the requested number of bytes, an additional second
+ segment is returned. Otherwise, i.e. if the first segment
+ is large enough, the second segment's pointer will be NULL.
+ */
+ PaUtil_GetRingBufferWriteRegions(pRb ,
+ lFramesPerBlock ,
+ &pRingBufferData1st,
+ &lRingBufferSize1st,
+ &pRingBufferData2nd,
+ &lRingBufferSize2nd);
+
+ /* Set number of frames to be copied to the ring buffer. */
+ PaUtil_SetOutputFrameCount( pBp, lRingBufferSize1st );
+ /* Setup ring buffer access. */
+ PaUtil_SetInterleavedOutputChannels(pBp , /* Buffer processor. */
+ 0 , /* The first channel's index. */
+ pRingBufferData1st, /* First ring buffer segment. */
+ 0 ); /* Use all available channels. */
+
+ /* If a second ring buffer segment is required. */
+ if( lRingBufferSize2nd ) {
+ /* Set number of frames to be copied to the ring buffer. */
+ PaUtil_Set2ndOutputFrameCount( pBp, lRingBufferSize2nd );
+ /* Setup ring buffer access. */
+ PaUtil_Set2ndInterleavedOutputChannels(pBp , /* Buffer processor. */
+ 0 , /* The first channel's index. */
+ pRingBufferData2nd, /* Second ring buffer segment. */
+ 0 ); /* Use all available channels. */
+ }
+
+ /* Let the buffer processor handle "copy and conversion" and
+ update the ring buffer indices manually. */
+ lFramesCopied = PaUtil_CopyOutput( pBp, &userBuffer, lFramesPerBlock );
+ PaUtil_AdvanceRingBufferWriteIndex( pRb, lFramesCopied );
+
+ /* Decrease number of unprocessed frames. */
+ lFramesRemaining -= lFramesCopied;
+
+ } /* Continue with the next data chunk. */
+ while( lFramesRemaining );
+
+
+ /* If there has been an output underflow within the callback */
+ if( blockingState->outputUnderflowFlag )
+ {
+ blockingState->outputUnderflowFlag = FALSE;
+
+ /* Return the corresponding error code. */
+ result = paOutputUnderflowed;
+ }
+
+ } /* If this is not an output stream. */
+ else
+ {
+ result = paCanNotWriteToAnInputOnlyStream;
+ }
+
+ return result;
}
@@ -2841,10 +3718,8 @@ static signed long GetStreamReadAvailable( PaStream* s )
{
PaAsioStream *stream = (PaAsioStream*)s;
- /* IMPLEMENT ME, see portaudio.h for required behavior*/
- (void) stream; /* unused parameter */
-
- return 0;
+ /* Call buffer utility routine to get the number of available frames. */
+ return PaUtil_GetRingBufferReadAvailable( &stream->blockingState->readRingBuffer );
}
@@ -2852,20 +3727,130 @@ static signed long GetStreamWriteAvailable( PaStream* s )
{
PaAsioStream *stream = (PaAsioStream*)s;
- /* IMPLEMENT ME, see portaudio.h for required behavior*/
- (void) stream; /* unused parameter */
+ /* Call buffer utility routine to get the number of empty buffers. */
+ return PaUtil_GetRingBufferWriteAvailable( &stream->blockingState->writeRingBuffer );
+}
+
+
+/* This routine will be called by the PortAudio engine when audio is needed.
+** It may called at interrupt level on some machines so don't do anything
+** that could mess up the system like calling malloc() or free().
+*/
+static int BlockingIoPaCallback(const void *inputBuffer ,
+ void *outputBuffer ,
+ unsigned long framesPerBuffer,
+ const PaStreamCallbackTimeInfo *timeInfo ,
+ PaStreamCallbackFlags statusFlags ,
+ void *userData )
+{
+ PaError result = paNoError; /* Initial return value. */
+ PaAsioStream *stream = *(PaAsioStream**)userData; /* The PA ASIO stream. */
+ PaAsioStreamBlockingState *blockingState = stream->blockingState; /* Persume blockingState is valid, otherwise the callback wouldn't be running. */
+
+ /* Get a pointer to the stream's blocking i/o buffer processor. */
+ PaUtilBufferProcessor *pBp = &blockingState->bufferProcessor;
+ PaUtilRingBuffer *pRb = NULL;
+
+ /* If output data has been requested. */
+ if( stream->outputChannelCount )
+ {
+ /* If the callback input argument signalizes a output underflow,
+ make sure the WriteStream() function knows about it, too! */
+ if( statusFlags & paOutputUnderflowed ) {
+ blockingState->outputUnderflowFlag = TRUE;
+ }
+
+ /* Access the corresponding ring buffer. */
+ pRb = &blockingState->writeRingBuffer;
+
+ /* If the blocking i/o buffer contains enough output data, */
+ if( PaUtil_GetRingBufferReadAvailable(pRb) >= (long) framesPerBuffer )
+ {
+ /* Extract the requested data from the ring buffer. */
+ PaUtil_ReadRingBuffer( pRb, outputBuffer, framesPerBuffer );
+ }
+ else /* If no output data is available :-( */
+ {
+ /* Signalize a write-buffer underflow. */
+ blockingState->outputUnderflowFlag = TRUE;
+
+ /* Fill the output buffer with silence. */
+ (*pBp->outputZeroer)( outputBuffer, 1, pBp->outputChannelCount * framesPerBuffer );
- return 0;
+ /* If playback is to be stopped */
+ if( blockingState->stopFlag && PaUtil_GetRingBufferReadAvailable(pRb) < (long) framesPerBuffer )
+ {
+ /* Extract all the remaining data from the ring buffer,
+ whether it is a complete data block or not. */
+ PaUtil_ReadRingBuffer( pRb, outputBuffer, PaUtil_GetRingBufferReadAvailable(pRb) );
+ }
+ }
+
+ /* Set blocking i/o event? */
+ if( blockingState->writeBuffersRequestedFlag && PaUtil_GetRingBufferWriteAvailable(pRb) >= (long) blockingState->writeBuffersRequested )
+ {
+ /* Reset buffer request. */
+ blockingState->writeBuffersRequestedFlag = FALSE;
+ blockingState->writeBuffersRequested = 0;
+ /* Signalize that requested buffers are ready. */
+ SetEvent( blockingState->writeBuffersReadyEvent );
+ /* What do we do if SetEvent() returns zero, i.e. the event
+ could not be set? How to return errors from within the
+ callback? - S.Fischer */
+ }
+ }
+
+ /* If input data has been supplied. */
+ if( stream->inputChannelCount )
+ {
+ /* If the callback input argument signalizes a input overflow,
+ make sure the ReadStream() function knows about it, too! */
+ if( statusFlags & paInputOverflowed ) {
+ blockingState->inputOverflowFlag = TRUE;
+ }
+
+ /* Access the corresponding ring buffer. */
+ pRb = &blockingState->readRingBuffer;
+
+ /* If the blocking i/o buffer contains not enough input buffers */
+ if( PaUtil_GetRingBufferWriteAvailable(pRb) < (long) framesPerBuffer )
+ {
+ /* Signalize a read-buffer overflow. */
+ blockingState->inputOverflowFlag = TRUE;
+
+ /* Remove some old data frames from the buffer. */
+ PaUtil_AdvanceRingBufferReadIndex( pRb, framesPerBuffer );
+ }
+
+ /* Insert the current input data into the ring buffer. */
+ PaUtil_WriteRingBuffer( pRb, inputBuffer, framesPerBuffer );
+
+ /* Set blocking i/o event? */
+ if( blockingState->readFramesRequestedFlag && PaUtil_GetRingBufferReadAvailable(pRb) >= (long) blockingState->readFramesRequested )
+ {
+ /* Reset buffer request. */
+ blockingState->readFramesRequestedFlag = FALSE;
+ blockingState->readFramesRequested = 0;
+ /* Signalize that requested buffers are ready. */
+ SetEvent( blockingState->readFramesReadyEvent );
+ /* What do we do if SetEvent() returns zero, i.e. the event
+ could not be set? How to return errors from within the
+ callback? - S.Fischer */
+ /** @todo report an error with PA_DEBUG */
+ }
+ }
+
+ return paContinue;
}
PaError PaAsio_ShowControlPanel( PaDeviceIndex device, void* systemSpecific )
{
- PaError result = paNoError;
+ PaError result = paNoError;
PaUtilHostApiRepresentation *hostApi;
PaDeviceIndex hostApiDevice;
ASIODriverInfo asioDriverInfo;
- ASIOError asioError;
+ ASIOError asioError;
int asioIsInitialized = 0;
PaAsioHostApiRepresentation *asioHostApi;
PaAsioDeviceInfo *asioDeviceInfo;
@@ -2896,7 +3881,10 @@ PaError PaAsio_ShowControlPanel( PaDeviceIndex device, void* systemSpecific )
asioDeviceInfo = (PaAsioDeviceInfo*)hostApi->deviceInfos[hostApiDevice];
- if( !loadAsioDriver( const_cast<char*>(asioDeviceInfo->commonDeviceInfo.name) ) )
+ /* See notes about CoInitialize(0) in LoadAsioDriver(). */
+ CoInitialize(0);
+
+ if( !asioHostApi->asioDrivers->loadDriver( const_cast<char*>(asioDeviceInfo->commonDeviceInfo.name) ) )
{
result = paUnanticipatedHostError;
goto error;
@@ -2944,15 +3932,19 @@ PA_DEBUG(("PaAsio_ShowControlPanel: ASIOControlPanel(): %s\n", PaAsio_GetAsioErr
goto error;
}
+ CoUninitialize();
PA_DEBUG(("PaAsio_ShowControlPanel: ASIOExit(): %s\n", PaAsio_GetAsioErrorText(asioError) ));
- return result;
+ return result;
error:
if( asioIsInitialized )
- ASIOExit();
+ {
+ ASIOExit();
+ }
+ CoUninitialize();
- return result;
+ return result;
}
@@ -3021,3 +4013,53 @@ PaError PaAsio_GetOutputChannelName( PaDeviceIndex device, int channelIndex,
error:
return result;
}
+
+
+/* NOTE: the following functions are ASIO-stream specific, and are called directly
+ by client code. We need to check for many more error conditions here because
+ we don't have the benefit of pa_front.c's parameter checking.
+*/
+
+static PaError GetAsioStreamPointer( PaAsioStream **stream, PaStream *s )
+{
+ PaError result;
+ PaUtilHostApiRepresentation *hostApi;
+ PaAsioHostApiRepresentation *asioHostApi;
+
+ result = PaUtil_ValidateStreamPointer( s );
+ if( result != paNoError )
+ return result;
+
+ result = PaUtil_GetHostApiRepresentation( &hostApi, paASIO );
+ if( result != paNoError )
+ return result;
+
+ asioHostApi = (PaAsioHostApiRepresentation*)hostApi;
+
+ if( PA_STREAM_REP( s )->streamInterface == &asioHostApi->callbackStreamInterface
+ || PA_STREAM_REP( s )->streamInterface == &asioHostApi->blockingStreamInterface )
+ {
+ /* s is an ASIO stream */
+ *stream = (PaAsioStream *)s;
+ return paNoError;
+ }
+ else
+ {
+ return paIncompatibleStreamHostApi;
+ }
+}
+
+
+PaError PaAsio_SetStreamSampleRate( PaStream* s, double sampleRate )
+{
+ PaAsioStream *stream;
+ PaError result = GetAsioStreamPointer( &stream, s );
+ if( result != paNoError )
+ return result;
+
+ if( stream != theAsioStream )
+ return paBadStreamPtr;
+
+ return ValidateAndSetSampleRate( sampleRate );
+}
+
diff --git a/pd/portaudio/src/hostapi/coreaudio/notes.txt b/pd/portaudio/src/hostapi/coreaudio/notes.txt
index ffe96962..145afe15 100644
--- a/pd/portaudio/src/hostapi/coreaudio/notes.txt
+++ b/pd/portaudio/src/hostapi/coreaudio/notes.txt
@@ -73,17 +73,24 @@ the stream with it. See below for creating a channel map.
Known issues:
-- Latency: Latency settings are ignored in most cases. Exceptions are when
-doing I/O between different devices and as a hint for selecting a realtively
-low or relatively high latency in conjunction with
-paHostFramesPerBufferUnspecified. Latency settings are always automatically
-bound to "safe" values, however, so setting extreme values here should not be
+- Buffering: No buffering beyond that provided by core audio is provided
+except where absolutely needed for the implementation to work. This may cause
+issues with large framesPerBuffer settings and it also means that no additional
+latency will be provided even if a large latency setting is selected.
+
+- Latency: Latency settings are generally ignored. They may be used as a
+hint for buffer size in paHostFramesPerBufferUnspecified, or the value may
+be used in cases where additional buffering is needed, such as doing input and
+output on seperate devices. Latency settings are always automatically bound
+to "safe" values, however, so setting extreme values here should not be
an issue.
- Buffer Size: paHostFramesPerBufferUnspecified and specific host buffer sizes
are supported. paHostFramesPerBufferUnspecified works best in "pro" mode,
where the buffer size and sample rate of the audio device is most likely
-to match the expected values.
+to match the expected values. In the case of paHostFramesPerBuffer, an
+appropriate framesPerBuffer value will be used that guarantees minimum
+requested latency if that's possible.
- Timing info. It reports on stream time, but I'm probably doing something
wrong since patest_sine_time often reports negative latency numbers. Also,
@@ -111,8 +118,7 @@ render quyality property is used to set the sample rate conversion quality
as "documented" here:
http://lists.apple.com/archives/coreaudio-api/2004/Jan/msg00141.html
-- x86/Universal Binary: to build a universal binary, be sure to use
-the darwin makefile and not the usual configure && make combo.
+- x86/Universal Binary: Universal binaries can be build.
diff --git a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core.c b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core.c
index 7c887bd6..98cfbb51 100644
--- a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core.c
+++ b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core.c
@@ -65,6 +65,7 @@
#include "pa_mac_core_internal.h"
#include <string.h> /* strlen(), memcmp() etc. */
+#include <libkern/OSAtomic.h>
#include "pa_mac_core.h"
#include "pa_mac_core_utilities.h"
@@ -127,6 +128,8 @@ const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input )
OSStatus error;
err = PaUtil_GetHostApiRepresentation( &hostApi, paCoreAudio );
assert(err == paNoError);
+ if( err != paNoError )
+ return NULL;
PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi;
AudioDeviceID hostApiDevice = macCoreHostApi->devIds[device];
@@ -261,11 +264,12 @@ static PaError GetChannelInfo( PaMacAUHAL *auhalHostApi,
int isInput);
static PaError OpenAndSetupOneAudioUnit(
+ const PaMacCoreStream *stream,
const PaStreamParameters *inStreamParams,
const PaStreamParameters *outStreamParams,
- const unsigned long requestedFramesPerBuffer,
- unsigned long *actualInputFramesPerBuffer,
- unsigned long *actualOutputFramesPerBuffer,
+ const UInt32 requestedFramesPerBuffer,
+ UInt32 *actualInputFramesPerBuffer,
+ UInt32 *actualOutputFramesPerBuffer,
const PaMacAUHAL *auhalHostApi,
AudioUnit *audioUnit,
AudioConverterRef *srConverter,
@@ -277,6 +281,37 @@ static PaError OpenAndSetupOneAudioUnit(
#define PA_AUHAL_SET_LAST_HOST_ERROR( errorCode, errorText ) \
PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
+/*
+ * Callback called when starting or stopping a stream.
+ */
+static void startStopCallback(
+ void * inRefCon,
+ AudioUnit ci,
+ AudioUnitPropertyID inID,
+ AudioUnitScope inScope,
+ AudioUnitElement inElement )
+{
+ PaMacCoreStream *stream = (PaMacCoreStream *) inRefCon;
+ UInt32 isRunning;
+ UInt32 size = sizeof( isRunning );
+ OSStatus err;
+ err = AudioUnitGetProperty( ci, kAudioOutputUnitProperty_IsRunning, inScope, inElement, &isRunning, &size );
+ assert( !err );
+ if( err )
+ isRunning = false; //it's very unclear what to do in case of error here. There's no real way to notify the user, and crashing seems unreasonable.
+ if( isRunning )
+ return; //We are only interested in when we are stopping
+ // -- if we are using 2 I/O units, we only need one notification!
+ if( stream->inputUnit && stream->outputUnit && stream->inputUnit != stream->outputUnit && ci == stream->inputUnit )
+ return;
+ PaStreamFinishedCallback *sfc = stream->streamRepresentation.streamFinishedCallback;
+ if( stream->state == STOPPING )
+ stream->state = STOPPED ;
+ if( sfc )
+ sfc( stream->streamRepresentation.userData );
+}
+
+
/*currently, this is only used in initialization, but it might be modified
to be used when the list of devices changes.*/
static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi)
@@ -497,9 +532,15 @@ PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIn
int i;
PaMacAUHAL *auhalHostApi;
PaDeviceInfo *deviceInfoArray;
+ int unixErr;
VVDBUG(("PaMacCore_Initialize(): hostApiIndex=%d\n", hostApiIndex));
+ unixErr = initializeXRunListenerList();
+ if( 0 != unixErr ) {
+ return UNIX_ERR(unixErr);
+ }
+
auhalHostApi = (PaMacAUHAL*)PaUtil_AllocateMemory( sizeof(PaMacAUHAL) );
if( !auhalHostApi )
{
@@ -618,10 +659,16 @@ error:
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
{
+ int unixErr;
+
PaMacAUHAL *auhalHostApi = (PaMacAUHAL*)hostApi;
VVDBUG(("Terminate()\n"));
+ unixErr = destroyXRunListenerList();
+ if( 0 != unixErr )
+ UNIX_ERR(unixErr);
+
/*
IMPLEMENT ME:
- clean up any resources not handled by the allocation group
@@ -737,11 +784,12 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
}
static PaError OpenAndSetupOneAudioUnit(
+ const PaMacCoreStream *stream,
const PaStreamParameters *inStreamParams,
const PaStreamParameters *outStreamParams,
- const unsigned long requestedFramesPerBuffer,
- unsigned long *actualInputFramesPerBuffer,
- unsigned long *actualOutputFramesPerBuffer,
+ const UInt32 requestedFramesPerBuffer,
+ UInt32 *actualInputFramesPerBuffer,
+ UInt32 *actualOutputFramesPerBuffer,
const PaMacAUHAL *auhalHostApi,
AudioUnit *audioUnit,
AudioConverterRef *srConverter,
@@ -753,7 +801,7 @@ static PaError OpenAndSetupOneAudioUnit(
Component comp;
/*An Apple TN suggests using CAStreamBasicDescription, but that is C++*/
AudioStreamBasicDescription desiredFormat;
- OSErr result = noErr;
+ OSStatus result = noErr;
PaError paResult = paNoError;
int line = 0;
UInt32 callbackKey;
@@ -881,7 +929,7 @@ static PaError OpenAndSetupOneAudioUnit(
audioDevice,
sizeof(AudioDeviceID) ) );
}
- if( outStreamParams )
+ if( outStreamParams && outStreamParams != inStreamParams )
{
*audioDevice = auhalHostApi->devIds[outStreamParams->device] ;
ERR_WRAP( AudioUnitSetProperty( *audioUnit,
@@ -891,6 +939,24 @@ static PaError OpenAndSetupOneAudioUnit(
audioDevice,
sizeof(AudioDeviceID) ) );
}
+ /* -- add listener for dropouts -- */
+ result = AudioDeviceAddPropertyListener( *audioDevice,
+ 0,
+ outStreamParams ? false : true,
+ kAudioDeviceProcessorOverload,
+ xrunCallback,
+ addToXRunListenerList( (void *)stream ) ) ;
+ if( result == kAudioHardwareIllegalOperationError ) {
+ // -- already registered, we're good
+ } else {
+ // -- not already registered, just check for errors
+ ERR_WRAP( result );
+ }
+ /* -- listen for stream start and stop -- */
+ ERR_WRAP( AudioUnitAddPropertyListener( *audioUnit,
+ kAudioOutputUnitProperty_IsRunning,
+ startStopCallback,
+ (void *)stream ) );
/* -- set format -- */
bzero( &desiredFormat, sizeof(desiredFormat) );
@@ -1010,7 +1076,7 @@ static PaError OpenAndSetupOneAudioUnit(
kAudioUnitScope_Input,
OUTPUT_ELEMENT,
actualOutputFramesPerBuffer,
- sizeof(unsigned long) ) );
+ sizeof(*actualOutputFramesPerBuffer) ) );
ERR_WRAP( AudioUnitGetProperty( *audioUnit,
kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global,
@@ -1025,7 +1091,7 @@ static PaError OpenAndSetupOneAudioUnit(
kAudioUnitScope_Output,
INPUT_ELEMENT,
actualInputFramesPerBuffer,
- sizeof(unsigned long) ) );
+ sizeof(*actualInputFramesPerBuffer) ) );
/* Don't know why this causes problems
ERR_WRAP( AudioUnitGetProperty( *audioUnit,
kAudioUnitProperty_MaximumFramesPerSlice,
@@ -1305,7 +1371,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/*requested a realtively low latency. make sure this is in range of devices */
/*try to get the device's min natural buffer size and use that (but no smaller than 64).*/
AudioValueRange audioRange;
- size_t size = sizeof( audioRange );
+ UInt32 size = sizeof( audioRange );
if( inputParameters ) {
WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[inputParameters->device],
0,
@@ -1315,6 +1381,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( result )
requested = MAX( requested, audioRange.mMinimum );
}
+ size = sizeof( audioRange );
if( outputParameters ) {
WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[outputParameters->device],
0,
@@ -1328,7 +1395,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* requested a realtively high latency. make sure this is in range of devices */
/*try to get the device's max natural buffer size and use that (but no larger than 1024).*/
AudioValueRange audioRange;
- size_t size = sizeof( audioRange );
+ UInt32 size = sizeof( audioRange );
requested = MIN( requested, 1024 );
if( inputParameters ) {
WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[inputParameters->device],
@@ -1339,6 +1406,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( result )
requested = MIN( requested, audioRange.mMaximum );
}
+ size = sizeof( audioRange );
if( outputParameters ) {
WARNING( result = AudioDeviceGetProperty( auhalHostApi->devIds[outputParameters->device],
0,
@@ -1359,17 +1427,22 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* -- Now we actually open and setup streams. -- */
if( inputParameters && outputParameters && outputParameters->device == inputParameters->device )
{ /* full duplex. One device. */
- result = OpenAndSetupOneAudioUnit( inputParameters,
+ UInt32 inputFramesPerBuffer = (UInt32) stream->inputFramesPerBuffer;
+ UInt32 outputFramesPerBuffer = (UInt32) stream->outputFramesPerBuffer;
+ result = OpenAndSetupOneAudioUnit( stream,
+ inputParameters,
outputParameters,
framesPerBuffer,
- &(stream->inputFramesPerBuffer),
- &(stream->outputFramesPerBuffer),
+ &inputFramesPerBuffer,
+ &outputFramesPerBuffer,
auhalHostApi,
&(stream->inputUnit),
&(stream->inputSRConverter),
&(stream->inputDevice),
sampleRate,
stream );
+ stream->inputFramesPerBuffer = inputFramesPerBuffer;
+ stream->outputFramesPerBuffer = outputFramesPerBuffer;
stream->outputUnit = stream->inputUnit;
stream->outputDevice = stream->inputDevice;
if( result != paNoError )
@@ -1377,11 +1450,14 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
else
{ /* full duplex, different devices OR simplex */
- result = OpenAndSetupOneAudioUnit( NULL,
+ UInt32 outputFramesPerBuffer = (UInt32) stream->outputFramesPerBuffer;
+ UInt32 inputFramesPerBuffer = (UInt32) stream->inputFramesPerBuffer;
+ result = OpenAndSetupOneAudioUnit( stream,
+ NULL,
outputParameters,
framesPerBuffer,
NULL,
- &(stream->outputFramesPerBuffer),
+ &outputFramesPerBuffer,
auhalHostApi,
&(stream->outputUnit),
NULL,
@@ -1390,10 +1466,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream );
if( result != paNoError )
goto error;
- result = OpenAndSetupOneAudioUnit( inputParameters,
+ result = OpenAndSetupOneAudioUnit( stream,
+ inputParameters,
NULL,
framesPerBuffer,
- &(stream->inputFramesPerBuffer),
+ &inputFramesPerBuffer,
NULL,
auhalHostApi,
&(stream->inputUnit),
@@ -1403,6 +1480,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
stream );
if( result != paNoError )
goto error;
+ stream->inputFramesPerBuffer = inputFramesPerBuffer;
+ stream->outputFramesPerBuffer = outputFramesPerBuffer;
}
if( stream->inputUnit ) {
@@ -1456,8 +1535,16 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
/* now we can initialize the ring buffer */
+ //FIXME: element size whould probably be szfl*inputchan
+ // but that will require some work all over the
+ // place to patch up. szfl may be sufficient and would
+ // be way easier to handle, but it seems clear from the
+ // discussion that buffer processor compatibility
+ // requires szfl*inputchan.
+ // See revision 1346 and discussion:
+ // http://techweb.rfa.org/pipermail/portaudio/2008-February/008295.html
PaUtil_InitializeRingBuffer( &stream->inputRingBuffer,
- ringSize*szfl, data ) ;
+ 1, ringSize*szfl, data ) ;
/* advance the read point a little, so we are reading from the
middle of the buffer */
if( stream->outputUnit )
@@ -1727,14 +1814,14 @@ static OSStatus AudioIOProc( void *inRefCon,
* we do not use the input SR converter or the input ring buffer.
*
*/
- OSErr err = 0;
+ OSStatus err = 0;
unsigned long frames;
/* -- start processing -- */
PaUtil_BeginBufferProcessing( &(stream->bufferProcessor),
&timeInfo,
stream->xrunFlags );
- stream->xrunFlags = 0;
+ stream->xrunFlags = 0; //FIXME: this flag also gets set outside by a callback, which calls the xrunCallback function. It should be in the same thread as the main audio callback, but the apple docs just use the word "usually" so it may be possible to loose an xrun notification, if that callback happens here.
/* -- compute frames. do some checks -- */
assert( ioData->mNumberBuffers == 1 );
@@ -1748,7 +1835,8 @@ static OSStatus AudioIOProc( void *inRefCon,
INPUT_ELEMENT,
inNumberFrames,
&stream->inputAudioBufferList );
- /* FEEDBACK: I'm not sure what to do when this call fails */
+ /* FEEDBACK: I'm not sure what to do when this call fails. There's nothing in the PA API to
+ * do about failures in the callback system. */
assert( !err );
PaUtil_SetInputFrameCount( &(stream->bufferProcessor), frames );
@@ -1868,7 +1956,7 @@ static OSStatus AudioIOProc( void *inRefCon,
PaUtil_AdvanceRingBufferReadIndex(&stream->inputRingBuffer, size1 );
} else if( ( size1 + size2 ) / ( flsz * inChan ) < frames ) {
/*we underflowed. take what data we can, zero the rest.*/
- float data[frames*inChan];
+ unsigned char data[frames*inChan*flsz];
if( size1 )
memcpy( data, data1, size1 );
if( size2 )
@@ -1922,7 +2010,7 @@ static OSStatus AudioIOProc( void *inRefCon,
* if this is an input-only stream, we need to process it more,
* otherwise, we let the output case deal with it.
*/
- OSErr err = 0;
+ OSStatus err = 0;
int chan = stream->inputAudioBufferList.mBuffers[0].mNumberChannels ;
/* FIXME: looping here may not actually be necessary, but it was something I tried in testing. */
do {
@@ -2054,6 +2142,24 @@ static PaError CloseStream( PaStream* s )
VDBUG( ( "Closing stream.\n" ) );
if( stream ) {
+ if( stream->outputUnit ) {
+ int count = removeFromXRunListenerList( stream );
+ if( count == 0 )
+ AudioDeviceRemovePropertyListener( stream->outputDevice,
+ 0,
+ false,
+ kAudioDeviceProcessorOverload,
+ xrunCallback );
+ }
+ if( stream->inputUnit && stream->outputUnit != stream->inputUnit ) {
+ int count = removeFromXRunListenerList( stream );
+ if( count == 0 )
+ AudioDeviceRemovePropertyListener( stream->inputDevice,
+ 0,
+ true,
+ kAudioDeviceProcessorOverload,
+ xrunCallback );
+ }
if( stream->outputUnit && stream->outputUnit != stream->inputUnit ) {
AudioUnitUninitialize( stream->outputUnit );
CloseComponent( stream->outputUnit );
@@ -2089,11 +2195,10 @@ static PaError CloseStream( PaStream* s )
return result;
}
-
static PaError StartStream( PaStream *s )
{
PaMacCoreStream *stream = (PaMacCoreStream*)s;
- OSErr result = noErr;
+ OSStatus result = noErr;
VVDBUG(("StartStream()\n"));
VDBUG( ( "Starting stream.\n" ) );
@@ -2138,7 +2243,7 @@ static ComponentResult BlockWhileAudioUnitIsRunning( AudioUnit audioUnit, AudioU
static PaError StopStream( PaStream *s )
{
PaMacCoreStream *stream = (PaMacCoreStream*)s;
- OSErr result = noErr;
+ OSStatus result = noErr;
PaError paErr;
VVDBUG(("StopStream()\n"));
diff --git a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c
index 3b81389d..6d31a713 100644
--- a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c
+++ b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c
@@ -53,7 +53,7 @@
/**
@file
- @ingroup hostaip_src
+ @ingroup hostapi_src
This file contains the implementation
required for blocking I/O. It is separated from pa_mac_core.c simply to ease
@@ -85,6 +85,22 @@ static size_t computeSampleSizeFromFormat( PaSampleFormat format )
default: return 0;
}
}
+/*
+ * Same as computeSampleSizeFromFormat, except that if
+ * the size is not a power of two, it returns the next power of two up
+ */
+static size_t computeSampleSizeFromFormatPow2( PaSampleFormat format )
+{
+ switch( format ) {
+ case paFloat32: return 4;
+ case paInt32: return 4;
+ case paInt24: return 4;
+ case paInt16: return 2;
+ case paInt8: case paUInt8: return 1;
+ default: return 0;
+ }
+}
+
/*
@@ -105,6 +121,7 @@ PaError initializeBlioRingBuffers(
{
void *data;
int result;
+ OSStatus err;
/* zeroify things */
bzero( blio, sizeof( PaMacBlio ) );
@@ -114,10 +131,14 @@ PaError initializeBlioRingBuffers(
blio->outputRingBuffer.buffer = NULL;
/* initialize simple data */
+ blio->ringBufferFrames = ringBufferSize;
blio->inputSampleFormat = inputSampleFormat;
- blio->inputSampleSize = computeSampleSizeFromFormat(inputSampleFormat);
+ blio->inputSampleSizeActual = computeSampleSizeFromFormat(inputSampleFormat);
+ blio->inputSampleSizePow2 = computeSampleSizeFromFormatPow2(inputSampleFormat);
blio->outputSampleFormat = outputSampleFormat;
- blio->outputSampleSize = computeSampleSizeFromFormat(outputSampleFormat);
+ blio->outputSampleSizeActual = computeSampleSizeFromFormat(outputSampleFormat);
+ blio->outputSampleSizePow2 = computeSampleSizeFromFormatPow2(outputSampleFormat);
+
blio->framesPerBuffer = framesPerBuffer;
blio->inChan = inChan;
blio->outChan = outChan;
@@ -142,30 +163,32 @@ PaError initializeBlioRingBuffers(
result = UNIX_ERR( pthread_cond_init( &(blio->outputCond), NULL ) );
#endif
if( inChan ) {
- data = calloc( ringBufferSize, blio->inputSampleSize );
+ data = calloc( ringBufferSize, blio->inputSampleSizePow2*inChan );
if( !data )
{
result = paInsufficientMemory;
goto error;
}
- assert( 0 == PaUtil_InitializeRingBuffer(
+ err = PaUtil_InitializeRingBuffer(
&blio->inputRingBuffer,
- ringBufferSize*blio->inputSampleSize,
- data ) );
+ 1, ringBufferSize*blio->inputSampleSizePow2*inChan,
+ data );
+ assert( !err );
}
if( outChan ) {
- data = calloc( ringBufferSize, blio->outputSampleSize );
+ data = calloc( ringBufferSize, blio->outputSampleSizePow2*outChan );
if( !data )
{
result = paInsufficientMemory;
goto error;
}
- assert( 0 == PaUtil_InitializeRingBuffer(
+ err = PaUtil_InitializeRingBuffer(
&blio->outputRingBuffer,
- ringBufferSize*blio->outputSampleSize,
- data ) );
+ 1, ringBufferSize*blio->outputSampleSizePow2*outChan,
+ data );
+ assert( !err );
}
result = resetBlioRingBuffers( blio );
@@ -247,7 +270,8 @@ PaError resetBlioRingBuffers( PaMacBlio *blio )
bzero( blio->outputRingBuffer.buffer,
blio->outputRingBuffer.bufferSize );
/* Advance buffer */
- PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->outputRingBuffer.bufferSize );
+ PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->ringBufferFrames*blio->outputSampleSizeActual*blio->outChan );
+ //PaUtil_AdvanceRingBufferWriteIndex( &blio->outputRingBuffer, blio->outputRingBuffer.bufferSize );
/* Update isOutputFull. */
#ifdef PA_MAC__BLIO_MUTEX
@@ -323,6 +347,8 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
long avail;
long toRead;
long toWrite;
+ long read;
+ long written;
/* set flags returned by OS: */
OSAtomicOr32( statusFlags, &blio->statusFlags ) ;
@@ -332,14 +358,15 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
avail = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer );
/* check for underflow */
- if( avail < frameCount * blio->inputSampleSize * blio->inChan )
+ if( avail < frameCount * blio->inputSampleSizeActual * blio->inChan )
OSAtomicOr32( paInputOverflow, &blio->statusFlags );
- toRead = MIN( avail, frameCount * blio->inputSampleSize * blio->inChan );
+ toRead = MIN( avail, frameCount * blio->inputSampleSizeActual * blio->inChan );
/* copy the data */
/*printf( "reading %d\n", toRead );*/
- assert( toRead == PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, toRead ) );
+ read = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, toRead );
+ assert( toRead == read );
#ifdef PA_MAC__BLIO_MUTEX
/* Priority inversion. See notes below. */
blioSetIsInputEmpty( blio, false );
@@ -352,17 +379,18 @@ int BlioCallback( const void *input, void *output, unsigned long frameCount,
avail = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
/* check for underflow */
- if( avail < frameCount * blio->outputSampleSize * blio->outChan )
+ if( avail < frameCount * blio->outputSampleSizeActual * blio->outChan )
OSAtomicOr32( paOutputUnderflow, &blio->statusFlags );
- toWrite = MIN( avail, frameCount * blio->outputSampleSize * blio->outChan );
+ toWrite = MIN( avail, frameCount * blio->outputSampleSizeActual * blio->outChan );
- if( toWrite != frameCount * blio->outputSampleSize * blio->outChan )
+ if( toWrite != frameCount * blio->outputSampleSizeActual * blio->outChan )
bzero( ((char *)output)+toWrite,
- frameCount * blio->outputSampleSize * blio->outChan - toWrite );
+ frameCount * blio->outputSampleSizeActual * blio->outChan - toWrite );
/* copy the data */
/*printf( "writing %d\n", toWrite );*/
- assert( toWrite == PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, toWrite ) );
+ written = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, toWrite );
+ assert( toWrite == written );
#ifdef PA_MAC__BLIO_MUTEX
/* We have a priority inversion here. However, we will only have to
wait if this was true and is now false, which means we've got
@@ -413,11 +441,11 @@ PaError ReadStream( PaStream* stream,
#endif
}
} while( avail == 0 );
- toRead = MIN( avail, frames * blio->inputSampleSize * blio->inChan );
- toRead -= toRead % blio->inputSampleSize * blio->inChan ;
+ toRead = MIN( avail, frames * blio->inputSampleSizeActual * blio->inChan );
+ toRead -= toRead % blio->inputSampleSizeActual * blio->inChan ;
PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, toRead );
cbuf += toRead;
- frames -= toRead / ( blio->inputSampleSize * blio->inChan );
+ frames -= toRead / ( blio->inputSampleSizeActual * blio->inChan );
if( toRead == avail ) {
#ifdef PA_MAC_BLIO_MUTEX
@@ -443,7 +471,7 @@ PaError ReadStream( PaStream* stream,
/* report underflow only once: */
if( ret ) {
- OSAtomicAnd32( ~paInputOverflow, &blio->statusFlags );
+ OSAtomicAnd32( (uint32_t)(~paInputOverflow), &blio->statusFlags );
ret = paInputOverflowed;
}
@@ -491,11 +519,11 @@ PaError WriteStream( PaStream* stream,
}
} while( avail == 0 );
- toWrite = MIN( avail, frames * blio->outputSampleSize * blio->outChan );
- toWrite -= toWrite % blio->outputSampleSize * blio->outChan ;
+ toWrite = MIN( avail, frames * blio->outputSampleSizeActual * blio->outChan );
+ toWrite -= toWrite % blio->outputSampleSizeActual * blio->outChan ;
PaUtil_WriteRingBuffer( &blio->outputRingBuffer, (void *)cbuf, toWrite );
cbuf += toWrite;
- frames -= toWrite / ( blio->outputSampleSize * blio->outChan );
+ frames -= toWrite / ( blio->outputSampleSizeActual * blio->outChan );
#ifdef PA_MAC_BLIO_MUTEX
if( toWrite == avail ) {
@@ -520,7 +548,7 @@ PaError WriteStream( PaStream* stream,
/* report underflow only once: */
if( ret ) {
- OSAtomicAnd32( ~paOutputUnderflow, &blio->statusFlags );
+ OSAtomicAnd32( (uint32_t)(~paOutputUnderflow), &blio->statusFlags );
ret = paOutputUnderflowed;
}
@@ -549,7 +577,7 @@ signed long GetStreamReadAvailable( PaStream* stream )
VVDBUG(("GetStreamReadAvailable()\n"));
return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer )
- / ( blio->outputSampleSize * blio->outChan );
+ / ( blio->inputSampleSizeActual * blio->inChan );
}
@@ -559,6 +587,6 @@ signed long GetStreamWriteAvailable( PaStream* stream )
VVDBUG(("GetStreamWriteAvailable()\n"));
return PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer )
- / ( blio->outputSampleSize * blio->outChan );
+ / ( blio->outputSampleSizeActual * blio->outChan );
}
diff --git a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h
index 8ad79eaa..971223b3 100644
--- a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h
+++ b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h
@@ -53,7 +53,7 @@
/**
@file
- @ingroup hostaip_src
+ @ingroup hostapi_src
*/
#ifndef PA_MAC_CORE_BLOCKING_H_
@@ -79,10 +79,13 @@
typedef struct {
PaUtilRingBuffer inputRingBuffer;
PaUtilRingBuffer outputRingBuffer;
+ size_t ringBufferFrames;
PaSampleFormat inputSampleFormat;
- size_t inputSampleSize;
+ size_t inputSampleSizeActual;
+ size_t inputSampleSizePow2;
PaSampleFormat outputSampleFormat;
- size_t outputSampleSize;
+ size_t outputSampleSizeActual;
+ size_t outputSampleSizePow2;
size_t framesPerBuffer;
diff --git a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h
index 998b819c..1797cbaf 100644
--- a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h
+++ b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_internal.h
@@ -61,10 +61,11 @@
#ifndef PA_MAC_CORE_INTERNAL_H__
#define PA_MAC_CORE_INTERNAL_H__
+#include <CoreAudio/CoreAudio.h>
+#include <CoreServices/CoreServices.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
-
#include "portaudio.h"
#include "pa_util.h"
#include "pa_hostapi.h"
@@ -139,6 +140,7 @@ typedef struct PaMacCoreStream
/* We need to preallocate an inputBuffer for reading data. */
AudioBufferList inputAudioBufferList;
AudioTimeStamp startTime;
+ /* FIXME: instead of volatile, these should be properly memory barriered */
volatile PaStreamCallbackFlags xrunFlags;
volatile bool isTimeSet;
volatile enum {
@@ -146,7 +148,8 @@ typedef struct PaMacCoreStream
and the user has called StopStream(). */
CALLBACK_STOPPED = 1, /* callback has requested stop,
but user has not yet called StopStream(). */
- STOPPING = 2, /* The stream is in the process of closing.
+ STOPPING = 2, /* The stream is in the process of closing
+ because the user has called StopStream.
This state is just used internally;
externally it is indistinguishable from
ACTIVE.*/
diff --git a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c
index 37403251..5bc592e8 100644
--- a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c
+++ b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c
@@ -57,6 +57,10 @@
*/
#include "pa_mac_core_utilities.h"
+#include "pa_mac_core_internal.h"
+#include <libkern/OSAtomic.h>
+#include <strings.h>
+#include <pthread.h>
PaError PaMacCore_SetUnixError( int err, int line )
{
@@ -199,10 +203,19 @@ PaError PaMacCore_SetError(OSStatus error, int line, int isError)
else
errorType = "Warning";
- if ((int)error < -99999 || (int)error > 99999)
- DBUG(("%s on line %d: err='%4s', msg='%s'\n", errorType, line, (const char *)&error, errorText));
- else
- DBUG(("%s on line %d: err=%d, 0x%x, msg='%s'\n", errorType, line, (int)error, (unsigned)error, errorText));
+ char str[20];
+ // see if it appears to be a 4-char-code
+ *(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error);
+ if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4]))
+ {
+ str[0] = str[5] = '\'';
+ str[6] = '\0';
+ } else {
+ // no, format it as an integer
+ sprintf(str, "%d", (int)error);
+ }
+
+ DBUG(("%s on line %d: err='%s', msg=%s\n", errorType, line, str, errorText));
PaUtil_SetLastHostErrorInfo( paCoreAudio, error, errorText );
@@ -520,9 +533,9 @@ PaError setBestSampleRateForDevice( const AudioDeviceID device,
not usually catastrophic.
*/
PaError setBestFramesPerBuffer( const AudioDeviceID device,
- const bool isOutput,
- unsigned long requestedFramesPerBuffer,
- unsigned long *actualFramesPerBuffer )
+ const bool isOutput,
+ UInt32 requestedFramesPerBuffer,
+ UInt32 *actualFramesPerBuffer )
{
UInt32 afpb;
const bool isInput = !isOutput;
@@ -609,3 +622,117 @@ PaError setBestFramesPerBuffer( const AudioDeviceID device,
return paNoError;
}
+
+/**********************
+ *
+ * XRun stuff
+ *
+ **********************/
+
+struct PaMacXRunListNode_s {
+ PaMacCoreStream *stream;
+ struct PaMacXRunListNode_s *next;
+} ;
+
+typedef struct PaMacXRunListNode_s PaMacXRunListNode;
+
+/** Always empty, so that it can always be the one returned by
+ addToXRunListenerList. note that it's not a pointer. */
+static PaMacXRunListNode firstXRunListNode;
+static int xRunListSize;
+static pthread_mutex_t xrunMutex;
+
+OSStatus xrunCallback(
+ AudioDeviceID inDevice,
+ UInt32 inChannel,
+ Boolean isInput,
+ AudioDevicePropertyID inPropertyID,
+ void* inClientData)
+{
+ PaMacXRunListNode *node = (PaMacXRunListNode *) inClientData;
+
+ int ret = pthread_mutex_trylock( &xrunMutex ) ;
+
+ if( ret == 0 ) {
+
+ node = node->next ; //skip the first node
+
+ for( ; node; node=node->next ) {
+ PaMacCoreStream *stream = node->stream;
+
+ if( stream->state != ACTIVE )
+ continue; //if the stream isn't active, we don't care if the device is dropping
+
+ if( isInput ) {
+ if( stream->inputDevice == inDevice )
+ OSAtomicOr32( paInputOverflow, (uint32_t *)&(stream->xrunFlags) );
+ } else {
+ if( stream->outputDevice == inDevice )
+ OSAtomicOr32( paOutputUnderflow, (uint32_t *)&(stream->xrunFlags) );
+ }
+ }
+
+ pthread_mutex_unlock( &xrunMutex );
+ }
+
+ return 0;
+}
+
+int initializeXRunListenerList()
+{
+ xRunListSize = 0;
+ bzero( (void *) &firstXRunListNode, sizeof(firstXRunListNode) );
+ return pthread_mutex_init( &xrunMutex, NULL );
+}
+int destroyXRunListenerList()
+{
+ PaMacXRunListNode *node;
+ node = firstXRunListNode.next;
+ while( node ) {
+ PaMacXRunListNode *tmp = node;
+ node = node->next;
+ free( tmp );
+ }
+ xRunListSize = 0;
+ return pthread_mutex_destroy( &xrunMutex );
+}
+
+void *addToXRunListenerList( void *stream )
+{
+ pthread_mutex_lock( &xrunMutex );
+ PaMacXRunListNode *newNode;
+ // setup new node:
+ newNode = (PaMacXRunListNode *) malloc( sizeof( PaMacXRunListNode ) );
+ newNode->stream = (PaMacCoreStream *) stream;
+ newNode->next = firstXRunListNode.next;
+ // insert:
+ firstXRunListNode.next = newNode;
+ pthread_mutex_unlock( &xrunMutex );
+
+ return &firstXRunListNode;
+}
+
+int removeFromXRunListenerList( void *stream )
+{
+ pthread_mutex_lock( &xrunMutex );
+ PaMacXRunListNode *node, *prev;
+ prev = &firstXRunListNode;
+ node = firstXRunListNode.next;
+ while( node ) {
+ if( node->stream == stream ) {
+ //found it:
+ --xRunListSize;
+ prev->next = node->next;
+ free( node );
+ pthread_mutex_unlock( &xrunMutex );
+ return xRunListSize;
+ }
+ prev = prev->next;
+ node = node->next;
+ }
+
+ pthread_mutex_unlock( &xrunMutex );
+ // failure
+ return xRunListSize;
+}
+
diff --git a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h
index 8a69c25a..899826d5 100644
--- a/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h
+++ b/pd/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.h
@@ -199,7 +199,32 @@ PaError setBestSampleRateForDevice( const AudioDeviceID device,
not usually catastrophic.
*/
PaError setBestFramesPerBuffer( const AudioDeviceID device,
- const bool isOutput,
- unsigned long requestedFramesPerBuffer,
- unsigned long *actualFramesPerBuffer );
+ const bool isOutput,
+ UInt32 requestedFramesPerBuffer,
+ UInt32 *actualFramesPerBuffer );
+
+
+/*********************
+ *
+ * xrun handling
+ *
+ *********************/
+
+OSStatus xrunCallback(
+ AudioDeviceID inDevice,
+ UInt32 inChannel,
+ Boolean isInput,
+ AudioDevicePropertyID inPropertyID,
+ void* inClientData ) ;
+
+/** returns zero on success or a unix style error code. */
+int initializeXRunListenerList();
+/** returns zero on success or a unix style error code. */
+int destroyXRunListenerList();
+
+/**Returns the list, so that it can be passed to CorAudio.*/
+void *addToXRunListenerList( void *stream );
+/**Returns the number of Listeners in the list remaining.*/
+int removeFromXRunListenerList( void *stream );
+
#endif /* PA_MAC_CORE_UTILITIES_H__*/
diff --git a/pd/portaudio/src/hostapi/jack/pa_jack.c b/pd/portaudio/src/hostapi/jack/pa_jack.c
index 6b6c2120..6732c9b1 100644
--- a/pd/portaudio/src/hostapi/jack/pa_jack.c
+++ b/pd/portaudio/src/hostapi/jack/pa_jack.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_jack.c 1238 2007-07-15 16:58:50Z aknudsen $
+ * $Id: pa_jack.c 1346 2008-02-20 10:09:20Z rossb $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* JACK Implementation by Joshua Haberman
@@ -254,7 +254,7 @@ static PaError BlockingInitFIFO( PaUtilRingBuffer *rbuf, long numFrames, long by
char *buffer = (char *) malloc( numBytes );
if( buffer == NULL ) return paInsufficientMemory;
memset( buffer, 0, numBytes );
- return (PaError) PaUtil_InitializeRingBuffer( rbuf, numBytes, buffer );
+ return (PaError) PaUtil_InitializeRingBuffer( rbuf, 1, numBytes, buffer );
}
/* Free buffer. */
@@ -717,14 +717,19 @@ PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
ASSERT_CALL( pthread_cond_init( &jackHostApi->cond, NULL ), 0 );
/* Try to become a client of the JACK server. If we cannot do
- * this, then this API cannot be used. */
+ * this, then this API cannot be used.
+ *
+ * Without the JackNoStartServer option, the jackd server is started
+ * automatically which we do not want.
+ */
- jackHostApi->jack_client = jack_client_open( clientName_, 0, &jackStatus );
+ jackHostApi->jack_client = jack_client_open( clientName_, JackNoStartServer, &jackStatus );
if( !jackHostApi->jack_client )
{
/* the V19 development docs say that if an implementation
* detects that it cannot be used, it should return a NULL
* interface and paNoError */
+ PA_DEBUG(( "%s: Couldn't connect to JACK, status: %d\n", __FUNCTION__, jackStatus ));
result = paNoError;
goto error;
}
@@ -737,7 +742,6 @@ PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
(*hostApi)->info.name = "JACK Audio Connection Kit";
/* Build a device list by querying the JACK server */
-
ENSURE_PA( BuildDeviceList( jackHostApi ) );
/* Register functions */
@@ -1748,7 +1752,8 @@ PaError PaJack_GetClientName(const char** clientName)
{
PaError result = paNoError;
PaJackHostApiRepresentation* jackHostApi = NULL;
- ENSURE_PA( PaUtil_GetHostApiRepresentation( (PaUtilHostApiRepresentation**)&jackHostApi, paJACK ) );
+ PaJackHostApiRepresentation** ref = &jackHostApi;
+ ENSURE_PA( PaUtil_GetHostApiRepresentation( (PaUtilHostApiRepresentation**)ref, paJACK ) );
*clientName = jack_get_client_name( jackHostApi->jack_client );
error:
diff --git a/pd/portaudio/src/hostapi/oss/pa_unix_oss.c b/pd/portaudio/src/hostapi/oss/pa_unix_oss.c
index 516f5a45..8d8424fc 100644
--- a/pd/portaudio/src/hostapi/oss/pa_unix_oss.c
+++ b/pd/portaudio/src/hostapi/oss/pa_unix_oss.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_unix_oss.c 1238 2007-07-15 16:58:50Z aknudsen $
+ * $Id: pa_unix_oss.c 1385 2008-06-05 21:13:54Z aknudsen $
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
* OSS implementation by:
@@ -65,7 +65,11 @@
#ifdef HAVE_SYS_SOUNDCARD_H
# include <sys/soundcard.h>
-# define DEVICE_NAME_BASE "/dev/dsp"
+# ifdef __NetBSD__
+# define DEVICE_NAME_BASE "/dev/audio"
+# else
+# define DEVICE_NAME_BASE "/dev/dsp"
+# endif
#elif defined(HAVE_LINUX_SOUNDCARD_H)
# include <linux/soundcard.h>
# define DEVICE_NAME_BASE "/dev/dsp"
@@ -97,7 +101,7 @@ static pthread_t mainThread_;
/* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \
if( (code) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
{ \
- PaUtil_SetLastHostErrorInfo( paALSA, sysErr_, strerror( errno ) ); \
+ PaUtil_SetLastHostErrorInfo( paOSS, sysErr_, strerror( errno ) ); \
} \
\
PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
@@ -332,7 +336,11 @@ static PaError QueryDirection( const char *deviceName, StreamMode mode, double *
}
else
{
- PA_DEBUG(( "%s: Can't access device: %s\n", __FUNCTION__, strerror( errno ) ));
+ /* Ignore ENOENT, which means we've tried a non-existent device */
+ if( errno != ENOENT )
+ {
+ PA_DEBUG(( "%s: Can't access device %s: %s\n", __FUNCTION__, deviceName, strerror( errno ) ));
+ }
}
return paDeviceUnavailable;
@@ -401,11 +409,7 @@ static PaError QueryDirection( const char *deviceName, StreamMode mode, double *
if( *defaultSampleRate < 0 )
{
sr = 44100;
- if( ioctl( devHandle, SNDCTL_DSP_SPEED, &sr ) < 0 )
- {
- result = paUnanticipatedHostError;
- goto error;
- }
+ ENSURE_( ioctl( devHandle, SNDCTL_DSP_SPEED, &sr ), paUnanticipatedHostError );
*defaultSampleRate = sr;
}
@@ -508,27 +512,20 @@ static PaError BuildDeviceList( PaOSSHostApiRepresentation *ossApi )
/* Find devices by calling QueryDevice on each
* potential device names. When we find a valid one,
* add it to a linked list.
- * A: Can there only be 10 devices? */
+ * A: Set an arbitrary of 100 devices, should probably be a smarter way. */
- for( i = 0; i < 10; i++ )
+ for( i = 0; i < 100; i++ )
{
char deviceName[32];
PaDeviceInfo *deviceInfo;
int testResult;
- struct stat stbuf;
if( i == 0 )
snprintf(deviceName, sizeof (deviceName), "%s", DEVICE_NAME_BASE);
else
snprintf(deviceName, sizeof (deviceName), "%s%d", DEVICE_NAME_BASE, i);
- /* PA_DEBUG(("PaOSS BuildDeviceList: trying device %s\n", deviceName )); */
- if( stat( deviceName, &stbuf ) < 0 )
- {
- if( ENOENT != errno )
- PA_DEBUG(( "%s: Error stat'ing %s: %s\n", __FUNCTION__, deviceName, strerror( errno ) ));
- continue;
- }
+ /* PA_DEBUG(("%s: trying device %s\n", __FUNCTION__, deviceName )); */
if( (testResult = QueryDevice( deviceName, ossApi, &deviceInfo )) != paNoError )
{
if( testResult != paDeviceUnavailable )
@@ -785,11 +782,15 @@ error:
return result;
}
+/** Open input and output devices.
+ *
+ * @param idev: Returned input device file descriptor.
+ * @param odev: Returned output device file descriptor.
+ */
static PaError OpenDevices( const char *idevName, const char *odevName, int *idev, int *odev )
{
PaError result = paNoError;
int flags = O_NONBLOCK, duplex = 0;
- int enableBits = 0;
*idev = *odev = -1;
if( idevName && odevName )
@@ -809,10 +810,6 @@ static PaError OpenDevices( const char *idevName, const char *odevName, int *ide
{
ENSURE_( *idev = open( idevName, flags ), paDeviceUnavailable );
PA_ENSURE( ModifyBlocking( *idev, 1 ) ); /* Blocking */
-
- /* Initially disable */
- enableBits = ~PCM_ENABLE_INPUT;
- ENSURE_( ioctl( *idev, SNDCTL_DSP_SETTRIGGER, &enableBits ), paUnanticipatedHostError );
}
if( odevName )
{
@@ -820,10 +817,6 @@ static PaError OpenDevices( const char *idevName, const char *odevName, int *ide
{
ENSURE_( *odev = open( odevName, flags ), paDeviceUnavailable );
PA_ENSURE( ModifyBlocking( *odev, 1 ) ); /* Blocking */
-
- /* Initially disable */
- enableBits = ~PCM_ENABLE_OUTPUT;
- ENSURE_( ioctl( *odev, SNDCTL_DSP_SETTRIGGER, &enableBits ), paUnanticipatedHostError );
}
else
{
@@ -976,8 +969,10 @@ static int CalcHigherLogTwo( int n )
return log2;
}
-static PaError PaOssStreamComponent_Configure( PaOssStreamComponent *component, double sampleRate, unsigned long framesPerBuffer,
- StreamMode streamMode, PaOssStreamComponent *master )
+/** Configure stream component device parameters.
+ */
+static PaError PaOssStreamComponent_Configure( PaOssStreamComponent *component, double sampleRate, unsigned long
+ framesPerBuffer, StreamMode streamMode, PaOssStreamComponent *master )
{
PaError result = paNoError;
int temp, nativeFormat;
@@ -1189,6 +1184,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
const PaDeviceInfo *inputDeviceInfo = 0, *outputDeviceInfo = 0;
int bpInitialized = 0;
double inLatency = 0., outLatency = 0.;
+ int i = 0;
/* validate platform specific flags */
if( (streamFlags & paPlatformSpecificFlags) != 0 )
@@ -1225,6 +1221,14 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
}
+ /* Round framesPerBuffer to the next power-of-two to make OSS happy. */
+ if( framesPerBuffer != paFramesPerBufferUnspecified )
+ {
+ framesPerBuffer &= INT_MAX;
+ for (i = 1; framesPerBuffer > i; i <<= 1) ;
+ framesPerBuffer = i;
+ }
+
/* allocate and do basic initialization of the stream structure */
PA_UNLESS( stream = (PaOssStream*)PaUtil_AllocateMemory( sizeof(PaOssStream) ), paInsufficientMemory );
PA_ENSURE( PaOssStream_Initialize( stream, inputParameters, outputParameters, streamCallback, userData, streamFlags, ossHostApi ) );
@@ -1428,6 +1432,12 @@ static PaError PaOssStream_Prepare( PaOssStream *stream )
if( stream->triggered )
return result;
+ /* The OSS reference instructs us to clear direction bits before setting them.*/
+ if( stream->playback )
+ ENSURE_( ioctl( stream->playback->fd, SNDCTL_DSP_SETTRIGGER, &enableBits ), paUnanticipatedHostError );
+ if( stream->capture )
+ ENSURE_( ioctl( stream->capture->fd, SNDCTL_DSP_SETTRIGGER, &enableBits ), paUnanticipatedHostError );
+
if( stream->playback )
{
size_t bufSz = PaOssStreamComponent_BufferSize( stream->playback );
@@ -1478,17 +1488,29 @@ static PaError PaOssStream_Stop( PaOssStream *stream, int abort )
PaError result = paNoError;
/* Looks like the only safe way to stop audio without reopening the device is SNDCTL_DSP_POST.
- * Also disable capture/playback till the stream is started again */
+ * Also disable capture/playback till the stream is started again.
+ */
+ int captureErr = 0, playbackErr = 0;
if( stream->capture )
{
- ENSURE_( ioctl( stream->capture->fd, SNDCTL_DSP_POST, 0 ), paUnanticipatedHostError );
+ if( (captureErr = ioctl( stream->capture->fd, SNDCTL_DSP_POST, 0 )) < 0 )
+ {
+ PA_DEBUG(( "%s: Failed to stop capture device, error: %d\n", __FUNCTION__, captureErr ));
+ }
}
if( stream->playback && !stream->sharedDevice )
{
- ENSURE_( ioctl( stream->playback->fd, SNDCTL_DSP_POST, 0 ), paUnanticipatedHostError );
+ if( (playbackErr = ioctl( stream->playback->fd, SNDCTL_DSP_POST, 0 )) < 0 )
+ {
+ PA_DEBUG(( "%s: Failed to stop playback device, error: %d\n", __FUNCTION__, playbackErr ));
+ }
+ }
+
+ if( captureErr || playbackErr )
+ {
+ result = paUnanticipatedHostError;
}
-error:
return result;
}
@@ -1852,6 +1874,7 @@ static PaError ReadStream( PaStream* s,
void *buffer,
unsigned long frames )
{
+ PaError result = paNoError;
PaOssStream *stream = (PaOssStream*)s;
int bytesRequested, bytesRead;
unsigned long framesRequested;
@@ -1872,21 +1895,28 @@ static PaError ReadStream( PaStream* s,
framesRequested = PA_MIN( frames, stream->capture->hostFrames );
bytesRequested = framesRequested * PaOssStreamComponent_FrameSize( stream->capture );
- bytesRead = read( stream->capture->fd, stream->capture->buffer, bytesRequested );
+ ENSURE_( (bytesRead = read( stream->capture->fd, stream->capture->buffer, bytesRequested )),
+ paUnanticipatedHostError );
if ( bytesRequested != bytesRead )
+ {
+ PA_DEBUG(( "Requested %d bytes, read %d\n", bytesRequested, bytesRead ));
return paUnanticipatedHostError;
+ }
PaUtil_SetInputFrameCount( &stream->bufferProcessor, stream->capture->hostFrames );
PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, stream->capture->buffer, stream->capture->hostChannelCount );
PaUtil_CopyInput( &stream->bufferProcessor, &userBuffer, framesRequested );
frames -= framesRequested;
}
- return paNoError;
+
+error:
+ return result;
}
static PaError WriteStream( PaStream *s, const void *buffer, unsigned long frames )
{
+ PaError result = paNoError;
PaOssStream *stream = (PaOssStream*)s;
int bytesRequested, bytesWritten;
unsigned long framesConverted;
@@ -1912,35 +1942,50 @@ static PaError WriteStream( PaStream *s, const void *buffer, unsigned long frame
frames -= framesConverted;
bytesRequested = framesConverted * PaOssStreamComponent_FrameSize( stream->playback );
- bytesWritten = write( stream->playback->fd, stream->playback->buffer, bytesRequested );
+ ENSURE_( (bytesWritten = write( stream->playback->fd, stream->playback->buffer, bytesRequested )),
+ paUnanticipatedHostError );
if ( bytesRequested != bytesWritten )
+ {
+ PA_DEBUG(( "Requested %d bytes, wrote %d\n", bytesRequested, bytesWritten ));
return paUnanticipatedHostError;
+ }
}
- return paNoError;
+
+error:
+ return result;
}
static signed long GetStreamReadAvailable( PaStream* s )
{
+ PaError result = paNoError;
PaOssStream *stream = (PaOssStream*)s;
audio_buf_info info;
- if( ioctl( stream->capture->fd, SNDCTL_DSP_GETISPACE, &info ) < 0 )
- return paUnanticipatedHostError;
+ ENSURE_( ioctl( stream->capture->fd, SNDCTL_DSP_GETISPACE, &info ), paUnanticipatedHostError );
return info.fragments * stream->capture->hostFrames;
+
+error:
+ return result;
}
/* TODO: Compute number of allocated bytes somewhere else, can we use ODELAY with capture */
static signed long GetStreamWriteAvailable( PaStream* s )
{
+ PaError result = paNoError;
PaOssStream *stream = (PaOssStream*)s;
int delay = 0;
-
- if( ioctl( stream->playback->fd, SNDCTL_DSP_GETODELAY, &delay ) < 0 )
- return paUnanticipatedHostError;
-
+#ifdef SNDCTL_DSP_GETODELAY
+ ENSURE_( ioctl( stream->playback->fd, SNDCTL_DSP_GETODELAY, &delay ), paUnanticipatedHostError );
+#endif
return (PaOssStreamComponent_BufferSize( stream->playback ) - delay) / PaOssStreamComponent_FrameSize( stream->playback );
+
+/* Conditionally compile this to avoid warning about unused label */
+#ifdef SNDCTL_DSP_GETODELAY
+error:
+ return result;
+#endif
}
diff --git a/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c b/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c
index 3264ebf8..d2c13f99 100644
--- a/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c
+++ b/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_win_wmme.c 1229 2007-06-15 16:11:11Z rossb $
+ * $Id: pa_win_wmme.c 1405 2009-03-08 08:10:55Z rossb $
* pa_win_wmme.c
* Implementation of PortAudio for Windows MultiMedia Extensions (WMME)
*
@@ -62,7 +62,9 @@
*/
/** @file
- @ingroup hostaip_src
+ @ingroup hostapi_src
+
+ @brief Win32 host API implementation for the Windows MultiMedia Extensions (WMME) audio API.
@todo Fix buffer catch up code, can sometimes get stuck (perhaps fixed now,
needs to be reviewed and tested.)
@@ -88,6 +90,10 @@ Non-critical stuff for the future:
@todo define UNICODE and _UNICODE in the project settings and see what breaks
+ @todo refactor conversion of MMSYSTEM errors into PA arrors into a single function.
+
+ @todo cleanup WAVEFORMATEXTENSIBLE retry in InitializeWaveHandles to not use a for loop
+
*/
/*
@@ -133,6 +139,24 @@ Non-critical stuff for the future:
#include "pa_debugprint.h"
#include "pa_win_wmme.h"
+#include "pa_win_waveformat.h"
+
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+#include "pa_win_wdmks_utils.h"
+#ifndef DRV_QUERYDEVICEINTERFACE
+#define DRV_QUERYDEVICEINTERFACE (DRV_RESERVED + 12)
+#endif
+#ifndef DRV_QUERYDEVICEINTERFACESIZE
+#define DRV_QUERYDEVICEINTERFACESIZE (DRV_RESERVED + 13)
+#endif
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
+/* use CreateThread for CYGWIN, _beginthreadex for all others */
+#ifndef __CYGWIN__
+#define CREATE_THREAD (HANDLE)_beginthreadex( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId )
+#else
+#define CREATE_THREAD CreateThread( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId )
+#endif
#if (defined(UNDER_CE))
#pragma comment(lib, "Coredll.lib")
@@ -374,6 +398,8 @@ typedef struct
{
PaDeviceInfo inheritedDeviceInfo;
DWORD dwFormats; /**<< standard formats bitmask from the WAVEINCAPS and WAVEOUTCAPS structures */
+ char deviceInputChannelCountIsKnown; /**<< if the system returns 0xFFFF then we don't really know the number of supported channels (1=>known, 0=>unknown)*/
+ char deviceOutputChannelCountIsKnown; /**<< if the system returns 0xFFFF then we don't really know the number of supported channels (1=>known, 0=>unknown)*/
}
PaWinMmeDeviceInfo;
@@ -445,6 +471,21 @@ static UINT LocalDeviceIndexToWinMmeDeviceId( PaWinMmeHostApiRepresentation *hos
}
+static int SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( PaSampleFormat sampleFormat, unsigned long winMmeSpecificFlags )
+{
+ int waveFormatTag = 0;
+
+ if( winMmeSpecificFlags & paWinMmeWaveFormatDolbyAc3Spdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ else if( winMmeSpecificFlags & paWinMmeWaveFormatWmaSpdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_WMA_SPDIF;
+ else
+ waveFormatTag = PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat );
+
+ return waveFormatTag;
+}
+
+
static PaError QueryInputWaveFormatEx( int deviceId, WAVEFORMATEX *waveFormatEx )
{
MMRESULT mmresult;
@@ -499,41 +540,57 @@ static PaError QueryOutputWaveFormatEx( int deviceId, WAVEFORMATEX *waveFormatEx
static PaError QueryFormatSupported( PaDeviceInfo *deviceInfo,
PaError (*waveFormatExQueryFunction)(int, WAVEFORMATEX*),
- int winMmeDeviceId, int channels, double sampleRate )
+ int winMmeDeviceId, int channels, double sampleRate, unsigned long winMmeSpecificFlags )
{
PaWinMmeDeviceInfo *winMmeDeviceInfo = (PaWinMmeDeviceInfo*)deviceInfo;
- WAVEFORMATEX waveFormatEx;
+ PaWinWaveFormat waveFormat;
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
- if( sampleRate == 11025.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1S16)) ) ){
+ /* @todo at the moment we only query with 16 bit sample format and directout speaker config*/
- return paNoError;
- }
+ sampleFormat = paInt16;
+ waveFormatTag = SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( sampleFormat, winMmeSpecificFlags );
- if( sampleRate == 22050.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2S16)) ) ){
+ if( waveFormatTag == PaWin_SampleFormatToLinearWaveFormatTag( paInt16 ) ){
+
+ /* attempt bypass querying the device for linear formats */
- return paNoError;
+ if( sampleRate == 11025.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1S16)) ) ){
+
+ return paNoError;
+ }
+
+ if( sampleRate == 22050.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2S16)) ) ){
+
+ return paNoError;
+ }
+
+ if( sampleRate == 44100.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4S16)) ) ){
+
+ return paNoError;
+ }
}
- if( sampleRate == 44100.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4S16)) ) ){
+ /* first, attempt to query the device using WAVEFORMATEXTENSIBLE,
+ if this fails we fall back to WAVEFORMATEX */
+
+ PaWin_InitializeWaveFormatExtensible( &waveFormat, channels, sampleFormat, waveFormatTag,
+ sampleRate, PAWIN_SPEAKER_DIRECTOUT );
+
+ if( waveFormatExQueryFunction( winMmeDeviceId, (WAVEFORMATEX*)&waveFormat ) == paNoError )
return paNoError;
- }
- waveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
- waveFormatEx.nChannels = (WORD)channels;
- waveFormatEx.nSamplesPerSec = (DWORD)sampleRate;
- waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * channels * sizeof(short);
- waveFormatEx.nBlockAlign = (WORD)(channels * sizeof(short));
- waveFormatEx.wBitsPerSample = 16;
- waveFormatEx.cbSize = 0;
+ PaWin_InitializeWaveFormatEx( &waveFormat, channels, sampleFormat, waveFormatTag, sampleRate );
- return waveFormatExQueryFunction( winMmeDeviceId, &waveFormatEx );
+ return waveFormatExQueryFunction( winMmeDeviceId, (WAVEFORMATEX*)&waveFormat );
}
@@ -553,7 +610,7 @@ static void DetectDefaultSampleRate( PaWinMmeDeviceInfo *winMmeDeviceInfo, int w
for( i=0; i < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++i )
{
double sampleRate = defaultSampleRateSearchOrder_[ i ];
- PaError paerror = QueryFormatSupported( deviceInfo, waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate );
+ PaError paerror = QueryFormatSupported( deviceInfo, waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate, 0 );
if( paerror == paNoError )
{
deviceInfo->defaultSampleRate = sampleRate;
@@ -563,6 +620,40 @@ static void DetectDefaultSampleRate( PaWinMmeDeviceInfo *winMmeDeviceInfo, int w
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+static int QueryWaveInKSFilterMaxChannels( int waveInDeviceId, int *maxChannels )
+{
+ void *devicePath;
+ DWORD devicePathSize;
+ int result = 0;
+
+ if( waveInMessage((HWAVEIN)waveInDeviceId, DRV_QUERYDEVICEINTERFACESIZE,
+ (DWORD_PTR)&devicePathSize, 0 ) != MMSYSERR_NOERROR )
+ return 0;
+
+ devicePath = PaUtil_AllocateMemory( devicePathSize );
+ if( !devicePath )
+ return 0;
+
+ /* apparently DRV_QUERYDEVICEINTERFACE returns a unicode interface path, although this is undocumented */
+ if( waveInMessage((HWAVEIN)waveInDeviceId, DRV_QUERYDEVICEINTERFACE,
+ (DWORD_PTR)devicePath, devicePathSize ) == MMSYSERR_NOERROR )
+ {
+ int count = PaWin_WDMKS_QueryFilterMaximumChannelCount( devicePath, /* isInput= */ 1 );
+ if( count > 0 )
+ {
+ *maxChannels = count;
+ result = 1;
+ }
+ }
+
+ PaUtil_FreeMemory( devicePath );
+
+ return result;
+}
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
+
static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeDeviceInfo *winMmeDeviceInfo, UINT winMmeInputDeviceId, int *success )
{
@@ -616,17 +707,30 @@ static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeH
}
deviceInfo->name = deviceName;
- deviceInfo->maxInputChannels = wic.wChannels;
- /* Sometimes a device can return a rediculously large number of channels.
- * This happened with an SBLive card on a Windows ME box.
- * If that happens, then force it to 2 channels. PLB20010413
+ if( wic.wChannels == 0xFFFF || wic.wChannels < 1 || wic.wChannels > 255 ){
+ /* For Windows versions using WDM (possibly Windows 98 ME and later)
+ * the kernel mixer sits between the application and the driver. As a result,
+ * wave*GetDevCaps often kernel mixer channel counts, which are unlimited.
+ * When this happens we assume the device is stereo and set a flag
+ * so that other channel counts can be tried with OpenStream -- i.e. when
+ * device*ChannelCountIsKnown is false, OpenStream will try whatever
+ * channel count you supply.
+ * see also InitializeOutputDeviceInfo() below.
*/
- if( (deviceInfo->maxInputChannels < 1) || (deviceInfo->maxInputChannels > 256) )
- {
- PA_DEBUG(("Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\n", deviceInfo->maxInputChannels ));
+
+ PA_DEBUG(("Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\n", wic.wChannels ));
deviceInfo->maxInputChannels = 2;
+ winMmeDeviceInfo->deviceInputChannelCountIsKnown = 0;
+ }else{
+ deviceInfo->maxInputChannels = wic.wChannels;
+ winMmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+ winMmeDeviceInfo->deviceInputChannelCountIsKnown =
+ QueryWaveInKSFilterMaxChannels( winMmeInputDeviceId, &deviceInfo->maxInputChannels );
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
winMmeDeviceInfo->dwFormats = wic.dwFormats;
DetectDefaultSampleRate( winMmeDeviceInfo, winMmeInputDeviceId,
@@ -639,6 +743,40 @@ error:
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+static int QueryWaveOutKSFilterMaxChannels( int waveOutDeviceId, int *maxChannels )
+{
+ void *devicePath;
+ DWORD devicePathSize;
+ int result = 0;
+
+ if( waveOutMessage((HWAVEOUT)waveOutDeviceId, DRV_QUERYDEVICEINTERFACESIZE,
+ (DWORD_PTR)&devicePathSize, 0 ) != MMSYSERR_NOERROR )
+ return 0;
+
+ devicePath = PaUtil_AllocateMemory( devicePathSize );
+ if( !devicePath )
+ return 0;
+
+ /* apparently DRV_QUERYDEVICEINTERFACE returns a unicode interface path, although this is undocumented */
+ if( waveOutMessage((HWAVEOUT)waveOutDeviceId, DRV_QUERYDEVICEINTERFACE,
+ (DWORD_PTR)devicePath, devicePathSize ) == MMSYSERR_NOERROR )
+ {
+ int count = PaWin_WDMKS_QueryFilterMaximumChannelCount( devicePath, /* isInput= */ 0 );
+ if( count > 0 )
+ {
+ *maxChannels = count;
+ result = 1;
+ }
+ }
+
+ PaUtil_FreeMemory( devicePath );
+
+ return result;
+}
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
+
static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeDeviceInfo *winMmeDeviceInfo, UINT winMmeOutputDeviceId, int *success )
{
@@ -647,7 +785,7 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
MMRESULT mmresult;
WAVEOUTCAPS woc;
PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
-
+
*success = 0;
mmresult = waveOutGetDevCaps( winMmeOutputDeviceId, &woc, sizeof( WAVEOUTCAPS ) );
@@ -692,17 +830,30 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
}
deviceInfo->name = deviceName;
- deviceInfo->maxOutputChannels = woc.wChannels;
- /* Sometimes a device can return a rediculously large number of channels.
- * This happened with an SBLive card on a Windows ME box.
- * It also happens on Win XP!
+ if( woc.wChannels == 0xFFFF || woc.wChannels < 1 || woc.wChannels > 255 ){
+ /* For Windows versions using WDM (possibly Windows 98 ME and later)
+ * the kernel mixer sits between the application and the driver. As a result,
+ * wave*GetDevCaps often kernel mixer channel counts, which are unlimited.
+ * When this happens we assume the device is stereo and set a flag
+ * so that other channel counts can be tried with OpenStream -- i.e. when
+ * device*ChannelCountIsKnown is false, OpenStream will try whatever
+ * channel count you supply.
+ * see also InitializeInputDeviceInfo() above.
*/
- if( (deviceInfo->maxOutputChannels < 1) || (deviceInfo->maxOutputChannels > 256) )
- {
- PA_DEBUG(("Pa_GetDeviceInfo: Num output channels reported as %d! Changed to 2.\n", deviceInfo->maxOutputChannels ));
+
+ PA_DEBUG(("Pa_GetDeviceInfo: Num output channels reported as %d! Changed to 2.\n", woc.wChannels ));
deviceInfo->maxOutputChannels = 2;
+ winMmeDeviceInfo->deviceOutputChannelCountIsKnown = 0;
+ }else{
+ deviceInfo->maxOutputChannels = woc.wChannels;
+ winMmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+ winMmeDeviceInfo->deviceOutputChannelCountIsKnown =
+ QueryWaveOutKSFilterMaxChannels( winMmeOutputDeviceId, &deviceInfo->maxOutputChannels );
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
winMmeDeviceInfo->dwFormats = woc.dwFormats;
DetectDefaultSampleRate( winMmeDeviceInfo, winMmeOutputDeviceId,
@@ -748,6 +899,8 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
PaWinMmeDeviceInfo *deviceInfoArray;
int deviceInfoInitializationSucceeded;
PaTime defaultLowLatency, defaultHighLatency;
+ DWORD waveInPreferredDevice, waveOutPreferredDevice;
+ DWORD preferredDeviceStatusFlags;
winMmeHostApi = (PaWinMmeHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinMmeHostApiRepresentation) );
if( !winMmeHostApi )
@@ -779,6 +932,19 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
winMmeHostApi->inputDeviceCount = 0;
winMmeHostApi->outputDeviceCount = 0;
+#if !defined(DRVM_MAPPER_PREFERRED_GET)
+/* DRVM_MAPPER_PREFERRED_GET is defined in mmddk.h but we avoid a dependency on the DDK by defining it here */
+#define DRVM_MAPPER_PREFERRED_GET (0x2000+21)
+#endif
+
+ /* the following calls assume that if wave*Message fails the preferred device parameter won't be modified */
+ preferredDeviceStatusFlags = 0;
+ waveInPreferredDevice = -1;
+ waveInMessage( (HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD)&waveInPreferredDevice, (DWORD)&preferredDeviceStatusFlags );
+
+ preferredDeviceStatusFlags = 0;
+ waveOutPreferredDevice = -1;
+ waveOutMessage( (HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD)&waveOutPreferredDevice, (DWORD)&preferredDeviceStatusFlags );
maximumPossibleDeviceCount = 0;
@@ -830,7 +996,9 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
deviceInfo->hostApi = hostApiIndex;
deviceInfo->maxInputChannels = 0;
+ wmmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
deviceInfo->maxOutputChannels = 0;
+ wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
@@ -843,8 +1011,14 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
goto error;
if( deviceInfoInitializationSucceeded ){
- if( (*hostApi)->info.defaultInputDevice == paNoDevice )
+ if( (*hostApi)->info.defaultInputDevice == paNoDevice ){
+ /* if there is currently no default device, use the first one available */
+ (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
+
+ }else if( winMmeDeviceId == waveInPreferredDevice ){
+ /* set the default device to the system preferred device */
(*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
+ }
winMmeHostApi->winMmeDeviceIds[ (*hostApi)->info.deviceCount ] = winMmeDeviceId;
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
@@ -865,7 +1039,9 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
deviceInfo->hostApi = hostApiIndex;
deviceInfo->maxInputChannels = 0;
+ wmmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
deviceInfo->maxOutputChannels = 0;
+ wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
@@ -878,8 +1054,14 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
goto error;
if( deviceInfoInitializationSucceeded ){
- if( (*hostApi)->info.defaultOutputDevice == paNoDevice )
+ if( (*hostApi)->info.defaultOutputDevice == paNoDevice ){
+ /* if there is currently no default device, use the first one available */
+ (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
+
+ }else if( winMmeDeviceId == waveOutPreferredDevice ){
+ /* set the default device to the system preferred device */
(*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
+ }
winMmeHostApi->winMmeDeviceIds[ (*hostApi)->info.deviceCount ] = winMmeDeviceId;
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
@@ -891,7 +1073,6 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
}
}
-
InitializeDefaultDeviceIdsFromEnv( winMmeHostApi );
(*hostApi)->Terminate = Terminate;
@@ -941,6 +1122,34 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
}
+static PaError IsInputChannelCountSupported( PaWinMmeDeviceInfo* deviceInfo, int channelCount )
+{
+ PaError result = paNoError;
+
+ if( channelCount > 0
+ && deviceInfo->deviceInputChannelCountIsKnown
+ && channelCount > deviceInfo->inheritedDeviceInfo.maxInputChannels ){
+
+ result = paInvalidChannelCount;
+ }
+
+ return result;
+}
+
+static PaError IsOutputChannelCountSupported( PaWinMmeDeviceInfo* deviceInfo, int channelCount )
+{
+ PaError result = paNoError;
+
+ if( channelCount > 0
+ && deviceInfo->deviceOutputChannelCountIsKnown
+ && channelCount > deviceInfo->inheritedDeviceInfo.maxOutputChannels ){
+
+ result = paInvalidChannelCount;
+ }
+
+ return result;
+}
+
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters,
@@ -985,13 +1194,19 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
inputDeviceInfo = hostApi->deviceInfos[ inputStreamInfo->devices[i].device ];
/* check that input device can support inputChannelCount */
- if( inputStreamInfo->devices[i].channelCount <= 0
- || inputStreamInfo->devices[i].channelCount > inputDeviceInfo->maxInputChannels )
+ if( inputStreamInfo->devices[i].channelCount < 1 )
return paInvalidChannelCount;
+ paerror = IsInputChannelCountSupported( (PaWinMmeDeviceInfo*)inputDeviceInfo,
+ inputStreamInfo->devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
+
/* test for valid sample rate, see comment above */
winMmeInputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, inputStreamInfo->devices[i].device );
- paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx, winMmeInputDeviceId, inputStreamInfo->devices[i].channelCount, sampleRate );
+ paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx,
+ winMmeInputDeviceId, inputStreamInfo->devices[i].channelCount, sampleRate,
+ ((inputStreamInfo) ? inputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1007,12 +1222,15 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
inputDeviceInfo = hostApi->deviceInfos[ inputParameters->device ];
/* check that input device can support inputChannelCount */
- if( inputChannelCount > inputDeviceInfo->maxInputChannels )
- return paInvalidChannelCount;
+ paerror = IsInputChannelCountSupported( (PaWinMmeDeviceInfo*)inputDeviceInfo, inputChannelCount );
+ if( paerror != paNoError )
+ return paerror;
/* test for valid sample rate, see comment above */
winMmeInputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, inputParameters->device );
- paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx, winMmeInputDeviceId, inputChannelCount, sampleRate );
+ paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx,
+ winMmeInputDeviceId, inputChannelCount, sampleRate,
+ ((inputStreamInfo) ? inputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1040,13 +1258,19 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
outputDeviceInfo = hostApi->deviceInfos[ outputStreamInfo->devices[i].device ];
/* check that output device can support outputChannelCount */
- if( outputStreamInfo->devices[i].channelCount <= 0
- || outputStreamInfo->devices[i].channelCount > outputDeviceInfo->maxOutputChannels )
+ if( outputStreamInfo->devices[i].channelCount < 1 )
return paInvalidChannelCount;
+ paerror = IsOutputChannelCountSupported( (PaWinMmeDeviceInfo*)outputDeviceInfo,
+ outputStreamInfo->devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
+
/* test for valid sample rate, see comment above */
winMmeOutputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, outputStreamInfo->devices[i].device );
- paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx, winMmeOutputDeviceId, outputStreamInfo->devices[i].channelCount, sampleRate );
+ paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx,
+ winMmeOutputDeviceId, outputStreamInfo->devices[i].channelCount, sampleRate,
+ ((outputStreamInfo) ? outputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1062,12 +1286,15 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
outputDeviceInfo = hostApi->deviceInfos[ outputParameters->device ];
/* check that output device can support outputChannelCount */
- if( outputChannelCount > outputDeviceInfo->maxOutputChannels )
- return paInvalidChannelCount;
+ paerror = IsOutputChannelCountSupported( (PaWinMmeDeviceInfo*)outputDeviceInfo, outputChannelCount );
+ if( paerror != paNoError )
+ return paerror;
/* test for valid sample rate, see comment above */
winMmeOutputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, outputParameters->device );
- paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx, winMmeOutputDeviceId, outputChannelCount, sampleRate );
+ paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx,
+ winMmeOutputDeviceId, outputChannelCount, sampleRate,
+ ((outputStreamInfo) ? outputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1491,9 +1718,10 @@ typedef struct
static void InitializeSingleDirectionHandlesAndBuffers( PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers );
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
- unsigned int deviceCount, int isInput );
+ unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask, int isInput );
static PaError TerminateWaveHandles( PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers, int isInput, int currentlyProcessingAnError );
static PaError InitializeWaveHeaders( PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
unsigned long hostBufferCount,
@@ -1515,15 +1743,16 @@ static void InitializeSingleDirectionHandlesAndBuffers( PaWinMmeSingleDirectionH
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
- unsigned int deviceCount, int isInput )
+ unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask, int isInput )
{
PaError result;
MMRESULT mmresult;
- unsigned long bytesPerFrame;
- WAVEFORMATEX wfx;
- signed int i;
+ signed int i, j;
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
/* for error cleanup we expect that InitializeSingleDirectionHandlesAndBuffers()
has already been called to zero some fields */
@@ -1551,64 +1780,98 @@ static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostA
((HWAVEOUT*)handlesAndBuffers->waveHandles)[i] = 0;
}
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nSamplesPerSec = (DWORD) sampleRate;
- wfx.cbSize = 0;
-
+ /* @todo at the moment we only use 16 bit sample format */
+ sampleFormat = paInt16;
+ waveFormatTag = SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( sampleFormat, winMmeSpecificFlags );
+
for( i = 0; i < (signed int)deviceCount; ++i )
{
- UINT winMmeDeviceId;
+ PaWinWaveFormat waveFormat;
+ UINT winMmeDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, devices[i].device );
+
+ /* @todo: consider providing a flag or #define to not try waveformat extensible
+ this could just initialize j to 1 the first time round. */
- winMmeDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, devices[i].device );
- wfx.nChannels = (WORD)devices[i].channelCount;
+ for( j = 0; j < 2; ++j )
+ {
+ if( j == 0 )
+ {
+ /* first, attempt to open the device using WAVEFORMATEXTENSIBLE,
+ if this fails we fall back to WAVEFORMATEX */
- bytesPerFrame = wfx.nChannels * bytesPerHostSample;
+ PaWin_InitializeWaveFormatExtensible( &waveFormat, devices[i].channelCount,
+ sampleFormat, waveFormatTag, sampleRate, channelMask );
- wfx.nAvgBytesPerSec = (DWORD)(bytesPerFrame * sampleRate);
- wfx.nBlockAlign = (WORD)bytesPerFrame;
- wfx.wBitsPerSample = (WORD)((bytesPerFrame/wfx.nChannels) * 8);
+ }
+ else
+ {
+ /* retry with WAVEFORMATEX */
- /* REVIEW: consider not firing an event for input when a full duplex
- stream is being used. this would probably depend on the
- neverDropInput flag. */
+ PaWin_InitializeWaveFormatEx( &waveFormat, devices[i].channelCount,
+ sampleFormat, waveFormatTag, sampleRate );
+ }
- if( isInput )
- mmresult = waveInOpen( &((HWAVEIN*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId, &wfx,
+ /* REVIEW: consider not firing an event for input when a full duplex
+ stream is being used. this would probably depend on the
+ neverDropInput flag. */
+
+ if( isInput )
+ {
+ mmresult = waveInOpen( &((HWAVEIN*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId,
+ (WAVEFORMATEX*)&waveFormat,
(DWORD_PTR)handlesAndBuffers->bufferEvent, (DWORD_PTR)0, CALLBACK_EVENT );
- else
- mmresult = waveOutOpen( &((HWAVEOUT*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId, &wfx,
+ }
+ else
+ {
+ mmresult = waveOutOpen( &((HWAVEOUT*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId,
+ (WAVEFORMATEX*)&waveFormat,
(DWORD_PTR)handlesAndBuffers->bufferEvent, (DWORD_PTR)0, CALLBACK_EVENT );
+ }
- if( mmresult != MMSYSERR_NOERROR )
- {
- switch( mmresult )
+ if( mmresult == MMSYSERR_NOERROR )
{
- case MMSYSERR_ALLOCATED: /* Specified resource is already allocated. */
- result = paDeviceUnavailable;
- break;
- case MMSYSERR_NODRIVER: /* No device driver is present. */
- result = paDeviceUnavailable;
- break;
- case MMSYSERR_NOMEM: /* Unable to allocate or lock memory. */
- result = paInsufficientMemory;
- break;
+ break; /* success */
+ }
+ else if( j == 0 )
+ {
+ continue; /* try again with WAVEFORMATEX */
+ }
+ else
+ {
+ switch( mmresult )
+ {
+ case MMSYSERR_ALLOCATED: /* Specified resource is already allocated. */
+ result = paDeviceUnavailable;
+ break;
+ case MMSYSERR_NODRIVER: /* No device driver is present. */
+ result = paDeviceUnavailable;
+ break;
+ case MMSYSERR_NOMEM: /* Unable to allocate or lock memory. */
+ result = paInsufficientMemory;
+ break;
- case MMSYSERR_BADDEVICEID: /* Specified device identifier is out of range. */
- /* falls through */
- case WAVERR_BADFORMAT: /* Attempted to open with an unsupported waveform-audio format. */
- /* falls through */
- default:
- result = paUnanticipatedHostError;
- if( isInput )
- {
- PA_MME_SET_LAST_WAVEIN_ERROR( mmresult );
- }
- else
- {
- PA_MME_SET_LAST_WAVEOUT_ERROR( mmresult );
- }
+ case MMSYSERR_BADDEVICEID: /* Specified device identifier is out of range. */
+ /* falls through */
+
+ case WAVERR_BADFORMAT: /* Attempted to open with an unsupported waveform-audio format. */
+ /* This can also occur if we try to open the device with an unsupported
+ * number of channels. This is attempted when device*ChannelCountIsKnown is
+ * set to 0.
+ */
+ /* falls through */
+ default:
+ result = paUnanticipatedHostError;
+ if( isInput )
+ {
+ PA_MME_SET_LAST_WAVEIN_ERROR( mmresult );
+ }
+ else
+ {
+ PA_MME_SET_LAST_WAVEOUT_ERROR( mmresult );
+ }
+ }
+ goto error;
}
- goto error;
}
}
@@ -1850,6 +2113,7 @@ struct PaWinMmeStream
static PaError ValidateWinMmeSpecificStreamInfo(
const PaStreamParameters *streamParameters,
const PaWinMmeStreamInfo *streamInfo,
+ unsigned long *winMmeSpecificFlags,
char *throttleProcessingThreadOnOverload,
unsigned long *deviceCount )
{
@@ -1861,6 +2125,8 @@ static PaError ValidateWinMmeSpecificStreamInfo(
return paIncompatibleHostApiSpecificStreamInfo;
}
+ *winMmeSpecificFlags = streamInfo->flags;
+
if( streamInfo->flags & paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
@@ -1926,12 +2192,20 @@ static PaError ValidateInputChannelCounts(
unsigned long deviceCount )
{
unsigned int i;
+ PaWinMmeDeviceInfo *inputDeviceInfo;
+ PaError paerror;
for( i=0; i < deviceCount; ++i )
{
- if( devices[i].channelCount < 1 || devices[i].channelCount
- > hostApi->deviceInfos[ devices[i].device ]->maxInputChannels )
+ if( devices[i].channelCount < 1 )
return paInvalidChannelCount;
+
+ inputDeviceInfo =
+ (PaWinMmeDeviceInfo*)hostApi->deviceInfos[ devices[i].device ];
+
+ paerror = IsInputChannelCountSupported( inputDeviceInfo, devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
}
return paNoError;
@@ -1943,12 +2217,20 @@ static PaError ValidateOutputChannelCounts(
unsigned long deviceCount )
{
unsigned int i;
+ PaWinMmeDeviceInfo *outputDeviceInfo;
+ PaError paerror;
for( i=0; i < deviceCount; ++i )
{
- if( devices[i].channelCount < 1 || devices[i].channelCount
- > hostApi->deviceInfos[ devices[i].device ]->maxOutputChannels )
+ if( devices[i].channelCount < 1 )
return paInvalidChannelCount;
+
+ outputDeviceInfo =
+ (PaWinMmeDeviceInfo*)hostApi->deviceInfos[ devices[i].device ];
+
+ paerror = IsOutputChannelCountSupported( outputDeviceInfo, devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
}
return paNoError;
@@ -1981,14 +2263,17 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
PaSampleFormat inputSampleFormat, outputSampleFormat;
double suggestedInputLatency, suggestedOutputLatency;
PaWinMmeStreamInfo *inputStreamInfo, *outputStreamInfo;
+ PaWinWaveFormatChannelMask inputChannelMask, outputChannelMask;
unsigned long framesPerHostInputBuffer;
unsigned long hostInputBufferCount;
unsigned long framesPerHostOutputBuffer;
unsigned long hostOutputBufferCount;
unsigned long framesPerBufferProcessorCall;
PaWinMmeDeviceAndChannelCount *inputDevices = 0; /* contains all devices and channel counts as local host api ids, even when PaWinMmeUseMultipleDevices is not used */
+ unsigned long winMmeSpecificInputFlags = 0;
unsigned long inputDeviceCount = 0;
PaWinMmeDeviceAndChannelCount *outputDevices = 0;
+ unsigned long winMmeSpecificOutputFlags = 0;
unsigned long outputDeviceCount = 0; /* contains all devices and channel counts as local host api ids, even when PaWinMmeUseMultipleDevices is not used */
char throttleProcessingThreadOnOverload = 1;
@@ -2004,6 +2289,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* validate input hostApiSpecificStreamInfo */
inputStreamInfo = (PaWinMmeStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( inputParameters, inputStreamInfo,
+ &winMmeSpecificInputFlags,
&throttleProcessingThreadOnOverload,
&inputDeviceCount );
if( result != paNoError ) return result;
@@ -2019,6 +2305,18 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
hostInputSampleFormat =
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
+
+ if( inputDeviceCount != 1 ){
+ /* always use direct speakers when using multi-device multichannel mode */
+ inputChannelMask = PAWIN_SPEAKER_DIRECTOUT;
+ }
+ else
+ {
+ if( inputStreamInfo && inputStreamInfo->flags & paWinMmeUseChannelMask )
+ inputChannelMask = inputStreamInfo->channelMask;
+ else
+ inputChannelMask = PaWin_DefaultChannelMask( inputDevices[0].channelCount );
+ }
}
else
{
@@ -2041,6 +2339,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* validate output hostApiSpecificStreamInfo */
outputStreamInfo = (PaWinMmeStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( outputParameters, outputStreamInfo,
+ &winMmeSpecificOutputFlags,
&throttleProcessingThreadOnOverload,
&outputDeviceCount );
if( result != paNoError ) return result;
@@ -2056,6 +2355,18 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
hostOutputSampleFormat =
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
+
+ if( outputDeviceCount != 1 ){
+ /* always use direct speakers when using multi-device multichannel mode */
+ outputChannelMask = PAWIN_SPEAKER_DIRECTOUT;
+ }
+ else
+ {
+ if( outputStreamInfo && outputStreamInfo->flags & paWinMmeUseChannelMask )
+ outputChannelMask = outputStreamInfo->channelMask;
+ else
+ outputChannelMask = PaWin_DefaultChannelMask( outputDevices[0].channelCount );
+ }
}
else
{
@@ -2078,6 +2389,14 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
return paInvalidFlag; /* unexpected platform specific flag */
+ /* always disable clipping and dithering if we are outputting a raw spdif stream */
+ if( (winMmeSpecificOutputFlags & paWinMmeWaveFormatDolbyAc3Spdif)
+ || (winMmeSpecificOutputFlags & paWinMmeWaveFormatWmaSpdif) ){
+
+ streamFlags = streamFlags | paClipOff | paDitherOff;
+ }
+
+
result = CalculateBufferSettings( &framesPerHostInputBuffer, &hostInputBufferCount,
&framesPerHostOutputBuffer, &hostOutputBufferCount,
inputChannelCount, hostInputSampleFormat, suggestedInputLatency, inputStreamInfo,
@@ -2176,16 +2495,18 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( inputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->input,
+ winMmeSpecificInputFlags,
stream->bufferProcessor.bytesPerHostInputSample, sampleRate,
- inputDevices, inputDeviceCount, 1 /* isInput */ );
+ inputDevices, inputDeviceCount, inputChannelMask, 1 /* isInput */ );
if( result != paNoError ) goto error;
}
if( outputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->output,
+ winMmeSpecificOutputFlags,
stream->bufferProcessor.bytesPerHostOutputSample, sampleRate,
- outputDevices, outputDeviceCount, 0 /* isInput */ );
+ outputDevices, outputDeviceCount, outputChannelMask, 0 /* isInput */ );
if( result != paNoError ) goto error;
}
@@ -2340,6 +2661,7 @@ static PaError AdvanceToNextInputBuffer( PaWinMmeStream *stream )
for( i=0; i < stream->input.deviceCount; ++i )
{
+ stream->input.waveHeaders[i][ stream->input.currentBufferIndex ].dwFlags &= ~WHDR_DONE;
mmresult = waveInAddBuffer( ((HWAVEIN*)stream->input.waveHandles)[i],
&stream->input.waveHeaders[i][ stream->input.currentBufferIndex ],
sizeof(WAVEHDR) );
@@ -2642,7 +2964,7 @@ static DWORD WINAPI ProcessingThreadProc( void *pArg )
for( i=0; i<stream->input.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
+ int channelCount = (int)stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, channel,
stream->input.waveHeaders[i][ hostInputBufferIndex ].lpData +
@@ -2663,7 +2985,7 @@ static DWORD WINAPI ProcessingThreadProc( void *pArg )
for( i=0; i<stream->output.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[i][ hostOutputBufferIndex ].lpData +
@@ -2866,6 +3188,7 @@ static PaError StartStream( PaStream *s )
{
for( j=0; j<stream->input.deviceCount; ++j )
{
+ stream->input.waveHeaders[j][i].dwFlags &= ~WHDR_DONE;
mmresult = waveInAddBuffer( ((HWAVEIN*)stream->input.waveHandles)[j], &stream->input.waveHeaders[j][i], sizeof(WAVEHDR) );
if( mmresult != MMSYSERR_NOERROR )
{
@@ -2912,7 +3235,7 @@ static PaError StartStream( PaStream *s )
for( j=0; j<stream->output.deviceCount; ++j )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[j][i].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[j][i].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[j][i].lpData +
@@ -2988,7 +3311,7 @@ static PaError StartStream( PaStream *s )
if( result != paNoError ) goto error;
/* Create thread that waits for audio buffers to be ready for processing. */
- stream->processingThread = CreateThread( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId );
+ stream->processingThread = CREATE_THREAD;
if( !stream->processingThread )
{
result = paUnanticipatedHostError;
@@ -3120,7 +3443,7 @@ static PaError StopStream( PaStream *s )
for( i=0; i<stream->output.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[i][ hostOutputBufferIndex ].lpData +
@@ -3344,7 +3667,7 @@ static PaError ReadStream( PaStream* s,
}
else
{
- userBuffer = alloca( sizeof(void*) * stream->bufferProcessor.inputChannelCount );
+ userBuffer = (void*)alloca( sizeof(void*) * stream->bufferProcessor.inputChannelCount );
if( !userBuffer )
return paInsufficientMemory;
for( i = 0; i<stream->bufferProcessor.inputChannelCount; ++i )
@@ -3372,7 +3695,7 @@ static PaError ReadStream( PaStream* s,
for( i=0; i<stream->input.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
+ int channelCount = (int)stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, channel,
stream->input.waveHeaders[i][ hostInputBufferIndex ].lpData +
@@ -3448,7 +3771,7 @@ static PaError WriteStream( PaStream* s,
}
else
{
- userBuffer = alloca( sizeof(void*) * stream->bufferProcessor.outputChannelCount );
+ userBuffer = (const void*)alloca( sizeof(void*) * stream->bufferProcessor.outputChannelCount );
if( !userBuffer )
return paInsufficientMemory;
for( i = 0; i<stream->bufferProcessor.outputChannelCount; ++i )
@@ -3477,7 +3800,7 @@ static PaError WriteStream( PaStream* s,
for( i=0; i<stream->output.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[i][ hostOutputBufferIndex ].lpData +
diff --git a/pd/portaudio/src/os/unix/pa_unix_hostapis.c b/pd/portaudio/src/os/unix/pa_unix_hostapis.c
index d695e1b1..339e1b14 100644
--- a/pd/portaudio/src/os/unix/pa_unix_hostapis.c
+++ b/pd/portaudio/src/os/unix/pa_unix_hostapis.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_unix_hostapis.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_unix_hostapis.c 1413 2009-05-24 17:00:36Z aknudsen $
* Portable Audio I/O Library UNIX initialization table
*
* Based on the Open Source API proposed by Ross Bencina
@@ -49,10 +49,26 @@ PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
/* Linux AudioScience HPI */
PaError PaAsiHpi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+/** Note that on Linux, ALSA is placed before OSS so that the former is preferred over the latter.
+ */
PaUtilHostApiInitializer *paHostApiInitializers[] =
{
+#ifdef __linux__
+
+#ifdef PA_USE_ALSA
+ PaAlsa_Initialize,
+#endif
+
+#ifdef PA_USE_OSS
+ PaOSS_Initialize,
+#endif
+
+#else /* __linux__ */
+
#ifdef PA_USE_OSS
PaOSS_Initialize,
#endif
@@ -61,6 +77,8 @@ PaUtilHostApiInitializer *paHostApiInitializers[] =
PaAlsa_Initialize,
#endif
+#endif /* __linux__ */
+
#ifdef PA_USE_JACK
PaJack_Initialize,
#endif
@@ -72,6 +90,15 @@ PaUtilHostApiInitializer *paHostApiInitializers[] =
#ifdef PA_USE_ASIHPI
PaAsiHpi_Initialize,
#endif
+
+#ifdef PA_USE_COREAUDIO
+ PaMacCore_Initialize,
+#endif
+
+#ifdef PA_USE_SKELETON
+ PaSkeleton_Initialize,
+#endif
+
0 /* NULL terminated array */
};
diff --git a/pd/portaudio/src/os/unix/pa_unix_util.c b/pd/portaudio/src/os/unix/pa_unix_util.c
index 1cb83875..de54e51d 100644
--- a/pd/portaudio/src/os/unix/pa_unix_util.c
+++ b/pd/portaudio/src/os/unix/pa_unix_util.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_unix_util.c 1232 2007-06-16 14:49:43Z rossb $
+ * $Id: pa_unix_util.c 1419 2009-10-22 17:28:35Z bjornroche $
* Portable Audio I/O Library
* UNIX platform-specific support functions
*
@@ -51,6 +51,13 @@
#include <math.h>
#include <errno.h>
+#if defined(__APPLE__) && !defined(HAVE_MACH_ABSOLUTE_TIME)
+#define HAVE_MACH_ABSOLUTE_TIME
+#endif
+#ifdef HAVE_MACH_ABSOLUTE_TIME
+#include <mach/mach_time.h>
+#endif
+
#include "pa_util.h"
#include "pa_unix_util.h"
#include "pa_debugprint.h"
@@ -118,27 +125,47 @@ void Pa_Sleep( long msec )
#endif
}
-/* *** NOT USED YET: ***
-static int usePerformanceCounter_;
-static double microsecondsPerTick_;
+#ifdef HAVE_MACH_ABSOLUTE_TIME
+/*
+ Discussion on the CoreAudio mailing list suggests that calling
+ gettimeofday (or anything else in the BSD layer) is not real-time
+ safe, so we use mach_absolute_time on OSX. This implementation is
+ based on these two links:
+
+ Technical Q&A QA1398 - Mach Absolute Time Units
+ http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
+
+ Tutorial: Performance and Time.
+ http://www.macresearch.org/tutorial_performance_and_time
*/
+/* Scaler to convert the result of mach_absolute_time to seconds */
+static double machSecondsConversionScaler_ = 0.0;
+#endif
+
void PaUtil_InitializeClock( void )
{
- /* TODO */
+#ifdef HAVE_MACH_ABSOLUTE_TIME
+ mach_timebase_info_data_t info;
+ kern_return_t err = mach_timebase_info( &info );
+ if( err == 0 )
+ machSecondsConversionScaler_ = 1e-9 * (double) info.numer / (double) info.denom;
+#endif
}
PaTime PaUtil_GetTime( void )
{
-#ifdef HAVE_CLOCK_GETTIME
+#ifdef HAVE_MACH_ABSOLUTE_TIME
+ return mach_absolute_time() * machSecondsConversionScaler_;
+#elif defined(HAVE_CLOCK_GETTIME)
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
- return (PaTime)(tp.tv_sec + tp.tv_nsec / 1.e9);
+ return (PaTime)(tp.tv_sec + tp.tv_nsec * 1e-9);
#else
struct timeval tv;
gettimeofday( &tv, NULL );
- return (PaTime) tv.tv_usec / 1000000. + tv.tv_sec;
+ return (PaTime) tv.tv_usec * 1e-6 + tv.tv_sec;
#endif
}
@@ -190,7 +217,7 @@ PaError PaUtil_CancelThreading( PaUtilThreading *threading, int wait, PaError *e
/* paUnixMainThread
* We have to be a bit careful with defining this global variable,
* as explained below. */
-#ifdef __apple__
+#ifdef __APPLE__
/* apple/gcc has a "problem" with global vars and dynamic libs.
Initializing it seems to fix the problem.
Described a bit in this thread:
diff --git a/pd/portaudio/src/os/win/pa_win_hostapis.c b/pd/portaudio/src/os/win/pa_win_hostapis.c
index 83f1e914..1cca3d9f 100644
--- a/pd/portaudio/src/os/win/pa_win_hostapis.c
+++ b/pd/portaudio/src/os/win/pa_win_hostapis.c
@@ -1,9 +1,9 @@
/*
- * $Id: pa_win_hostapis.c 1097 2006-08-26 08:27:53Z rossb $
+ * $Id: pa_win_hostapis.c 1339 2008-02-15 07:50:33Z rossb $
* Portable Audio I/O Library Windows initialization table
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -39,7 +39,7 @@
/** @file
@ingroup win_src
- Win32 host API initialization function table.
+ @brief Win32 host API initialization function table.
@todo Consider using PA_USE_WMME etc instead of PA_NO_WMME. This is what
the Unix version does, we should consider being consistent.
diff --git a/pd/portaudio/src/os/win/pa_win_util.c b/pd/portaudio/src/os/win/pa_win_util.c
index 2f0cdf34..1354b9ab 100644
--- a/pd/portaudio/src/os/win/pa_win_util.c
+++ b/pd/portaudio/src/os/win/pa_win_util.c
@@ -1,10 +1,10 @@
/*
- * $Id: pa_win_util.c 1197 2007-05-04 13:07:10Z gordon_gidluck $
+ * $Id: pa_win_util.c 1410 2009-04-07 10:08:48Z rossb $
* Portable Audio I/O Library
* Win32 platform-specific support functions
*
* Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2000 Ross Bencina
+ * Copyright (c) 1999-2008 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -40,7 +40,7 @@
/** @file
@ingroup win_src
- Win32 platform-specific support functions.
+ @brief Win32 implementation of platform-specific PaUtil support functions.
@todo Implement workaround for QueryPerformanceCounter() skipping forward
bug. (see msdn kb Q274323).
@@ -51,6 +51,10 @@
#include "pa_util.h"
+#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
+#pragma comment( lib, "winmm.lib" )
+#endif
+
/*
Track memory allocations to avoid leaks.
diff --git a/pd/portaudio/src/os/win/pa_win_waveformat.c b/pd/portaudio/src/os/win/pa_win_waveformat.c
new file mode 100644
index 00000000..bbf616c3
--- /dev/null
+++ b/pd/portaudio/src/os/win/pa_win_waveformat.c
@@ -0,0 +1,154 @@
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Windows WAVEFORMAT* data structure utilities
+ * portaudio.h should be included before this file.
+ *
+ * Copyright (c) 2007 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "portaudio.h"
+#include "pa_win_waveformat.h"
+
+
+#if !defined(WAVE_FORMAT_EXTENSIBLE)
+#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
+#endif
+
+static GUID pawin_ksDataFormatSubtypeGuidBase =
+ { (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };
+
+
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat )
+{
+ if( sampleFormat == paFloat32 )
+ return PAWIN_WAVE_FORMAT_IEEE_FLOAT;
+
+ return PAWIN_WAVE_FORMAT_PCM;
+}
+
+
+void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate )
+{
+ WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;
+ int bytesPerSample = Pa_GetSampleSize(sampleFormat);
+ unsigned long bytesPerFrame = numChannels * bytesPerSample;
+
+ waveFormatEx->wFormatTag = waveFormatTag;
+ waveFormatEx->nChannels = (WORD)numChannels;
+ waveFormatEx->nSamplesPerSec = (DWORD)sampleRate;
+ waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec * bytesPerFrame;
+ waveFormatEx->nBlockAlign = (WORD)bytesPerFrame;
+ waveFormatEx->wBitsPerSample = bytesPerSample * 8;
+ waveFormatEx->cbSize = 0;
+}
+
+
+void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,
+ PaWinWaveFormatChannelMask channelMask )
+{
+ WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;
+ int bytesPerSample = Pa_GetSampleSize(sampleFormat);
+ unsigned long bytesPerFrame = numChannels * bytesPerSample;
+ GUID guid;
+
+ waveFormatEx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+ waveFormatEx->nChannels = (WORD)numChannels;
+ waveFormatEx->nSamplesPerSec = (DWORD)sampleRate;
+ waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec * bytesPerFrame;
+ waveFormatEx->nBlockAlign = (WORD)bytesPerFrame;
+ waveFormatEx->wBitsPerSample = bytesPerSample * 8;
+ waveFormatEx->cbSize = 22;
+
+ *((WORD*)&waveFormat->fields[PAWIN_INDEXOF_WVALIDBITSPERSAMPLE]) =
+ waveFormatEx->wBitsPerSample;
+
+ *((DWORD*)&waveFormat->fields[PAWIN_INDEXOF_DWCHANNELMASK]) = channelMask;
+
+ guid = pawin_ksDataFormatSubtypeGuidBase;
+ guid.Data1 = (USHORT)waveFormatTag;
+ *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) = guid;
+}
+
+
+PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels )
+{
+ switch( numChannels ){
+ case 1:
+ return PAWIN_SPEAKER_MONO;
+ case 2:
+ return PAWIN_SPEAKER_STEREO;
+ case 3:
+ return PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_FRONT_RIGHT;
+ case 4:
+ return PAWIN_SPEAKER_QUAD;
+ case 5:
+ return PAWIN_SPEAKER_QUAD | PAWIN_SPEAKER_FRONT_CENTER;
+ case 6:
+ /* The meaning of the PAWIN_SPEAKER_5POINT1 flag has changed over time:
+ http://msdn2.microsoft.com/en-us/library/aa474707.aspx
+ We use PAWIN_SPEAKER_5POINT1 (not PAWIN_SPEAKER_5POINT1_SURROUND)
+ because on some cards (eg Audigy) PAWIN_SPEAKER_5POINT1_SURROUND
+ results in a virtual mixdown placing the rear output in the
+ front _and_ rear speakers.
+ */
+ return PAWIN_SPEAKER_5POINT1;
+ /* case 7: */
+ case 8:
+ return PAWIN_SPEAKER_7POINT1;
+ }
+
+ /* Apparently some Audigy drivers will output silence
+ if the direct-out constant (0) is used. So this is not ideal.
+ */
+ return PAWIN_SPEAKER_DIRECTOUT;
+
+ /* Note that Alec Rogers proposed the following as an alternate method to
+ generate the default channel mask, however it doesn't seem to be an improvement
+ over the above, since some drivers will matrix outputs mapping to non-present
+ speakers accross multiple physical speakers.
+
+ if(nChannels==1) {
+ pwfFormat->dwChannelMask = SPEAKER_FRONT_CENTER;
+ }
+ else {
+ pwfFormat->dwChannelMask = 0;
+ for(i=0; i<nChannels; i++)
+ pwfFormat->dwChannelMask = (pwfFormat->dwChannelMask << 1) | 0x1;
+ }
+ */
+}
diff --git a/pd/portaudio/src/os/win/pa_win_wdmks_utils.c b/pd/portaudio/src/os/win/pa_win_wdmks_utils.c
new file mode 100644
index 00000000..7119b43a
--- /dev/null
+++ b/pd/portaudio/src/os/win/pa_win_wdmks_utils.c
@@ -0,0 +1,260 @@
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Windows WDM KS utilities
+ *
+ * Copyright (c) 1999 - 2007 Andrew Baldwin, Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+#include <windows.h>
+#include <mmreg.h>
+#include <ks.h>
+#include <ksmedia.h>
+#include <stdio.h> // just for some development printfs
+
+#include "portaudio.h"
+#include "pa_util.h"
+#include "pa_win_wdmks_utils.h"
+
+
+static PaError WdmGetPinPropertySimple(
+ HANDLE handle,
+ unsigned long pinId,
+ unsigned long property,
+ void* value,
+ unsigned long valueSize )
+{
+ DWORD bytesReturned;
+ KSP_PIN ksPProp;
+ ksPProp.Property.Set = KSPROPSETID_Pin;
+ ksPProp.Property.Id = property;
+ ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
+ ksPProp.PinId = pinId;
+ ksPProp.Reserved = 0;
+
+ if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN),
+ value, valueSize, &bytesReturned, NULL ) == 0 || bytesReturned != valueSize )
+ {
+ return paUnanticipatedHostError;
+ }
+ else
+ {
+ return paNoError;
+ }
+}
+
+
+static PaError WdmGetPinPropertyMulti(
+ HANDLE handle,
+ unsigned long pinId,
+ unsigned long property,
+ KSMULTIPLE_ITEM** ksMultipleItem)
+{
+ unsigned long multipleItemSize = 0;
+ KSP_PIN ksPProp;
+ DWORD bytesReturned;
+
+ *ksMultipleItem = 0;
+
+ ksPProp.Property.Set = KSPROPSETID_Pin;
+ ksPProp.Property.Id = property;
+ ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
+ ksPProp.PinId = pinId;
+ ksPProp.Reserved = 0;
+
+ if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp.Property,
+ sizeof(KSP_PIN), NULL, 0, &multipleItemSize, NULL ) == 0 && GetLastError() != ERROR_MORE_DATA )
+ {
+ return paUnanticipatedHostError;
+ }
+
+ *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize );
+ if( !*ksMultipleItem )
+ {
+ return paInsufficientMemory;
+ }
+
+ if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN),
+ (void*)*ksMultipleItem, multipleItemSize, &bytesReturned, NULL ) == 0 || bytesReturned != multipleItemSize )
+ {
+ PaUtil_FreeMemory( ksMultipleItem );
+ return paUnanticipatedHostError;
+ }
+
+ return paNoError;
+}
+
+
+static int GetKSFilterPinCount( HANDLE deviceHandle )
+{
+ DWORD result;
+
+ if( WdmGetPinPropertySimple( deviceHandle, 0, KSPROPERTY_PIN_CTYPES, &result, sizeof(result) ) == paNoError ){
+ return result;
+ }else{
+ return 0;
+ }
+}
+
+
+static KSPIN_COMMUNICATION GetKSFilterPinPropertyCommunication( HANDLE deviceHandle, int pinId )
+{
+ KSPIN_COMMUNICATION result;
+
+ if( WdmGetPinPropertySimple( deviceHandle, pinId, KSPROPERTY_PIN_COMMUNICATION, &result, sizeof(result) ) == paNoError ){
+ return result;
+ }else{
+ return KSPIN_COMMUNICATION_NONE;
+ }
+}
+
+
+static KSPIN_DATAFLOW GetKSFilterPinPropertyDataflow( HANDLE deviceHandle, int pinId )
+{
+ KSPIN_DATAFLOW result;
+
+ if( WdmGetPinPropertySimple( deviceHandle, pinId, KSPROPERTY_PIN_DATAFLOW, &result, sizeof(result) ) == paNoError ){
+ return result;
+ }else{
+ return (KSPIN_DATAFLOW)0;
+ }
+}
+
+
+static int KSFilterPinPropertyIdentifiersInclude(
+ HANDLE deviceHandle, int pinId, unsigned long property, const GUID *identifierSet, unsigned long identifierId )
+{
+ KSMULTIPLE_ITEM* item = NULL;
+ KSIDENTIFIER* identifier;
+ int i;
+ int result = 0;
+
+ if( WdmGetPinPropertyMulti( deviceHandle, pinId, property, &item) != paNoError )
+ return 0;
+
+ identifier = (KSIDENTIFIER*)(item+1);
+
+ for( i = 0; i < (int)item->Count; i++ )
+ {
+ if( !memcmp( (void*)&identifier[i].Set, (void*)identifierSet, sizeof( GUID ) ) &&
+ ( identifier[i].Id == identifierId ) )
+ {
+ result = 1;
+ break;
+ }
+ }
+
+ PaUtil_FreeMemory( item );
+
+ return result;
+}
+
+
+/* return the maximum channel count supported by any pin on the device.
+ if isInput is non-zero we query input pins, otherwise output pins.
+*/
+int PaWin_WDMKS_QueryFilterMaximumChannelCount( void *wcharDevicePath, int isInput )
+{
+ HANDLE deviceHandle;
+ int pinCount, pinId, i;
+ int result = 0;
+ KSPIN_DATAFLOW requiredDataflowDirection = (isInput ? KSPIN_DATAFLOW_OUT : KSPIN_DATAFLOW_IN );
+
+ if( !wcharDevicePath )
+ return 0;
+
+ deviceHandle = CreateFileW( (LPCWSTR)wcharDevicePath, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
+ if( deviceHandle == INVALID_HANDLE_VALUE )
+ return 0;
+
+ pinCount = GetKSFilterPinCount( deviceHandle );
+ for( pinId = 0; pinId < pinCount; ++pinId )
+ {
+ KSPIN_COMMUNICATION communication = GetKSFilterPinPropertyCommunication( deviceHandle, pinId );
+ KSPIN_DATAFLOW dataflow = GetKSFilterPinPropertyDataflow( deviceHandle, pinId );
+ if( ( dataflow == requiredDataflowDirection ) &&
+ (( communication == KSPIN_COMMUNICATION_SINK) ||
+ ( communication == KSPIN_COMMUNICATION_BOTH))
+ && ( KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId,
+ KSPROPERTY_PIN_INTERFACES, &KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_STREAMING )
+ || KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId,
+ KSPROPERTY_PIN_INTERFACES, &KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_LOOPED_STREAMING ) )
+ && KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId,
+ KSPROPERTY_PIN_MEDIUMS, &KSMEDIUMSETID_Standard, KSMEDIUM_STANDARD_DEVIO ) )
+ {
+ KSMULTIPLE_ITEM* item = NULL;
+ if( WdmGetPinPropertyMulti( deviceHandle, pinId, KSPROPERTY_PIN_DATARANGES, &item ) == paNoError )
+ {
+ KSDATARANGE *dataRange = (KSDATARANGE*)(item+1);
+
+ for( i=0; i < item->Count; ++i ){
+
+ if( IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat)
+ || memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID) ) == 0
+ || memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID) ) == 0
+ || ( ( memcmp( (void*)&dataRange->MajorFormat, (void*)&KSDATAFORMAT_TYPE_AUDIO, sizeof(GUID) ) == 0 )
+ && ( memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_WILDCARD, sizeof(GUID) ) == 0 ) ) )
+ {
+ KSDATARANGE_AUDIO *dataRangeAudio = (KSDATARANGE_AUDIO*)dataRange;
+
+ /*
+ printf( ">>> %d %d %d %d %S\n", isInput, dataflow, communication, dataRangeAudio->MaximumChannels, devicePath );
+
+ if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, sizeof(GUID) ) == 0 )
+ printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WAVEFORMATEX\n" );
+ else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_DSOUND, sizeof(GUID) ) == 0 )
+ printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_DSOUND\n" );
+ else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WILDCARD, sizeof(GUID) ) == 0 )
+ printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WILDCARD\n" );
+ else
+ printf( "\tspecifier: ?\n" );
+ */
+
+ /*
+ We assume that very high values for MaximumChannels are not useful and indicate
+ that the driver isn't prepared to tell us the real number of channels which it supports.
+ */
+ if( dataRangeAudio->MaximumChannels < 0xFFFFUL && (int)dataRangeAudio->MaximumChannels > result )
+ result = (int)dataRangeAudio->MaximumChannels;
+ }
+
+ dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize);
+ }
+
+ PaUtil_FreeMemory( item );
+ }
+ }
+ }
+
+ CloseHandle( deviceHandle );
+ return result;
+}
diff --git a/pd/portaudio/src/os/win/pa_win_wdmks_utils.h b/pd/portaudio/src/os/win/pa_win_wdmks_utils.h
new file mode 100644
index 00000000..f54035f4
--- /dev/null
+++ b/pd/portaudio/src/os/win/pa_win_wdmks_utils.h
@@ -0,0 +1,65 @@
+#ifndef PA_WIN_WDMKS_UTILS_H
+#define PA_WIN_WDMKS_UTILS_H
+
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Windows WDM KS utilities
+ *
+ * Copyright (c) 1999 - 2007 Ross Bencina, Andrew Baldwin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/** @file
+ @brief Utilities for working with the Windows WDM KS API
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ Query for the maximum number of channels supported by any pin of the
+ specified device. Returns 0 if the query fails for any reason.
+
+ @param wcharDevicePath A system level PnP interface path, supplied as a WCHAR unicode string.
+ Declard as void* to avoid introducing a dependency on wchar_t here.
+
+ @param isInput A flag specifying whether to query for input (non-zero) or output (zero) channels.
+*/
+int PaWin_WDMKS_QueryFilterMaximumChannelCount( void *wcharDevicePath, int isInput );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_WIN_WDMKS_UTILS_H */ \ No newline at end of file
diff --git a/pd/portaudio/src/os/win/pa_x86_plain_converters.c b/pd/portaudio/src/os/win/pa_x86_plain_converters.c
index 63b058df..d3d0fdaf 100644
--- a/pd/portaudio/src/os/win/pa_x86_plain_converters.c
+++ b/pd/portaudio/src/os/win/pa_x86_plain_converters.c
@@ -124,7 +124,7 @@ static const double ditheredInt16Scaler_ = 0x7FFE;
#define PA_DITHER_BITS_ (15)
/* Multiply by PA_FLOAT_DITHER_SCALE_ to get a float between -2.0 and +1.99999 */
-#define PA_FLOAT_DITHER_SCALE_ (1.0 / ((1<<PA_DITHER_BITS_)-1))
+#define PA_FLOAT_DITHER_SCALE_ (1.0F / ((1<<PA_DITHER_BITS_)-1))
static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
#define PA_DITHER_SHIFT_ ((32 - PA_DITHER_BITS_) + 1)
diff --git a/pd/portmidi/Makefile.am b/pd/portmidi/Makefile.am
new file mode 100644
index 00000000..1b4d61a4
--- /dev/null
+++ b/pd/portmidi/Makefile.am
@@ -0,0 +1,44 @@
+# this is built as a "libtool convenience library"
+# http://sources.redhat.com/automake/automake.html#Libtool-Convenience-Libraries
+AUTOMAKE_OPTIONS = foreign
+AM_CFLAGS = -DNEWBUFFER
+INCLUDES = -Ipm_common -Iporttime
+
+noinst_LTLIBRARIES = libportmidi.la
+
+libportmidi_la_SOURCES = pm_common/pmutil.c pm_common/portmidi.c
+
+if LINUX
+INCLUDES += -Ipm_linux
+libportmidi_la_SOURCES += porttime/ptlinux.c \
+ pm_linux/pmlinux.c \
+ pm_linux/pmlinuxalsa.c
+endif
+
+if MACOSX
+INCLUDES += -Ipm_mac
+libportmidi_la_SOURCES += porttime/ptmacosx_cf.c \
+ pm_mac/pmmac.c \
+ pm_mac/pmmacosxcm.c
+endif
+
+if WINDOWS
+INCLUDES += -Ipm_win
+libportmidi_la_SOURCES += porttime/porttime.c \
+ porttime/ptwinmm.c \
+ pm_win/pmwin.c \
+ pm_win/pmwinmm.c
+endif
+
+# include the headers in the dist so you can build
+nobase_noinst_HEADERS = \
+ pm_common/pminternal.h \
+ pm_common/pmutil.h \
+ pm_common/portmidi.h \
+ pm_linux/pmlinux.h \
+ pm_linux/pmlinuxalsa.h \
+ pm_mac/pmmac.h \
+ pm_mac/pmmacosxcm.h \
+ pm_win/pmdll.h \
+ pm_win/pmwinmm.h \
+ porttime/porttime.h
diff --git a/pd/src/Makefile.am b/pd/src/Makefile.am
new file mode 100644
index 00000000..b85f726d
--- /dev/null
+++ b/pd/src/Makefile.am
@@ -0,0 +1,145 @@
+AUTOMAKE_OPTIONS = foreign
+
+pd_CFLAGS = -DPD -DINSTALL_PREFIX=\"$(prefix)\"
+pd_LDFLAGS =
+
+pdsend_CFLAGS =
+pdreceive_CFLAGS =
+pd_watchdog_CFLAGS =
+LIBS =
+INCLUDES = @INCLUDES@
+
+SUFFIXES = .@EXTENSION@ .@SHARED_LIB@
+
+bin_PROGRAMS = pd pdsend pdreceive
+pdsend_SOURCES = u_pdsend.c
+pdreceive_SOURCES = u_pdreceive.c
+pd_watchdog_SOURCES = s_watchdog.c
+pd_LDADD =
+pd_SOURCES = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c \
+ g_io.c g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
+ g_all_guis.c g_bang.c g_hdial.c g_hslider.c g_mycanvas.c g_numbox.c \
+ g_toggle.c g_vdial.c g_vslider.c g_vumeter.c \
+ m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
+ m_conf.c m_glob.c m_sched.c \
+ s_main.c s_inter.c s_file.c s_print.c \
+ s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ s_utf8.c \
+ d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
+ d_math.c d_fft.c d_array.c d_global.c \
+ d_delay.c d_resample.c \
+ x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
+ x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c x_list.c d_soundfile.c
+
+pd_includedir = ${includedir}/pd
+pd_include_HEADERS = m_pd.h m_imp.h g_canvas.h s_stuff.h g_all_guis.h
+# compatibility: m_pd.h also goes into ${includedir}/
+include_HEADERS = m_pd.h
+noinst_HEADERS = g_all_guis.h s_audio_alsa.h s_audio_paring.h s_utf8.h
+
+# we want these in the dist tarball
+EXTRA_DIST = CHANGELOG.txt notes.txt makefile.mingw
+
+# configurations per library
+if ALSA
+pd_CFLAGS += -DUSEAPI_ALSA
+pd_SOURCES += s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c
+endif
+
+if COREAUDIO
+LIBS += -framework CoreAudio -framework CoreMIDI \
+ -framework AudioUnit -framework AudioToolbox
+endif
+
+if FFTW
+pd_SOURCES += d_fft_fftw.c d_fftroutine.c
+else
+pd_SOURCES += d_fft_mayer.c d_fftroutine.c
+endif
+
+# TODO support Jack xrun
+if JACK
+pd_CFLAGS += -DUSEAPI_JACK -DJACK_XRUN
+pd_SOURCES += s_audio_jack.c
+if MACOSX
+LIBS += -weak_framework Jackmp
+else
+LIBS += -ljack
+endif
+endif
+
+# Cygwin has a function OSS /dev/dsp, but not MIDI, and Pd is only set up to
+# handle a single MIDI API
+if OSS
+if !WINDOWS
+pd_CFLAGS += -DUSEAPI_OSS
+pd_SOURCES += s_audio_oss.c s_midi_oss.c
+endif
+endif
+
+if PORTAUDIO
+pd_CFLAGS += -DUSEAPI_PORTAUDIO -I../portaudio/include
+pd_LDADD += ../portaudio/libportaudio.la
+pd_SOURCES += s_audio_pa.c s_audio_paring.c
+endif
+
+# ASIO needs to go after PORTAUDIO in order for it to link properly
+if ASIO
+pd_LDADD += ../asio/libasio.la
+endif
+
+if PORTMIDI
+INCLUDES += -I../portmidi/pm_common -I../portmidi/porttime
+pd_LDADD += ../portmidi/libportmidi.la
+pd_SOURCES += s_midi_pm.c
+endif
+
+
+# FIXXXME
+# GNU/HURD, IPHONEOS, ... have no MIDI (not even OSS)
+# i think it would be better to add s_midi_dummy.c only if no other midi API can be found
+# (without OS-specific checks)
+# even better would be, to allow Pd to have simply have no MIDI (nor AUDIO)
+if IPHONEOS
+pd_SOURCES += s_midi_dummy.c
+endif
+
+if HURD
+pd_SOURCES += s_midi_dummy.c
+endif
+
+if LINUX
+libpdbindir = $(pkglibdir)/bin
+libpdbin_DATA =
+libpdbin_PROGRAMS = pd-watchdog pd
+# this flag has to have a single leading "-" for libtool, even though ld uses
+# --export-dynamic, and libtool sends -Wl,--export-dynamic to ld...
+pd_LDFLAGS += -export-dynamic
+# on Ubuntu/Karmic 9.10, it doesn't seem to find libm, so force it
+pd_LDFLAGS += $(LIBM)
+endif
+
+if MACOSX
+LIBS += -framework Carbon
+pd_CFLAGS += -DMACOSX #kludge, should use auto macro __APPLE__
+bin_SCRIPTS =
+bin_PROGRAMS += pd-watchdog
+endif
+
+if WINDOWS
+LIBS += -lwsock32 -lwinmm -lole32
+pd_CFLAGS += -DUSEAPI_MMIO -DPD_INTERNAL
+pd_SOURCES += s_audio_mmio.c s_midi_mmio.c
+bin_SCRIPTS =
+endif
+
+# Cygwin is not _WIN32 and MSW vaguely means the same thing, so MINGW only
+if MINGW
+pd_CFLAGS += -DWISHAPP='"wish85.exe"' -DMSW #kludge, MSW should be _WIN32
+pdsend_CFLAGS += -DMSW #kludge, should use _WIN32
+pdreceive_CFLAGS += -DMSW #kludge, should use _WIN32
+bin_PROGRAMS += pd-watchdog
+endif
+
+etags: TAGS
+ etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl
diff --git a/pd/src/configure.in b/pd/src/configure.in
index e4f4edd7..e5d2e00b 100644
--- a/pd/src/configure.in
+++ b/pd/src/configure.in
@@ -95,8 +95,8 @@ AC_CHECK_LIB(pthread, pthread_create,PDLIB="$PDLIB -lpthread",
dnl Check for fftw package
if test x$fftw = "xyes";
then
-AC_CHECK_LIB(fftw, fftw_one,PDLIB="$PDLIB -lfftw",
- echo "fftw package not found - using built-in FFT"; fftw=no)
+AC_CHECK_LIB(fftw3f, fftwf_version,PDLIB="$PDLIB -lfftw3f",
+ echo "fftw3 package not found - using built-in FFT"; fftw=no)
fi
dnl look for tcl 8.x... do I really have to go through all this!?
@@ -173,7 +173,7 @@ else
GUISRC=
fi
-if test `uname -s` = Linux;
+if test `uname -s` = Linux -o `uname -s` = "GNU/kFreeBSD" -o `uname -s` = "GNU";
then
dnl Ckecking for ALSA
echo .................... alsa= $alsa
@@ -195,10 +195,19 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
LDFLAGS="$LDFLAGS -static"
fi
EXT=pd_linux
- CPPFLAGS="-DHAVE_LIBDL -DPA_USE_OSS -DUNIX -DHAVE_UNISTD_H\
- -DUSEAPI_OSS \
+ CPPFLAGS="-DHAVE_LIBDL -DUNIX -DHAVE_UNISTD_H\
+ -DPDGUIDIR=\\\"tcl/\\\" \
-fno-strict-aliasing"
- SYSSRC="s_midi_oss.c s_audio_oss.c"
+dnl No OSS on hurd
+ if test `uname -s` = "GNU";
+ then
+ SYSSRC="s_midi_dummy.c"
+ else
+ SYSSRC="s_midi_oss.c s_audio_oss.c"
+ CPPFLAGS=$CPPFLAGS" -DPA_USE_OSS -DUSEAPI_OSS"
+ fi
+
+
if test x$alsa = "xyes";
then
SYSSRC=$SYSSRC" s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c"
@@ -215,7 +224,6 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
-I../portmidi/pm_common \
-I../portmidi/pm_linux"
SYSSRC="s_audio_pa.c \
- s_audio_pablio.c \
s_audio_paring.c \
../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \
@@ -295,7 +303,6 @@ then
EXTERNTARGET=d_ppc
fi
SYSSRC="s_midi_pm.c s_audio_pa.c \
- s_audio_pablio.c \
s_audio_paring.c \
../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \
@@ -347,11 +354,11 @@ then
OSNUMBER=2
if test x$jack = "xyes";
then
- LDFLAGS=$LDFLAGS" -weak_framework Jack"
+ LDFLAGS=$LDFLAGS" -weak_framework Jackmp"
fi
if test x$jack = "xrun";
then
- LDFLAGS=$LDFLAGS" -weak_framework Jack"
+ LDFLAGS=$LDFLAGS" -weak_framework Jackmp"
fi
fi
@@ -367,7 +374,7 @@ then
-mwindows -mms-bitfields "$MORECFLAGS
PDLIB=$PDLIB" -lwsock32 -lwinmm -lole32 -lstdc++"
- SYSSRC="s_audio_pa.c s_audio_pablio.c s_audio_paring.c \
+ SYSSRC="s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c s_midi_mmio.c \
../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \
@@ -408,7 +415,7 @@ fi
if test x$fftw = "xyes";
then
SYSSRC=$SYSSRC" d_fft_fftw.c d_fftroutine.c"
- LDFLAGS=$LDFLAGS" -lfftw"
+ LDFLAGS=$LDFLAGS" -lfftw3"
else
SYSSRC=$SYSSRC" d_fft_mayer.c d_fftroutine.c"
fi
diff --git a/pd/src/d_array.c b/pd/src/d_array.c
index 11a55b5d..c0aab61e 100644
--- a/pd/src/d_array.c
+++ b/pd/src/d_array.c
@@ -498,50 +498,52 @@ static void tabread4_tilde_setup(void)
/* this is all copied from d_osc.c... what include file could this go in? */
#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
- /* machine-dependent definitions. These ifdefs really
- should have been by CPU type and not by operating system! */
#ifdef IRIX
- /* big-endian. Most significant byte is at low address in memory */
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#define int32 long /* a data type that has 32 bits */
-#endif /* IRIX */
-
-#ifdef MSW
- /* little-endian; most significant byte is at highest address */
-#define HIOFFSET 1
-#define LOWOFFSET 0
-#define int32 long
+#include <sys/endian.h>
#endif
-#if defined(__FreeBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__)
#include <machine/endian.h>
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(ANDROID)
#include <endian.h>
#endif
-#if defined(__unix__) || defined(__APPLE__)
+#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
+#endif
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define HIOFFSET 1
-#define LOWOFFSET 0
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define HIOFFSET 1
+# define LOWOFFSET 0
#else
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#endif /* __BYTE_ORDER */
-#include <sys/types.h>
-#define int32 int32_t
-#endif /* __unix__ or __APPLE__*/
+# define HIOFFSET 0 /* word offset to find MSB */
+# define LOWOFFSET 1 /* word offset to find LSB */
+#endif
+
+#ifdef _MSC_VER
+ typedef __int32 int32_t; /* use MSVC's internal type */
+#elif defined(IRIX)
+ typedef long int32_t; /* a data type that has 32 bits */
+#else
+# include <stdint.h> /* this is where int32_t is defined in C99 */
+#endif
union tabfudge
{
double tf_d;
- int32 tf_i[2];
+ int32_t tf_i[2];
};
static t_class *tabosc4_tilde_class;
diff --git a/pd/src/d_ctl.c b/pd/src/d_ctl.c
index 92467abe..8d6bb000 100644
--- a/pd/src/d_ctl.c
+++ b/pd/src/d_ctl.c
@@ -657,7 +657,7 @@ static void env_tilde_dsp(t_sigenv *x, t_signal **sp)
(x->x_npoints + sp[0]->s_n) * sizeof(t_sample));
if (!xx)
{
- post("env~: out of memory");
+ error("env~: out of memory");
return;
}
x->x_buf = (t_sample *)xx;
diff --git a/pd/src/d_delay.c b/pd/src/d_delay.c
index 98cc1149..a6e5f7cf 100644
--- a/pd/src/d_delay.c
+++ b/pd/src/d_delay.c
@@ -24,6 +24,7 @@ typedef struct _sigdelwrite
{
t_object x_obj;
t_symbol *x_sym;
+ t_float x_deltime; /* delay in msec (added by Mathieu Bouchard) */
t_delwritectl x_cspace;
int x_sortno; /* DSP sort number at which this was last put on chain */
int x_rsortno; /* DSP sort # for first delread or write in chain */
@@ -34,6 +35,21 @@ typedef struct _sigdelwrite
#define XTRASAMPS 4
#define SAMPBLK 4
+static void sigdelwrite_updatesr (t_sigdelwrite *x, t_float sr) /* added by Mathieu Bouchard */
+{
+ int nsamps = x->x_deltime * sr * (t_float)(0.001f);
+ if (nsamps < 1) nsamps = 1;
+ nsamps += ((- nsamps) & (SAMPBLK - 1));
+ nsamps += DEFDELVS;
+ if (x->x_cspace.c_n != nsamps) {
+ x->x_cspace.c_vec = (t_sample *)resizebytes(x->x_cspace.c_vec,
+ (x->x_cspace.c_n + XTRASAMPS) * sizeof(t_sample),
+ ( nsamps + XTRASAMPS) * sizeof(t_sample));
+ x->x_cspace.c_n = nsamps;
+ x->x_cspace.c_phase = XTRASAMPS;
+ }
+}
+
/* routine to check that all delwrites/delreads/vds have same vecsize */
static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
{
@@ -54,19 +70,13 @@ static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize)
static void *sigdelwrite_new(t_symbol *s, t_floatarg msec)
{
- int nsamps;
t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class);
if (!*s->s_name) s = gensym("delwrite~");
pd_bind(&x->x_obj.ob_pd, s);
x->x_sym = s;
- nsamps = msec * sys_getsr() * (t_float)(0.001f);
- if (nsamps < 1) nsamps = 1;
- nsamps += ((- nsamps) & (SAMPBLK - 1));
- nsamps += DEFDELVS;
- x->x_cspace.c_n = nsamps;
- x->x_cspace.c_vec =
- (t_sample *)getbytes((nsamps + XTRASAMPS) * sizeof(t_sample));
- x->x_cspace.c_phase = XTRASAMPS;
+ x->x_deltime = msec;
+ x->x_cspace.c_n = 0;
+ x->x_cspace.c_vec = getbytes(XTRASAMPS * sizeof(t_sample));
x->x_sortno = 0;
x->x_vecsize = 0;
x->x_f = 0;
@@ -98,8 +108,6 @@ static t_int *sigdelwrite_perform(t_int *w)
phase -= nsamps;
}
}
- bp = vp + c->c_phase;
-
c->c_phase = phase;
return (w+4);
}
@@ -109,6 +117,7 @@ static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp)
dsp_add(sigdelwrite_perform, 3, sp[0]->s_vec, &x->x_cspace, sp[0]->s_n);
x->x_sortno = ugen_getsortno();
sigdelwrite_checkvecsize(x, sp[0]->s_n);
+ sigdelwrite_updatesr(x, sp[0]->s_sr);
}
static void sigdelwrite_free(t_sigdelwrite *x)
@@ -200,6 +209,7 @@ static void sigdelread_dsp(t_sigdelread *x, t_signal **sp)
x->x_n = sp[0]->s_n;
if (delwriter)
{
+ sigdelwrite_updatesr(delwriter, sp[0]->s_sr);
sigdelwrite_checkvecsize(delwriter, sp[0]->s_n);
x->x_zerodel = (delwriter->x_sortno == ugen_getsortno() ?
0 : delwriter->x_vecsize);
diff --git a/pd/src/d_fft_fftw.c b/pd/src/d_fft_fftw.c
index 0ead62be..04e4729d 100644
--- a/pd/src/d_fft_fftw.c
+++ b/pd/src/d_fft_fftw.c
@@ -4,31 +4,32 @@
/* --------- Pd interface to FFTW library; imitate Mayer API ---------- */
-#include "m_pd.h"
-#ifdef MSW
-#include <malloc.h>
-#else
-#include <alloca.h>
-#endif
-
-#error oops -- I'm talking to the old fftw. Apparently it's still changing.
+/* changes and additions for FFTW3 by Thomas Grill */
-#include <fftw.h>
+#include "m_pd.h"
+#include <fftw3.h>
int ilog2(int n);
-#define MINFFT 5
+#define MINFFT 0
#define MAXFFT 30
/* from the FFTW website:
- fftw_complex in[N], out[N];
+ #include <fftw3.h>
+ ...
+ {
+ fftw_complex *in, *out;
fftw_plan p;
...
- p = fftw_create_plan(N, FFTW_FORWARD, FFTW_ESTIMATE);
+ in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
+ out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
+ p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
...
- fftw_one(p, in, out);
+ fftw_execute(p);
...
fftw_destroy_plan(p);
+ fftw_free(in); fftw_free(out);
+ }
FFTW_FORWARD or FFTW_BACKWARD, and indicates the direction of the transform you
are interested in. Alternatively, you can use the sign of the exponent in the
@@ -37,57 +38,126 @@ respectively. The flags argument is either FFTW_MEASURE
*/
-static fftw_plan fftw_pvec[2 * (MAXFFT+1 - MINFFT)];
+/* complex stuff */
+
+typedef struct {
+ fftwf_plan plan;
+ fftwf_complex *in,*out;
+} cfftw_info;
+
+static cfftw_info cfftw_fwd[MAXFFT+1 - MINFFT],cfftw_bwd[MAXFFT+1 - MINFFT];
+
+static cfftw_info *cfftw_getplan(int n,int fwd)
+{
+ cfftw_info *info;
+ int logn = ilog2(n);
+ if (logn < MINFFT || logn > MAXFFT)
+ return (0);
+ info = (fwd?cfftw_fwd:cfftw_bwd)+(logn-MINFFT);
+ if (!info->plan)
+ {
+ info->in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
+ info->out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
+ info->plan = fftwf_plan_dft_1d(n, info->in, info->out, fwd?FFTW_FORWARD:FFTW_BACKWARD, FFTW_MEASURE);
+ }
+ return info;
+}
+
-static fftw_plan fftw_getplan(int n, int dir)
+/* real stuff */
+
+typedef struct {
+ fftwf_plan plan;
+ float *in,*out;
+} rfftw_info;
+
+static rfftw_info rfftw_fwd[MAXFFT+1 - MINFFT],rfftw_bwd[MAXFFT+1 - MINFFT];
+
+static rfftw_info *rfftw_getplan(int n,int fwd)
{
- logn = ilog2(n);
+ rfftw_info *info;
+ int logn = ilog2(n);
if (logn < MINFFT || logn > MAXFFT)
return (0);
- int indx = 2*(logn-MINFFT) + inverse);
- if (!fftw_pvec[indx]
- fftw_pvec[indx] = fftw_create_plan(N, dir, FFTW_MEASURE);
- return (fftw_pvec[indx]);
+ info = (fwd?rfftw_fwd:rfftw_bwd)+(logn-MINFFT);
+ if (!info->plan)
+ {
+ info->in = (float*) fftwf_malloc(sizeof(float) * n);
+ info->out = (float*) fftwf_malloc(sizeof(float) * n);
+ info->plan = fftwf_plan_r2r_1d(n, info->in, info->out, fwd?FFTW_R2HC:FFTW_HC2R, FFTW_MEASURE);
+ }
+ return info;
}
+
+
EXTERN void mayer_fht(float *fz, int n)
{
post("FHT: not yet implemented");
}
-static void mayer_dofft(int n, float *fz1, float *fz2, int dir)
+static void mayer_do_cfft(int n, float *fz1, float *fz2, int fwd)
{
- float *inbuf, *outbuf, *fp1, *fp2, *fp3;
int i;
- fftw_plan p = fftw_getplan(n, dir);
- inbuf = alloca(n * (4 * sizeof(float)));
- outbuf = inbuf + 2*n;
+ float *fz;
+ cfftw_info *p = cfftw_getplan(n, fwd);
if (!p)
return;
- for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = inbuf; i < n; i++)
- fp3[0] = *fp1++, fp3[1] = *fp2++, fp3 += 2;
- fftw_one(p, inbuf, outbuf);
- for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = outbuf; i < n; i++)
- *fp1++ = fp3[0], *fp2++ = fp3[1], fp3 += 2;
+
+ for (i = 0, fz = (float *)p->in; i < n; i++)
+ fz[i*2] = fz1[i], fz[i*2+1] = fz2[i];
+
+ fftwf_execute(p->plan);
+
+ for (i = 0, fz = (float *)p->out; i < n; i++)
+ fz1[i] = fz[i*2], fz2[i] = fz[i*2+1];
}
EXTERN void mayer_fft(int n, float *fz1, float *fz2)
{
- mayer_dofft(n, fz1, fz2, FFTW_FORWARD);
+ mayer_do_cfft(n, fz1, fz2, 1);
}
EXTERN void mayer_ifft(int n, float *fz1, float *fz2)
{
- mayer_dofft(n, fz1, fz2, FFTW_BACKWARD);
+ mayer_do_cfft(n, fz1, fz2, 0);
}
+/*
+ in the following the sign flips are done to
+ be compatible with the mayer_fft implementation,
+ but it's probably the mayer_fft that should be corrected...
+*/
+
EXTERN void mayer_realfft(int n, float *fz)
{
- post("rfft: not yet implemented");
+ int i;
+ rfftw_info *p = rfftw_getplan(n, 1);
+ if (!p)
+ return;
+
+ for (i = 0; i < n; i++)
+ p->in[i] = fz[i];
+ fftwf_execute(p->plan);
+ for (i = 0; i < n/2+1; i++)
+ fz[i] = p->out[i];
+ for (; i < n; i++)
+ fz[i] = -p->out[i];
}
EXTERN void mayer_realifft(int n, float *fz)
{
- post("rifft: not yet implemented");
+ int i;
+ rfftw_info *p = rfftw_getplan(n, 0);
+ if (!p)
+ return;
+
+ for (i = 0; i < n/2+1; i++)
+ p->in[i] = fz[i];
+ for (; i < n; i++)
+ p->in[i] = -fz[i];
+ fftwf_execute(p->plan);
+ for (i = 0; i < n; i++)
+ fz[i] = p->out[i];
}
diff --git a/pd/src/d_fftroutine.c b/pd/src/d_fftroutine.c
index 0222a0c0..5882abb2 100644
--- a/pd/src/d_fftroutine.c
+++ b/pd/src/d_fftroutine.c
@@ -98,11 +98,10 @@
#define FALSE 0
#endif
-#define SAMPLE PD_FLOATTYPE /* data type used in calculation */
+#define SAMPLE t_float /* data type used in calculation */
#define SHORT_SIZE sizeof(short)
#define INT_SIZE sizeof(int)
-#define FLOAT_SIZE sizeof(float)
#define SAMPLE_SIZE sizeof(SAMPLE)
#define PNTR_SIZE sizeof(char *)
@@ -171,7 +170,7 @@ void net_dealloc(FFT_NET *fft_net);
int power_of_two(int n);
void create_hanning(SAMPLE *window, int n, SAMPLE scale);
void create_rectangular(SAMPLE *window, int n, SAMPLE scale);
-void short_to_float(short *short_buf, float *float_buf, int n);
+void short_to_float(short *short_buf, SAMPLE *float_buf, int n);
void load_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
int buf_scale, int trnsfrm_dir);
void compute_fft(FFT_NET *fft_net);
@@ -629,20 +628,20 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
switch (buf_form) {
case REAL: { /* pure REAL */
do {
- *buf++ = (float)fft_net->regr[i];
+ *buf++ = (SAMPLE)fft_net->regr[i];
} while (++i < n);
} break;
case IMAG: { /* pure IMAGinary */
do {
- *buf++ = (float)fft_net->regi[i];
+ *buf++ = (SAMPLE)fft_net->regi[i];
} while (++i < n);
} break;
case RECT: { /* both REAL and IMAGinary */
do {
- *buf++ = (float)fft_net->regr[i];
- *buf++ = (float)fft_net->regi[i];
+ *buf++ = (SAMPLE)fft_net->regr[i];
+ *buf++ = (SAMPLE)fft_net->regi[i];
} while (++i < n);
} break;
@@ -650,7 +649,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)sqrt(real*real+imag*imag);
+ *buf++ = (SAMPLE)sqrt(real*real+imag*imag);
} while (++i < n);
} break;
@@ -659,7 +658,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
real = fft_net->regr[i];
imag = fft_net->regi[i];
if (real > .00001)
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0){ *buf++ = PI / 2.;
if(debug) fprintf(stderr,"real=0 and imag > 0\n");}
@@ -675,9 +674,9 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)sqrt(real*real+imag*imag);
+ *buf++ = (SAMPLE)sqrt(real*real+imag*imag);
if (real) /* a hack to avoid div by zero */
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0) *buf++ = PI / 2.;
else if (imag < 0) *buf++ = -PI / 2.;
@@ -698,20 +697,20 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
switch (buf_form) {
case REAL: { /* real only */
do {
- *buf++ = (float)20.*log10(fft_net->regr[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regr[i]);
} while (++i < n);
} break;
case IMAG: { /* imag only */
do {
- *buf++ = (float)20.*log10(fft_net->regi[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regi[i]);
} while (++i < n);
} break;
case RECT: { /* real and imag */
do {
- *buf++ = (float)20.*log10(fft_net->regr[i]);
- *buf++ = (float)20.*log10(fft_net->regi[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regr[i]);
+ *buf++ = (SAMPLE)20.*log10(fft_net->regi[i]);
} while (++i < n);
} break;
@@ -719,7 +718,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)20.*log10(sqrt(real*real+imag*imag));
+ *buf++ = (SAMPLE)20.*log10(sqrt(real*real+imag*imag));
} while (++i < n);
} break;
@@ -728,7 +727,7 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
real = fft_net->regr[i];
imag = fft_net->regi[i];
if (real)
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0) *buf++ = PI / 2.;
else if (imag < 0) *buf++ = -PI / 2.;
@@ -741,9 +740,9 @@ void store_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
do {
real = fft_net->regr[i];
imag = fft_net->regi[i];
- *buf++ = (float)20.*log10(sqrt(real*real+imag*imag));
+ *buf++ = (SAMPLE)20.*log10(sqrt(real*real+imag*imag));
if (real)
- *buf++ = (float)atan2(imag, real);
+ *buf++ = (SAMPLE)atan2(imag, real);
else { /* deal with bad case */
if (imag > 0) *buf++ = PI / 2.;
else if (imag < 0) *buf++ = -PI / 2.;
@@ -975,14 +974,14 @@ void create_rectangular(SAMPLE *window, int n, SAMPLE scale)
}
-void short_to_float(short *short_buf, float *float_buf, int n)
+void short_to_float(short *short_buf, SAMPLE *float_buf, int n)
/* effects; Converts short_buf to floats and stores them in float_buf.
*/
{
while (n--) {
- *float_buf++ = (float)*short_buf++;
+ *float_buf++ = (SAMPLE)*short_buf++;
}
}
diff --git a/pd/src/d_math.c b/pd/src/d_math.c
index 31c6c655..f76bffef 100644
--- a/pd/src/d_math.c
+++ b/pd/src/d_math.c
@@ -67,13 +67,12 @@ static void clip_setup(void)
#define DUMTAB1SIZE 256
#define DUMTAB2SIZE 1024
-#ifdef MSW
-#define int32 long
-#endif
-
-#if defined(__unix__) || defined(__APPLE__)
-#include <sys/types.h>
-#define int32 int32_t
+#ifdef _MSC_VER
+ typedef __int32 int32_t; /* use MSVC's internal type */
+#elif defined(IRIX)
+ typedef long int32_t; /* a data type that has 32 bits */
+#else
+# include <stdint.h> /* this is where int32_t is defined in C99 */
#endif
static float rsqrt_exptab[DUMTAB1SIZE], rsqrt_mantissatab[DUMTAB2SIZE];
@@ -84,8 +83,8 @@ static void init_rsqrt(void)
for (i = 0; i < DUMTAB1SIZE; i++)
{
float f;
- int32 l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23;
- *(int32 *)(&f) = l;
+ int32_t l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23;
+ *(int32_t *)(&f) = l;
rsqrt_exptab[i] = 1./sqrt(f);
}
for (i = 0; i < DUMTAB2SIZE; i++)
@@ -97,16 +96,18 @@ static void init_rsqrt(void)
/* these are used in externs like "bonk" */
-t_float q8_rsqrt(t_float f)
+t_float q8_rsqrt(t_float f0)
{
+ float f = (float)f0;
long l = *(long *)(&f);
if (f < 0) return (0);
else return (rsqrt_exptab[(l >> 23) & 0xff] *
rsqrt_mantissatab[(l >> 13) & 0x3ff]);
}
-t_float q8_sqrt(t_float f)
+t_float q8_sqrt(t_float f0)
{
+ float f = (float)f0;
long l = *(long *)(&f);
if (f < 0) return (0);
else return (f * rsqrt_exptab[(l >> 23) & 0xff] *
diff --git a/pd/src/d_osc.c b/pd/src/d_osc.c
index 8336dd34..25e490db 100644
--- a/pd/src/d_osc.c
+++ b/pd/src/d_osc.c
@@ -10,50 +10,53 @@
#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */
- /* machine-dependent definitions. These ifdefs really
- should have been by CPU type and not by operating system! */
+
#ifdef IRIX
- /* big-endian. Most significant byte is at low address in memory */
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#define int32 long /* a data type that has 32 bits */
-#endif /* IRIX */
-
-#ifdef MSW
- /* little-endian; most significant byte is at highest address */
-#define HIOFFSET 1
-#define LOWOFFSET 0
-#define int32 long
+#include <sys/endian.h>
#endif
-#if defined(__FreeBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__)
#include <machine/endian.h>
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || defined(ANDROID)
#include <endian.h>
#endif
-#if defined(__unix__) || defined(__APPLE__)
+#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
+#endif
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define HIOFFSET 1
-#define LOWOFFSET 0
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define HIOFFSET 1
+# define LOWOFFSET 0
#else
-#define HIOFFSET 0 /* word offset to find MSB */
-#define LOWOFFSET 1 /* word offset to find LSB */
-#endif /* __BYTE_ORDER */
-#include <sys/types.h>
-#define int32 int32_t
-#endif /* __unix__ or __APPLE__*/
+# define HIOFFSET 0 /* word offset to find MSB */
+# define LOWOFFSET 1 /* word offset to find LSB */
+#endif
+
+#ifdef _MSC_VER
+ typedef __int32 int32_t; /* use MSVC's internal type */
+#elif defined(IRIX)
+ typedef long int32_t; /* a data type that has 32 bits */
+#else
+# include <stdint.h> /* this is where int32_t is defined in C99 */
+#endif
union tabfudge
{
double tf_d;
- int32 tf_i[2];
+ int32_t tf_i[2];
};
/* -------------------------- phasor~ ------------------------------ */
diff --git a/pd/src/d_soundfile.c b/pd/src/d_soundfile.c
index 8768fa55..8c350305 100644
--- a/pd/src/d_soundfile.c
+++ b/pd/src/d_soundfile.c
@@ -831,7 +831,7 @@ static void soundfile_finishwrite(void *obj, char *filename, int fd,
if (itemswritten < nframes)
{
if (nframes < 0x7fffffff)
- pd_error(obj, "soundfiler_write: %d out of %d bytes written",
+ pd_error(obj, "soundfiler_write: %ld out of %ld bytes written",
itemswritten, nframes);
/* try to fix size fields in header */
if (filetype == FORMAT_WAVE)
@@ -1261,7 +1261,7 @@ static void soundfiler_read(t_soundfiler *x, t_symbol *s,
framesinfile = (eofis - poswas) / (channels * bytespersamp);
if (framesinfile > maxsize)
{
- pd_error(x, "soundfiler_read: truncated to %d elements", maxsize);
+ pd_error(x, "soundfiler_read: truncated to %ld elements", maxsize);
framesinfile = maxsize;
}
if (framesinfile > bytelimit / (channels * bytespersamp))
@@ -1271,7 +1271,7 @@ static void soundfiler_read(t_soundfiler *x, t_symbol *s,
{
int vecsize;
- garray_resize(garrays[i], finalsize);
+ garray_resize_long(garrays[i], finalsize);
/* for sanity's sake let's clear the save-in-patch flag here */
garray_setsaveit(garrays[i], 0);
garray_getfloatwords(garrays[i], &vecsize,
diff --git a/pd/src/d_ugen.c b/pd/src/d_ugen.c
index fe49b7de..3fa7db54 100644
--- a/pd/src/d_ugen.c
+++ b/pd/src/d_ugen.c
@@ -219,7 +219,7 @@ static void block_float(t_block *x, t_floatarg f)
static void block_bang(t_block *x)
{
- if (x->x_switched && !x->x_switchon)
+ if (x->x_switched && !x->x_switchon && dsp_chain)
{
t_int *ip;
x->x_return = 1;
diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c
index f9314995..88f8d256 100644
--- a/pd/src/g_all_guis.c
+++ b/pd/src/g_all_guis.c
@@ -425,8 +425,8 @@ void iemgui_label_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av
if(glist_isvisible(iemgui->x_glist))
sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
glist_getcanvas(iemgui->x_glist), x,
- iemgui->x_obj.te_xpix+iemgui->x_ldx,
- iemgui->x_obj.te_ypix+iemgui->x_ldy);
+ text_xpix((t_object *)x,iemgui->x_glist)+iemgui->x_ldx,
+ text_ypix((t_object *)x,iemgui->x_glist)+iemgui->x_ldy);
}
void iemgui_label_font(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
@@ -456,7 +456,7 @@ void iemgui_size(void *x, t_iemgui *iemgui)
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(iemgui->x_glist), (t_text*)x);
+ canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}
@@ -467,7 +467,7 @@ void iemgui_delta(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(iemgui->x_glist), (t_text*)x);
+ canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}
@@ -478,7 +478,7 @@ void iemgui_pos(void *x, t_iemgui *iemgui, t_symbol *s, int ac, t_atom *av)
if(glist_isvisible(iemgui->x_glist))
{
(*iemgui->x_draw)(x, iemgui->x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(iemgui->x_glist), (t_text*)x);
+ canvas_fixlinesfor(iemgui->x_glist, (t_text*)x);
}
}
@@ -503,7 +503,7 @@ void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy)
x->x_gui.x_obj.te_xpix += dx;
x->x_gui.x_obj.te_ypix += dy;
(*x->x_gui.x_draw)((void *)z, glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(glist), (t_text *)z);
+ canvas_fixlinesfor(glist, (t_text *)z);
}
void iemgui_select(t_gobj *z, t_glist *glist, int selected)
@@ -630,6 +630,7 @@ int iemgui_dialog(t_iemgui *iemgui, t_symbol **srl, int argc, t_atom *argv)
fs = 4;
iemgui->x_fontsize = fs;
iemgui_verify_snd_ne_rcv(iemgui);
+ canvas_dirty(iemgui->x_glist, 1);
return(oldsndrcvable);
}
diff --git a/pd/src/g_array.c b/pd/src/g_array.c
index a73c5ba5..2c8f86d9 100644
--- a/pd/src/g_array.c
+++ b/pd/src/g_array.c
@@ -385,6 +385,7 @@ void glist_arraydialog(t_glist *parent, t_symbol *name, t_floatarg size,
gl = glist_addglist(parent, &s_, 0, 1,
(size > 1 ? size-1 : size), -1, 0, 0, 0, 0);
a = graph_array(gl, sharptodollar(name), &s_float, size, flags);
+ canvas_dirty(parent, 1);
}
/* this is called from the properties dialog window for an existing array */
@@ -403,7 +404,7 @@ void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
}
else
{
- int size;
+ long size;
int styleonset, styletype;
t_symbol *stylearraytype;
t_symbol *argname = sharptodollar(name);
@@ -445,7 +446,7 @@ void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
if (size < 1)
size = 1;
if (size != a->a_n)
- garray_resize(x, size);
+ garray_resize_long(x, size);
else if (style != stylewas)
garray_fittograph(x, size, style);
template_setfloat(scalartemplate, gensym("style"),
@@ -453,6 +454,7 @@ void garray_arraydialog(t_garray *x, t_symbol *name, t_floatarg fsize,
garray_setsaveit(x, (saveit != 0));
garray_redraw(x);
+ canvas_dirty(x->x_glist, 1);
}
}
@@ -1136,12 +1138,12 @@ int garray_getfloatwords(t_garray *x, int *size, t_word **vec)
t_array *a = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!a)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return (0);
}
else if (elemsize != sizeof(t_word))
{
- error("%s: has more than one field", x->x_realname);
+ error("%s: has more than one field", x->x_realname->s_name);
return (0);
}
*size = garray_npoints(x);
@@ -1178,7 +1180,7 @@ static void garray_const(t_garray *x, t_floatarg g)
int yonset, i, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
else for (i = 0; i < array->a_n; i++)
*((t_float *)((char *)array->a_vec
+ elemsize * i) + yonset) = g;
@@ -1186,7 +1188,7 @@ static void garray_const(t_garray *x, t_floatarg g)
}
/* sum of Fourier components; called from routines below */
-static void garray_dofo(t_garray *x, int npoints, t_float dcval,
+static void garray_dofo(t_garray *x, long npoints, t_float dcval,
int nsin, t_float *vsin, int sineflag)
{
double phase, phaseincr, fj;
@@ -1194,7 +1196,7 @@ static void garray_dofo(t_garray *x, int npoints, t_float dcval,
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
if (npoints == 0)
@@ -1202,7 +1204,7 @@ static void garray_dofo(t_garray *x, int npoints, t_float dcval,
if (npoints != (1 << ilog2(npoints)))
post("%s: rounnding to %d points", array->a_templatesym->s_name,
(npoints = (1<<ilog2(npoints))));
- garray_resize(x, npoints + 3);
+ garray_resize_long(x, npoints + 3);
phaseincr = 2. * 3.14159 / npoints;
for (i = 0, phase = -phaseincr; i < array->a_n; i++, phase += phaseincr)
{
@@ -1221,8 +1223,9 @@ static void garray_dofo(t_garray *x, int npoints, t_float dcval,
static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
- t_float *svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
- int npoints, i;
+ t_float *svec;
+ long npoints;
+ int i;
if (argc < 2)
{
error("sinesum: %s: need number of points and partial strengths",
@@ -1244,8 +1247,9 @@ static void garray_sinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
{
- t_float *svec = (t_float *)t_getbytes(sizeof(t_float) * argc);
- int npoints, i;
+ t_float *svec;
+ long npoints;
+ int i;
if (argc < 2)
{
error("sinesum: %s: need number of points and partial strengths",
@@ -1267,13 +1271,13 @@ static void garray_cosinesum(t_garray *x, t_symbol *s, int argc, t_atom *argv)
static void garray_normalize(t_garray *x, t_float f)
{
- int type, npoints, i;
+ int type, i;
double maxv, renormer;
int yonset, elemsize;
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
@@ -1308,7 +1312,7 @@ static void garray_list(t_garray *x, t_symbol *s, int argc, t_atom *argv)
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
if (argc < 2) return;
@@ -1389,7 +1393,7 @@ static void garray_read(t_garray *x, t_symbol *filename)
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
nelem = array->a_n;
@@ -1402,8 +1406,8 @@ static void garray_read(t_garray *x, t_symbol *filename)
}
for (i = 0; i < nelem; i++)
{
- float f;
- if (!fscanf(fd, "%f", &f))
+ double f;
+ if (!fscanf(fd, "%lf", &f))
{
post("%s: read %d elements into table of size %d",
filename->s_name, i, nelem);
@@ -1426,7 +1430,7 @@ static void garray_write(t_garray *x, t_symbol *filename)
t_array *array = garray_getarray_floatonly(x, &yonset, &elemsize);
if (!array)
{
- error("%s: needs floating-point 'y' field", x->x_realname);
+ error("%s: needs floating-point 'y' field", x->x_realname->s_name);
return;
}
canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
@@ -1458,11 +1462,12 @@ int garray_ambigendian(void)
return (c==0);
}
-void garray_resize(t_garray *x, t_floatarg f)
+void garray_resize_long(t_garray *x, long n)
{
t_array *array = garray_getarray(x);
t_glist *gl = x->x_glist;
- int n = (f < 1 ? 1 : f);
+ if (n < 1)
+ n = 1;
garray_fittograph(x, n, template_getfloat(
template_findbyname(x->x_scalar->sc_template),
gensym("style"), x->x_scalar->sc_vec, 1));
@@ -1471,6 +1476,12 @@ void garray_resize(t_garray *x, t_floatarg f)
canvas_update_dsp();
}
+ /* float version to use as Pd method */
+void garray_resize(t_garray *x, t_floatarg f)
+{
+ garray_resize_long(x, f);
+}
+
static void garray_print(t_garray *x)
{
t_array *array = garray_getarray(x);
diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c
index 8606b0ac..551b7aeb 100644
--- a/pd/src/g_bang.c
+++ b/pd/src/g_bang.c
@@ -55,19 +55,19 @@ void bng_draw_new(t_bng *x, t_glist *glist)
xpos + x->x_gui.x_w-1, ypos + x->x_gui.x_h-1,
x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xpos,
ypos + x->x_gui.x_h-1, xpos + IOWIDTH,
ypos + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xpos, ypos,
xpos + IOWIDTH, ypos+1, x, 0);
}
@@ -329,7 +329,7 @@ static void bng_dialog(t_bng *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void bng_click(t_bng *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index fd2df161..e5116c0c 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -46,7 +46,7 @@ t_canvas *canvas_list; /* list of all root canvases */
static void canvas_start_dsp(void);
static void canvas_stop_dsp(void);
static void canvas_drawlines(t_canvas *x);
-static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2);
+static void canvas_dosetbounds(t_canvas *x, int x1, int y1, int x2, int y2);
void canvas_reflecttitle(t_canvas *x);
static void canvas_addtolist(t_canvas *x);
static void canvas_takeofflist(t_canvas *x);
@@ -59,46 +59,11 @@ static t_symbol *canvas_newdirectory = &s_;
static int canvas_newargc;
static t_atom *canvas_newargv;
-static void glist_doupdatewindowlist(t_glist *gl, char *sbuf)
-{
- t_gobj *g;
- if (glist_amreloadingabstractions) /* not if we're in a reload */
- return;
- if (!gl->gl_owner)
- {
- /* this is a canvas; if we have a window, put on "windows" list */
- t_canvas *canvas = (t_canvas *)gl;
- if (canvas->gl_havewindow)
- {
- if (strlen(sbuf) + strlen(gl->gl_name->s_name) + 100 <= 1024)
- {
- char tbuf[1024];
- sprintf(tbuf, "{{%s} .x%lx} ", gl->gl_name->s_name,
- (t_int)canvas);
- strcat(sbuf, tbuf);
- }
- }
- }
- for (g = gl->gl_list; g; g = g->g_next)
- {
- if (pd_class(&g->g_pd) == canvas_class)
- glist_doupdatewindowlist((t_glist *)g, sbuf);
- }
- return;
-}
-
/* maintain the list of visible toplevels for the GUI's "windows" menu */
void canvas_updatewindowlist( void)
{
- t_canvas *x;
- char sbuf[1024];
- strcpy(sbuf, "set menu_windowlist {");
- /* find all root canvases */
- for (x = canvas_list; x; x = x->gl_next)
- glist_doupdatewindowlist(x, sbuf);
- /* next line updates the window menu state before -postcommand tries it */
- strcat(sbuf, "}\npdtk_fixwindowmenu\n");
- sys_gui(sbuf);
+ if (! glist_amreloadingabstractions) /* not if we're in a reload */
+ sys_gui("::pd_menus::update_window_menu\n");
}
/* add a glist the list of "root" canvases (toplevels without parents.) */
@@ -159,7 +124,7 @@ t_canvasenvironment *canvas_getenv(t_canvas *x)
if (!x) bug("canvas_getenv");
while (!x->gl_env)
if (!(x = x->gl_owner))
- bug("t_canvasenvironment", x);
+ bug("t_canvasenvironment");
return (x->gl_env);
}
@@ -234,7 +199,7 @@ void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir)
x->gl_name = s;
if (strcmp(x->gl_name->s_name, "Pd"))
pd_bind(&x->gl_pd, canvas_makebindsym(x->gl_name));
- if (glist_isvisible(x))
+ if (x->gl_havewindow)
canvas_reflecttitle(x);
if (dir && dir != &s_)
{
@@ -399,7 +364,7 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv)
x->gl_y1 = 0;
x->gl_x2 = 1;
x->gl_y2 = 1;
- canvas_setbounds(x, xloc, yloc, xloc + width, yloc + height);
+ canvas_dosetbounds(x, xloc, yloc, xloc + width, yloc + height);
x->gl_owner = owner;
x->gl_name = (*s->s_name ? s :
(canvas_newfilename ? canvas_newfilename : gensym("Pd")));
@@ -539,7 +504,14 @@ int glist_isgraph(t_glist *x)
/* This is sent from the GUI to inform a toplevel that its window has been
moved or resized. */
-static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2)
+static void canvas_setbounds(t_canvas *x, t_float left, t_float top,
+ t_float right, t_float bottom)
+{
+ canvas_dosetbounds(x, (int)left, (int)top, (int)right, (int)bottom);
+}
+
+/* this is the internal version using ints */
+static void canvas_dosetbounds(t_canvas *x, int x1, int y1, int x2, int y2)
{
int heightwas = y2 - y1;
int heightchange = y2 - y1 - (x->gl_screeny2 - x->gl_screeny1);
@@ -597,9 +569,8 @@ void canvas_reflecttitle(t_canvas *x)
strcat(namebuf, ")");
}
else namebuf[0] = 0;
- sys_vgui("wm title .x%lx {%s%c%s - %s}\n",
- x, x->gl_name->s_name, (x->gl_dirty? '*' : ' '), namebuf,
- canvas_getdir(x)->s_name);
+ sys_vgui("pdtk_canvas_reflecttitle .x%lx {%s} {%s} {%s} %d\n",
+ x, canvas_getdir(x)->s_name, x->gl_name->s_name, namebuf, x->gl_dirty);
}
/* mark a glist dirty or clean */
@@ -611,7 +582,7 @@ void canvas_dirty(t_canvas *x, t_floatarg n)
if ((unsigned)n != x2->gl_dirty)
{
x2->gl_dirty = n;
- if (glist_isvisible(x2))
+ if (x2->gl_havewindow)
canvas_reflecttitle(x2);
}
}
@@ -762,7 +733,7 @@ static void canvas_drawlines(t_canvas *x)
{
linetraverser_start(&t, x);
while (oc = linetraverser_next(&t))
- sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags l%lx\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n",
glist_getcanvas(x),
t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2,
(outlet_getsymbol(t.tr_outlet) == &s_signal ? 2:1),
@@ -904,22 +875,8 @@ void canvas_loadbang(t_canvas *x)
canvas_loadbangsubpatches(x);
}
- /* When you ask a canvas its size the result is more than what
- you gave it to open it; how much bigger apparently depends on the OS. */
-
-#ifdef __unix__
-#define HORIZBORDER 2
-#define VERTBORDER 2
-#else
-#ifdef MACOSX
-#define HORIZBORDER 6
-#define VERTBORDER 6
-#else
-#define HORIZBORDER 4
-#define VERTBORDER 4
-#endif
-#endif
-
+/* no longer used by 'pd-gui', but kept here for backwards compatibility. The
+ * new method calls canvas_setbounds() directly. */
static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom,
t_symbol *topgeom)
{
@@ -931,8 +888,8 @@ static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom,
/* for some reason this is initially called with cw=ch=1 so
we just suppress that here. */
if (cw > 5 && ch > 5)
- canvas_setbounds(x, txpix, typix,
- txpix + cw - HORIZBORDER, typix + ch - VERTBORDER);
+ canvas_dosetbounds(x, txpix, typix,
+ txpix + cw, typix + ch);
}
void canvas_popabstraction(t_canvas *x)
@@ -1543,6 +1500,8 @@ void g_canvas_setup(void)
A_DEFFLOAT, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_loadbang,
gensym("loadbang"), A_NULL);
+ class_addmethod(canvas_class, (t_method)canvas_setbounds,
+ gensym("setbounds"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_relocate,
gensym("relocate"), A_SYMBOL, A_SYMBOL, A_NULL);
class_addmethod(canvas_class, (t_method)canvas_vis,
diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h
index e36fb48b..5dd55b45 100644
--- a/pd/src/g_canvas.h
+++ b/pd/src/g_canvas.h
@@ -108,6 +108,9 @@ typedef struct _editor
unsigned int e_lastmoved: 1; /* one if mouse has moved since click */
unsigned int e_textdirty: 1; /* one if e_textedfor has changed */
unsigned int e_selectedline: 1; /* one if a line is selected */
+ t_clock *e_clock; /* clock to filter GUI move messages */
+ int e_xnew; /* xpos for next move event */
+ int e_ynew; /* ypos, similarly */
} t_editor;
#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
@@ -478,7 +481,7 @@ EXTERN void canvas_resortinlets(t_canvas *x);
EXTERN void canvas_resortoutlets(t_canvas *x);
EXTERN void canvas_free(t_canvas *x);
EXTERN void canvas_updatewindowlist( void);
-EXTERN void canvas_editmode(t_canvas *x, t_floatarg yesplease);
+EXTERN void canvas_editmode(t_canvas *x, t_floatarg state);
EXTERN int canvas_isabstraction(t_canvas *x);
EXTERN int canvas_istable(t_canvas *x);
EXTERN int canvas_showtext(t_canvas *x);
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 0890d465..89dd874c 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -8,7 +8,11 @@
#include "m_imp.h"
#include "s_stuff.h"
#include "g_canvas.h"
+#include "s_utf8.h" /*-- moo --*/
#include <string.h>
+#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
+#define snprintf sprintf_s
+#endif
void glist_readfrombinbuf(t_glist *x, t_binbuf *b, char *filename,
int selectem);
@@ -66,7 +70,8 @@ int gobj_shouldvis(t_gobj *x, struct _glist *glist)
{
t_object *ob;
if (!glist->gl_havewindow && glist->gl_isgraph && glist->gl_goprect &&
- glist->gl_owner && (pd_class(&glist->gl_pd) != garray_class))
+ glist->gl_owner && (pd_class(&x->g_pd) != scalar_class)
+ && (pd_class(&x->g_pd) != garray_class))
{
/* if we're graphing-on-parent and the object falls outside the
graph rectangle, don't draw it. */
@@ -236,7 +241,7 @@ void glist_deselect(t_glist *x, t_gobj *y)
rtext_gettext(z, &buf, &bufsize);
text_setto((t_text *)y, x, buf, bufsize);
- canvas_fixlinesfor(glist_getcanvas(x), (t_text *)y);
+ canvas_fixlinesfor(x, (t_text *)y);
x->gl_editor->e_textedfor = 0;
}
if (fixdsp)
@@ -713,7 +718,7 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
{
t_gobj *g;
int i, nobj = glist_getindex(gl, 0); /* number of objects */
- int hadwindow = gl->gl_havewindow;
+ int hadwindow = (gl->gl_editor != 0);
for (g = gl->gl_list, i = 0; g && i < nobj; i++)
{
if (g != except && pd_class(&g->g_pd) == canvas_class &&
@@ -726,8 +731,10 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
replacement will be at the end of the list, so we don't
do g = g->g_next in this case. */
int j = glist_getindex(gl, g);
- if (!gl->gl_havewindow)
- canvas_vis(glist_getcanvas(gl), 1);
+ if (!gl->gl_editor)
+ canvas_vis(gl, 1);
+ if (!gl->gl_editor)
+ bug("editor");
glist_noselect(gl);
glist_select(gl, g);
canvas_setundo(gl, canvas_undo_cut,
@@ -744,7 +751,7 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
g = g->g_next;
}
}
- if (!hadwindow && gl->gl_havewindow)
+ if (!hadwindow && gl->gl_editor)
canvas_vis(glist_getcanvas(gl), 0);
}
@@ -768,17 +775,13 @@ void canvas_reload(t_symbol *name, t_symbol *dir, t_gobj *except)
/* ------------------------ event handling ------------------------ */
static char *cursorlist[] = {
-#ifdef MSW
- "right_ptr", /* CURSOR_RUNMODE_NOTHING */
-#else
- "left_ptr", /* CURSOR_RUNMODE_NOTHING */
-#endif
- "arrow", /* CURSOR_RUNMODE_CLICKME */
- "sb_v_double_arrow", /* CURSOR_RUNMODE_THICKEN */
- "plus", /* CURSOR_RUNMODE_ADDPOINT */
- "hand2", /* CURSOR_EDITMODE_NOTHING */
- "circle", /* CURSOR_EDITMODE_CONNECT */
- "X_cursor" /* CURSOR_EDITMODE_DISCONNECT */
+ "$cursor_runmode_nothing",
+ "$cursor_runmode_clickme",
+ "$cursor_runmode_thicken",
+ "$cursor_runmode_addpoint",
+ "$cursor_editmode_nothing",
+ "$cursor_editmode_connect",
+ "$cursor_editmode_disconnect"
};
void canvas_setcursor(t_canvas *x, unsigned int cursornum)
@@ -866,6 +869,7 @@ static t_editor *editor_new(t_glist *owner)
x->e_glist = owner;
sprintf(buf, ".x%lx", (t_int)owner);
x->e_guiconnect = guiconnect_new(&owner->gl_pd, gensym(buf));
+ x->e_clock = 0;
return (x);
}
@@ -875,6 +879,8 @@ static void editor_free(t_editor *x, t_glist *y)
guiconnect_notarget(x->e_guiconnect, 1000);
binbuf_free(x->e_connectbuf);
binbuf_free(x->e_deleted);
+ if (x->e_clock)
+ clock_free(x->e_clock);
freebytes((void *)x, sizeof(*x));
}
@@ -897,6 +903,7 @@ void canvas_destroy_editor(t_glist *x)
{
t_gobj *y;
t_object *ob;
+ glist_noselect(x);
if (x->gl_editor)
{
for (y = x->gl_list; y; y = y->g_next)
@@ -917,33 +924,38 @@ void canvas_vis(t_canvas *x, t_floatarg f)
{
char buf[30];
int flag = (f != 0);
- if (x != glist_getcanvas(x))
- bug("canvas_vis");
if (flag)
{
- /* post("havewindow %d, isgraph %d, isvisible %d editor %d",
- x->gl_havewindow, x->gl_isgraph, glist_isvisible(x),
- (x->gl_editor != 0)); */
- /* test if we're already visible and toplevel */
- if (x->gl_editor)
+ /* If a subpatch/abstraction has GOP/gl_isgraph set, then it will have
+ * a gl_editor already, if its not, it will not have a gl_editor.
+ * canvas_create_editor(x) checks if a gl_editor is already created,
+ * so its ok to run it on a canvas that already has a gl_editor. */
+ if (x->gl_editor && x->gl_havewindow)
{ /* just put us in front */
-#ifdef MSW
- canvas_vis(x, 0);
- canvas_vis(x, 1);
-#else
- sys_vgui("raise .x%lx\n", x);
- sys_vgui("focus .x%lx.c\n", x);
- sys_vgui("wm deiconify .x%lx\n", x);
-#endif
+ sys_vgui("pdtk_canvas_raise .x%lx\n", x);
}
else
{
+ char cbuf[MAXPDSTRING];
+ int cbuflen;
+ t_canvas *c = x;
canvas_create_editor(x);
sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x,
(int)(x->gl_screenx2 - x->gl_screenx1),
(int)(x->gl_screeny2 - x->gl_screeny1),
(int)(x->gl_screenx1), (int)(x->gl_screeny1),
x->gl_edit);
+ snprintf(cbuf, MAXPDSTRING - 2, "pdtk_canvas_setparents .x%lx",
+ (unsigned long)c);
+ while (c->gl_owner) {
+ c = c->gl_owner;
+ cbuflen = strlen(cbuf);
+ snprintf(cbuf + cbuflen,
+ MAXPDSTRING - cbuflen - 2,/* leave 2 for "\n\0" */
+ " .x%lx", (unsigned long)c);
+ }
+ strcat(cbuf, "\n");
+ sys_gui(cbuf);
canvas_reflecttitle(x);
x->gl_havewindow = 1;
canvas_updatewindowlist();
@@ -964,7 +976,6 @@ void canvas_vis(t_canvas *x, t_floatarg f)
canvas_destroy_editor(x);
return;
}
- sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
glist_noselect(x);
if (glist_isvisible(x))
canvas_map(x, 0);
@@ -972,7 +983,6 @@ void canvas_vis(t_canvas *x, t_floatarg f)
sys_vgui("destroy .x%lx\n", x);
for (i = 1, x2 = x; x2; x2 = x2->gl_next, i++)
;
- sys_vgui(".mbar.find delete %d\n", i);
/* if we're a graph on our parent, and if the parent exists
and is visible, show ourselves on parent. */
if (glist_isgraph(x) && x->gl_owner)
@@ -1019,16 +1029,7 @@ void canvas_setgraph(t_glist *x, int flag, int nogoprect)
gobj_vis(&x->gl_gobj, x->gl_owner, 0);
x->gl_isgraph = 1;
x->gl_hidetext = !(!(flag&2));
- if (!nogoprect && !x->gl_goprect)
- {
- t_gobj *g;
- for (g = x->gl_list; g; g = g->g_next)
- if (pd_checkobject(&g->g_pd))
- {
- x->gl_goprect = 1;
- break;
- }
- }
+ x->gl_goprect = !nogoprect;
if (glist_isvisible(x) && x->gl_goprect)
glist_redraw(x);
if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner))
@@ -1139,6 +1140,7 @@ static void canvas_donecanvasdialog(t_glist *x,
}
/* LATER avoid doing 2 redraws here (possibly one inside setgraph) */
canvas_setgraph(x, graphme, 0);
+ canvas_dirty(x, 1);
if (x->gl_havewindow)
canvas_redraw(x);
else if (glist_isvisible(x->gl_owner))
@@ -1513,10 +1515,11 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
((x22-x21-IOWIDTH) * closest2)/(ninlet2-1) : 0)
+ IOMIDDLE;
ly2 = y21;
- sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags l%lx\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n",
glist_getcanvas(x),
lx1, ly1, lx2, ly2,
(obj_issignaloutlet(ob1, closest1) ? 2 : 1), oc);
+ canvas_dirty(x, 1);
canvas_setundo(x, canvas_undo_connect,
canvas_undo_set_connect(x,
canvas_getindex(x, &ob1->ob_g), closest1,
@@ -1608,8 +1611,6 @@ void canvas_mouseup(t_canvas *x,
gobj_activate(x->gl_editor->e_selection->sel_what, x, 1);
}
}
- if (x->gl_editor->e_onmotion != MA_NONE)
- sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
x->gl_editor->e_onmotion = MA_NONE;
}
@@ -1634,6 +1635,7 @@ static void canvas_displaceselection(t_canvas *x, int dx, int dy)
}
if (resortin) canvas_resortinlets(x);
if (resortout) canvas_resortoutlets(x);
+ sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
if (x->gl_editor->e_selection)
canvas_dirty(x, 1);
}
@@ -1661,9 +1663,20 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
gotkeysym = av[1].a_w.w_symbol;
else if (av[1].a_type == A_FLOAT)
{
- char buf[3];
- sprintf(buf, "%c", (int)(av[1].a_w.w_float));
- gotkeysym = gensym(buf);
+ char buf[UTF8_MAXBYTES1];
+ switch((int)(av[1].a_w.w_float))
+ {
+ case 8: gotkeysym = gensym("BackSpace"); break;
+ case 9: gotkeysym = gensym("Tab"); break;
+ case 10: gotkeysym = gensym("Return"); break;
+ case 27: gotkeysym = gensym("Escape"); break;
+ case 32: gotkeysym = gensym("Space"); break;
+ case 127:gotkeysym = gensym("Delete"); break;
+ default:
+ /*-- moo: assume keynum is a Unicode codepoint; encode as UTF-8 --*/
+ u8_wc_toutf8_nul(buf, (UCS4)(av[1].a_w.w_float));
+ gotkeysym = gensym(buf);
+ }
}
else gotkeysym = gensym("?");
fflag = (av[0].a_type == A_FLOAT ? av[0].a_w.w_float : 0);
@@ -1770,6 +1783,15 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
CURSOR_RUNMODE_NOTHING :CURSOR_EDITMODE_NOTHING);
}
+static void delay_move(t_canvas *x)
+{
+ canvas_displaceselection(x,
+ x->gl_editor->e_xnew - x->gl_editor->e_xwas,
+ x->gl_editor->e_ynew - x->gl_editor->e_ywas);
+ x->gl_editor->e_xwas = x->gl_editor->e_xnew;
+ x->gl_editor->e_ywas = x->gl_editor->e_ynew;
+}
+
void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
t_floatarg fmod)
{
@@ -1783,10 +1805,12 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
glist_setlastxy(x, xpos, ypos);
if (x->gl_editor->e_onmotion == MA_MOVE)
{
- canvas_displaceselection(x,
- xpos - x->gl_editor->e_xwas, ypos - x->gl_editor->e_ywas);
- x->gl_editor->e_xwas = xpos;
- x->gl_editor->e_ywas = ypos;
+ if (!x->gl_editor->e_clock)
+ x->gl_editor->e_clock = clock_new(x, (t_method)delay_move);
+ clock_unset(x->gl_editor->e_clock);
+ clock_delay(x->gl_editor->e_clock, 5);
+ x->gl_editor->e_xnew = xpos;
+ x->gl_editor->e_ynew = ypos;
}
else if (x->gl_editor->e_onmotion == MA_REGION)
canvas_doregion(x, xpos, ypos, 0);
@@ -1858,13 +1882,12 @@ void glob_verifyquit(void *dummy, t_floatarg f)
if (g2 = glist_finddirty(g))
{
canvas_vis(g2, 1);
- sys_vgui(
-"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx menuclose 3;\n} no\n",
- canvas_getrootfor(g2), canvas_getrootfor(g2)->gl_name->s_name, g2);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;\n}\n",
+ canvas_getrootfor(g2), g2);
return;
}
if (f == 0 && sys_perf)
- sys_vgui("pdtk_check . {really quit?} {pd quit;\n} yes\n");
+ sys_vgui("pdtk_check .pdwindow {really quit?} {pd quit} yes\n");
else glob_quit(0);
}
@@ -1887,16 +1910,14 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce)
if (g)
{
vmess(&g->gl_pd, gensym("menu-open"), "");
- sys_vgui(
-"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx menuclose 2;\n} no\n",
- canvas_getrootfor(g), canvas_getrootfor(g)->gl_name->s_name, g);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n",
+ canvas_getrootfor(g), g);
return;
}
else if (sys_perf)
{
- sys_vgui(
-"pdtk_check .x%lx {Close '%s'?} {.x%lx menuclose 1;\n} yes\n",
- canvas_getrootfor(x), canvas_getrootfor(x)->gl_name->s_name, x);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 1;\n}\n",
+ canvas_getrootfor(g), g);
}
else pd_free(&x->gl_pd);
}
@@ -1911,9 +1932,8 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce)
if (g)
{
vmess(&g->gl_pd, gensym("menu-open"), "");
- sys_vgui(
-"pdtk_check .x%lx {Discard changes to '%s'?} {.x%lx menuclose 2;\n} no\n",
- canvas_getrootfor(x), canvas_getrootfor(x)->gl_name->s_name, g);
+ sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n",
+ canvas_getrootfor(x), g);
return;
}
else pd_free(&x->gl_pd);
@@ -1997,7 +2017,7 @@ static void canvas_find(t_canvas *x, t_symbol *s, t_floatarg wholeword)
if (!canvas_dofind(x, &myindex1))
{
binbuf_print(canvas_findbuf);
- post("... couldn't find");
+ sys_vgui("pdtk_couldnotfind .x%lx\n", x);
}
}
@@ -2009,7 +2029,7 @@ static void canvas_find_again(t_canvas *x)
if (!canvas_dofind(canvas_whichfind, &myindex1))
{
binbuf_print(canvas_findbuf);
- post("... couldn't find");
+ sys_vgui("pdtk_couldnotfind .x%lx\n", x);
}
}
@@ -2051,7 +2071,7 @@ void canvas_finderror(void *error_object)
if (glist_dofinderror(x, error_object))
return;
}
- post("... sorry, I couldn't find the source of that error.");
+ error("... sorry, I couldn't find the source of that error.");
}
void canvas_stowconnections(t_canvas *x)
@@ -2155,22 +2175,8 @@ static void canvas_copy(t_canvas *x)
char *buf;
int bufsize;
rtext_getseltext(x->gl_editor->e_textedfor, &buf, &bufsize);
-
-#if defined(MSW) || defined(__APPLE__)
- /* for Mac or Windows, copy the text to the clipboard here */
- sys_vgui("clipboard clear\n", bufsize, buf);
+ sys_gui("clipboard clear\n");
sys_vgui("clipboard append {%.*s}\n", bufsize, buf);
-#else
- /* in X windows the selection already went to the
- clipboard when it was made; here we "copy" it to our own buffer
- as well, because, annoyingly, the clipboard will usually be
- destroyed by the time the user asks to "paste". */
- if (canvas_textcopybuf)
- t_freebytes(canvas_textcopybuf, canvas_textcopybufsize);
- canvas_textcopybuf = (char *)getbytes(bufsize);
- memcpy(canvas_textcopybuf, buf, bufsize);
- canvas_textcopybufsize = bufsize;
-#endif
}
}
@@ -2182,6 +2188,7 @@ static void canvas_clearline(t_canvas *x)
x->gl_editor->e_selectline_outno,
x->gl_editor->e_selectline_index2,
x->gl_editor->e_selectline_inno);
+ canvas_dirty(x, 1);
canvas_setundo(x, canvas_undo_disconnect,
canvas_undo_set_disconnect(x,
x->gl_editor->e_selectline_index1,
@@ -2321,19 +2328,8 @@ static void canvas_paste(t_canvas *x)
return;
if (x->gl_editor->e_textedfor)
{
- /* simulate keystrokes as if the copy buffer were typed in. */
-#if defined(MSW) || defined(__APPLE__)
- /* for Mac or Windows, ask the GUI to send the clipboard down */
+ /* simulate keystrokes as if the copy buffer were typed in. */
sys_gui("pdtk_pastetext\n");
-#else
- /* in X windows we kept the text in our own copy buffer */
- int i;
- for (i = 0; i < canvas_textcopybufsize; i++)
- {
- pd_vmess(&x->gl_gobj.g_pd, gensym("key"), "iii",
- 1, canvas_textcopybuf[i]&0xff, 0);
- }
-#endif
}
else
{
@@ -2446,7 +2442,7 @@ void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
if (!(oc = obj_connect(objsrc, outno, objsink, inno))) goto bad;
if (glist_isvisible(x))
{
- sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags l%lx\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -width %d -tags [list l%lx cord]\n",
glist_getcanvas(x), 0, 0, 0, 0,
(obj_issignaloutlet(objsrc, outno) ? 2 : 1),oc);
canvas_fixlinesfor(x, objsrc);
@@ -2586,12 +2582,9 @@ void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av)
canvas_key(canvas_editing, s, ac, av);
}
-void canvas_editmode(t_canvas *x, t_floatarg fyesplease)
+void canvas_editmode(t_canvas *x, t_floatarg state)
{
- int yesplease = fyesplease;
- if (yesplease && x->gl_edit)
- return;
- x->gl_edit = !x->gl_edit;
+ x->gl_edit = (unsigned int) state;
if (x->gl_edit && glist_isvisible(x) && glist_istoplevel(x))
canvas_setcursor(x, CURSOR_EDITMODE_NOTHING);
else
@@ -2600,7 +2593,7 @@ void canvas_editmode(t_canvas *x, t_floatarg fyesplease)
if (glist_isvisible(x) && glist_istoplevel(x))
canvas_setcursor(x, CURSOR_RUNMODE_NOTHING);
}
- sys_vgui("pdtk_canvas_editval .x%lx %d\n",
+ sys_vgui("pdtk_canvas_editmode .x%lx %d\n",
glist_getcanvas(x), x->gl_edit);
}
diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c
index b4112ddd..57db6556 100644
--- a/pd/src/g_graph.c
+++ b/pd/src/g_graph.c
@@ -176,8 +176,7 @@ void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
t_canvas *glist_getcanvas(t_glist *x)
{
- while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph &&
- gobj_shouldvis(&x->gl_gobj, x->gl_owner))
+ while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph)
x = x->gl_owner;
return((t_canvas *)x);
}
@@ -658,7 +657,6 @@ void glist_redraw(t_glist *x)
canvas_drawredrect(x, 0);
if (x->gl_goprect)
{
- post("draw it");
canvas_drawredrect(x, 1);
}
}
@@ -708,7 +706,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
if (vis)
{
sys_vgui(".x%lx.c create polygon\
- %d %d %d %d %d %d %d %d %d %d -tags %s -fill #c0c0c0\n",
+ %d %d %d %d %d %d %d %d %d %d -tags [list %s graph] -fill #c0c0c0\n",
glist_getcanvas(x->gl_owner),
x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
}
@@ -729,7 +727,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
t_garray *ga;
/* draw a rectangle around the graph */
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d -tags %s\n",
+ %d %d %d %d %d %d %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
@@ -741,7 +739,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
{
i -= sys_fontheight(glist_getfont(x));
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor nw\
- -font {{%s} -%d %s} -tags %s\n",
+ -font {{%s} -%d %s} -tags [list %s label graph]\n",
(long)glist_getcanvas(x), x1, i, arrayname->s_name, sys_font,
sys_hostfontsize(glist_getfont(x)), sys_fontweight, tag);
}
@@ -759,11 +757,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
f += x->gl_xtick.k_inc)
{
int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)upix,
(int)glist_xtopixels(x, f), (int)upix - tickpix, tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)lpix,
(int)glist_xtopixels(x, f), (int)lpix + tickpix, tag);
@@ -773,11 +771,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
i++, f -= x->gl_xtick.k_inc)
{
int tickpix = (i % x->gl_xtick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)upix,
(int)glist_xtopixels(x, f), (int)upix - tickpix, tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
(int)glist_xtopixels(x, f), (int)lpix,
(int)glist_xtopixels(x, f), (int)lpix + tickpix, tag);
@@ -796,11 +794,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
i++, f += x->gl_ytick.k_inc)
{
int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x1, (int)glist_ytopixels(x, f),
x1 + tickpix, (int)glist_ytopixels(x, f), tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x2, (int)glist_ytopixels(x, f),
x2 - tickpix, (int)glist_ytopixels(x, f), tag);
@@ -810,11 +808,11 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
i++, f -= x->gl_ytick.k_inc)
{
int tickpix = (i % x->gl_ytick.k_lperb ? 2 : 4);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x1, (int)glist_ytopixels(x, f),
x1 + tickpix, (int)glist_ytopixels(x, f), tag);
- sys_vgui(".x%lx.c create line %d %d %d %d -tags %s\n",
+ sys_vgui(".x%lx.c create line %d %d %d %d -tags [list %s graph]\n",
glist_getcanvas(x->gl_owner),
x2, (int)glist_ytopixels(x, f),
x2 - tickpix, (int)glist_ytopixels(x, f), tag);
@@ -823,7 +821,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
/* draw x labels */
for (i = 0; i < x->gl_nxlabels; i++)
sys_vgui(".x%lx.c create text\
- %d %d -text {%s} -font {{%s} -%d %s} -tags %s\n",
+ %d %d -text {%s} -font {{%s} -%d %s} -tags [list %s label graph]\n",
glist_getcanvas(x),
(int)glist_xtopixels(x, atof(x->gl_xlabel[i]->s_name)),
(int)glist_ytopixels(x, x->gl_xlabely),
@@ -833,7 +831,7 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
/* draw y labels */
for (i = 0; i < x->gl_nylabels; i++)
sys_vgui(".x%lx.c create text\
- %d %d -text {%s} -font {{%s} -%d %s} -tags %s\n",
+ %d %d -text {%s} -font {{%s} -%d %s} -tags [list %s label graph]\n",
glist_getcanvas(x),
(int)glist_xtopixels(x, x->gl_ylabelx),
(int)glist_ytopixels(x, atof(x->gl_ylabel[i]->s_name)),
@@ -936,7 +934,7 @@ static void graph_displace(t_gobj *z, t_glist *glist, int dx, int dy)
x->gl_obj.te_xpix += dx;
x->gl_obj.te_ypix += dy;
glist_redraw(x);
- canvas_fixlinesfor(glist_getcanvas(glist), &x->gl_obj);
+ canvas_fixlinesfor(glist, &x->gl_obj);
}
}
diff --git a/pd/src/g_hdial.c b/pd/src/g_hdial.c
index 19d21e84..2027dab9 100644
--- a/pd/src/g_hdial.c
+++ b/pd/src/g_hdial.c
@@ -73,16 +73,16 @@ void hradio_draw_new(t_hradio *x, t_glist *glist)
x->x_drawn = x->x_on;
}
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx11b+x->x_gui.x_ldx, yy11+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx11b, yy12-1, xx11b + IOWIDTH, yy12, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx11b, yy11, xx11b + IOWIDTH, yy11+1, x, 0);
}
@@ -311,7 +311,7 @@ static void hradio_dialog(t_hradio *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}
diff --git a/pd/src/g_hslider.c b/pd/src/g_hslider.c
index 143a8988..bf843f1a 100644
--- a/pd/src/g_hslider.c
+++ b/pd/src/g_hslider.c
@@ -33,12 +33,11 @@ static t_class *hslider_class;
static void hslider_draw_update(t_gobj *client, t_glist *glist)
{
t_hslider *x = (t_hslider *)client;
- t_canvas *canvas=glist_getcanvas(glist);
- int ypos=text_ypix(&x->x_gui.x_obj, glist);
-
if (glist_isvisible(glist))
{
int r = text_xpix(&x->x_gui.x_obj, glist) + (x->x_val + 50)/100;
+ int ypos=text_ypix(&x->x_gui.x_obj, glist);
+ t_canvas *canvas=glist_getcanvas(glist);
sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n",
canvas, x, r, ypos+1,
r, ypos + x->x_gui.x_h);
@@ -76,18 +75,18 @@ static void hslider_draw_new(t_hslider *x, t_glist *glist)
canvas, r, ypos+1, r,
ypos + x->x_gui.x_h, x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx,
ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xpos-3, ypos + x->x_gui.x_h-1,
xpos+4, ypos + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xpos-3, ypos,
xpos+4, ypos+1, x, 0);
}
@@ -370,7 +369,7 @@ static void hslider_dialog(t_hslider *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void hslider_motion(t_hslider *x, t_floatarg dx, t_floatarg dy)
diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c
index f673f8ed..741e6871 100644
--- a/pd/src/g_mycanvas.c
+++ b/pd/src/g_mycanvas.c
@@ -44,7 +44,7 @@ void my_canvas_draw_new(t_my_canvas *x, t_glist *glist)
xpos + x->x_gui.x_w, ypos + x->x_gui.x_h,
x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c
index 75f6bbbf..60a6e51b 100644
--- a/pd/src/g_numbox.c
+++ b/pd/src/g_numbox.c
@@ -195,7 +195,7 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
xpos, ypos + x->x_gui.x_h,
x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
@@ -207,13 +207,13 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
x->x_buf, x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_fcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h-1,
xpos+IOWIDTH, ypos + x->x_gui.x_h,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos,
xpos+IOWIDTH, ypos+1,
@@ -512,7 +512,7 @@ static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc,
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy)
diff --git a/pd/src/g_readwrite.c b/pd/src/g_readwrite.c
index 97b56c02..9f809759 100644
--- a/pd/src/g_readwrite.c
+++ b/pd/src/g_readwrite.c
@@ -704,7 +704,11 @@ static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir)
{
/* if not an abstraction, reset title bar and directory */
if (!x->gl_owner)
+{
canvas_rename(x, filename, dir);
+ /* update window list in case Save As changed the window name */
+ canvas_updatewindowlist();
+}
post("saved to: %s/%s", dir->s_name, filename->s_name);
canvas_dirty(x, 0);
canvas_reload(filename, dir, &x->gl_gobj);
@@ -715,7 +719,7 @@ static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir)
static void canvas_menusaveas(t_canvas *x)
{
t_canvas *x2 = canvas_getrootfor(x);
- sys_vgui("pdtk_canvas_saveas .x%lx \"%s\" \"%s\"\n", x2,
+ sys_vgui("pdtk_canvas_saveas .x%lx {%s} {%s}\n", x2,
x2->gl_name->s_name, canvas_getdir(x2)->s_name);
}
@@ -724,7 +728,8 @@ static void canvas_menusave(t_canvas *x)
t_canvas *x2 = canvas_getrootfor(x);
char *name = x2->gl_name->s_name;
if (*name && strncmp(name, "Untitled", 8)
- && (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat")))
+ && (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat")
+ || strcmp(name + strlen(name)-4, ".mxt")))
canvas_savetofile(x2, x2->gl_name, canvas_getdir(x2));
else canvas_menusaveas(x2);
}
diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c
index 976901e9..e63a172d 100644
--- a/pd/src/g_rtext.c
+++ b/pd/src/g_rtext.c
@@ -13,6 +13,7 @@
#include "m_pd.h"
#include "s_stuff.h"
#include "g_canvas.h"
+#include "s_utf8.h"
#define LMARGIN 2
@@ -32,10 +33,10 @@
struct _rtext
{
- char *x_buf;
- int x_bufsize;
- int x_selstart;
- int x_selend;
+ char *x_buf; /*-- raw byte string, assumed UTF-8 encoded (moo) --*/
+ int x_bufsize; /*-- byte length --*/
+ int x_selstart; /*-- byte offset --*/
+ int x_selend; /*-- byte offset --*/
int x_active;
int x_dragfrom;
int x_height;
@@ -104,8 +105,30 @@ void rtext_getseltext(t_rtext *x, char **buf, int *bufsize)
*bufsize = x->x_selend - x->x_selstart;
}
+/* convert t_text te_type symbol for use as a Tk tag */
+static t_symbol *rtext_gettype(t_rtext *x)
+{
+ switch (x->x_text->te_type)
+ {
+ case T_TEXT: return gensym("text");
+ case T_OBJECT: return gensym("obj");
+ case T_MESSAGE: return gensym("msg");
+ case T_ATOM: return gensym("atom");
+ }
+ return (&s_);
+}
+
/* LATER deal with tcl-significant characters */
+/* firstone(), lastone()
+ * + returns byte offset of (first|last) occurrence of 'c' in 's[0..n-1]', or
+ * -1 if none was found
+ * + 's' is a raw byte string
+ * + 'c' is a byte value
+ * + 'n' is the length (in bytes) of the prefix of 's' to be searched.
+ * + we could make these functions work on logical characters in utf8 strings,
+ * but we don't really need to...
+ */
static int firstone(char *s, int c, int n)
{
char *s2 = s + n;
@@ -142,6 +165,16 @@ static int lastone(char *s, int c, int n)
of the entire text in pixels.
*/
+ /*-- moo:
+ * + some variables from the original version have been renamed
+ * + variables with a "_b" suffix are raw byte strings, lengths, or offsets
+ * + variables with a "_c" suffix are logical character lengths or offsets
+ * (assuming valid UTF-8 encoded byte string in x->x_buf)
+ * + a fair amount of O(n) computations required to convert between raw byte
+ * offsets (needed by the C side) and logical character offsets (needed by
+ * the GUI)
+ */
+
/* LATER get this and sys_vgui to work together properly,
breaking up messages as needed. As of now, there's
a limit of 1950 characters, imposed by sys_vgui(). */
@@ -158,14 +191,16 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
{
t_float dispx, dispy;
char smallbuf[200], *tempbuf;
- int outchars = 0, nlines = 0, ncolumns = 0,
+ int outchars_b = 0, nlines = 0, ncolumns = 0,
pixwide, pixhigh, font, fontwidth, fontheight, findx, findy;
int reportedindex = 0;
t_canvas *canvas = glist_getcanvas(x->x_glist);
- int widthspec = x->x_text->te_width;
- int widthlimit = (widthspec ? widthspec : BOXWIDTH);
- int inindex = 0;
- int selstart = 0, selend = 0;
+ int widthspec_c = x->x_text->te_width;
+ int widthlimit_c = (widthspec_c ? widthspec_c : BOXWIDTH);
+ int inindex_b = 0;
+ int inindex_c = 0;
+ int selstart_b = 0, selend_b = 0;
+ int x_bufsize_c = u8_charnum(x->x_buf, x->x_bufsize);
/* if we're a GOP (the new, "goprect" style) borrow the font size
from the inside to preserve the spacing */
if (pd_class(&x->x_text->te_pd) == canvas_class &&
@@ -180,97 +215,109 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
if (x->x_bufsize >= 100)
tempbuf = (char *)t_getbytes(2 * x->x_bufsize + 1);
else tempbuf = smallbuf;
- while (x->x_bufsize - inindex > 0)
+ while (x_bufsize_c - inindex_c > 0)
{
- int inchars = x->x_bufsize - inindex;
- int maxindex = (inchars > widthlimit ? widthlimit : inchars);
+ int inchars_b = x->x_bufsize - inindex_b;
+ int inchars_c = x_bufsize_c - inindex_c;
+ int maxindex_c = (inchars_c > widthlimit_c ? widthlimit_c : inchars_c);
+ int maxindex_b = u8_offset(x->x_buf + inindex_b, maxindex_c);
int eatchar = 1;
- int foundit = firstone(x->x_buf + inindex, '\n', maxindex);
- if (foundit < 0)
+ int foundit_b = firstone(x->x_buf + inindex_b, '\n', maxindex_b);
+ int foundit_c;
+ if (foundit_b < 0)
{
- if (inchars > widthlimit)
+ if (inchars_c > widthlimit_c)
{
- foundit = lastone(x->x_buf + inindex, ' ', maxindex);
- if (foundit < 0)
+ foundit_b = lastone(x->x_buf + inindex_b, ' ', maxindex_b);
+ if (foundit_b < 0)
{
- foundit = maxindex;
+ foundit_b = maxindex_b;
+ foundit_c = maxindex_c;
eatchar = 0;
}
+ else
+ foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b);
}
else
{
- foundit = inchars;
+ foundit_b = inchars_b;
+ foundit_c = inchars_c;
eatchar = 0;
}
}
+ else
+ foundit_c = u8_charnum(x->x_buf + inindex_b, foundit_b);
+
if (nlines == findy)
{
int actualx = (findx < 0 ? 0 :
- (findx > foundit ? foundit : findx));
- *indexp = inindex + actualx;
+ (findx > foundit_c ? foundit_c : findx));
+ *indexp = inindex_b + u8_offset(x->x_buf + inindex_b, actualx);
reportedindex = 1;
}
- strncpy(tempbuf+outchars, x->x_buf + inindex, foundit);
- if (x->x_selstart >= inindex &&
- x->x_selstart <= inindex + foundit + eatchar)
- selstart = x->x_selstart + outchars - inindex;
- if (x->x_selend >= inindex &&
- x->x_selend <= inindex + foundit + eatchar)
- selend = x->x_selend + outchars - inindex;
- outchars += foundit;
- inindex += (foundit + eatchar);
- if (inindex < x->x_bufsize)
- tempbuf[outchars++] = '\n';
- if (foundit > ncolumns)
- ncolumns = foundit;
+ strncpy(tempbuf+outchars_b, x->x_buf + inindex_b, foundit_b);
+ if (x->x_selstart >= inindex_b &&
+ x->x_selstart <= inindex_b + foundit_b + eatchar)
+ selstart_b = x->x_selstart + outchars_b - inindex_b;
+ if (x->x_selend >= inindex_b &&
+ x->x_selend <= inindex_b + foundit_b + eatchar)
+ selend_b = x->x_selend + outchars_b - inindex_b;
+ outchars_b += foundit_b;
+ inindex_b += (foundit_b + eatchar);
+ inindex_c += (foundit_c + eatchar);
+ if (inindex_b < x->x_bufsize)
+ tempbuf[outchars_b++] = '\n';
+ if (foundit_c > ncolumns)
+ ncolumns = foundit_c;
nlines++;
}
if (!reportedindex)
- *indexp = outchars;
+ *indexp = outchars_b;
dispx = text_xpix(x->x_text, x->x_glist);
dispy = text_ypix(x->x_text, x->x_glist);
if (nlines < 1) nlines = 1;
- if (!widthspec)
+ if (!widthspec_c)
{
while (ncolumns < 3)
{
- tempbuf[outchars++] = ' ';
+ tempbuf[outchars_b++] = ' ';
ncolumns++;
}
}
- else ncolumns = widthspec;
+ else ncolumns = widthspec_c;
pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
if (action == SEND_FIRST)
- sys_vgui("pdtk_text_new .x%lx.c %s %f %f {%.*s} %d %s\n",
- canvas, x->x_tag,
+ sys_vgui("pdtk_text_new .x%lx.c {%s %s text} %f %f {%.*s} %d %s\n",
+ canvas, x->x_tag, rtext_gettype(x)->s_name,
dispx + LMARGIN, dispy + TMARGIN,
- outchars, tempbuf, sys_hostfontsize(font),
+ outchars_b, tempbuf, sys_hostfontsize(font),
(glist_isselected(x->x_glist,
&x->x_glist->gl_gobj)? "blue" : "black"));
else if (action == SEND_UPDATE)
{
sys_vgui("pdtk_text_set .x%lx.c %s {%.*s}\n",
- canvas, x->x_tag, outchars, tempbuf);
+ canvas, x->x_tag, outchars_b, tempbuf);
if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight)
text_drawborder(x->x_text, x->x_glist, x->x_tag,
pixwide, pixhigh, 0);
if (x->x_active)
{
- if (selend > selstart)
+ if (selend_b > selstart_b)
{
sys_vgui(".x%lx.c select from %s %d\n", canvas,
- x->x_tag, selstart);
+ x->x_tag, u8_charnum(x->x_buf, selstart_b));
sys_vgui(".x%lx.c select to %s %d\n", canvas,
- x->x_tag, selend + (sys_oldtclversion ? 0 : -1));
+ x->x_tag, u8_charnum(x->x_buf, selend_b)
+ + (sys_oldtclversion ? 0 : -1));
sys_vgui(".x%lx.c focus \"\"\n", canvas);
}
else
{
sys_vgui(".x%lx.c select clear\n", canvas);
sys_vgui(".x%lx.c icursor %s %d\n", canvas, x->x_tag,
- selstart);
+ u8_charnum(x->x_buf, selstart_b));
sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag);
}
}
@@ -398,7 +445,7 @@ void rtext_activate(t_rtext *x, int state)
t_canvas *canvas = glist_getcanvas(glist);
if (state)
{
- sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag);
+ sys_vgui("pdtk_text_editing .x%lx %s 1\n", canvas, x->x_tag);
glist->gl_editor->e_textedfor = x;
glist->gl_editor->e_textdirty = 0;
x->x_dragfrom = x->x_selstart = 0;
@@ -407,8 +454,7 @@ void rtext_activate(t_rtext *x, int state)
}
else
{
- sys_vgui("selection clear .x%lx.c\n", canvas);
- sys_vgui(".x%lx.c focus \"\"\n", canvas);
+ sys_vgui("pdtk_text_editing .x%lx {} 0\n", canvas);
if (glist->gl_editor->e_textedfor == x)
glist->gl_editor->e_textedfor = 0;
x->x_active = 0;
@@ -433,12 +479,12 @@ void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
....
} */
if (x->x_selstart && (x->x_selstart == x->x_selend))
- x->x_selstart--;
+ u8_dec(x->x_buf, &x->x_selstart);
}
else if (n == 127) /* delete */
{
if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend))
- x->x_selend++;
+ u8_inc(x->x_buf, &x->x_selend);
}
ndel = x->x_selend - x->x_selstart;
@@ -451,7 +497,13 @@ void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
/* at Guenter's suggestion, use 'n>31' to test wither a character might
be printable in whatever 8-bit character set we find ourselves. */
- if (n == '\n' || (n > 31 && n != 127))
+/*-- moo:
+ ... but test with "<" rather than "!=" in order to accomodate unicode
+ codepoints for n (which we get since Tk is sending the "%A" substitution
+ for bind <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);
@@ -461,20 +513,39 @@ be printable in whatever 8-bit character set we find ourselves. */
x->x_bufsize = newsize;
x->x_selstart = x->x_selstart + 1;
}
+ /*--moo: check for unicode codepoints beyond 7-bit ASCII --*/
+ else if (n > 127)
+ {
+ int ch_nbytes = u8_wc_nbytes(n);
+ newsize = x->x_bufsize + ch_nbytes;
+ x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize);
+ for (i = x->x_bufsize; i > x->x_selstart; i--)
+ x->x_buf[i] = x->x_buf[i-1];
+ x->x_bufsize = newsize;
+ /*-- moo: assume canvas_key() has encoded keysym as UTF-8 */
+ strncpy(x->x_buf+x->x_selstart, keysym->s_name, ch_nbytes);
+ x->x_selstart = x->x_selstart + ch_nbytes;
+ }
x->x_selend = x->x_selstart;
x->x_glist->gl_editor->e_textdirty = 1;
}
else if (!strcmp(keysym->s_name, "Right"))
{
if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize)
- x->x_selend = x->x_selstart = x->x_selstart + 1;
+ {
+ u8_inc(x->x_buf, &x->x_selstart);
+ x->x_selend = x->x_selstart;
+ }
else
x->x_selstart = x->x_selend;
}
else if (!strcmp(keysym->s_name, "Left"))
{
if (x->x_selend == x->x_selstart && x->x_selstart > 0)
- x->x_selend = x->x_selstart = x->x_selstart - 1;
+ {
+ u8_dec(x->x_buf, &x->x_selstart);
+ x->x_selend = x->x_selstart;
+ }
else
x->x_selend = x->x_selstart;
}
@@ -482,18 +553,18 @@ be printable in whatever 8-bit character set we find ourselves. */
else if (!strcmp(keysym->s_name, "Up"))
{
if (x->x_selstart)
- x->x_selstart--;
+ u8_dec(x->x_buf, &x->x_selstart);
while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
- x->x_selstart--;
+ u8_dec(x->x_buf, &x->x_selstart);
x->x_selend = x->x_selstart;
}
else if (!strcmp(keysym->s_name, "Down"))
{
while (x->x_selend < x->x_bufsize &&
x->x_buf[x->x_selend] != '\n')
- x->x_selend++;
+ u8_inc(x->x_buf, &x->x_selend);
if (x->x_selend < x->x_bufsize)
- x->x_selend++;
+ u8_inc(x->x_buf, &x->x_selend);
x->x_selstart = x->x_selend;
}
rtext_senditup(x, SEND_UPDATE, &w, &h, &indx);
diff --git a/pd/src/g_template.c b/pd/src/g_template.c
index f216b104..a2b583d0 100644
--- a/pd/src/g_template.c
+++ b/pd/src/g_template.c
@@ -762,14 +762,20 @@ static void fielddesc_setfloat_var(t_fielddesc *fd, t_symbol *s)
else
{
int cpy = s1 - s->s_name, got;
+ double v1, v2, screen1, screen2, quantum;
if (cpy > MAXPDSTRING-5)
cpy = MAXPDSTRING-5;
strncpy(strbuf, s->s_name, cpy);
strbuf[cpy] = 0;
fd->fd_un.fd_varsym = gensym(strbuf);
- got = sscanf(s1, "(%f:%f)(%f:%f)(%f)",
- &fd->fd_v1, &fd->fd_v2, &fd->fd_screen1, &fd->fd_screen2,
- &fd->fd_quantum);
+ got = sscanf(s1, "(%lf:%lf)(%lf:%lf)(%lf)",
+ &v1, &v2, &screen1, &screen2,
+ &quantum);
+ fd->fd_v1=v1;
+ fd->fd_v2=v2;
+ fd->fd_screen1=screen1;
+ fd->fd_screen2=screen2;
+ fd->fd_quantum=quantum;
if (got < 2)
goto fail;
if (got == 3 || (got < 4 && strchr(s2, '(')))
@@ -1715,8 +1721,8 @@ static void plot_vis(t_gobj *z, t_glist *glist,
minyval = yval;
if (i == nelem-1 || inextx != ixpix)
{
- sys_vgui(
-".x%lx.c create rectangle %d %d %d %d -fill black -width 0 -tags plot%lx\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d \
+-fill black -width 0 -tags [list plot%lx array]\n",
glist_getcanvas(glist),
ixpix, (int)glist_ytopixels(glist,
basey + fielddesc_cvttocoord(yfielddesc, minyval)),
@@ -1815,7 +1821,7 @@ static void plot_vis(t_gobj *z, t_glist *glist,
outline, outline);
if (style == PLOTSTYLE_BEZ) sys_vgui("-smooth 1\\\n");
- sys_vgui("-tags plot%lx\n", data);
+ sys_vgui("-tags [list plot%lx array]\n", data);
}
else if (linewidth > 0)
{
@@ -1858,7 +1864,7 @@ static void plot_vis(t_gobj *z, t_glist *glist,
sys_vgui("-fill %s\\\n", outline);
if (style == PLOTSTYLE_BEZ) sys_vgui("-smooth 1\\\n");
- sys_vgui("-tags plot%lx\n", data);
+ sys_vgui("-tags [list plot%lx array]\n", data);
}
}
/* We're done with the outline; now draw all the points.
@@ -2138,7 +2144,7 @@ static void drawnumber_vis(t_gobj *z, t_glist *glist,
glist_getcanvas(glist), xloc, yloc, colorstring, buf);
sys_vgui(" -font {{%s} -%d %s}", sys_font,
sys_hostfontsize(glist_getfont(glist)), sys_fontweight);
- sys_vgui(" -tags drawnumber%lx\n", data);
+ sys_vgui(" -tags [list drawnumber%lx label]\n", data);
}
else sys_vgui(".x%lx.c delete drawnumber%lx\n", glist_getcanvas(glist), data);
}
@@ -2225,7 +2231,7 @@ static void drawnumber_key(void *z, t_floatarg fkey)
else
{
/* key entry for a numeric field. This is just a stopgap. */
- float newf;
+ double newf;
if (drawnumber_motion_firstkey)
sbuf[0] = 0;
else sprintf(sbuf, "%g", template_getfloat(drawnumber_motion_template,
@@ -2241,10 +2247,10 @@ static void drawnumber_key(void *z, t_floatarg fkey)
sbuf[strlen(sbuf)+1] = 0;
sbuf[strlen(sbuf)] = key;
}
- if (sscanf(sbuf, "%g", &newf) < 1)
+ if (sscanf(sbuf, "%lg", &newf) < 1)
newf = 0;
template_setfloat(drawnumber_motion_template,
- f->fd_un.fd_varsym, drawnumber_motion_wp, newf, 1);
+ f->fd_un.fd_varsym, drawnumber_motion_wp, (t_float)newf, 1);
if (drawnumber_motion_scalar)
template_notifyforscalar(drawnumber_motion_template,
drawnumber_motion_glist, drawnumber_motion_scalar,
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index cff52274..a6e50491 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -16,6 +16,8 @@
#include <string.h>
#include <math.h>
+#include "s_utf8.h"
+
t_class *text_class;
static t_class *message_class;
static t_class *gatom_class;
@@ -97,13 +99,13 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
if (!newest)
{
binbuf_print(b);
- post("... couldn't create");
+ error("... couldn't create");
x = 0;
}
else if (!(x = pd_checkobject(newest)))
{
binbuf_print(b);
- post("... didn't return a patchable object");
+ error("... didn't return a patchable object");
}
}
else x = 0;
@@ -675,7 +677,6 @@ static void gatom_key(void *z, t_floatarg f)
gatom_retext(x, 1);
return;
}
- else if (c == ' ') return;
else if (c == '\b')
{
if (len > 0)
@@ -700,8 +701,22 @@ static void gatom_key(void *z, t_floatarg f)
(c >= '0' && c <= '9' || c == '.' || c == '-'
|| c == 'e' || c == 'E'))
{
- x->a_buf[len] = c;
- x->a_buf[len+1] = 0;
+ /* the wchar could expand to up to 4 bytes, which
+ * which might overrun our a_buf;
+ * therefore we first expand into a temporary buffer,
+ * and only if the resulting utf8 string fits into a_buf
+ * we apply it
+ */
+ char utf8[UTF8_MAXBYTES];
+ int utf8len = u8_wc_toutf8(utf8, c);
+ if((len+utf8len) < (ATOMBUFSIZE-1))
+ {
+ int j=0;
+ for(j=0; j<utf8len; j++)
+ x->a_buf[len+j] = utf8[j];
+
+ x->a_buf[len+utf8len] = 0;
+ }
goto redraw;
}
}
@@ -793,6 +808,7 @@ static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv)
x->a_symto = symto;
x->a_expanded_to = canvas_realizedollar(x->a_glist, x->a_symto);
gobj_vis(&x->a_text.te_g, x->a_glist, 1);
+ canvas_dirty(x->a_glist, 1);
/* glist_retext(x->a_glist, &x->a_text); */
}
@@ -847,7 +863,7 @@ static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
{
int x1, y1;
gatom_getwherelabel(x, glist, &x1, &y1);
- sys_vgui("pdtk_text_new .x%lx.c %lx.l %f %f {%s} %d %s\n",
+ sys_vgui("pdtk_text_new .x%lx.c {%lx.l label text} %f %f {%s} %d %s\n",
glist_getcanvas(glist), x,
(double)x1, (double)y1,
canvas_realizedollar(x->a_glist, x->a_label)->s_name,
@@ -1026,7 +1042,7 @@ static void text_displace(t_gobj *z, t_glist *glist,
rtext_displace(y, dx, dy);
text_drawborder(x, glist, rtext_gettag(y),
rtext_width(y), rtext_height(y), 0);
- canvas_fixlinesfor(glist_getcanvas(glist), x);
+ canvas_fixlinesfor(glist, x);
}
}
@@ -1210,7 +1226,8 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
{
int onset = x1 + (width - IOWIDTH) * i / nplus;
if (firsttime)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %so%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d \
+-tags [list %so%d outlet]\n",
glist_getcanvas(glist),
onset, y2 - 1,
onset + IOWIDTH, y2,
@@ -1227,7 +1244,8 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
{
int onset = x1 + (width - IOWIDTH) * i / nplus;
if (firsttime)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %si%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d \
+-tags [list %si%d inlet]\n",
glist_getcanvas(glist),
onset, y1,
onset + IOWIDTH, y1 + EXTRAPIX,
@@ -1253,7 +1271,7 @@ void text_drawborder(t_text *x, t_glist *glist,
char *pattern = ((pd_class(&x->te_pd) == text_class) ? "-" : "\"\"");
if (firsttime)
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d -dash %s -tags %sR\n",
+ %d %d %d %d %d %d %d %d %d %d -dash %s -tags [list %sR obj]\n",
glist_getcanvas(glist),
x1, y1, x2, y1, x2, y2, x1, y2, x1, y1, pattern, tag);
else
@@ -1270,7 +1288,7 @@ void text_drawborder(t_text *x, t_glist *glist,
{
if (firsttime)
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
+ %d %d %d %d %d %d %d %d %d %d %d %d %d %d -tags [list %sR msg]\n",
glist_getcanvas(glist),
x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2,
x1, y2, x1, y1,
@@ -1286,7 +1304,7 @@ void text_drawborder(t_text *x, t_glist *glist,
{
if (firsttime)
sys_vgui(".x%lx.c create line\
- %d %d %d %d %d %d %d %d %d %d %d %d -tags %sR\n",
+ %d %d %d %d %d %d %d %d %d %d %d %d -tags [list %sR atom]\n",
glist_getcanvas(glist),
x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1,
tag);
diff --git a/pd/src/g_toggle.c b/pd/src/g_toggle.c
index 344e1522..7e112a47 100644
--- a/pd/src/g_toggle.c
+++ b/pd/src/g_toggle.c
@@ -61,17 +61,17 @@ void toggle_draw_new(t_toggle *x, t_glist *glist)
canvas, xx+w+1, yy + x->x_gui.x_h-w-1, xx + x->x_gui.x_w-w, yy+w, w,
(x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx+x->x_gui.x_ldx,
yy+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx, yy + x->x_gui.x_h-1, xx + IOWIDTH, yy + x->x_gui.x_h, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx, yy, xx + IOWIDTH, yy+1, x, 0);
}
@@ -271,7 +271,7 @@ static void toggle_dialog(t_toggle *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void toggle_click(t_toggle *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
diff --git a/pd/src/g_vdial.c b/pd/src/g_vdial.c
index f5364750..71347794 100644
--- a/pd/src/g_vdial.c
+++ b/pd/src/g_vdial.c
@@ -75,16 +75,16 @@ void vradio_draw_new(t_vradio *x, t_glist *glist)
x->x_drawn = x->x_on;
}
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xx11+x->x_gui.x_ldx, yy11b+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas, xx11, yy11-1, xx11 + IOWIDTH, yy11, x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas, xx11, yy11b, xx11 + IOWIDTH, yy11b+1, x, 0);
}
@@ -312,7 +312,7 @@ static void vradio_dialog(t_vradio *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}
diff --git a/pd/src/g_vslider.c b/pd/src/g_vslider.c
index 6b547f84..ddeb5421 100644
--- a/pd/src/g_vslider.c
+++ b/pd/src/g_vslider.c
@@ -59,19 +59,19 @@ static void vslider_draw_new(t_vslider *x, t_glist *glist)
canvas, xpos+1, r,
xpos + x->x_gui.x_w, r, x->x_gui.x_fcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos, ypos + x->x_gui.x_h+2,
xpos+7, ypos + x->x_gui.x_h+3,
x, 0);
if(!x->x_gui.x_fsf.x_rcv_able)
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos, ypos-2,
xpos+7, ypos-1,
@@ -336,7 +336,7 @@ static void vslider_dialog(t_vslider *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void vslider_motion(t_vslider *x, t_floatarg dx, t_floatarg dy)
diff --git a/pd/src/g_vumeter.c b/pd/src/g_vumeter.c
index 75047e8d..fb275b78 100644
--- a/pd/src/g_vumeter.c
+++ b/pd/src/g_vumeter.c
@@ -138,19 +138,19 @@ static void vu_draw_new(t_vu *x, t_glist *glist)
canvas, mid, ypos+10,
mid, ypos+10, x->x_led_size, x->x_gui.x_bcol, x);
sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
- -font {{%s} -%d %s} -fill #%6.6x -tags %lxLABEL\n",
+ -font {{%s} -%d %s} -fill #%6.6x -tags [list %lxLABEL label text]\n",
canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
x->x_gui.x_font, x->x_gui.x_fontsize, sys_fontweight,
x->x_gui.x_lcol, x);
if(!x->x_gui.x_fsf.x_snd_able)
{
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]\n",
canvas,
xpos-1, ypos + x->x_gui.x_h+1,
xpos + IOWIDTH-1, ypos + x->x_gui.x_h+2,
x, 0);
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxOUT%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxOUT%d outlet]x\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos + x->x_gui.x_h+1,
xpos+x->x_gui.x_w+1, ypos + x->x_gui.x_h+2,
@@ -158,12 +158,12 @@ static void vu_draw_new(t_vu *x, t_glist *glist)
}
if(!x->x_gui.x_fsf.x_rcv_able)
{
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos-1, ypos-2,
xpos + IOWIDTH-1, ypos-1,
x, 0);
- sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxIN%d\n",
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags [list %lxIN%d inlet]\n",
canvas,
xpos+x->x_gui.x_w+1-IOWIDTH, ypos-2,
xpos+x->x_gui.x_w+1, ypos-1,
@@ -542,7 +542,7 @@ static void vu_dialog(t_vu *x, t_symbol *s, int argc, t_atom *argv)
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av)
@@ -554,7 +554,7 @@ static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av)
{
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
- canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
}
}
diff --git a/pd/src/m_atom.c b/pd/src/m_atom.c
index f8859c6f..16df0e35 100644
--- a/pd/src/m_atom.c
+++ b/pd/src/m_atom.c
@@ -79,7 +79,7 @@ void atom_string(t_atom *a, char *buf, unsigned int bufsize)
sprintf(tbuf, "%g", a->a_w.w_float);
if (strlen(tbuf) < bufsize-1) strcpy(buf, tbuf);
else if (a->a_w.w_float < 0) strcpy(buf, "-");
- else strcat(buf, "+");
+ else strcpy(buf, "+");
break;
case A_SYMBOL:
{
diff --git a/pd/src/m_binbuf.c b/pd/src/m_binbuf.c
index 360512d0..d109ae56 100644
--- a/pd/src/m_binbuf.c
+++ b/pd/src/m_binbuf.c
@@ -862,7 +862,8 @@ int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
if (*dir)
strcat(fbuf, dir), strcat(fbuf, "/");
strcat(fbuf, filename);
- if (!strcmp(filename + strlen(filename) - 4, ".pat"))
+ if (!strcmp(filename + strlen(filename) - 4, ".pat") ||
+ !strcmp(filename + strlen(filename) - 4, ".mxt"))
{
x = binbuf_convert(x, 0);
deleteit = 1;
@@ -943,14 +944,15 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
t_binbuf *newb = binbuf_new();
t_atom *vec = oldb->b_vec;
t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK],
- nobj = 0, i;
+ nobj = 0, i, gotfontsize = 0;
t_atom outmess[MAXSTACK], *nextmess;
+ t_float fontsize = 10;
if (!maxtopd)
binbuf_addv(newb, "ss;", gensym("max"), gensym("v2"));
for (nextindex = 0; nextindex < n; )
{
int endmess, natom;
- char *first, *second;
+ char *first, *second, *third;
for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI;
endmess++)
;
@@ -993,7 +995,7 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
{
if (stackdepth >= MAXSTACK)
{
- post("too many embedded patches");
+ error("stack depth exceeded: too many embedded patches");
return (newb);
}
stack[stackdepth] = nobj;
@@ -1137,11 +1139,49 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
}
else if (!strcmp(second, "user"))
{
- binbuf_addv(newb, "ssffs;",
- gensym("#X"), gensym("obj"),
- atom_getfloatarg(3, natom, nextmess),
- atom_getfloatarg(4, natom, nextmess),
- atom_getsymbolarg(2, natom, nextmess));
+ third = (nextmess+2)->a_w.w_symbol->s_name;
+ if (!strcmp(third, "hslider"))
+ {
+ t_float range = atom_getfloatarg(7, natom, nextmess);
+ t_float multiplier = atom_getfloatarg(8, natom, nextmess);
+ t_float offset = atom_getfloatarg(9, natom, nextmess);
+ binbuf_addv(newb, "ssffsffffffsssfffffffff;",
+ gensym("#X"), gensym("obj"),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(4, natom, nextmess),
+ gensym("hsl"),
+ atom_getfloatarg(6, natom, nextmess),
+ atom_getfloatarg(5, natom, nextmess),
+ offset,
+ range + offset,
+ 0., 0.,
+ gensym("empty"), gensym("empty"), gensym("empty"),
+ 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
+ }
+ else if (!strcmp(third, "uslider"))
+ {
+ t_float range = atom_getfloatarg(7, natom, nextmess);
+ t_float multiplier = atom_getfloatarg(8, natom, nextmess);
+ t_float offset = atom_getfloatarg(9, natom, nextmess);
+ binbuf_addv(newb, "ssffsffffffsssfffffffff;",
+ gensym("#X"), gensym("obj"),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(4, natom, nextmess),
+ gensym("vsl"),
+ atom_getfloatarg(5, natom, nextmess),
+ atom_getfloatarg(6, natom, nextmess),
+ offset,
+ range + offset,
+ 0., 0.,
+ gensym("empty"), gensym("empty"), gensym("empty"),
+ 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
+ }
+ else
+ binbuf_addv(newb, "ssffs;",
+ gensym("#X"), gensym("obj"),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(4, natom, nextmess),
+ atom_getsymbolarg(2, natom, nextmess));
nobj++;
}
else if (!strcmp(second, "connect")||
@@ -1162,20 +1202,26 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
{
if (!strcmp(second, "canvas"))
{
+ t_float x, y;
if (stackdepth >= MAXSTACK)
{
- post("too many embedded patches");
+ error("stack depth exceeded: too many embedded patches");
return (newb);
}
stack[stackdepth] = nobj;
stackdepth++;
nobj = 0;
+ if(!gotfontsize) { /* only the first canvas sets the font size */
+ fontsize = atom_getfloatarg(6, natom, nextmess);
+ gotfontsize = 1;
+ }
+ x = atom_getfloatarg(2, natom, nextmess);
+ y = atom_getfloatarg(3, natom, nextmess);
binbuf_addv(newb, "ssffff;",
gensym("#N"), gensym("vpatcher"),
- atom_getfloatarg(2, natom, nextmess),
- atom_getfloatarg(3, natom, nextmess),
- atom_getfloatarg(4, natom, nextmess),
- atom_getfloatarg(5, natom, nextmess));
+ x, y,
+ atom_getfloatarg(4, natom, nextmess) + x,
+ atom_getfloatarg(5, natom, nextmess) + y);
}
}
if (!strcmp(first, "#X"))
@@ -1184,12 +1230,17 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
&& (ISSYMBOL (&nextmess[4], "pd")))
{
binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
- binbuf_addv(newb, "ssffffss;",
- gensym("#P"), gensym("newobj"),
- atom_getfloatarg(2, natom, nextmess),
- atom_getfloatarg(3, natom, nextmess), 50., 1.,
- gensym("patcher"),
- atom_getsymbolarg(5, natom, nextmess));
+ SETSYMBOL(outmess, gensym("#P"));
+ SETSYMBOL(outmess + 1, gensym("newobj"));
+ outmess[2] = nextmess[2];
+ outmess[3] = nextmess[3];
+ SETFLOAT(outmess + 4, 50.*(natom-5));
+ SETFLOAT(outmess + 5, fontsize);
+ SETSYMBOL(outmess + 6, gensym("p"));
+ for (i = 5; i < natom; i++)
+ outmess[i+2] = nextmess[i];
+ SETSEMI(outmess + natom + 2);
+ binbuf_add(newb, natom + 3, outmess);
if (stackdepth) stackdepth--;
nobj = stack[stackdepth];
nobj++;
@@ -1203,25 +1254,25 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
gensym("inlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15.);
+ 10. + fontsize);
else if (classname == gensym("inlet~"))
binbuf_addv(newb, "ssffff;", gensym("#P"),
gensym("inlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15., 1.);
+ 10. + fontsize, 1.);
else if (classname == gensym("outlet"))
binbuf_addv(newb, "ssfff;", gensym("#P"),
gensym("outlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15.);
+ 10. + fontsize);
else if (classname == gensym("outlet~"))
binbuf_addv(newb, "ssffff;", gensym("#P"),
gensym("outlet"),
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(3, natom, nextmess),
- 15., 1.);
+ 10. + fontsize, 1.);
else if (classname == gensym("bng"))
binbuf_addv(newb, "ssffff;", gensym("#P"),
gensym("button"),
@@ -1246,16 +1297,65 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
(atom_getfloatarg(6, natom, nextmess) == 1? 1 :
atom_getfloatarg(6, natom, nextmess) - 1),
atom_getfloatarg(7, natom, nextmess));
+ else if (classname == gensym("hsl"))
+ {
+ t_float slmin = atom_getfloatarg(7, natom, nextmess);
+ t_float slmax = atom_getfloatarg(8, natom, nextmess);
+ binbuf_addv(newb, "sssffffffff;", gensym("#P"),
+ gensym("user"),
+ gensym("hslider"),
+ atom_getfloatarg(2, natom, nextmess),
+ atom_getfloatarg(3, natom, nextmess),
+ atom_getfloatarg(6, natom, nextmess),
+ atom_getfloatarg(5, natom, nextmess),
+ slmax - slmin + 1, /* range */
+ 1., /* multiplier */
+ slmin, /* offset */
+ 0.);
+ }
+ else if ( (classname == gensym("trigger")) ||
+ (classname == gensym("t")) )
+ {
+ t_symbol *arg;
+ SETSYMBOL(outmess, gensym("#P"));
+ SETSYMBOL(outmess + 1, gensym("newex"));
+ outmess[2] = nextmess[2];
+ outmess[3] = nextmess[3];
+ SETFLOAT(outmess + 4, 50.*(natom-4));
+ SETFLOAT(outmess + 5, fontsize);
+ outmess[6] = nextmess[4];
+ for (i = 5; i < natom; i++) {
+ arg = atom_getsymbolarg(i, natom, nextmess);
+ if (arg == gensym("a"))
+ SETSYMBOL(outmess + i + 2, gensym("l"));
+ else if (arg == gensym("anything"))
+ SETSYMBOL(outmess + i + 2, gensym("l"));
+ else if (arg == gensym("bang"))
+ SETSYMBOL(outmess + i + 2, gensym("b"));
+ else if (arg == gensym("float"))
+ SETSYMBOL(outmess + i + 2, gensym("f"));
+ else if (arg == gensym("list"))
+ SETSYMBOL(outmess + i + 2, gensym("l"));
+ else if (arg == gensym("symbol"))
+ SETSYMBOL(outmess + i + 2, gensym("s"));
+ else
+ outmess[i+2] = nextmess[i];
+ }
+ SETSEMI(outmess + natom + 2);
+ binbuf_add(newb, natom + 3, outmess);
+ }
else
{
SETSYMBOL(outmess, gensym("#P"));
SETSYMBOL(outmess + 1, gensym("newex"));
outmess[2] = nextmess[2];
outmess[3] = nextmess[3];
- SETFLOAT(outmess + 4, 50);
- SETFLOAT(outmess + 5, 1);
+ SETFLOAT(outmess + 4, 50.*(natom-4));
+ SETFLOAT(outmess + 5, fontsize);
for (i = 4; i < natom; i++)
outmess[i+2] = nextmess[i];
+ if (classname == gensym("osc~"))
+ SETSYMBOL(outmess + 6, gensym("cycle~"));
SETSEMI(outmess + natom + 2);
binbuf_add(newb, natom + 3, outmess);
}
@@ -1270,8 +1370,8 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
(strcmp(second, "msg") ? "comment" : "message")));
outmess[2] = nextmess[2];
outmess[3] = nextmess[3];
- SETFLOAT(outmess + 4, 50);
- SETFLOAT(outmess + 5, 1);
+ SETFLOAT(outmess + 4, 50.*(natom-4));
+ SETFLOAT(outmess + 5, fontsize);
for (i = 4; i < natom; i++)
outmess[i+2] = nextmess[i];
SETSEMI(outmess + natom + 2);
@@ -1280,10 +1380,13 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
}
else if (!strcmp(second, "floatatom"))
{
+ t_float width = atom_getfloatarg(4, natom, nextmess)*fontsize;
+ if(width<8) width = 150; /* if pd width=0, set it big */
binbuf_addv(newb, "ssfff;",
gensym("#P"), gensym("flonum"),
atom_getfloatarg(2, natom, nextmess),
- atom_getfloatarg(3, natom, nextmess), 35);
+ atom_getfloatarg(3, natom, nextmess),
+ width);
nobj++;
}
else if (!strcmp(second, "connect"))
@@ -1350,7 +1453,8 @@ void pd_doloadbang(void);
void binbuf_evalfile(t_symbol *name, t_symbol *dir)
{
t_binbuf *b = binbuf_new();
- int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat");
+ int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat") ||
+ !strcmp(name->s_name + strlen(name->s_name) - 4, ".mxt");
/* set filename so that new canvases can pick them up */
int dspstate = canvas_suspend_dsp();
glob_setfilename(0, name, dir);
diff --git a/pd/src/m_class.c b/pd/src/m_class.c
index 93d9c71b..0c67d34f 100644
--- a/pd/src/m_class.c
+++ b/pd/src/m_class.c
@@ -522,6 +522,7 @@ static t_symbol *addfileextent(t_symbol *s)
return (gensym(namebuf));
}
+#define MAXOBJDEPTH 1000
static int tryingalready;
void canvas_popabstraction(t_canvas *x);
@@ -537,14 +538,17 @@ void new_anything(void *dummy, t_symbol *s, int argc, t_atom *argv)
t_pd *current;
int fd;
char dirbuf[MAXPDSTRING], *nameptr;
- if (tryingalready) return;
+ if (tryingalready>MAXOBJDEPTH){
+ error("maximum object loading depth %d reached", MAXOBJDEPTH);
+ return;
+ }
newest = 0;
class_loadsym = s;
if (sys_load_lib(canvas_getcurrent(), s->s_name))
{
- tryingalready = 1;
+ tryingalready++;
typedmess(dummy, s, argc, argv);
- tryingalready = 0;
+ tryingalready--;
return;
}
class_loadsym = 0;
diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c
index ca3b5d1a..4431883c 100644
--- a/pd/src/m_glob.c
+++ b/pd/src/m_glob.c
@@ -20,6 +20,7 @@ void glob_meters(void *dummy, t_floatarg f);
void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av);
void glob_audiostatus(void *dummy);
void glob_finderror(t_pd *dummy);
+void glob_findinstance(t_pd *dummy, t_symbol*s);
void glob_audio_properties(t_pd *dummy, t_floatarg flongform);
void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
void glob_audio_setapi(t_pd *dummy, t_floatarg f);
@@ -103,6 +104,8 @@ void glob_init(void)
gensym("audiostatus"), 0);
class_addmethod(glob_pdobject, (t_method)glob_finderror,
gensym("finderror"), 0);
+ class_addmethod(glob_pdobject, (t_method)glob_findinstance,
+ gensym("findinstance"), A_SYMBOL, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_properties,
gensym("audio-properties"), A_DEFFLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_audio_dialog,
@@ -130,7 +133,7 @@ void glob_init(void)
gensym("version"), A_FLOAT, 0);
class_addmethod(glob_pdobject, (t_method)glob_perf,
gensym("perf"), A_FLOAT, 0);
-#ifdef UNIX
+#if defined(__linux__) || defined(IRIX) || defined(__FreeBSD_kernel__)
class_addmethod(glob_pdobject, (t_method)glob_watchdog,
gensym("watchdog"), 0);
#endif
diff --git a/pd/src/m_obj.c b/pd/src/m_obj.c
index df8a2c12..bc6056b4 100644
--- a/pd/src/m_obj.c
+++ b/pd/src/m_obj.c
@@ -75,12 +75,16 @@ static void inlet_wrong(t_inlet *x, t_symbol *s)
x->i_symfrom->s_name, s->s_name);
}
+static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv);
+
/* LATER figure out how to make these efficient: */
static void inlet_bang(t_inlet *x)
{
if (x->i_symfrom == &s_bang)
pd_vmess(x->i_dest, x->i_symto, "");
else if (!x->i_symfrom) pd_bang(x->i_dest);
+ else if (x->i_symfrom == &s_list)
+ inlet_list(x, &s_bang, 0, 0);
else inlet_wrong(x, &s_bang);
}
@@ -89,6 +93,12 @@ static void inlet_pointer(t_inlet *x, t_gpointer *gp)
if (x->i_symfrom == &s_pointer)
pd_vmess(x->i_dest, x->i_symto, "p", gp);
else if (!x->i_symfrom) pd_pointer(x->i_dest, gp);
+ else if (x->i_symfrom == &s_list)
+ {
+ t_atom a;
+ SETPOINTER(&a, gp);
+ inlet_list(x, &s_pointer, 1, &a);
+ }
else inlet_wrong(x, &s_pointer);
}
@@ -100,6 +110,12 @@ static void inlet_float(t_inlet *x, t_float f)
x->i_un.iu_floatsignalvalue = f;
else if (!x->i_symfrom)
pd_float(x->i_dest, f);
+ else if (x->i_symfrom == &s_list)
+ {
+ t_atom a;
+ SETFLOAT(&a, f);
+ inlet_list(x, &s_float, 1, &a);
+ }
else inlet_wrong(x, &s_float);
}
@@ -108,6 +124,12 @@ static void inlet_symbol(t_inlet *x, t_symbol *s)
if (x->i_symfrom == &s_symbol)
pd_vmess(x->i_dest, x->i_symto, "s", s);
else if (!x->i_symfrom) pd_symbol(x->i_dest, s);
+ else if (x->i_symfrom == &s_list)
+ {
+ t_atom a;
+ SETSYMBOL(&a, s);
+ inlet_list(x, &s_symbol, 1, &a);
+ }
else inlet_wrong(x, &s_symbol);
}
@@ -118,6 +140,12 @@ static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
|| x->i_symfrom == &s_symbol || x->i_symfrom == &s_pointer)
typedmess(x->i_dest, x->i_symto, argc, argv);
else if (!x->i_symfrom) pd_list(x->i_dest, s, argc, argv);
+ else if (!argc)
+ inlet_bang(x);
+ else if (argc==1 && argv->a_type == A_FLOAT)
+ inlet_float(x, atom_getfloat(argv));
+ else if (argc==1 && argv->a_type == A_SYMBOL)
+ inlet_symbol(x, atom_getsymbol(argv));
else inlet_wrong(x, &s_list);
}
diff --git a/pd/src/m_pd.h b/pd/src/m_pd.h
index 31d7847f..d04eae3a 100644
--- a/pd/src/m_pd.h
+++ b/pd/src/m_pd.h
@@ -9,8 +9,8 @@ extern "C" {
#endif
#define PD_MAJOR_VERSION 0
-#define PD_MINOR_VERSION 42
-#define PD_BUGFIX_VERSION 5
+#define PD_MINOR_VERSION 43
+#define PD_BUGFIX_VERSION 0
#define PD_TEST_VERSION ""
/* old name for "MSW" flag -- we have to take it for the sake of many old
@@ -46,6 +46,12 @@ extern "C" {
#define EXTERN_STRUCT extern struct
#endif
+/* Define some attributes, specific to the compiler */
+#if defined(__GNUC__)
+#define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b)))
+#else
+#define ATTRIBUTE_FORMAT_PRINTF(a, b)
+#endif
#if !defined(_SIZE_T) && !defined(_SIZE_T_)
#include <stddef.h> /* just for size_t -- how lame! */
@@ -450,10 +456,12 @@ EXTERN void poststring(const char *s);
EXTERN void postfloat(t_floatarg f);
EXTERN void postatom(int argc, t_atom *argv);
EXTERN void endpost(void);
-EXTERN void error(const char *fmt, ...);
-EXTERN void verbose(int level, const char *fmt, ...);
-EXTERN void bug(const char *fmt, ...);
-EXTERN void pd_error(void *object, const char *fmt, ...);
+EXTERN void error(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
+EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
+EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2);
+EXTERN void pd_error(void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3);
+EXTERN void logpost(const void *object, const int level, const char *fmt, ...)
+ ATTRIBUTE_FORMAT_PRINTF(3, 4);
EXTERN void sys_logerror(const char *object, const char *s);
EXTERN void sys_unixerror(const char *object);
EXTERN void sys_ouch(void);
@@ -466,6 +474,7 @@ EXTERN void sys_bashfilename(const char *from, char *to);
EXTERN void sys_unbashfilename(const char *from, char *to);
EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
char *dirresult, char **nameresult, unsigned int size, int bin);
+EXTERN int sys_close(int fd);
EXTERN int sched_geteventno(void);
EXTERN double sys_getrealtime(void);
EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */
@@ -580,11 +589,11 @@ EXTERN_STRUCT _garray;
EXTERN t_class *garray_class;
EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec);
EXTERN int garray_getfloatwords(t_garray *x, int *size, t_word **vec);
-EXTERN t_float garray_get(t_garray *x, t_symbol *s, t_int indx);
EXTERN void garray_redraw(t_garray *x);
EXTERN int garray_npoints(t_garray *x);
EXTERN char *garray_vec(t_garray *x);
-EXTERN void garray_resize(t_garray *x, t_floatarg f);
+EXTERN void garray_resize(t_garray *x, t_floatarg f); /* avoid; use this: */
+EXTERN void garray_resize_long(t_garray *x, long n); /* better version */
EXTERN void garray_usedindsp(t_garray *x);
EXTERN void garray_setsaveit(t_garray *x, int saveit);
EXTERN t_class *scalar_class;
diff --git a/pd/src/m_sched.c b/pd/src/m_sched.c
index ae9f3664..634db357 100644
--- a/pd/src/m_sched.c
+++ b/pd/src/m_sched.c
@@ -272,7 +272,7 @@ static void sched_pollformeters( void)
/* if there's no GUI but we're running in "realtime", here is
where we arrange to ping the watchdog every 2 seconds. */
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
if (sys_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0))
{
glob_watchdog(0);
@@ -439,7 +439,7 @@ static void m_pollingscheduler( void)
timeforward = sys_send_dacs();
#ifdef THREAD_LOCKING
/* T.Grill - done */
- sys_unlock();
+ sys_lock();
#endif
/* if dacs remain "idle" for 1 sec, they're hung up. */
if (timeforward != 0)
@@ -461,7 +461,7 @@ static void m_pollingscheduler( void)
idletime = sys_getrealtime();
else if (sys_getrealtime() - idletime > 1.)
{
- post("audio I/O stuck... closing audio\n");
+ error("audio I/O stuck... closing audio\n");
sys_close_audio();
sched_set_using_audio(SCHED_AUDIO_NONE);
goto waitfortick;
@@ -522,6 +522,7 @@ static void m_pollingscheduler( void)
void sched_audio_callbackfn(void)
{
+ sys_lock();
sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
sys_addhist(1);
sched_tick(sys_time + sys_time_per_dsp_tick);
@@ -532,6 +533,7 @@ void sched_audio_callbackfn(void)
sys_addhist(5);
sched_pollformeters();
sys_addhist(0);
+ sys_unlock();
}
static void m_callbackscheduler(void)
@@ -539,11 +541,19 @@ static void m_callbackscheduler(void)
sys_initmidiqueue();
while (!sys_quit)
{
+ double timewas = sys_time;
#ifdef MSW
- Sleep(1000);
+ Sleep(1000);
#else
sleep(1);
#endif
+ if (sys_time == timewas)
+ {
+ sys_lock();
+ sys_pollgui();
+ sched_tick(sys_time + sys_time_per_dsp_tick);
+ sys_unlock();
+ }
if (sys_idlehook)
sys_idlehook();
}
diff --git a/pd/src/makefile.in b/pd/src/makefile.in
index e68c6781..23933085 100644
--- a/pd/src/makefile.in
+++ b/pd/src/makefile.in
@@ -55,6 +55,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_array.c d_global.c \
d_delay.c d_resample.c \
@@ -189,7 +190,7 @@ install: all
@echo "Pd install succeeded."
local-clean:
- -rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/$(GUINAME) $(BIN_DIR)/pdsend \
+ -rm -f ../obj/* $(BIN_DIR)/pd $(BIN_DIR)/pdsend \
$(BIN_DIR)/pdreceive $(BIN_DIR)/pd-watchdog m_stamp.c \
$(BIN_DIR)/*.tcl
-rm -f `find ../portaudio -name "*.o"`
diff --git a/pd/src/makefile.mingw b/pd/src/makefile.mingw
new file mode 100644
index 00000000..30e2bd9f
--- /dev/null
+++ b/pd/src/makefile.mingw
@@ -0,0 +1,297 @@
+# how Miller builds Pd on Windows:
+# http://lists.puredata.info/pipermail/pd-dev/2004-10/002981.html
+
+CC = gcc
+CXX = g++
+
+cvs_root_dir = ../..
+pd_src = $(cvs_root_dir)/pd
+DLL_DIR = $(pd_src)/src
+
+BIN_DIR = ../bin
+
+VPATH = $(pd_src)/src
+
+prefix = /usr/local/pd
+exec_prefix = $(prefix)
+includedir = $(prefix)/include
+libdir = $(exec_prefix)/lib
+mandir = $(prefix)/man
+bindir = $(exec_prefix)/bin
+
+GFLAGS = -DINSTALL_PREFIX=\"$(prefix)\"
+
+# varibles to match packages/Makefile.buildlayout so that they can be easily
+# overridden when building Pd-extended builds. <hans@at.or.at>
+libpddir = $(prefix)
+pddocdir = $(libpddir)/doc
+libpdbindir = $(libpddir)/bin
+
+PDEXEC = pd.exe
+PDDLL = pd.dll
+DLLWRAP= dllwrap
+
+MORECFLAGS = -O3 -funroll-loops -fomit-frame-pointer
+
+PADIR = $(pd_src)/portaudio
+ASIODIR = $(pd_src)/asio/ASIOSDK2
+# there is some old code in ASIO/common/combase.h that needs to be ignored, we
+# do this by setting the WINVER macro
+ASIOINC = -I$(ASIODIR)/common -I$(ASIODIR)/host -I$(ASIODIR)/host/pc -DWINVER=0xffff
+INCPA = -I$(PADIR) -I$(PADIR)/include -I$(PADIR)/src/common $(ASIOINC)
+INCLUDE = -I$(pd_src)/src
+GINCLUDE = -I/usr/local/include $(INCLUDE)
+
+LDFLAGS =
+LIBS = -lm -lwsock32 -lwinmm -lole32 -lpthreadGC2
+
+OPT_CFLAGS =
+
+WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Wno-unused \
+ -Wno-unused-parameter -Wno-parentheses -Wno-switch
+ARCH_CFLAGS = -DPD -DPD_INTERNAL -DMSW -D_WIN32 -DPA_NO_DS -DUSEAPI_MMIO \
+ -DUSEAPI_PORTAUDIO -DPA19 -DPA_LITTLE_ENDIAN -mms-bitfields \
+ -DWISHAPP='"wish85.exe"'
+
+CFLAGS += $(ARCH_CFLAGS) $(WARN_CFLAGS) $(OPT_CFLAGS) $(MORECFLAGS)
+
+STRIP = strip --strip-unneeded -R .note -R .comment
+
+# the sources
+
+PASRC = s_audio_pa.c s_audio_paring.c \
+ s_audio_mmio.c s_midi_mmio.c \
+ $(PADIR)/src/common/pa_stream.c \
+ $(PADIR)/src/common/pa_trace.c \
+ $(PADIR)/src/common/pa_skeleton.c \
+ $(PADIR)/src/common/pa_process.c \
+ $(PADIR)/src/common/pa_front.c \
+ $(PADIR)/src/common/pa_dither.c \
+ $(PADIR)/src/common/pa_cpuload.c \
+ $(PADIR)/src/common/pa_converters.c \
+ $(PADIR)/src/common/pa_allocation.c \
+ $(PADIR)/src/common/pa_ringbuffer.c \
+ $(PADIR)/src/os/win/pa_win_hostapis.c \
+ $(PADIR)/src/os/win/pa_win_util.c \
+ $(PADIR)/src/os/win/pa_win_waveformat.c \
+ $(PADIR)/src/hostapi/wmme/pa_win_wmme.c
+
+ASIOSRC = $(PADIR)/src/hostapi/asio/iasiothiscallresolver.cpp \
+ $(PADIR)/src/hostapi/asio/pa_asio.cpp \
+ $(ASIODIR)/common/asio.cpp \
+ $(ASIODIR)/host/asiodrivers.cpp \
+ $(ASIODIR)/host/pc/asiolist.cpp
+
+#VSRC = s_audio_vst.c
+
+PMDIR = ../portmidi
+PMINCLUDE = -I$(PMDIR)/pm_common -I$(PMDIR)/pm_win -I$(PMDIR)/porttime -DNEWBUFFER
+PMSRC = $(PMDIR)/pm_common/portmidi.c \
+ $(PMDIR)/pm_common/pmutil.c \
+ $(PMDIR)/porttime/porttime.c \
+ $(PMDIR)/porttime/ptwinmm.c \
+ $(PMDIR)/pm_win/pmwin.c \
+ $(PMDIR)/pm_win/pmwinmm.c
+
+PMOBJ = $(PMSRC:.c=.o)
+
+HEADERS = g_all_guis.h m_imp.h g_canvas.h m_pd.h s_stuff.h \
+ $(wildcard ../portaudio/common/*.h) s_audio_paring.h
+
+SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
+ g_scalar.c g_traversal.c g_guiconnect.c g_readwrite.c g_editor.c \
+ g_all_guis.c g_bang.c g_hdial.c g_mycanvas.c g_numbox.c g_toggle.c \
+ g_hslider.c g_vumeter.c m_pd.c m_class.c m_obj.c m_atom.c m_memory.c \
+ m_binbuf.c m_conf.c m_glob.c m_sched.c s_main.c s_inter.c s_file.c \
+ s_print.c s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
+ d_math.c d_fft.c d_fft_mayer.c d_fftroutine.c d_array.c d_global.c \
+ d_delay.c d_resample.c x_arithmetic.c x_connective.c x_interface.c \
+ x_midi.c x_misc.c x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c \
+ x_list.c d_soundfile.c g_vslider.c g_vdial.c
+
+SRSRC = u_pdsend.c u_pdreceive.c
+
+OBJ = $(SRC:.c=.o)
+SROBJ = $(SRSRC:.c=.o)
+PAOBJ = $(PASRC:.c=.o)
+ASIOOBJ = $(ASIOSRC:.cpp=.o)
+#VOBJ = $(VSRC:.c=.o)
+OBJC = $(OBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)
+
+
+# get version from m_pd.h to use in doc/1.manual/1.introduction.txt
+PD_MAJOR_VERSION := $(shell grep PD_MAJOR_VERSION m_pd.h | \
+ sed 's|^.define *PD_MAJOR_VERSION *\([0-9]*\).*|\1|' )
+PD_MINOR_VERSION := $(shell grep PD_MINOR_VERSION m_pd.h | \
+ sed 's|^.define *PD_MINOR_VERSION *\([0-9]*\).*|\1|' )
+PD_BUGFIX_VERSION := $(shell grep PD_BUGFIX_VERSION m_pd.h | \
+ sed 's|^.define *PD_BUGFIX_VERSION *\([0-9]*\).*|\1|' )
+PD_TEST_VERSION := $(shell grep PD_TEST_VERSION m_pd.h | \
+ sed 's|^.define *PD_TEST_VERSION *"\(.*\)".*|\1|' )
+PD_VERSION := $(PD_MAJOR_VERSION).$(PD_MINOR_VERSION).$(PD_BUGFIX_VERSION)
+ifneq ($(PD_TEST_VERSION),)
+ PD_VERSION := $(PD_VERSION)-$(PD_TEST_VERSION)
+endif
+
+
+#
+# ------------------ targets ------------------------------------
+#
+
+.PHONY: all install clean externs testbin
+
+all: $(PDDLL) $(PDEXEC) externs pdsend.exe pdreceive.exe pd.com
+
+$(OBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c
+
+$(GOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(GINCLUDE) -c -o $*.o $*.c
+
+$(SROBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c
+
+$(PAOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCPA) -c -o $*.o $*.c
+
+$(ASIOOBJ) : %.o : %.cpp
+ $(CXX) $(CFLAGS) $(INCPA) -c -o $*.o $*.cpp
+
+$(PMOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(PMINCLUDE) -c -o $*.o $*.c
+
+$(VOBJ) : %.o : %.c
+ $(CC) $(CFLAGS) $(GFLAGS) $(INCLUDE) -c -o $*.o $*.c
+
+pdsend.exe: u_pdsend.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o pdsend.exe u_pdsend.o $(LIBS)
+ $(STRIP) pdsend.exe
+
+pdreceive.exe: u_pdreceive.o
+ $(CC) $(CFLAGS) $(LDFLAGS) -o pdreceive.exe u_pdreceive.o $(LIBS)
+ $(STRIP) pdreceive.exe
+
+$(PDEXEC): s_entry.o pd.res
+ $(CC) $(LDFLAGS) -mwindows -o $(PDEXEC) s_entry.o pd.res $(LIBS) -L. -lpd
+ $(STRIP) -s $(PDEXEC)
+
+pd.com: s_entry.o
+ $(CC) $(LDFLAGS) -o pd.com s_entry.o $(LIBS) -L. -lpd
+ $(STRIP) -s pd.com
+
+$(PDDLL): $(OBJC)
+ $(CXX) -shared $(LDFLAGS) -o $(PDDLL) $(OBJC) $(LIBS) \
+ -Wl,--export-all-symbols -Wl,--out-implib=pd.a;
+ $(STRIP) $(PDDLL)
+
+pd.res: pd.rc
+ windres pd.rc -O coff -o pd.res
+
+#vstschedlib.dll: $(VOBJ)
+# $(DLLWRAP) --export-all-symbols --output-def vst.def \
+# --output-lib=vst.a --dllname=vstschedlib.dll s_audio_vst.o pd.a $(LIBS)
+
+externs:
+ make -C ../extra all
+
+# kludge to put stuff into the pd/bin dir for testing
+testbin: $(PDEXEC) $(PDDLL) pd.com
+ echo "Copying files to $(BIN_DIR)"
+ install -d $(BIN_DIR)
+ install -p *.tcl $(BIN_DIR)
+ install -p $(PDDLL) $(BIN_DIR)
+ install -p pd.ico $(BIN_DIR)
+ install -p pd.com $(BIN_DIR)
+ install -p $(PDEXEC) $(BIN_DIR)
+
+ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
+install: all
+# locales
+ make libpddir=$(libpddir) -C ../po install
+# install extra stuff
+ make libpddir=$(libpddir) -C ../extra install
+# the real install
+ install -d $(DESTDIR)$(bindir)
+ install -p *.tcl $(DESTDIR)$(bindir)/
+ install -p $(PDEXEC) $(DESTDIR)$(bindir)/$(PDEXEC)
+ install -p pd.com $(DESTDIR)$(bindir)/pd.com
+ install -p pd.dll $(DESTDIR)$(bindir)/pd.dll
+ install -p pd.ico $(DESTDIR)$(bindir)/pd.ico
+ install -p pdsend.exe $(DESTDIR)$(bindir)/pdsend.exe
+ install -p pdreceive.exe $(DESTDIR)$(bindir)/pdreceive.exe
+ for dir in $(shell ls -1 ../doc | grep -v CVS); do \
+ echo "installing $$dir"; \
+ install -d $(DESTDIR)$(pddocdir)/$$dir ; \
+ install -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
+ done
+ for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
+ echo "installing 7.stuff/$$dir"; \
+ install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
+ install -p ../doc/7.stuff/$$dir/*.* $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
+ done
+ mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
+ cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
+ > $(ABOUT_FILE)
+ rm $(ABOUT_FILE).tmp
+ install -d $(DESTDIR)$(libpddir)/extra
+ install -p $(pd_src)/extra/*/*.dll $(DESTDIR)$(libpddir)/extra
+ install -p $(pd_src)/extra/*.pd $(DESTDIR)$(libpddir)/extra
+ install -d $(DESTDIR)$(pddocdir)/5.reference
+ install -p ../extra/*/*.pd $(DESTDIR)$(pddocdir)/5.reference
+ install -p ../extra/*-help.pd $(DESTDIR)$(pddocdir)/5.reference
+ install -d $(DESTDIR)$(prefix)/startup
+ install -p $(pd_src)/startup/*.* $(DESTDIR)$(prefix)/startup
+ install -d $(DESTDIR)$(prefix)/startup/disabled
+ install -p $(pd_src)/startup/disabled/*.* $(DESTDIR)$(prefix)/startup/disabled
+ install -d $(DESTDIR)$(includedir)
+ install -p m_pd.h $(DESTDIR)$(includedir)/m_pd.h
+ install -p s_stuff.h $(DESTDIR)$(includedir)/s_stuff.h
+ @echo "Pd install succeeded."
+
+
+clean:
+ -rm -f -- $(BIN_DIR)/*.*
+ -rm -f -- *.o *.a *.def
+ -rm -f -- pd*.exe pd*.dll pd.com
+ -rm -f -- $(OBJ) $(GOBJ) $(SROBJ) $(PAOBJ) $(ASIOOBJ) $(PMOBJ)
+ -rm -f -- $(pd_src)/extra/*/*.dll $(pd_src)/extra/*/*.o
+ -rm -f makefile.dependencies
+
+distclean: clean
+ rm -rf -- config.cache config.log config.status makefile tags \
+ autom4te-*.cache
+
+tags: $(SRC) $(GSRC); ctags *.[ch]
+
+depend: makefile.dependencies
+
+makefile.dependencies: $(SRC) $(PASRC) $(HEADERS)
+ $(CC) $(INCLUDE) $(INCPA) $(CFLAGS) -M $(SRC) $(PASRC) $(HEADERS) \
+ > makefile.dependencies
+
+uninstall:
+ -rm $(prefix)/bin/pd*.exe
+ -rm $(prefix)/bin/pd*.com
+ -rm $(prefix)/bin/pd*.dll
+ -rm $(prefix)/bin/*.tcl
+
+
+test_locations:
+ @echo "PD_VERSION: $(PD_VERSION)"
+ @echo "PACKAGE_VERSION: $(PACKAGE_VERSION)"
+ @echo "CWD $(CWD)"
+ @echo "DESTDIR $(DESTDIR)"
+ @echo "PREFIX $(prefix)"
+ @echo "BINDIR $(bindir)"
+ @echo "LIBDIR $(libdir)"
+ @echo "OBJECTSDIR $(objectsdir)"
+ @echo "PDDOCDIR $(pddocdir)"
+ @echo "LIBPDDIR $(libpddir)"
+ @echo "LIBPDBINDIR $(libpdbindir)"
+ @echo "HELPDIR $(helpdir)"
+ @echo "MANUALSDIR $(manualsdir)"
+ @echo "EXAMPLESDIR $(examplesdir)"
+
+
+include makefile.dependencies
diff --git a/pd/src/makefile.nt b/pd/src/makefile.nt
index 7b4e834e..b57c3d08 100644
--- a/pd/src/makefile.nt
+++ b/pd/src/makefile.nt
@@ -6,14 +6,14 @@ all: pd ..\bin\pdsend.exe ..\bin\pdreceive.exe
VCSDK = "C:\Program Files\Microsoft SDKs\Windows\v6.0A"
VC9 = "C:\Program Files\Microsoft Visual Studio 9.0\VC"
#VC="\Program Files\DevStudio\Vc"
-INCLUDE = -I.\ -I..\Tcl\include -I\DXSDK\include -I$(VC9)\Include \
+INCLUDE = -I.\ -I..\Tcl\include -I$(VC9)\Include \
-I$(VCSDK)\Include
LDIR = $(VCSDK)\lib
LD2 = $(VC9)\lib
-LIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:oldnames /NODEFAULTLIB:libc \
- /NODEFAULTLIB:uuid $(LDIR)\kernel32.lib \
+LIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:libcpmt /NODEFAULTLIB:oldnames \
+ /NODEFAULTLIB:libc /NODEFAULTLIB:uuid $(LDIR)\kernel32.lib \
$(LDIR)\wsock32.lib $(LDIR)\winmm.lib $(LDIR)\advapi32.lib \
$(LDIR)\setupapi.lib ..\bin\pthreadVC.lib \
$(LD2)\libcmt.lib $(LD2)\oldnames.lib
@@ -23,7 +23,7 @@ CFLAGS = /nologo /W3 /DMSW /DNT /DPD /DPD_INTERNAL /DWIN32 /DWINDOWS /Ox \
-D_CRT_SECURE_NO_WARNINGS
LFLAGS = /nologo
-SYSSRC = s_audio_pa.c s_audio_pablio.c s_audio_paring.c \
+SYSSRC = s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c s_midi_pm.c
SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
@@ -33,7 +33,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
m_pd.c m_class.c m_obj.c m_atom.c m_memory.c m_binbuf.c \
m_conf.c m_glob.c m_sched.c \
s_main.c s_inter.c s_file.c s_print.c \
- s_loader.c s_path.c s_entry.c s_audio.c s_midi.c \
+ s_loader.c s_path.c s_entry.c s_audio.c s_midi.c s_utf8.c \
d_ugen.c d_ctl.c d_arithmetic.c d_osc.c d_filter.c d_dac.c d_misc.c \
d_math.c d_fft.c d_fft_mayer.c d_fftroutine.c d_array.c d_global.c \
d_delay.c d_resample.c \
@@ -53,8 +53,10 @@ SRCPA = $(PASRC)/common/pa_stream.c \
$(PASRC)/common/pa_cpuload.c \
$(PASRC)/common/pa_converters.c \
$(PASRC)/common/pa_allocation.c \
+ $(PASRC)/common/pa_ringbuffer.c \
$(PASRC)/os/win/pa_win_hostapis.c \
$(PASRC)/os/win/pa_win_util.c \
+ $(PASRC)/os/win/pa_win_waveformat.c \
$(PASRC)/hostapi/wmme/pa_win_wmme.c
SRCASIO = $(PADIR)/pa_asio/pa_asio.cpp
@@ -67,8 +69,11 @@ $(LDIR)\odbc32.lib $(LDIR)\odbccp32.lib ..\lib\asio\asiolib.lib
PAOBJ = pa_stream.obj pa_trace.obj pa_skeleton.obj pa_process.obj \
pa_front.obj pa_dither.obj pa_cpuload.obj pa_converters.obj \
- pa_allocation.obj pa_win_hostapis.obj pa_win_util.obj pa_asio.obj \
- pa_win_wmme.obj
+ pa_allocation.obj pa_ringbuffer.obj \
+ pa_win_hostapis.obj pa_win_util.obj pa_win_waveformat.obj \
+ pa_win_wmme.obj \
+ pa_asio.obj
+
# pa_win_wdmks.obj
PMDIR = ..\portmidi
@@ -141,11 +146,15 @@ pa_converters.obj: $(PASRC)\common\pa_converters.c
cl /c $(ALLCF) $(PASRC)\common\pa_converters.c
pa_allocation.obj: $(PASRC)\common\pa_allocation.c
cl /c $(ALLCF) $(PASRC)\common\pa_allocation.c
+pa_ringbuffer.obj: $(PASRC)\common\pa_ringbuffer.c
+ cl /c $(ALLCF) $(PASRC)\common\pa_ringbuffer.c
pa_win_hostapis.obj: $(PASRC)\os\win\pa_win_hostapis.c
cl /c $(ALLCF) $(PASRC)\os\win\pa_win_hostapis.c
pa_win_util.obj: $(PASRC)\os\win\pa_win_util.c
cl /c $(ALLCF) $(PASRC)\os\win\pa_win_util.c
+pa_win_waveformat.obj: $(PASRC)\os\win\pa_win_waveformat.c
+ cl /c $(ALLCF) $(PASRC)\os\win\pa_win_waveformat.c
pa_win_wmme.obj: $(PASRC)\hostapi\wmme\pa_win_wmme.c
cl /c $(ALLCF) $(PASRC)\hostapi\wmme\pa_win_wmme.c
pa_win_wdmks.obj: $(PADIR)\pa_win_wdmks\pa_win_wdmks.c
diff --git a/pd/src/notes.txt b/pd/src/notes.txt
index 0cf0ee61..f9bf2dd8 100644
--- a/pd/src/notes.txt
+++ b/pd/src/notes.txt
@@ -1,6 +1,13 @@
+font courier not found?
+carriage returns after posting
+lose makesfx.bat, etc. from msw (and move out personal stuff?)
+control C control
+window titles wrong on Macintosh
---------------- dolist --------------------
+portaudio: put call to PA_Terminate back in where appropriate
+ (first test situation on windows)
compile on various versions of linux
windows:
modal dialogs confuse watchdog
diff --git a/pd/src/pd.ico b/pd/src/pd.ico
new file mode 100755
index 00000000..2da5c243
--- /dev/null
+++ b/pd/src/pd.ico
Binary files differ
diff --git a/pd/src/pd.rc b/pd/src/pd.rc
new file mode 100644
index 00000000..a51d9462
--- /dev/null
+++ b/pd/src/pd.rc
@@ -0,0 +1,25 @@
+id ICON "pd.ico"
+1 VERSIONINFO
+FILEVERSION 0,43,0,0
+PRODUCTVERSION 0,43,0,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "puredata.info"
+ VALUE "FileDescription", "Pure Data Application"
+ VALUE "FileVersion", "0.43"
+ VALUE "InternalName", "pd.exe"
+ VALUE "LegalCopyright", "Miller Puckette, et al."
+ VALUE "OriginalFilename", "pd.exe"
+ VALUE "ProductName", "Pure Data"
+ VALUE "ProductVersion", "0.43"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c
index 2f274fc6..bff3c3ab 100644
--- a/pd/src/s_audio.c
+++ b/pd/src/s_audio.c
@@ -9,17 +9,18 @@
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
-#ifdef HAVE_UNISTD_H
+#ifdef _WIN32
+#include <time.h>
+#else
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
-#endif
+#endif /* _WIN32 */
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define SYS_DEFAULTCH 2
-#define SYS_MAXCH 100
typedef long t_pa_sample;
#define SYS_SAMPLEWIDTH sizeof(t_pa_sample)
#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH)
@@ -37,7 +38,6 @@ static void audio_getdevs(char *indevlist, int *nindevs,
int sys_inchannels;
int sys_outchannels;
int sys_advance_samples; /* scheduler advance in samples */
-int sys_blocksize = 0; /* audio I/O block size in sample frames */
int sys_audioapi = API_DEFAULT;
int sys_audioapiopened = -1; /* save last API opened for later closing */
static int sys_meters; /* true if we're metering */
@@ -64,8 +64,9 @@ static int audio_naudiooutdev = -1;
static int audio_audiooutdev[MAXAUDIOOUTDEV];
static int audio_audiochoutdev[MAXAUDIOOUTDEV];
static int audio_rate;
-static int audio_advance;
+static int audio_advance = -1;
static int audio_callback;
+static int audio_blocksize;
static int audio_callback_is_open; /* reflects true actual state */
static int audio_nextinchans, audio_nextoutchans;
@@ -82,7 +83,7 @@ static int audio_isopen(void)
void sys_get_audio_params(
int *pnaudioindev, int *paudioindev, int *chindev,
int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
- int *prate, int *padvance, int *pcallback)
+ int *prate, int *padvance, int *pcallback, int *pblocksize)
{
int i;
*pnaudioindev = audio_naudioindev;
@@ -96,12 +97,13 @@ void sys_get_audio_params(
*prate = audio_rate;
*padvance = audio_advance;
*pcallback = audio_callback;
+ *pblocksize = audio_blocksize;
}
void sys_save_audio_params(
int naudioindev, int *audioindev, int *chindev,
int naudiooutdev, int *audiooutdev, int *choutdev,
- int rate, int advance, int callback)
+ int rate, int advance, int callback, int blocksize)
{
int i;
audio_naudioindev = naudioindev;
@@ -115,6 +117,7 @@ void sys_save_audio_params(
audio_rate = rate;
audio_advance = advance;
audio_callback = callback;
+ audio_blocksize = blocksize;
}
/* init routines for any API which needs to set stuff up before
@@ -156,8 +159,8 @@ void sys_setchsr(int chin, int chout, int sr)
sys_outchannels = chout;
sys_dacsr = sr;
sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.);
- if (sys_advance_samples < 3 * DEFDACBLKSIZE)
- sys_advance_samples = 3 * DEFDACBLKSIZE;
+ if (sys_advance_samples < DEFDACBLKSIZE)
+ sys_advance_samples = DEFDACBLKSIZE;
sys_soundin = (t_sample *)getbytes(inbytes);
memset(sys_soundin, 0, inbytes);
@@ -180,7 +183,7 @@ void sys_setchsr(int chin, int chout, int sr)
void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate, int advance, int callback)
+ int *choutdev, int rate, int advance, int callback, int blocksize)
{
int i, *ip;
int defaultchannels = SYS_DEFAULTCH;
@@ -195,8 +198,10 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
if (rate < 1)
rate = DEFAULTSRATE;
- if (advance <= 0)
+ if (advance < 0)
advance = DEFAULTADVANCE;
+ if (blocksize != (1 << ilog2(blocksize)) || blocksize < DEFDACBLKSIZE)
+ blocksize = DEFDACBLKSIZE;
audio_init();
/* Since the channel vector might be longer than the
audio device vector, or vice versa, we fill the shorter one
@@ -324,7 +329,8 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
audio_nextinchans = inchans;
audio_nextoutchans = outchans;
sys_save_audio_params(nrealindev, realindev, realinchans,
- nrealoutdev, realoutdev, realoutchans, rate, advance, callback);
+ nrealoutdev, realoutdev, realoutchans, rate, advance, callback,
+ blocksize);
}
void sys_close_audio(void)
@@ -360,12 +366,29 @@ void sys_close_audio(void)
mmio_close_audio();
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapiopened == API_AUDIOUNIT)
+ audiounit_close_audio();
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapiopened == API_ESD)
+ esd_close_audio();
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapiopened == API_DUMMY)
+ dummy_close_audio();
+ else
+#endif
post("sys_close_audio: unknown API %d", sys_audioapiopened);
sys_inchannels = sys_outchannels = 0;
sys_audioapiopened = -1;
sched_set_using_audio(SCHED_AUDIO_NONE);
audio_state = 0;
audio_callback_is_open = 0;
+
+ sys_vgui("set pd_whichapi 0\n");
}
/* open audio using whatever parameters were last used */
@@ -373,9 +396,10 @@ void sys_reopen_audio( void)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int rate, advance, callback, outcome = 0;
+ int rate, advance, callback, blocksize, outcome = 0;
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
if (!naudioindev && !naudiooutdev)
{
@@ -385,7 +409,9 @@ void sys_reopen_audio( void)
#ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO)
{
- int blksize = (sys_blocksize ? sys_blocksize : 64);
+ int blksize = (audio_blocksize ? audio_blocksize : 64);
+ if (sys_verbose)
+ fprintf(stderr, "blksize %d, advance %d\n", blksize, sys_advance_samples/blksize);
outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
(naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
sys_soundout, blksize, sys_advance_samples/blksize,
@@ -398,14 +424,16 @@ void sys_reopen_audio( void)
#ifdef USEAPI_JACK
if (sys_audioapi == API_JACK)
outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
- (naudioindev > 0 ? choutdev[0] : 0), rate);
+ (naudioindev > 0 ? choutdev[0] : 0), rate,
+ (callback ? sched_audio_callbackfn : 0));
else
#endif
#ifdef USEAPI_OSS
if (sys_audioapi == API_OSS)
outcome = oss_open_audio(naudioindev, audioindev, naudioindev,
- chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+ chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+ audio_blocksize);
else
#endif
#ifdef USEAPI_ALSA
@@ -413,13 +441,32 @@ void sys_reopen_audio( void)
be open for both input and output. */
if (sys_audioapi == API_ALSA)
outcome = alsa_open_audio(naudioindev, audioindev, naudioindev,
- chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+ chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+ audio_blocksize);
else
#endif
#ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO)
outcome = mmio_open_audio(naudioindev, audioindev, naudioindev,
+ chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+ audio_blocksize);
+ else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0),
+ (naudioindev > 0 ? choutdev[0] : 0), rate);
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ALSA)
+ outcome = esd_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ outcome = dummy_open_audio(naudioindev, naudiooutdev, rate);
else
#endif
if (sys_audioapi == API_NONE)
@@ -493,6 +540,21 @@ int sys_send_dacs(void)
return (mmio_send_dacs());
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ return (audiounit_send_dacs());
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ESD)
+ return (esd_send_dacs());
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ return (dummy_send_dacs());
+ else
+#endif
post("unknown API");
return (0);
}
@@ -549,6 +611,7 @@ static void audio_getdevs(char *indevlist, int *nindevs,
{
jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
+ *cancallback = 1;
}
else
#endif
@@ -576,6 +639,28 @@ static void audio_getdevs(char *indevlist, int *nindevs,
}
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ {
+ }
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ESD)
+ {
+ esd_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+ maxndev, devdescsize);
+ }
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ {
+ dummy_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+ maxndev, devdescsize);
+ }
+ else
+#endif
{
/* this shouldn't happen once all the above get filled in. */
int i;
@@ -635,7 +720,7 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
audioinchan1, audioinchan2, audioinchan3, audioinchan4,
audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4;
- int rate, advance, callback;
+ int rate, advance, callback, blocksize;
/* these are all the devices on your system: */
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i;
@@ -654,7 +739,8 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
outdevlist + i * DEVDESCSIZE);
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
/* post("naudioindev %d naudiooutdev %d longform %f",
naudioindev, naudiooutdev, flongform); */
@@ -681,13 +767,13 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
"pdtk_audio_dialog %%s \
%d %d %d %d %d %d %d %d \
%d %d %d %d %d %d %d %d \
-%d %d %d %d %d\n",
+%d %d %d %d %d %d\n",
audioindev1, audioindev2, audioindev3, audioindev4,
audioinchan1, audioinchan2, audioinchan3, audioinchan4,
audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4,
rate, advance, canmulti, (cancallback ? callback : -1),
- (flongform != 0));
+ (flongform != 0), blocksize);
gfxstub_deleteforkey(0);
gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf);
}
@@ -706,6 +792,7 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
int newrate = atom_getintarg(16, argc, argv);
int newadvance = atom_getintarg(17, argc, argv);
int newcallback = atom_getintarg(18, argc, argv);
+ int newblocksize = atom_getintarg(19, argc, argv);
for (i = 0; i < 4; i++)
{
@@ -738,14 +825,27 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
}
}
- if (newcallback < 0)
- newcallback = 0;
- if (!audio_callback_is_open && !newcallback)
- sys_close_audio();
- sys_set_audio_settings(nindev, newaudioindev, nindev, newaudioinchan,
+ sys_set_audio_settings_reopen(nindev, newaudioindev, nindev, newaudioinchan,
noutdev, newaudiooutdev, noutdev, newaudiooutchan,
- newrate, newadvance, (newcallback >= 0 ? newcallback : 0));
- if (!audio_callback_is_open && !newcallback)
+ newrate, newadvance, newcallback, newblocksize);
+}
+
+void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, int nchindev,
+ int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+ int *choutdev, int rate, int advance, int callback, int newblocksize)
+{
+ if (callback < 0)
+ callback = 0;
+ if (newblocksize != (1<<ilog2(newblocksize)) ||
+ newblocksize < DEFDACBLKSIZE || newblocksize > 2048)
+ newblocksize = DEFDACBLKSIZE;
+
+ if (!audio_callback_is_open && !callback)
+ sys_close_audio();
+ sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
+ naudiooutdev, audiooutdev, nchoutdev, choutdev,
+ rate, advance, (callback >= 0 ? callback : 0), newblocksize);
+ if (!audio_callback_is_open && !callback)
sys_reopen_audio();
else sched_reopenmeplease();
}
@@ -777,19 +877,34 @@ void sys_listdevs(void )
sys_listaudiodevs();
else
#endif
+#ifdef USEAPI_AUDIOUNIT
+ if (sys_audioapi == API_AUDIOUNIT)
+ sys_listaudiodevs();
+ else
+#endif
+#ifdef USEAPI_ESD
+ if (sys_audioapi == API_ESD)
+ sys_listaudiodevs();
+ else
+#endif
+#ifdef USEAPI_DUMMY
+ if (sys_audioapi == API_DUMMY)
+ sys_listaudiodevs();
+ else
+#endif
post("unknown API");
sys_listmididevs();
}
-void sys_setblocksize(int n)
+void sys_get_audio_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
+ int maxndev, int devdescsize)
{
- if (n < 1)
- n = 1;
- if (n != (1 << ilog2(n)))
- post("warning: adjusting blocksize to power of 2: %d",
- (n = (1 << ilog2(n))));
- sys_blocksize = n;
+ audio_getdevs(indevlist, nindevs,
+ outdevlist, noutdevs,
+ canmulti, cancallback,
+ maxndev, devdescsize);
}
void sys_set_audio_api(int which)
@@ -872,6 +987,15 @@ void sys_get_audio_apis(char *buf)
#ifdef USEAPI_JACK
sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++;
#endif
+#ifdef USEAPI_AUDIOUNIT
+ sprintf(buf + strlen(buf), "{AudioUnit %d} ", API_AUDIOUNIT); n++;
+#endif
+#ifdef USEAPI_ESD
+ sprintf(buf + strlen(buf), "{ESD %d} ", API_ESD); n++;
+#endif
+#ifdef USEAPI_DUMMY
+ sprintf(buf + strlen(buf), "{dummy %d} ", API_DUMMY); n++;
+#endif
strcat(buf, "}");
/* then again, if only one API (or none) we don't offer any choice. */
if (n < 2)
diff --git a/pd/src/s_audio_alsa.c b/pd/src/s_audio_alsa.c
index a5034c8d..cf731109 100644
--- a/pd/src/s_audio_alsa.c
+++ b/pd/src/s_audio_alsa.c
@@ -90,9 +90,17 @@ static int alsaio_canmmap(t_alsa_dev *dev)
return ((err1 < 0) && (err2 >= 0));
}
+static void check_setup_error(int err, int out, const char *why) {
+ char bf[256];
+ snprintf(bf, sizeof bf, "%s (%s)", why, out ? "output" : "input");
+ check_error(err, bf);
+}
+
static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
int nfrags, int frag_size)
{
+#define CHECK_ERROR(why_) check_setup_error(err, out, why_)
+
int bufsizeforthis, err;
snd_pcm_hw_params_t* hw_params;
unsigned int tmp_uint;
@@ -110,14 +118,14 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
/* get the default params */
err = snd_pcm_hw_params_any(dev->a_handle, hw_params);
- check_error(err, "snd_pcm_hw_params_any");
+ CHECK_ERROR("snd_pcm_hw_params_any");
/* try to set interleaved access */
err = snd_pcm_hw_params_set_access(dev->a_handle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
return (-1);
- check_error(err, "snd_pcm_hw_params_set_access");
+ CHECK_ERROR("snd_pcm_hw_params_set_access");
#if 0 /* enable this to print out which formats are available */
{
int i;
@@ -141,7 +149,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
"PD-ALSA: 32/24 bit format not available - using 16\n"); */
err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
SND_PCM_FORMAT_S16);
- check_error(err, "snd_pcm_hw_params_set_format");
+ CHECK_ERROR("_pcm_hw_params_set_format");
dev->a_sampwidth = 2;
}
else dev->a_sampwidth = 3;
@@ -154,22 +162,22 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
/* set the subformat */
err = snd_pcm_hw_params_set_subformat(dev->a_handle,
hw_params, SND_PCM_SUBFORMAT_STD);
- check_error(err, "snd_pcm_hw_params_set_subformat");
+ CHECK_ERROR("snd_pcm_hw_params_set_subformat");
/* set the number of channels */
tmp_uint = *channels;
err = snd_pcm_hw_params_set_channels_min(dev->a_handle,
hw_params, &tmp_uint);
- check_error(err, "snd_pcm_hw_params_set_channels");
+ CHECK_ERROR("snd_pcm_hw_params_set_channels");
if (tmp_uint != (unsigned)*channels)
post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint);
*channels = tmp_uint;
dev->a_channels = *channels;
/* set the sampling rate */
- err = snd_pcm_hw_params_set_rate_min(dev->a_handle, hw_params,
+ err = snd_pcm_hw_params_set_rate_near(dev->a_handle, hw_params,
(unsigned int *)rate, 0);
- check_error(err, "snd_pcm_hw_params_set_rate_min (input)");
+ CHECK_ERROR("snd_pcm_hw_params_set_rate_min");
#if 0
err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
post("input sample rate %d", err);
@@ -185,7 +193,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
err = snd_pcm_hw_params_set_period_size_near(dev->a_handle,
hw_params, &tmp_snd_pcm_uframes, 0);
#endif
- check_error(err, "snd_pcm_hw_params_set_period_size_near (input)");
+ CHECK_ERROR("snd_pcm_hw_params_set_period_size_near");
/* set the buffer size */
#ifdef ALSAAPI9
@@ -196,10 +204,10 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle,
hw_params, &tmp_snd_pcm_uframes);
#endif
- check_error(err, "snd_pcm_hw_params_set_buffer_size_near (input)");
+ CHECK_ERROR("snd_pcm_hw_params_set_buffer_size_near");
err = snd_pcm_hw_params(dev->a_handle, hw_params);
- check_error(err, "snd_pcm_hw_params (input)");
+ CHECK_ERROR("snd_pcm_hw_params");
/* set up the buffer */
bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels;
@@ -227,18 +235,19 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
alsa_snd_bufsize = bufsizeforthis;
}
return (1);
+#undef CHECK_ERROR
}
/* return 0 on success */
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate)
+ int *choutdev, int rate, int blocksize)
{
int err, inchans = 0, outchans = 0, subunitdir;
char devname[512];
snd_output_t* out;
- int frag_size = (sys_blocksize ? sys_blocksize : ALSA_DEFFRAGSIZE);
+ int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE);
int nfrags, i, iodev, dev2;
int wantinchans, wantoutchans, device;
@@ -292,7 +301,7 @@ int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
if (alsa_usemmap)
{
post("using mmap audio interface");
- if (alsamm_open_audio(rate))
+ if (alsamm_open_audio(rate, blocksize))
goto blewit;
else return (0);
}
@@ -469,7 +478,7 @@ int alsa_send_dacs(void)
((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
- fprintf(stderr("big endian 24-bit not supported");
+ fprintf(stderr, "big endian 24-bit not supported");
#endif
}
for (; i < thisdevchans; i++, ch++)
@@ -581,7 +590,7 @@ int alsa_send_dacs(void)
* (1./ INT32_MAX);
}
#else
- fprintf(stderr("big endian 24-bit not supported");
+ fprintf(stderr, "big endian 24-bit not supported");
#endif
}
else
diff --git a/pd/src/s_audio_alsa.h b/pd/src/s_audio_alsa.h
index 813be211..f59cff3c 100644
--- a/pd/src/s_audio_alsa.h
+++ b/pd/src/s_audio_alsa.h
@@ -35,6 +35,6 @@ extern t_alsa_dev alsa_outdev[ALSA_MAXDEV];
extern int alsa_nindev;
extern int alsa_noutdev;
-int alsamm_open_audio(int rate);
+int alsamm_open_audio(int rate, int blocksize);
void alsamm_close_audio(void);
int alsamm_send_dacs(void);
diff --git a/pd/src/s_audio_alsamm.c b/pd/src/s_audio_alsamm.c
index 3bc4b369..abcb0a85 100644
--- a/pd/src/s_audio_alsamm.c
+++ b/pd/src/s_audio_alsamm.c
@@ -182,7 +182,7 @@ static void check_error(int err, const char *why)
error("%s: %s\n", why, snd_strerror(err));
}
-int alsamm_open_audio(int rate)
+int alsamm_open_audio(int rate, int blocksize)
{
int err;
char devname[80];
@@ -238,16 +238,16 @@ int alsamm_open_audio(int rate)
/* set the asked buffer time (alsa buffertime in us)*/
alsamm_buffertime = alsamm_buffersize = 0;
- if(sys_blocksize == 0)
+ if(blocksize == 0)
alsamm_buffertime = sys_schedadvance;
else
- alsamm_buffersize = sys_blocksize;
+ alsamm_buffersize = blocksize;
if(sys_verbose)
post("syschedadvance=%d us(%d Samples)so buffertime max should be this=%d"
"or sys_blocksize=%d (samples) to use buffersize=%d",
sys_schedadvance,sys_advance_samples,alsamm_buffertime,
- sys_blocksize,alsamm_buffersize);
+ blocksize,alsamm_buffersize);
alsamm_periods = 0; /* no one wants periods setting from command line ;-) */
diff --git a/pd/src/s_audio_audiounit.c b/pd/src/s_audio_audiounit.c
new file mode 100644
index 00000000..d9d7f667
--- /dev/null
+++ b/pd/src/s_audio_audiounit.c
@@ -0,0 +1,43 @@
+
+/* ------------- routines for Apple AudioUnit in AudioToolbox -------------- */
+#ifdef USEAPI_AUDIOUNIT
+
+/* this is currently a placeholder file while we decide which one of three implementations of this API we use */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "m_pd.h"
+#include "s_stuff.h"
+#include <AudioToolbox/AudioToolbox.h>
+
+pthread_mutex_t audiounit_mutex;
+pthread_cond_t audiounit_sem;
+
+int audiounit_open_audio(int inchans, int outchans, int rate)
+{
+ return 0;
+}
+
+void audiounit_close_audio(void)
+{
+}
+
+int audiounit_send_dacs(void)
+{
+ return 0;
+}
+
+void audiounit_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize)
+{
+ post("device getting not implemented for AudioUnit yet\n");
+}
+
+void audiounit_listdevs( void)
+{
+ post("device listing not implemented for AudioUnit yet\n");
+}
+
+#endif /* AUDIOUNIT */
diff --git a/pd/src/s_audio_dummy.c b/pd/src/s_audio_dummy.c
new file mode 100644
index 00000000..5ea1dd9f
--- /dev/null
+++ b/pd/src/s_audio_dummy.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com)
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ */
+
+#ifdef USEAPI_DUMMY
+
+#include <stdio.h>
+
+int dummy_open_audio(int nin, int nout, int sr) {
+ return 0;
+}
+
+int dummy_close_audio() {
+ return 0;
+}
+
+int dummy_send_dacs() {
+ return 0;
+}
+
+void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist,
+ int *noutdevs, int *canmulti, int maxndev, int devdescsize) {
+ sprintf(indevlist, "NONE");
+ sprintf(outdevlist, "NONE");
+ *nindevs = *noutdevs = 1;
+ *canmulti = 0;
+}
+
+void dummy_listdevs() {
+ // do nothing
+}
+
+#endif
+
diff --git a/pd/src/s_audio_esd.c b/pd/src/s_audio_esd.c
new file mode 100644
index 00000000..eb08815d
--- /dev/null
+++ b/pd/src/s_audio_esd.c
@@ -0,0 +1,135 @@
+/* Copyright (c) 2006 Guenter Geiger,
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#ifdef USEAPI_ESD
+
+#include <stdio.h>
+#include <string.h> /* memset */
+#include <esd.h>
+#include "m_pd.h"
+#include "s_stuff.h"
+#include "m_fixed.h"
+
+/* exported variables */
+
+float sys_dacsr;
+
+
+/* private data */
+
+static int esd_socket_out;
+static int esd_channels_out;
+
+static int esd_socket_in;
+static int esd_channels_in;
+
+
+int esd_open_audio(int nindev, int *indev, int nchin, int *chin,
+ int noutdev, int *outdev, int nchout, int *chout, int rate)
+{
+
+ esd_format_t format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_PLAY;
+
+ indev[0] = 0;
+ nindev = 1;
+
+ outdev[0] = 0;
+ noutdev = 1;
+
+ rate = sys_dacsr = ESD_DEFAULT_RATE;
+
+ if (*chout == 2) {
+ esd_socket_out = esd_play_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd");
+ if (esd_socket_out <= 0) {
+ fprintf (stderr, "Error at esd open: %d\n", esd_socket_out);
+ esd_channels_out = *chout = 0;
+ return 0;
+ }
+ esd_channels_out = *chout = 2;
+ }
+
+ if (*chin == 2) {
+ esd_socket_in = esd_record_stream_fallback(format, ESD_DEFAULT_RATE, NULL, "pd-in");
+ if (esd_socket_in <= 0) {
+ fprintf (stderr, "Error at esd open: %d\n", esd_socket_in);
+ esd_channels_in = *chin = 0;
+ return 0;
+ }
+ esd_channels_in = *chin = 2;
+ }
+ return (0);
+}
+
+void esd_close_audio( void)
+{
+ close(esd_socket_out);
+ close(esd_socket_in);
+}
+
+
+#define DEFDACBLKSIZE 64
+#define MAXCHANS 2
+
+static short buf[DEFDACBLKSIZE*MAXCHANS];
+
+int esd_send_dacs(void)
+{
+ t_sample* fp1,*fp2;
+ short* sp;
+ int i,j;
+
+ /* Do input */
+
+ if (esd_channels_in) {
+ read(esd_socket_in,buf,DEFDACBLKSIZE*esd_channels_out*2);
+ for (i = DEFDACBLKSIZE, fp1 = sys_soundin,
+ sp = (short *)buf; i--; fp1++, sp += esd_channels_in) {
+ for (j=0, fp2 = fp1; j<esd_channels_in; j++, fp2 += DEFDACBLKSIZE)
+ {
+ int s = INVSCALE16(sp[j]);
+ *fp2 = s;
+ }
+ }
+ }
+
+ /* Do output */
+
+ if (esd_channels_out) {
+ for (i = DEFDACBLKSIZE, fp1 = sys_soundout,
+ sp = (short *)buf; i--; fp1++, sp += esd_channels_out) {
+ for (j=0, fp2 = fp1; j<esd_channels_out; j++, fp2 += DEFDACBLKSIZE)
+ {
+ int s = SCALE16(*fp2);
+ if (s > 32767) s = 32767;
+ else if (s < -32767) s = -32767;
+ sp[j] = s;
+ }
+ }
+
+ write(esd_socket_out,buf,DEFDACBLKSIZE*esd_channels_out*2);
+ }
+
+ memset(sys_soundin,0,DEFDACBLKSIZE*esd_channels_out*2);
+ memset(sys_soundout,0,DEFDACBLKSIZE*esd_channels_out*4);
+
+ return (SENDDACS_YES);
+}
+
+void esd_listdevs( void)
+{
+ post("device listing not implemented for ESD yet\n");
+}
+
+void esd_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize)
+{
+ int i, ndev;
+ *canmulti = 1; /* supports multiple devices */
+ sprintf(indevlist, "ESD device");
+ sprintf(outdevlist, "ESD device");
+ *nindevs = *noutdevs = 1;
+}
+
+#endif
diff --git a/pd/src/s_audio_jack.c b/pd/src/s_audio_jack.c
index 990a7a8c..79d4692e 100644
--- a/pd/src/s_audio_jack.c
+++ b/pd/src/s_audio_jack.c
@@ -11,25 +11,24 @@
#include <jack/jack.h>
#include <regex.h>
-
#define MAX_CLIENTS 100
-#define NUM_JACK_PORTS 128 /* seems like higher values give bad xrun problems */
+#define MAX_JACK_PORTS 128 /* seems like higher values give bad xrun problems */
#define BUF_JACK 4096
static jack_nframes_t jack_out_max;
#define JACK_OUT_MAX 64
static jack_nframes_t jack_filled = 0;
-static t_sample jack_outbuf[NUM_JACK_PORTS*BUF_JACK];
-static t_sample jack_inbuf[NUM_JACK_PORTS*BUF_JACK];
+static t_sample *jack_outbuf;
+static t_sample *jack_inbuf;
static int jack_started = 0;
-static jack_port_t *input_port[NUM_JACK_PORTS];
-static jack_port_t *output_port[NUM_JACK_PORTS];
+static jack_port_t *input_port[MAX_JACK_PORTS];
+static jack_port_t *output_port[MAX_JACK_PORTS];
static int outport_count = 0;
static jack_client_t *jack_client = NULL;
char *jack_client_names[MAX_CLIENTS];
static int jack_dio_error;
-
+static t_audiocallback jack_callback;
pthread_mutex_t jack_mutex;
pthread_cond_t jack_sem;
@@ -38,56 +37,114 @@ pthread_cond_t jack_sem;
static int
process (jack_nframes_t nframes, void *arg)
{
- int j;
- jack_default_audio_sample_t *out, *in;
-
- if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
- else jack_out_max = JACK_OUT_MAX;
- if (jack_filled >= nframes) {
- if (jack_filled != nframes) fprintf(stderr,"Partial read");
- /* hmm, how to find out whether 't_sample' and 'jack_default_audio_sample_t' are actually the same type??? */
- if(sizeof(t_sample)==sizeof(jack_default_audio_sample_t))
+ int j;
+ jack_default_audio_sample_t *out, *in;
+
+ pthread_mutex_lock(&jack_mutex);
+ if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
+ else jack_out_max = JACK_OUT_MAX;
+ if (jack_filled >= nframes)
+ {
+ if (jack_filled != nframes)
+ fprintf(stderr,"Partial read\n");
+ /* hmm, how to find out whether 't_sample' and
+ 'jack_default_audio_sample_t' are actually the same type??? */
+ if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t))
+ {
+ for (j = 0; j < sys_outchannels; j++)
+ {
+ out = jack_port_get_buffer (output_port[j], nframes);
+ memcpy(out, jack_outbuf + (j * BUF_JACK),
+ sizeof (jack_default_audio_sample_t) * nframes);
+ }
+ for (j = 0; j < sys_inchannels; j++)
+ {
+ in = jack_port_get_buffer( input_port[j], nframes);
+ memcpy(jack_inbuf + (j * BUF_JACK), in,
+ sizeof (jack_default_audio_sample_t) * nframes);
+ }
+ }
+ else
+ {
+ unsigned int frame=0;
+ t_sample*data;
+ for (j = 0; j < sys_outchannels; j++)
+ {
+ out = jack_port_get_buffer (output_port[j], nframes);
+ data = jack_outbuf + (j * BUF_JACK);
+ for(frame=0; frame<nframes; frame++)
{
- for (j = 0; j < sys_outchannels; j++) {
- out = jack_port_get_buffer (output_port[j], nframes);
- memcpy(out, jack_outbuf + (j * BUF_JACK), sizeof (jack_default_audio_sample_t) * nframes);
- }
- for (j = 0; j < sys_inchannels; j++) {
- in = jack_port_get_buffer( input_port[j], nframes);
- memcpy(jack_inbuf + (j * BUF_JACK), in, sizeof (jack_default_audio_sample_t) * nframes);
- }
- }
- else
+ *out++=*data++;
+ }
+ }
+ for (j = 0; j < sys_inchannels; j++)
+ {
+ in = jack_port_get_buffer( input_port[j], nframes);
+ data = jack_inbuf + (j * BUF_JACK);
+ for(frame=0; frame<nframes; frame++)
{
- unsigned int frame=0;
- t_sample*data;
- for (j = 0; j < sys_outchannels; j++) {
- out = jack_port_get_buffer (output_port[j], nframes);
- data=jack_outbuf + (j * BUF_JACK);
- for(frame=0; frame<nframes; frame++) {
- *out++=*data++;
- }
- }
- for (j = 0; j < sys_inchannels; j++) {
- in = jack_port_get_buffer( input_port[j], nframes);
- data=jack_inbuf+(j*BUF_JACK);
- for(frame=0; frame<nframes; frame++) {
- *data++=*in++;
- }
- }
+ *data++=*in++;
}
- jack_filled -= nframes;
- } else { /* PD could not keep up ! */
- if (jack_started) jack_dio_error = 1;
- for (j = 0; j < outport_count; j++) {
- out = jack_port_get_buffer (output_port[j], nframes);
- memset(out, 0, sizeof (float) * nframes);
- }
- memset(jack_outbuf,0,sizeof(jack_outbuf));
- jack_filled = 0;
+ }
}
- pthread_cond_broadcast(&jack_sem);
- return 0;
+ jack_filled -= nframes;
+ }
+ else
+ { /* PD could not keep up ! */
+ if (jack_started) jack_dio_error = 1;
+ for (j = 0; j < outport_count; j++)
+ {
+ out = jack_port_get_buffer (output_port[j], nframes);
+ memset(out, 0, sizeof (float) * nframes);
+ memset(jack_outbuf + j * BUF_JACK, 0, BUF_JACK * sizeof(t_sample));
+ }
+ jack_filled = 0;
+ }
+ pthread_cond_broadcast(&jack_sem);
+ pthread_mutex_unlock(&jack_mutex);
+ return 0;
+}
+
+static int callbackprocess(jack_nframes_t nframes, void *arg)
+{
+ int chan, j, k;
+ unsigned int n;
+ jack_default_audio_sample_t *out[MAX_JACK_PORTS], *in[MAX_JACK_PORTS], *jp;
+
+ if (nframes % DEFDACBLKSIZE)
+ {
+ fprintf(stderr, "jack: nframes %d not a multiple of blocksize %d\n",
+ nframes, DEFDACBLKSIZE);
+ nframes -= (nframes % DEFDACBLKSIZE);
+ }
+ for (chan = 0; chan < sys_inchannels; chan++)
+ in[chan] = jack_port_get_buffer(input_port[chan], nframes);
+ for (chan = 0; chan < sys_outchannels; chan++)
+ out[chan] = jack_port_get_buffer(output_port[chan], nframes);
+ for (n = 0; n < nframes; n += DEFDACBLKSIZE)
+ {
+ t_sample *fp;
+ for (chan = 0; chan < sys_inchannels; chan++)
+ {
+ for (fp = sys_soundin + chan*DEFDACBLKSIZE,
+ jp = in[chan] + n, j=0; j < DEFDACBLKSIZE; j++)
+ *fp++ = *jp++;
+ }
+ for (chan = 0; chan < sys_outchannels; chan++)
+ {
+ for (fp = sys_soundout + chan*DEFDACBLKSIZE,
+ j = 0; j < DEFDACBLKSIZE; j++)
+ *fp++ = 0;
+ }
+ (*jack_callback)();
+ for (chan = 0; chan < sys_outchannels; chan++)
+ {
+ for (fp = sys_soundout + chan*DEFDACBLKSIZE, jp = out[chan] + n,
+ j=0; j < DEFDACBLKSIZE; j++)
+ *jp++ = *fp++;
+ }
+ }
+ return 0;
}
static int
@@ -97,11 +154,19 @@ jack_srate (jack_nframes_t srate, void *arg)
return 0;
}
+
+void glob_audio_setapi(void *dummy, t_floatarg f);
+
static void
jack_shutdown (void *arg)
{
- /* Ignore for now */
- // exit (1);
+ error("JACK: server shut down");
+
+ jack_deactivate (jack_client);
+ //jack_client_close(jack_client); /* likely to hang if the server shut down */
+ jack_client = NULL;
+
+ glob_audio_setapi(NULL, API_NONE); // set pd_whichapi 0
}
static int jack_xrun(void* arg) {
@@ -128,6 +193,9 @@ static char** jack_get_clients(void)
regmatch_t match_info;
char tmp_client_name[100];
+ if(num_clients>=MAX_CLIENTS)break;
+
+
/* extract the client name from the port name, using a regex
* that parses the clientname:portname syntax */
regexec( &port_regex, jack_ports[i], 1, &match_info, 0 );
@@ -166,7 +234,6 @@ static char** jack_get_clients(void)
strcpy( jack_client_names[ num_clients ], tmp_client_name );
}
num_clients++;
-
}
}
@@ -196,7 +263,7 @@ static int jack_connect_ports(char* client)
if (jack_ports)
for (i=0;jack_ports[i] != NULL && i < sys_inchannels;i++)
if (jack_connect (jack_client, jack_ports[i], jack_port_name (input_port[i])))
- fprintf (stderr, "cannot connect input ports %s -> %s\n", jack_ports[i],jack_port_name (input_port[i]));
+ error ("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i]));
@@ -205,7 +272,7 @@ static int jack_connect_ports(char* client)
if (jack_ports)
for (i=0;jack_ports[i] != NULL && i < sys_outchannels;i++)
if (jack_connect (jack_client, jack_port_name (output_port[i]), jack_ports[i]))
- fprintf (stderr, "cannot connect output ports %s -> %s\n", jack_port_name (output_port[i]),jack_ports[i]);
+ error( "JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]);
@@ -214,172 +281,244 @@ static int jack_connect_ports(char* client)
}
-void pd_jack_error_callback(const char *desc) {
+static void pd_jack_error_callback(const char *desc) {
+ error("JACKerror: %s", desc);
return;
}
-
int
-jack_open_audio(int inchans, int outchans, int rate)
-
+jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback)
{
- int j;
- char port_name[80] = "";
- int client_iterator = 0;
- int new_jack = 0;
- int srate;
+ int j;
+ char port_name[80] = "";
+ char client_name[80] = "";
- jack_dio_error = 0;
-
- if ((inchans == 0) && (outchans == 0)) return 0;
+ int client_iterator = 0;
+ int new_jack = 0;
+ int srate;
+ jack_status_t status;
- if (outchans > NUM_JACK_PORTS) {
- fprintf(stderr,"%d output ports not supported, setting to %d\n",outchans, NUM_JACK_PORTS);
- outchans = NUM_JACK_PORTS;
- }
+ if (NULL==jack_client_new)
+ {
+ fprintf(stderr,"JACK framework not available\n");
+ return 1;
+ }
+
+ jack_dio_error = 0;
+
+ if ((inchans == 0) && (outchans == 0)) return 0;
- if (inchans > NUM_JACK_PORTS) {
- fprintf(stderr,"%d input ports not supported, setting to %d\n",inchans, NUM_JACK_PORTS);
- inchans = NUM_JACK_PORTS;
+ if (outchans > MAX_JACK_PORTS) {
+ error("JACK: %d output ports not supported, setting to %d",
+ outchans, MAX_JACK_PORTS);
+ outchans = MAX_JACK_PORTS;
+ }
+
+ if (inchans > MAX_JACK_PORTS) {
+ error("JACK: %d input ports not supported, setting to %d",
+ inchans, MAX_JACK_PORTS);
+ inchans = MAX_JACK_PORTS;
+ }
+ /* try to become a client of the JACK server */
+ /* if no JACK server exists, start a default one (jack_client_open() does that for us... */
+ if (!jack_client) {
+ do {
+ sprintf(client_name,"pure_data_%d",client_iterator);
+ client_iterator++;
+ jack_client = jack_client_open (client_name, JackNullOption, &status, NULL);
+ if (status & JackServerFailed) {
+ error("JACK: unable to connect to JACK server");
+ jack_client=NULL;
+ break;
+ }
+ } while (status & JackNameNotUnique);
+
+ if(status) {
+ if (status & JackServerStarted) {
+ verbose(1, "JACK: started server");
+ } else {
+ error("JACK: server returned status %d", status);
+ }
}
+ verbose(1, "JACK: started server as '%s'", client_name);
- /* try to become a client of the JACK server (we allow two pd's)*/
if (!jack_client) {
- do {
- sprintf(port_name,"pure_data_%d",client_iterator);
- client_iterator++;
- } while (((jack_client = jack_client_new (port_name)) == 0) && client_iterator < 2);
-
-
- if (!jack_client) { // jack spits out enough messages already, do not warn
+ /* jack spits out enough messages already, do not warn */
sys_inchannels = sys_outchannels = 0;
return 1;
- }
-
- jack_get_clients();
-
- /* tell the JACK server to call `process()' whenever
- there is work to be done.
- */
-
- jack_set_process_callback (jack_client, process, 0);
-
- jack_set_error_function (pd_jack_error_callback);
-
+ }
+
+ sys_inchannels = inchans;
+ sys_outchannels = outchans;
+ if (jack_inbuf)
+ free(jack_inbuf);
+ if (sys_inchannels)
+ jack_inbuf = calloc(sizeof(t_sample), sys_inchannels * BUF_JACK);
+ if (jack_outbuf)
+ free(jack_outbuf);
+ if (sys_outchannels)
+ jack_outbuf = calloc(sizeof(t_sample), sys_outchannels * BUF_JACK);
+
+ jack_get_clients();
+
+ /* tell the JACK server to call `process()' whenever
+ there is work to be done.
+ */
+ jack_callback = callback;
+ jack_set_process_callback (jack_client,
+ (callback? callbackprocess : process), 0);
+
+ jack_set_error_function (pd_jack_error_callback);
+
#ifdef JACK_XRUN
- jack_set_xrun_callback (jack_client, jack_xrun, NULL);
+ jack_set_xrun_callback (jack_client, jack_xrun, NULL);
#endif
-
- /* tell the JACK server to call `srate()' whenever
- the sample rate of the system changes.
- */
-
- jack_set_sample_rate_callback (jack_client, jack_srate, 0);
-
-
- /* tell the JACK server to call `jack_shutdown()' if
- it ever shuts down, either entirely, or if it
- just decides to stop calling us.
- */
-
- jack_on_shutdown (jack_client, jack_shutdown, 0);
-
- for (j=0;j<NUM_JACK_PORTS;j++) {
- input_port[j]=NULL;
- output_port[j] = NULL;
- }
-
- new_jack = 1;
- }
- /* display the current sample rate. once the client is activated
- (see below), you should rely on your own sample rate
- callback (see above) for this value.
+ /* tell the JACK server to call `srate()' whenever
+ the sample rate of the system changes.
*/
-
- srate = jack_get_sample_rate (jack_client);
- sys_dacsr = srate;
-
- /* create the ports */
-
- for (j = 0; j < inchans; j++) {
- sprintf(port_name, "input%d", j);
- if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+
+ jack_set_sample_rate_callback (jack_client, jack_srate, 0);
+
+
+ /* tell the JACK server to call `jack_shutdown()' if
+ it ever shuts down, either entirely, or if it
+ just decides to stop calling us.
+ */
+
+ jack_on_shutdown (jack_client, jack_shutdown, 0);
+
+ for (j=0; j<sys_inchannels; j++)
+ input_port[j]=NULL;
+ for (j=0; j<sys_outchannels; j++)
+ output_port[j] = NULL;
+
+ new_jack = 1;
+ }
+
+ /* display the current sample rate. once the client is activated
+ (see below), you should rely on your own sample rate
+ callback (see above) for this value.
+ */
+
+ srate = jack_get_sample_rate (jack_client);
+ sys_dacsr = srate;
+
+ /* create the ports */
+
+ for (j = 0; j < inchans; j++) {
+ sprintf(port_name, "input%d", j);
+ if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ if (!input_port[j]) {
+ error("JACK: can only register %d input ports (instead of requested %d)", j, inchans);
+ sys_inchannels = inchans = j;
+ break;
}
+ }
- for (j = 0; j < outchans; j++) {
- sprintf(port_name, "output%d", j);
- if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- }
- outport_count = outchans;
+ for (j = 0; j < outchans; j++) {
+ sprintf(port_name, "output%d", j);
+ if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ if (!output_port[j]) {
+ error("JACK: can only register %d output ports (instead of requested %d)", j, outchans);
+ sys_outchannels = outchans = j;
+ break;
+ }
+ }
+ outport_count = outchans;
- /* tell the JACK server that we are ready to roll */
-
- if (new_jack) {
- if (jack_activate (jack_client)) {
- fprintf (stderr, "cannot activate client\n");
+ /* tell the JACK server that we are ready to roll */
+
+ if (new_jack) {
+ if (jack_activate (jack_client)) {
+ error("cannot activate client");
sys_inchannels = sys_outchannels = 0;
return 1;
- }
-
- memset(jack_outbuf,0,sizeof(jack_outbuf));
-
- if (jack_client_names[0])
+ }
+
+ for (j = 0; j < outchans; j++)
+ memset(jack_outbuf + j * BUF_JACK, 0,
+ BUF_JACK * sizeof(t_sample));
+
+ if (jack_client_names[0])
jack_connect_ports(jack_client_names[0]);
- pthread_mutex_init(&jack_mutex,NULL);
- pthread_cond_init(&jack_sem,NULL);
- }
- return 0;
+ pthread_mutex_init(&jack_mutex, NULL);
+ pthread_cond_init(&jack_sem, NULL);
+ }
+ return 0;
}
void jack_close_audio(void)
-
{
- jack_started = 0;
+ if (jack_client){
+ jack_deactivate (jack_client);
+ jack_client_close(jack_client);
+ }
+
+ jack_client=NULL;
+ jack_started = 0;
+
+ pthread_cond_broadcast(&jack_sem);
+
+ pthread_cond_destroy(&jack_sem);
+ pthread_mutex_destroy(&jack_mutex);
+ if (jack_inbuf)
+ free(jack_inbuf), jack_inbuf = 0;
+ if (jack_outbuf)
+ free(jack_outbuf), jack_outbuf = 0;
+
}
int jack_send_dacs(void)
{
- t_sample * fp;
- int j;
- int rtnval = SENDDACS_YES;
- int timenow;
- int timeref = sys_getrealtime();
-
- if (!jack_client) return SENDDACS_NO;
-
- if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO);
-
- if (jack_dio_error) {
- sys_log_error(ERR_RESYNC);
- jack_dio_error = 0;
- }
- if (jack_filled >= jack_out_max)
- pthread_cond_wait(&jack_sem,&jack_mutex);
-
- jack_started = 1;
-
- fp = sys_soundout;
- for (j = 0; j < sys_outchannels; j++) {
- memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled,fp, DEFDACBLKSIZE*sizeof(t_sample));
- fp += DEFDACBLKSIZE;
- }
- fp = sys_soundin;
- for (j = 0; j < sys_inchannels; j++) {
- memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(t_sample));
- fp += DEFDACBLKSIZE;
- }
+ t_sample * fp;
+ int j;
+ int rtnval = SENDDACS_YES;
+ int timenow;
+ int timeref = sys_getrealtime();
+ if (!jack_client) return SENDDACS_NO;
+ if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO);
+ if (jack_dio_error)
+ {
+ sys_log_error(ERR_RESYNC);
+ jack_dio_error = 0;
+ }
+ pthread_mutex_lock(&jack_mutex);
+ if (jack_filled >= jack_out_max)
+ pthread_cond_wait(&jack_sem,&jack_mutex);
- if ((timenow = sys_getrealtime()) - timeref > 0.002)
- {
- rtnval = SENDDACS_SLEPT;
- }
+ if (!jack_client)
+ {
+ pthread_mutex_unlock(&jack_mutex);
+ return SENDDACS_NO;
+ }
+ jack_started = 1;
- memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
- jack_filled += DEFDACBLKSIZE;
- return rtnval;
+ fp = sys_soundout;
+ for (j = 0; j < sys_outchannels; j++)
+ {
+ memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp,
+ DEFDACBLKSIZE*sizeof(t_sample));
+ fp += DEFDACBLKSIZE;
+ }
+ fp = sys_soundin;
+ for (j = 0; j < sys_inchannels; j++)
+ {
+ memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled,
+ DEFDACBLKSIZE*sizeof(t_sample));
+ fp += DEFDACBLKSIZE;
+ }
+ jack_filled += DEFDACBLKSIZE;
+ pthread_mutex_unlock(&jack_mutex);
+
+ if ((timenow = sys_getrealtime()) - timeref > 0.002)
+ {
+ rtnval = SENDDACS_SLEPT;
+ }
+ memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
+ return rtnval;
}
void jack_getdevs(char *indevlist, int *nindevs,
diff --git a/pd/src/s_audio_mmio.c b/pd/src/s_audio_mmio.c
index fd17a1ce..0324c941 100644
--- a/pd/src/s_audio_mmio.c
+++ b/pd/src/s_audio_mmio.c
@@ -696,11 +696,11 @@ idle:
int mmio_open_audio(int naudioindev, int *audioindev,
int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
- int nchoutdev, int *choutdev, int rate)
+ int nchoutdev, int *choutdev, int rate, int blocksize)
{
int nbuf;
- nt_realdacblksize = (sys_blocksize ? sys_blocksize : DEFREALDACBLKSIZE);
+ nt_realdacblksize = (blocksize ? blocksize : DEFREALDACBLKSIZE);
nbuf = sys_advance_samples/nt_realdacblksize;
if (nbuf >= MAXBUFFER)
{
diff --git a/pd/src/s_audio_oss.c b/pd/src/s_audio_oss.c
index 73f916ce..10329fed 100644
--- a/pd/src/s_audio_oss.c
+++ b/pd/src/s_audio_oss.c
@@ -5,7 +5,11 @@
/* this file inputs and outputs audio using the OSS API available on linux. */
-#include <linux/soundcard.h>
+#if defined(__FreeBSD_kernel__)
+# include <sys/soundcard.h>
+#else
+# include <linux/soundcard.h>
+#endif
#include "m_pd.h"
#include "s_stuff.h"
@@ -45,7 +49,7 @@ static int linux_meters; /* true if we're metering */
static t_sample linux_inmax; /* max input amplitude */
static t_sample linux_outmax; /* max output amplitude */
static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
-
+extern int audio_blocksize; /* stolen from s_audio.c */
/* our device handles */
typedef struct _oss_dev
@@ -121,7 +125,8 @@ int oss_reset(int fd) {
return err;
}
-void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
+void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize,
+ int suggestedblocksize)
{
int orig, param, nblk, fd = dev->d_fd, wantformat;
int nchannels = dev->d_nchannels;
@@ -153,7 +158,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
{
int fragbytes, logfragsize, nfragment;
/* setting fragment count and size. */
- linux_fragsize = sys_blocksize;
+ linux_fragsize = suggestedblocksize;
if (!linux_fragsize)
{
linux_fragsize = OSS_DEFFRAGSIZE;
@@ -256,7 +261,8 @@ whynot:
#define O_AUDIOFLAG O_NDELAY
int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
- int noutdev, int *outdev, int nchout, int *chout, int rate)
+ int noutdev, int *outdev, int nchout, int *chout, int rate,
+ int blocksize)
{
int capabilities = 0;
int inchannels = 0, outchannels = 0;
@@ -358,7 +364,7 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
{
linux_dacs[linux_noutdevs].d_nchannels = gotchans;
linux_dacs[linux_noutdevs].d_fd = fd;
- oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
+ oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize);
linux_noutdevs++;
outchannels += gotchans;
@@ -433,7 +439,8 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
linux_adcs[linux_nindevs].d_nchannels = gotchans;
- oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
+ oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened,
+ blocksize);
inchannels += gotchans;
linux_nindevs++;
diff --git a/pd/src/s_audio_pa.c b/pd/src/s_audio_pa.c
index de5fe711..3f9ca51c 100644
--- a/pd/src/s_audio_pa.c
+++ b/pd/src/s_audio_pa.c
@@ -6,18 +6,29 @@
the main way in for Mac OS and, with Michael Casey's help, also into
ASIO in Windows. */
+/* dolist...
+ put in a real FIFO (compare to Zmoelnig and keep FIFO if OK)
+ switch to usleep in s_inter.c
+ try blocking and nonblocking calls here
+ for blocking, offer pthreads or usleep method
+ (see if pthreads is still inefficient with FIFO?)
+*/
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
#include <portaudio.h>
-#include "s_audio_pablio.h"
#ifdef MSW
#include <malloc.h>
+#include <windows.h>
#else
#include <alloca.h>
+#include <unistd.h>
#endif
+#include "s_audio_paring.h"
/* LATER try to figure out how to handle default devices in portaudio;
the way s_audio.c handles them isn't going to work here. */
@@ -25,16 +36,24 @@
/* public interface declared in m_imp.h */
/* implementation */
-static PABLIO_Stream *pa_stream;
+static PaStream *pa_stream;
static int pa_inchans, pa_outchans;
static float *pa_soundin, *pa_soundout;
static t_audiocallback pa_callback;
-int pa_foo;
+static float *pa_outbuf;
+static sys_ringbuf pa_outring;
+static float *pa_inbuf;
+static sys_ringbuf pa_inring;
+static int pa_started = 0;
+static int pa_dio_error;
+
+pthread_mutex_t pa_mutex;
+pthread_cond_t pa_sem;
+
+/* define this to enable thread signaling instead of polling */
+/* #define THREADSIGNAL */
-#ifndef MSW
-#include <unistd.h>
-#endif
static void pa_init(void)
{
static int initialized;
@@ -68,54 +87,117 @@ static void pa_init(void)
}
static int pa_lowlevel_callback(const void *inputBuffer,
- void *outputBuffer, unsigned long framesPerBuffer,
+ void *outputBuffer, unsigned long nframes,
const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
void *userData)
{
int i;
- unsigned int j;
+ unsigned int n, j;
float *fbuf, *fp2, *fp3, *soundiop;
- if (pa_foo)
- fprintf(stderr, "pa_lowlevel_callback\n");
- if (framesPerBuffer != DEFDACBLKSIZE)
+ if (nframes % DEFDACBLKSIZE)
{
- fprintf(stderr, "ignoring buffer size %d\n", (int)framesPerBuffer);
- return 0;
+ fprintf(stderr, "portaudio: nframes %ld not a multiple of blocksize %d\n",
+ nframes, (int)DEFDACBLKSIZE);
+ nframes -= (nframes % DEFDACBLKSIZE);
}
- if (inputBuffer != NULL)
+ for (n = 0; n < nframes; n += DEFDACBLKSIZE)
{
- fbuf = (float *)inputBuffer;
- soundiop = pa_soundin;
- for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
- for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans)
- *soundiop++ = *fp3;
+ if (inputBuffer != NULL)
+ {
+ fbuf = ((float *)inputBuffer) + n*pa_inchans;
+ soundiop = pa_soundin;
+ for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
+ for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
+ j++, fp3 += pa_inchans)
+ *soundiop++ = *fp3;
+ }
+ else memset((void *)pa_soundin, 0,
+ DEFDACBLKSIZE * pa_inchans * sizeof(float));
+ memset((void *)pa_soundout, 0,
+ DEFDACBLKSIZE * pa_outchans * sizeof(float));
+ (*pa_callback)();
+ if (outputBuffer != NULL)
+ {
+ fbuf = ((float *)outputBuffer) + n*pa_outchans;
+ soundiop = pa_soundout;
+ for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
+ for (j = 0, fp3 = fp2; j < DEFDACBLKSIZE;
+ j++, fp3 += pa_outchans)
+ *fp3 = *soundiop++;
+ }
}
- else memset((void *)pa_soundin, 0,
- framesPerBuffer * pa_inchans * sizeof(float));
- memset((void *)pa_soundout, 0,
- framesPerBuffer * pa_outchans * sizeof(float));
- (*pa_callback)();
- if (outputBuffer != NULL)
+ return 0;
+}
+
+ /* callback for "non-callback" case where we communicate with the
+ main thread via FIFO. Here we first read the sudio output FIFO (which
+ we sync on, not waiting for it but supplying zeros to the audio output if
+ there aren't enough samples in the FIFO when we are called), then write
+ to the audio input FIFO. The main thread will wait for the input fifo.
+ We can either throw it a pthreads condition or just allow the main thread
+ to poll for us; so far polling seems to work better. */
+static int pa_fifo_callback(const void *inputBuffer,
+ void *outputBuffer, unsigned long nframes,
+ const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
+ void *userData)
+{
+ /* callback routine for non-callback client... throw samples into
+ and read them out of a FIFO */
+ int ch;
+ long fiforoom;
+ float *fbuf;
+
+#if CHECKFIFOS
+ if (pa_inchans * sys_ringbuf_GetReadAvailable(&pa_outring) !=
+ pa_outchans * sys_ringbuf_GetWriteAvailable(&pa_inring))
+ fprintf(stderr, "warning: in and out rings unequal (%d, %d)\n",
+ sys_ringbuf_GetReadAvailable(&pa_outring),
+ sys_ringbuf_GetWriteAvailable(&pa_inring));
+#endif
+ fiforoom = sys_ringbuf_GetReadAvailable(&pa_outring);
+ if ((unsigned)fiforoom >= nframes*pa_outchans*sizeof(float))
{
- fbuf = (float *)outputBuffer;
- soundiop = pa_soundout;
- for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
- for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_outchans)
- *fp3 = *soundiop++;
+ if (outputBuffer)
+ sys_ringbuf_Read(&pa_outring, outputBuffer,
+ nframes*pa_outchans*sizeof(float));
+ else if (pa_outchans)
+ fprintf(stderr, "no outputBuffer but output channels\n");
+ if (inputBuffer)
+ sys_ringbuf_Write(&pa_inring, inputBuffer,
+ nframes*pa_inchans*sizeof(float));
+ else if (pa_inchans)
+ fprintf(stderr, "no inputBuffer but input channels\n");
}
- if (pa_foo)
- fprintf(stderr, "done pa_lowlevel_callback\n");
+ else
+ { /* PD could not keep up; generate zeros */
+ if (pa_started)
+ pa_dio_error = 1;
+ if (outputBuffer)
+ {
+ for (ch = 0; ch < pa_outchans; ch++)
+ {
+ unsigned long frame;
+ fbuf = ((float *)outputBuffer) + ch;
+ for (frame = 0; frame < nframes; frame++, fbuf += pa_outchans)
+ *fbuf = 0;
+ }
+ }
+ }
+#ifdef THREADSIGNAL
+ pthread_mutex_lock(&pa_mutex);
+ pthread_cond_signal(&pa_sem);
+ pthread_mutex_unlock(&pa_mutex);
+#endif
return 0;
}
PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
- int framesperbuf, int nbuffers, int indeviceno, int outdeviceno)
+ int framesperbuf, int nbuffers, int indeviceno, int outdeviceno, PaStreamCallback *callbackfn)
{
long bytesPerSample;
PaError err;
- PABLIO_Stream *pastream;
- long numFrames;
PaStreamParameters instreamparams, outstreamparams;
+ PaStreamParameters*p_instreamparams=0, *p_outstreamparams=0;
if (indeviceno < 0)
{
@@ -130,58 +212,84 @@ PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
/* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
nchannels, flags, nbuffers, framesperbuf); */
- /* Allocate PABLIO_Stream structure for caller. */
- pastream = (PABLIO_Stream *)malloc( sizeof(PABLIO_Stream));
- if (pastream == NULL)
- return (1);
- memset(pastream, 0, sizeof(PABLIO_Stream));
-
- /* Determine size of a sample. */
- bytesPerSample = Pa_GetSampleSize(paFloat32);
- if (bytesPerSample < 0)
- {
- err = (PaError) bytesPerSample;
- goto error;
- }
- pastream->insamplesPerFrame = inchannels;
- pastream->inbytesPerFrame = bytesPerSample * pastream->insamplesPerFrame;
- pastream->outsamplesPerFrame = outchannels;
- pastream->outbytesPerFrame = bytesPerSample * pastream->outsamplesPerFrame;
-
- numFrames = nbuffers * framesperbuf;
-
instreamparams.device = indeviceno;
instreamparams.channelCount = inchannels;
instreamparams.sampleFormat = paFloat32;
- instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
+ instreamparams.suggestedLatency = 0; /* was nbuffers*framesperbuf/sampleRate */
instreamparams.hostApiSpecificStreamInfo = 0;
outstreamparams.device = outdeviceno;
outstreamparams.channelCount = outchannels;
outstreamparams.sampleFormat = paFloat32;
- outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
+ outstreamparams.suggestedLatency = 0;
outstreamparams.hostApiSpecificStreamInfo = 0;
+ if(inchannels>0)
+ p_instreamparams=&instreamparams;
+ if(outchannels>0)
+ p_outstreamparams=&outstreamparams;
+
+ err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams, sampleRate);
+
+ if (paFormatIsSupported != err)
+ {
+ /* check whether we have to change the numbers of channel and/or samplerate */
+ const PaDeviceInfo* info = 0;
+ double inRate=0, outRate=0;
+
+ if (inchannels>0)
+ {
+ if (NULL != (info = Pa_GetDeviceInfo( instreamparams.device )))
+ {
+ inRate=info->defaultSampleRate;
+
+ if(info->maxInputChannels<inchannels)
+ instreamparams.channelCount=info->maxInputChannels;
+ }
+ }
+
+ if (outchannels>0)
+ {
+ if (NULL != (info = Pa_GetDeviceInfo( outstreamparams.device )))
+ {
+ outRate=info->defaultSampleRate;
+
+ if(info->maxOutputChannels<outchannels)
+ outstreamparams.channelCount=info->maxOutputChannels;
+ }
+ }
+
+ if (err == paInvalidSampleRate)
+ {
+ sampleRate=outRate;
+ }
+
+ err=Pa_IsFormatSupported(p_instreamparams, p_outstreamparams,
+ sampleRate);
+ if (paFormatIsSupported != err)
+ goto error;
+ }
+
err = Pa_OpenStream(
- &pastream->stream,
- (inchannels ? &instreamparams : 0),
- (outchannels ? &outstreamparams : 0),
+ &pa_stream,
+ p_instreamparams,
+ p_outstreamparams,
sampleRate,
- DEFDACBLKSIZE,
+ framesperbuf,
paNoFlag, /* portaudio will clip for us */
- pa_lowlevel_callback,
- pastream);
+ callbackfn,
+ 0);
if (err != paNoError)
goto error;
- err = Pa_StartStream(pastream->stream);
+ err = Pa_StartStream(pa_stream);
if (err != paNoError)
{
fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
- CloseAudioStream( pastream );
+ pa_close_audio();
goto error;
}
- pa_stream = pastream;
+ sys_dacsr=sampleRate;
return paNoError;
error:
pa_stream = NULL;
@@ -200,6 +308,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
pa_init();
/* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
+ if (pa_stream)
+ pa_close_audio();
+
if (inchans > 0)
{
for (j = 0, devno = 0; j < Pa_GetDeviceCount(); j++)
@@ -209,6 +320,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
{
if (devno == indeviceno)
{
+ if (inchans > info->maxInputChannels)
+ inchans = info->maxInputChannels;
+
pa_indev = j;
break;
}
@@ -226,6 +340,9 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
{
if (devno == outdeviceno)
{
+ if (outchans > info->maxOutputChannels)
+ outchans = info->maxOutputChannels;
+
pa_outdev = j;
break;
}
@@ -240,23 +357,42 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
post("output device %d, channels %d", pa_outdev, outchans);
post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
}
- pa_inchans = inchans;
- pa_outchans = outchans;
+ pa_inchans = sys_inchannels = inchans;
+ pa_outchans = sys_outchannels = outchans;
pa_soundin = soundin;
pa_soundout = soundout;
+
+ if (pa_inbuf)
+ free(pa_inbuf), pa_inbuf = 0;
+ if (pa_outbuf)
+ free(pa_outbuf), pa_outbuf = 0;
+
if (! inchans && !outchans)
- return(0);
+ return (0);
+
if (callbackfn)
{
pa_callback = callbackfn;
err = pa_open_callback(rate, inchans, outchans,
- framesperbuf, nbuffers, pa_indev, pa_outdev);
+ framesperbuf, nbuffers, pa_indev, pa_outdev, pa_lowlevel_callback);
}
else
{
- err = OpenAudioStream( &pa_stream, rate, paFloat32,
- inchans, outchans, framesperbuf, nbuffers,
- pa_indev, pa_outdev);
+ if (pa_inchans)
+ {
+ pa_inbuf = malloc(nbuffers*framesperbuf*pa_inchans*sizeof(float));
+ sys_ringbuf_Init(&pa_inring,
+ nbuffers*framesperbuf*pa_inchans*sizeof(float), pa_inbuf,
+ nbuffers*framesperbuf*pa_inchans*sizeof(float));
+ }
+ if (pa_outchans)
+ {
+ pa_outbuf = malloc(nbuffers*framesperbuf*pa_outchans*sizeof(float));
+ sys_ringbuf_Init(&pa_outring,
+ nbuffers*framesperbuf*pa_outchans*sizeof(float), pa_outbuf, 0);
+ }
+ err = pa_open_callback(rate, inchans, outchans,
+ framesperbuf, nbuffers, pa_indev, pa_outdev, pa_fifo_callback);
}
if ( err != paNoError )
{
@@ -273,95 +409,117 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
void pa_close_audio( void)
{
- /* fprintf(stderr, "close\n"); */
- if (pa_inchans || pa_outchans)
- CloseAudioStream( pa_stream );
- pa_inchans = pa_outchans = 0;
+ if (pa_stream)
+ {
+ Pa_AbortStream(pa_stream);
+ Pa_CloseStream(pa_stream);
+ }
+ pa_stream = 0;
+ if (pa_inbuf)
+ free(pa_inbuf), pa_inbuf = 0;
+ if (pa_outbuf)
+ free(pa_outbuf), pa_outbuf = 0;
+
}
int pa_send_dacs(void)
{
- unsigned int framesize = (sizeof(float) * DEFDACBLKSIZE) *
- (pa_inchans > pa_outchans ? pa_inchans:pa_outchans);
- float *samples, *fp1, *fp2;
- int i, j;
- double timebefore;
-
-
- samples = alloca(framesize);
-
- timebefore = sys_getrealtime();
- if ((pa_inchans && GetAudioStreamReadable(pa_stream) < DEFDACBLKSIZE) ||
- (pa_outchans && GetAudioStreamWriteable(pa_stream) < DEFDACBLKSIZE))
+ t_sample *fp;
+ float *fp2, *fp3;
+ float *conversionbuf;
+ int j, k;
+ int rtnval = SENDDACS_YES;
+ int timenow;
+ int timeref = sys_getrealtime();
+ if (!sys_inchannels && !sys_outchannels)
+ return (SENDDACS_NO);
+#if CHECKFIFOS
+ if (sys_outchannels * sys_ringbuf_GetReadAvailable(&pa_inring) !=
+ sys_inchannels * sys_ringbuf_GetWriteAvailable(&pa_outring))
+ fprintf(stderr, "warning (2): in and out rings unequal (%d, %d)\n",
+ sys_ringbuf_GetReadAvailable(&pa_inring),
+ sys_ringbuf_GetWriteAvailable(&pa_outring));
+#endif
+ conversionbuf = (float *)alloca((sys_inchannels > sys_outchannels?
+ sys_inchannels:sys_outchannels) * DEFDACBLKSIZE * sizeof(float));
+ if (pa_dio_error)
{
- if (pa_inchans && pa_outchans)
- {
- int synced = 0;
- while (GetAudioStreamWriteable(pa_stream) > 2*DEFDACBLKSIZE)
- {
- for (j = 0; j < pa_outchans; j++)
- for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
- fp2 += pa_outchans)
- {
- *fp2 = 0;
- }
- synced = 1;
- WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
- }
- while (GetAudioStreamReadable(pa_stream) > 2*DEFDACBLKSIZE)
- {
- synced = 1;
- ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
- }
- /* if (synced)
- post("sync"); */
- }
- return (SENDDACS_NO);
+ sys_log_error(ERR_RESYNC);
+ pa_dio_error = 0;
}
- if (pa_inchans)
+
+ if (!sys_inchannels) /* if no input channels sync on output */
{
- ReadAudioStream(pa_stream, samples, DEFDACBLKSIZE);
- for (j = 0, fp1 = pa_soundin; j < pa_inchans; j++, fp1 += DEFDACBLKSIZE)
- for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
- fp2 += pa_inchans)
- {
- fp1[i] = *fp2;
- }
+#ifdef THREADSIGNAL
+ pthread_mutex_lock(&pa_mutex);
+#endif
+ while (sys_ringbuf_GetWriteAvailable(&pa_outring) <
+ (long)(sys_outchannels * DEFDACBLKSIZE * sizeof(float)))
+#ifdef THREADSIGNAL
+ pthread_cond_wait(&pa_sem, &pa_mutex);
+#else
+#ifdef MSW
+ Sleep(1);
+#else
+ usleep(1000);
+#endif /* MSW */
+#endif /* THREADSIGNAL */
+#ifdef THREADSIGNAL
+ pthread_mutex_unlock(&pa_mutex);
+#endif
}
-#if 0
- {
- static int nread;
- if (nread == 0)
- {
- post("it's %f %f %f %f",
- pa_soundin[0], pa_soundin[1], pa_soundin[2], pa_soundin[3]);
- nread = 1000;
- }
- nread--;
- }
+ /* write output */
+ if (sys_outchannels)
+ {
+ for (j = 0, fp = sys_soundout, fp2 = conversionbuf;
+ j < sys_outchannels; j++, fp2++)
+ for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+ k++, fp++, fp3 += sys_outchannels)
+ *fp3 = *fp;
+ sys_ringbuf_Write(&pa_outring, conversionbuf,
+ sys_outchannels*(DEFDACBLKSIZE*sizeof(float)));
+ }
+ if (sys_inchannels) /* if there is input sync on it */
+ {
+#ifdef THREADSIGNAL
+ pthread_mutex_lock(&pa_mutex);
#endif
- if (pa_outchans)
+ while (sys_ringbuf_GetReadAvailable(&pa_inring) <
+ (long)(sys_inchannels * DEFDACBLKSIZE * sizeof(float)))
+#ifdef THREADSIGNAL
+ pthread_cond_wait(&pa_sem, &pa_mutex);
+#else
+#ifdef MSW
+ Sleep(1);
+#else
+ usleep(1000);
+#endif /* MSW */
+#endif /* THREADSIGNAL */
+#ifdef THREADSIGNAL
+ pthread_mutex_unlock(&pa_mutex);
+#endif
+ }
+ pa_started = 1;
+
+ if (sys_inchannels)
{
- for (j = 0, fp1 = pa_soundout; j < pa_outchans; j++,
- fp1 += DEFDACBLKSIZE)
- for (i = 0, fp2 = samples + j; i < DEFDACBLKSIZE; i++,
- fp2 += pa_outchans)
- {
- *fp2 = fp1[i];
- fp1[i] = 0;
- }
- WriteAudioStream(pa_stream, samples, DEFDACBLKSIZE);
+ sys_ringbuf_Read(&pa_inring, conversionbuf,
+ sys_inchannels*(DEFDACBLKSIZE*sizeof(float)));
+ for (j = 0, fp = sys_soundin, fp2 = conversionbuf;
+ j < sys_inchannels; j++, fp2++)
+ for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
+ k++, fp++, fp3 += sys_inchannels)
+ *fp = *fp3;
}
- if (sys_getrealtime() > timebefore + 0.002)
+ if ((timenow = sys_getrealtime()) - timeref > 0.002)
{
- /* post("slept"); */
- return (SENDDACS_SLEPT);
+ rtnval = SENDDACS_SLEPT;
}
- else return (SENDDACS_YES);
+ memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
+ return rtnval;
}
-
void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
{
int i,j;
diff --git a/pd/src/s_audio_pablio.c b/pd/src/s_audio_pablio.c
deleted file mode 100644
index 0873f269..00000000
--- a/pd/src/s_audio_pablio.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
-
- * pablio.c
- * Portable Audio Blocking Input/Output utility.
- *
- * Author: Phil Burk, http://www.softsynth.com
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.audiomulch.com/portaudio/
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
- /* changes by Miller Puckette to support Pd: device selection,
- settable audio buffer size, and settable number of channels.
- LATER also fix it to poll for input and output fifo fill points. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "portaudio.h"
-#include "s_audio_paring.h"
-#include "s_audio_pablio.h" /* MSP */
-#include <string.h>
-
- /* MSP -- FRAMES_PER_BUFFER constant removed */
-static void NPa_Sleep(int n) /* MSP wrapper to check we never stall... */
-{
-#if 0
- fprintf(stderr, "sleep\n");
-#endif
- Pa_Sleep(n);
-}
-
-/************************************************************************/
-/******** Prototypes ****************************************************/
-/************************************************************************/
-
-static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /*MSP */
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo *outTime,
- PaStreamCallbackFlags myflags,
- void *userData );
-static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame );
-static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf );
-
-/************************************************************************/
-/******** Functions *****************************************************/
-/************************************************************************/
-
-/* Called from PortAudio.
- * Read and write data only if there is room in FIFOs.
- */
-static int blockingIOCallback( const void *inputBuffer, void *outputBuffer, /* MSP */
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo *outTime,
- PaStreamCallbackFlags myflags,
- void *userData )
-{
- PABLIO_Stream *data = (PABLIO_Stream*)userData;
- (void) outTime;
-
- /* This may get called with NULL inputBuffer during initial setup. */
- if( inputBuffer != NULL )
- {
- sys_ringbuf_Write( &data->inFIFO, inputBuffer,
- data->inbytesPerFrame * framesPerBuffer );
- }
- if( outputBuffer != NULL )
- {
- int i;
- int numBytes = data->outbytesPerFrame * framesPerBuffer;
- int numRead = sys_ringbuf_Read( &data->outFIFO, outputBuffer,
- numBytes);
- /* Zero out remainder of buffer if we run out of data. */
- for( i=numRead; i<numBytes; i++ )
- {
- ((char *)outputBuffer)[i] = 0;
- }
- }
-
- return 0;
-}
-
-/* Allocate buffer. */
-static PaError PABLIO_InitFIFO( sys_ringbuf *rbuf, long numFrames, long bytesPerFrame )
-{
- long numBytes = numFrames * bytesPerFrame;
- char *buffer = (char *) malloc( numBytes );
- if( buffer == NULL ) return paInsufficientMemory;
- memset( buffer, 0, numBytes );
- return (PaError) sys_ringbuf_Init( rbuf, numBytes, buffer );
-}
-
-/* Free buffer. */
-static PaError PABLIO_TermFIFO( sys_ringbuf *rbuf )
-{
- if( rbuf->buffer ) free( rbuf->buffer );
- rbuf->buffer = NULL;
- return paNoError;
-}
-
-/************************************************************
- * Write data to ring buffer.
- * Will not return until all the data has been written.
- */
-long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
-{
- long bytesWritten;
- char *p = (char *) data;
- long numBytes = aStream->outbytesPerFrame * numFrames;
- while( numBytes > 0)
- {
- bytesWritten = sys_ringbuf_Write( &aStream->outFIFO, p, numBytes );
- numBytes -= bytesWritten;
- p += bytesWritten;
- if( numBytes > 0) NPa_Sleep(10); /* MSP */
- }
- return numFrames;
-}
-
-/************************************************************
- * Read data from ring buffer.
- * Will not return until all the data has been read.
- */
-long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames )
-{
- long bytesRead;
- char *p = (char *) data;
- long numBytes = aStream->inbytesPerFrame * numFrames;
- while( numBytes > 0)
- {
- bytesRead = sys_ringbuf_Read( &aStream->inFIFO, p, numBytes );
- numBytes -= bytesRead;
- p += bytesRead;
- if( numBytes > 0) NPa_Sleep(10); /* MSP */
- }
- return numFrames;
-}
-
-/************************************************************
- * Return the number of frames that could be written to the stream without
- * having to wait.
- */
-long GetAudioStreamWriteable( PABLIO_Stream *aStream )
-{
- int bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- return bytesEmpty / aStream->outbytesPerFrame;
-}
-
-/************************************************************
- * Return the number of frames that are available to be read from the
- * stream without having to wait.
- */
-long GetAudioStreamReadable( PABLIO_Stream *aStream )
-{
- int bytesFull = sys_ringbuf_GetReadAvailable( &aStream->inFIFO );
- return bytesFull / aStream->inbytesPerFrame;
-}
-
-/************************************************************/
-static unsigned long RoundUpToNextPowerOf2( unsigned long n )
-{
- long numBits = 0;
- if( ((n-1) & n) == 0) return n; /* Already Power of two. */
- while( n > 0 )
- {
- n= n>>1;
- numBits++;
- }
- return (1<<numBits);
-}
-
-/************************************************************
- * Opens a PortAudio stream with default characteristics.
- * Allocates PABLIO_Stream structure.
- *
- * flags parameter can be an ORed combination of:
- * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE
- */
-PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate,
- PaSampleFormat format, int inchannels,
- int outchannels, int framesperbuf, int nbuffers,
- int indeviceno, int outdeviceno) /* MSP */
-{
- long bytesPerSample;
- long doRead = 0;
- long doWrite = 0;
- PaError err;
- PABLIO_Stream *aStream;
- long numFrames;
- PaStreamParameters instreamparams, outstreamparams; /* MSP */
-
- /* fprintf(stderr,
- "open %lf fmt %d flags %d ch: %d fperbuf: %d nbuf: %d devs: %d %d\n",
- sampleRate, format, flags, nchannels,
- framesperbuf, nbuffers, indeviceno, outdeviceno); */
-
- if (indeviceno < 0) /* MSP... */
- {
- indeviceno = Pa_GetDefaultInputDevice();
- fprintf(stderr, "using default input device number: %d\n", indeviceno);
- }
- if (outdeviceno < 0)
- {
- outdeviceno = Pa_GetDefaultOutputDevice();
- fprintf(stderr, "using default output device number: %d\n", outdeviceno);
- }
- /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
- nchannels, flags, nbuffers, framesperbuf); */
- /* ...MSP */
-
- /* Allocate PABLIO_Stream structure for caller. */
- aStream = (PABLIO_Stream *) malloc( sizeof(PABLIO_Stream) );
- if( aStream == NULL ) return paInsufficientMemory;
- memset( aStream, 0, sizeof(PABLIO_Stream) );
-
- /* Determine size of a sample. */
- bytesPerSample = Pa_GetSampleSize( format );
- if( bytesPerSample < 0 )
- {
- err = (PaError) bytesPerSample;
- goto error;
- }
- aStream->insamplesPerFrame = inchannels; /* MSP */
- aStream->inbytesPerFrame = bytesPerSample * aStream->insamplesPerFrame;
- aStream->outsamplesPerFrame = outchannels;
- aStream->outbytesPerFrame = bytesPerSample * aStream->outsamplesPerFrame;
-
- /* Initialize PortAudio */
- err = Pa_Initialize();
- if( err != paNoError ) goto error;
-
- numFrames = nbuffers * framesperbuf; /* ...MSP */
-
- instreamparams.device = indeviceno; /* MSP... */
- instreamparams.channelCount = inchannels;
- instreamparams.sampleFormat = format;
- instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
- instreamparams.hostApiSpecificStreamInfo = 0;
-
- outstreamparams.device = outdeviceno;
- outstreamparams.channelCount = outchannels;
- outstreamparams.sampleFormat = format;
- outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
- outstreamparams.hostApiSpecificStreamInfo = 0; /* ... MSP */
-
- numFrames = nbuffers * framesperbuf;
- /* fprintf(stderr, "numFrames %d\n", numFrames); */
- /* Initialize Ring Buffers */
- doRead = (inchannels != 0);
- doWrite = (outchannels != 0);
- if(doRead)
- {
- err = PABLIO_InitFIFO( &aStream->inFIFO, numFrames,
- aStream->inbytesPerFrame );
- if( err != paNoError ) goto error;
- }
- if(doWrite)
- {
- long numBytes;
- err = PABLIO_InitFIFO( &aStream->outFIFO, numFrames,
- aStream->outbytesPerFrame );
- if( err != paNoError ) goto error;
- /* Make Write FIFO appear full initially. */
- numBytes = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- sys_ringbuf_AdvanceWriteIndex( &aStream->outFIFO, numBytes );
- }
-
- /* Open a PortAudio stream that we will use to communicate with the underlying
- * audio drivers. */
- err = Pa_OpenStream(
- &aStream->stream,
- (doRead ? &instreamparams : 0), /* MSP */
- (doWrite ? &outstreamparams : 0), /* MSP */
- sampleRate,
- framesperbuf, /* MSP */
- paNoFlag, /* MSP -- portaudio will clip for us */
- blockingIOCallback,
- aStream );
- if( err != paNoError ) goto error;
-
- err = Pa_StartStream( aStream->stream );
- if( err != paNoError ) /* MSP */
- {
- fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
- CloseAudioStream( aStream );
- goto error;
- }
-
- *rwblPtr = aStream;
- return paNoError;
-
-error:
- *rwblPtr = NULL;
- return err;
-}
-
-/************************************************************/
-PaError CloseAudioStream( PABLIO_Stream *aStream )
-{
- PaError err;
- int bytesEmpty;
- int byteSize = aStream->outFIFO.bufferSize;
-
- /* If we are writing data, make sure we play everything written. */
- if( byteSize > 0 )
- {
- bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- while( bytesEmpty < byteSize )
- {
- NPa_Sleep( 10 ); /* MSP */
- bytesEmpty = sys_ringbuf_GetWriteAvailable( &aStream->outFIFO );
- }
- }
-
- err = Pa_StopStream( aStream->stream );
- if( err != paNoError ) goto error;
- err = Pa_CloseStream( aStream->stream );
- if( err != paNoError ) goto error;
- Pa_Terminate();
-
-error:
- PABLIO_TermFIFO( &aStream->inFIFO );
- PABLIO_TermFIFO( &aStream->outFIFO );
- free( aStream );
- return err;
-}
diff --git a/pd/src/s_audio_pablio.h b/pd/src/s_audio_pablio.h
deleted file mode 100644
index f4d32614..00000000
--- a/pd/src/s_audio_pablio.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef _PABLIO_H
-#define _PABLIO_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-/*
- * PABLIO.h
- * Portable Audio Blocking read/write utility.
- *
- * Author: Phil Burk, http://www.softsynth.com/portaudio/
- *
- * Include file for PABLIO, the Portable Audio Blocking I/O Library.
- * PABLIO is built on top of PortAudio, the Portable Audio Library.
- * For more information see: http://www.audiomulch.com/portaudio/
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include "portaudio.h"
-#include "s_audio_paring.h"
-#include <string.h>
-
-typedef struct
-{
- sys_ringbuf inFIFO;
- sys_ringbuf outFIFO;
- PaStream *stream;
- int inbytesPerFrame;
- int insamplesPerFrame;
- int outbytesPerFrame;
- int outsamplesPerFrame;
-}
-PABLIO_Stream;
-
-/* Values for flags for OpenAudioStream(). */
-#define PABLIO_READ (1<<0)
-#define PABLIO_WRITE (1<<1)
-#define PABLIO_READ_WRITE (PABLIO_READ|PABLIO_WRITE)
-#define PABLIO_MONO (1<<2)
-#define PABLIO_STEREO (1<<3)
-
-/************************************************************
- * Write data to ring buffer.
- * Will not return until all the data has been written.
- */
-long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames );
-
-/************************************************************
- * Read data from ring buffer.
- * Will not return until all the data has been read.
- */
-long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames );
-
-/************************************************************
- * Return the number of frames that could be written to the stream without
- * having to wait.
- */
-long GetAudioStreamWriteable( PABLIO_Stream *aStream );
-
-/************************************************************
- * Return the number of frames that are available to be read from the
- * stream without having to wait.
- */
-long GetAudioStreamReadable( PABLIO_Stream *aStream );
-
-/************************************************************
- * Opens a PortAudio stream with default characteristics.
- * Allocates PABLIO_Stream structure.
- *
- * flags parameter can be an ORed combination of:
- * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
- */
-PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate,
- PaSampleFormat format, int inchannels,
- int outchannels, int framesperbuf, int nbuffers,
- int indeviceno, int outdeviceno); /* MSP */
-
-PaError CloseAudioStream( PABLIO_Stream *aStream );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-#endif /* _PABLIO_H */
diff --git a/pd/src/s_audio_paring.c b/pd/src/s_audio_paring.c
index 6e645e45..af2771ff 100644
--- a/pd/src/s_audio_paring.c
+++ b/pd/src/s_audio_paring.c
@@ -46,11 +46,11 @@
/***************************************************************************
* Initialize FIFO.
*/
-long sys_ringbuf_Init( sys_ringbuf *rbuf, long numBytes, void *dataPtr )
+long sys_ringbuf_Init(sys_ringbuf *rbuf, long numBytes, void *dataPtr, long nfill)
{
rbuf->bufferSize = numBytes;
rbuf->buffer = (char *)dataPtr;
- sys_ringbuf_Flush( rbuf );
+ sys_ringbuf_Flush(rbuf, dataPtr, nfill);
return 0;
}
/***************************************************************************
@@ -74,9 +74,14 @@ long sys_ringbuf_GetWriteAvailable( sys_ringbuf *rbuf )
/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
-void sys_ringbuf_Flush( sys_ringbuf *rbuf )
+void sys_ringbuf_Flush(sys_ringbuf *rbuf, void *dataPtr, long nfill)
{
- rbuf->writeIndex = rbuf->readIndex = 0;
+ char *s;
+ long n;
+ rbuf->readIndex = 0;
+ rbuf->writeIndex = nfill;
+ for (n = nfill, s = dataPtr; n--; s++)
+ *s = 0;
}
/***************************************************************************
diff --git a/pd/src/s_audio_paring.h b/pd/src/s_audio_paring.h
index e5e5e6b2..8c417cd9 100644
--- a/pd/src/s_audio_paring.h
+++ b/pd/src/s_audio_paring.h
@@ -58,12 +58,11 @@ typedef struct
sys_ringbuf;
/*
* Initialize Ring Buffer.
- * numBytes must be power of 2, returns -1 if not.
*/
-long sys_ringbuf_Init( sys_ringbuf *rbuf, long numBytes, void *dataPtr );
+long sys_ringbuf_Init(sys_ringbuf *rbuf, long numBytes, void *dataPtr, long nfill);
/* Clear buffer. Should only be called when buffer is NOT being read. */
-void sys_ringbuf_Flush( sys_ringbuf *rbuf );
+void sys_ringbuf_Flush(sys_ringbuf *rbuf, void *dataPtr, long nfill);
/* Return number of bytes available for writing. */
long sys_ringbuf_GetWriteAvailable( sys_ringbuf *rbuf );
diff --git a/pd/src/s_file.c b/pd/src/s_file.c
index e5510011..c5a4f763 100644
--- a/pd/src/s_file.c
+++ b/pd/src/s_file.c
@@ -24,7 +24,7 @@
#include <fcntl.h>
#include <unistd.h>
#endif
-#ifdef MSW
+#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#endif
@@ -36,7 +36,7 @@ int sys_defeatrt;
t_symbol *sys_flags = &s_;
void sys_doflags( void);
-#ifdef UNIX
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD_kernel__) || defined(__GNU__) || defined(ANDROID)
static char *sys_prefbuf;
static int sys_prefbufsize;
@@ -159,9 +159,9 @@ static void sys_donesavepreferences( void)
}
}
-#endif /* UNIX */
+#endif /* __linux__ || __CYGWIN__ || __FreeBSD_kernel__ || __GNU__ */
-#ifdef MSW
+#ifdef _WIN32
static void sys_initloadpreferences( void)
{
@@ -203,12 +203,12 @@ static void sys_putpreference(const char *key, const char *value)
NULL, &hkey, NULL);
if (err != ERROR_SUCCESS)
{
- post("unable to create registry entry: %s\n", key);
+ error("unable to create registry entry: %s\n", key);
return;
}
- err = RegSetValueEx(hkey, key, 0, REG_SZ, value, strlen(value)+1);
+ err = RegSetValueEx(hkey, key, 0, REG_EXPAND_SZ, value, strlen(value)+1);
if (err != ERROR_SUCCESS)
- post("unable to set registry entry: %s\n", key);
+ error("unable to set registry entry: %s\n", key);
RegCloseKey(hkey);
}
@@ -216,7 +216,7 @@ static void sys_donesavepreferences( void)
{
}
-#endif /* MSW */
+#endif /* _WIN32 */
#ifdef __APPLE__
@@ -291,7 +291,8 @@ void sys_loadpreferences( void)
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
- int i, rate = 0, advance = 0, callback = 0, api, nolib, maxi;
+ int i, rate = 0, advance = -1, callback = 0, blocksize = 0,
+ api, nolib, maxi;
char prefbuf[MAXPDSTRING], keybuf[80];
sys_initloadpreferences();
@@ -342,9 +343,11 @@ void sys_loadpreferences( void)
sscanf(prefbuf, "%d", &advance);
if (sys_getpreference("callback", prefbuf, MAXPDSTRING))
sscanf(prefbuf, "%d", &callback);
+ if (sys_getpreference("blocksize", prefbuf, MAXPDSTRING))
+ sscanf(prefbuf, "%d", &blocksize);
sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev,
naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
- callback);
+ callback, blocksize);
/* load MIDI preferences */
/* JMZ/MB: brackets for initializing */
@@ -414,10 +417,10 @@ void sys_loadpreferences( void)
if (sys_defeatrt)
sys_hipriority = 0;
else
-#ifdef UNIX
- sys_hipriority = !geteuid();
+#if defined(__linux__) || defined(__CYGWIN__)
+ sys_hipriority = 1;
#else
-#ifdef MSW
+#if defined(_WIN32) || defined(ANDROID)
sys_hipriority = 0;
#else
sys_hipriority = 1;
@@ -429,7 +432,7 @@ void glob_savepreferences(t_pd *dummy)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int i, rate, advance, callback;
+ int i, rate, advance, callback, blocksize;
char buf1[MAXPDSTRING], buf2[MAXPDSTRING];
int nmidiindev, midiindev[MAXMIDIINDEV];
int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
@@ -442,7 +445,8 @@ void glob_savepreferences(t_pd *dummy)
sys_putpreference("audioapi", buf1);
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+ &blocksize);
sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False"));
for (i = 0; i < naudioindev; i++)
@@ -468,6 +472,9 @@ void glob_savepreferences(t_pd *dummy)
sprintf(buf1, "%d", callback);
sys_putpreference("callback", buf1);
+ sprintf(buf1, "%d", blocksize);
+ sys_putpreference("blocksize", buf1);
+
/* MIDI settings */
sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev);
sys_putpreference("nomidiin", (nmidiindev <= 0 ? "True" : "False"));
diff --git a/pd/src/s_inter.c b/pd/src/s_inter.c
index 1549f9de..6efa098c 100644
--- a/pd/src/s_inter.c
+++ b/pd/src/s_inter.c
@@ -9,7 +9,7 @@ that didn't really belong anywhere. */
#include "s_stuff.h"
#include "m_imp.h"
#include "g_canvas.h" /* for GUI queueing stuff */
-#ifndef MSW
+#ifndef _WIN32
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -59,15 +59,15 @@ typedef int socklen_t;
#define PDBINDIR "bin/"
#endif
-#ifndef PDTCLDIR
-#define PDTCLDIR "tcl/"
+#ifndef PDGUIDIR
+#define PDGUIDIR "tcl/"
#endif
#ifndef WISHAPP
#define WISHAPP "wish84.exe"
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#define LOCALHOST "127.0.0.1"
#else
#define LOCALHOST "localhost"
@@ -93,7 +93,6 @@ struct _socketreceiver
t_socketreceivefn sr_socketreceivefn;
};
-extern char *pd_version;
extern int sys_guisetportnumber;
static int sys_nfdpoll;
@@ -104,10 +103,13 @@ static int sys_guisock;
static t_binbuf *inbinbuf;
static t_socketreceiver *sys_socketreceiver;
extern int sys_addhist(int phase);
+void sys_set_searchpath(void);
+void sys_set_extrapath(void);
+void sys_set_startup(void);
/* ----------- functions for timing, signals, priorities, etc --------- */
-#ifdef MSW
+#ifdef _WIN32
static LARGE_INTEGER nt_inittime;
static double nt_freq = 0;
@@ -136,13 +138,13 @@ double nt_tixtotime(LARGE_INTEGER *dumbass)
return (((double)(dumbass->QuadPart - nt_inittime.QuadPart)) / nt_freq);
}
#endif
-#endif /* MSW */
+#endif /* _WIN32 */
/* get "real time" in seconds; take the
first time we get called as a reference time of zero. */
double sys_getrealtime(void)
{
-#ifndef MSW
+#ifndef _WIN32
static struct timeval then;
struct timeval now;
gettimeofday(&now, 0);
@@ -174,7 +176,7 @@ static int sys_domicrosleep(int microsec, int pollem)
FD_ZERO(&exceptset);
for (fp = sys_fdpoll, i = sys_nfdpoll; i--; fp++)
FD_SET(fp->fdp_fd, &readset);
-#ifdef MSW
+#ifdef _WIN32
if (sys_maxfd == 0)
Sleep(microsec/1000);
else
@@ -196,7 +198,7 @@ static int sys_domicrosleep(int microsec, int pollem)
}
else
{
-#ifdef MSW
+#ifdef _WIN32
if (sys_maxfd == 0)
Sleep(microsec/1000);
else
@@ -211,10 +213,8 @@ void sys_microsleep(int microsec)
sys_domicrosleep(microsec, 1);
}
-#ifdef HAVE_UNISTD_H
-typedef void (*sighandler_t)(int);
-
-static void sys_signal(int signo, sighandler_t sigfun)
+#if !defined(_WIN32) && !defined(__CYGWIN__)
+static void sys_signal(int signo, sig_t sigfun)
{
struct sigaction action;
action.sa_flags = 0;
@@ -270,9 +270,9 @@ void sys_setalarm(int microsec)
setitimer(ITIMER_REAL, &gonzo, 0);
}
-#endif
+#endif /* NOT _WIN32 && NOT __CYGWIN__ */
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#if defined(_POSIX_PRIORITY_SCHEDULING) || defined(_POSIX_MEMLOCK)
#include <sched.h>
@@ -346,7 +346,7 @@ void sys_set_priority(int higher)
void sys_sockerror(char *s)
{
-#ifdef MSW
+#ifdef _WIN32
int err = WSAGetLastError();
if (err == 10054) return;
else if (err == 10044)
@@ -562,7 +562,7 @@ void sys_closesocket(int fd)
#ifdef HAVE_UNISTD_H
close(fd);
#endif
-#ifdef MSW
+#ifdef _WIN32
closesocket(fd);
#endif
}
@@ -844,7 +844,7 @@ int sys_pollgui(void)
static int sys_watchfd;
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
void glob_watchdog(t_pd *dummy)
{
if (write(sys_watchfd, "\n", 1) < 1)
@@ -873,24 +873,25 @@ int sys_startgui(const char *libdir)
int len = sizeof(server);
int ntry = 0, portno = FIRSTPORTNUM;
int xsock = -1;
-#ifdef MSW
+#ifdef _WIN32
short version = MAKEWORD(2, 0);
WSADATA nobby;
-#endif
-#ifdef HAVE_UNISTD_H
+#else
int stdinpipe[2];
-#endif
+#endif /* _WIN32 */
/* create an empty FD poll list */
sys_fdpoll = (t_fdpoll *)t_getbytes(0);
sys_nfdpoll = 0;
inbinbuf = binbuf_new();
-#ifdef HAVE_UNISTD_H
+#if !defined(_WIN32) && !defined(__CYGWIN__)
signal(SIGHUP, sys_huphandler);
signal(SIGINT, sys_exithandler);
signal(SIGQUIT, sys_exithandler);
signal(SIGILL, sys_exithandler);
+# ifdef SIGIOT
signal(SIGIOT, sys_exithandler);
+# endif
signal(SIGFPE, SIG_IGN);
/* signal(SIGILL, sys_exithandler);
signal(SIGBUS, sys_exithandler);
@@ -900,10 +901,11 @@ int sys_startgui(const char *libdir)
#if 0 /* GG says: don't use that */
signal(SIGSTKFLT, sys_exithandler);
#endif
-#endif
-#ifdef MSW
+#endif /* NOT _WIN32 && NOT __CYGWIN__ */
+
+#ifdef _WIN32
if (WSAStartup(version, &nobby)) sys_sockerror("WSAstartup");
-#endif
+#endif /* _WIN32 */
if (sys_nogui)
{
@@ -911,11 +913,10 @@ int sys_startgui(const char *libdir)
skip starting the GUI up. */
t_atom zz[NDEFAULTFONT+2];
int i;
-#ifdef MSW
+#ifdef _WIN32
if (GetCurrentDirectory(MAXPDSTRING, cmdbuf) == 0)
strcpy(cmdbuf, ".");
-#endif
-#ifdef HAVE_UNISTD_H
+#else
if (!getcwd(cmdbuf, MAXPDSTRING))
strcpy(cmdbuf, ".");
@@ -961,12 +962,9 @@ int sys_startgui(const char *libdir)
}
else /* default behavior: start up the GUI ourselves. */
{
-#ifdef MSW
+#ifdef _WIN32
char scriptbuf[MAXPDSTRING+30], wishbuf[MAXPDSTRING+30], portbuf[80];
int spawnret;
-
-#endif
-#ifdef MSW
char intarg;
#else
int intarg;
@@ -988,7 +986,7 @@ int sys_startgui(const char *libdir)
intarg = 1;
if (setsockopt(xsock, IPPROTO_TCP, TCP_NODELAY,
&intarg, sizeof(intarg)) < 0)
-#ifndef MSW
+#ifndef _WIN32
post("setsockopt (TCP_NODELAY) failed\n")
#endif
;
@@ -1003,7 +1001,7 @@ int sys_startgui(const char *libdir)
/* name the socket */
while (bind(xsock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
-#ifdef MSW
+#ifdef _WIN32
int err = WSAGetLastError();
#else
int err = errno;
@@ -1024,7 +1022,7 @@ int sys_startgui(const char *libdir)
if (sys_verbose) fprintf(stderr, "port %d\n", portno);
-#ifdef HAVE_UNISTD_H
+#ifndef _WIN32
if (!sys_guicmd)
{
#ifdef __APPLE__
@@ -1063,14 +1061,13 @@ int sys_startgui(const char *libdir)
if (stat(wish_paths[i], &statbuf) >= 0)
break;
}
- sprintf(cmdbuf,"\"%s\" %s/tcl/pd-gui.tcl %d\n", wish_paths[i],
- libdir, portno);
-#else
+ sprintf(cmdbuf,"\"%s\" %d\n", wish_paths[i], portno);
+#else /* __APPLE__ */
sprintf(cmdbuf,
"TCL_LIBRARY=\"%s/lib/tcl/library\" TK_LIBRARY=\"%s/lib/tk/library\" \
- wish \"%s/tcl/pd-gui.tcl\" %d\n",
+ wish \"%s/" PDGUIDIR "/pd-gui.tcl\" %d\n",
libdir, libdir, libdir, portno);
-#endif
+#endif /* __APPLE__ */
sys_guicmd = cmdbuf;
}
@@ -1104,19 +1101,17 @@ int sys_startgui(const char *libdir)
close(stdinpipe[0]);
}
}
-#endif
+#endif /* NOT __APPLE__ */
execl("/bin/sh", "sh", "-c", sys_guicmd, (char*)0);
perror("pd: exec");
_exit(1);
}
-#endif /* UNISTD */
-
-#ifdef MSW
+#else /* NOT _WIN32 */
/* fprintf(stderr, "%s\n", libdir); */
strcpy(scriptbuf, "\"");
strcat(scriptbuf, libdir);
- strcat(scriptbuf, "/" PDTCLDIR "pd-gui.tcl\"");
+ strcat(scriptbuf, "/" PDGUIDIR "pd-gui.tcl\"");
sys_bashfilename(scriptbuf, scriptbuf);
sprintf(portbuf, "%d", portno);
@@ -1133,18 +1128,23 @@ int sys_startgui(const char *libdir)
exit(1);
}
-#endif /* MSW */
+#endif /* NOT _WIN32 */
}
-#if defined(__linux__) || defined(IRIX)
+#if defined(__linux__) || defined(IRIX) || defined(__FreeBSD_kernel__)
/* now that we've spun off the child process we can promote
our process's priority, if we can and want to. If not specfied
- (-1), we check root status. This misses the case where we might
- have permission from a "security module" (linux 2.6) -- I don't
- know how to test for that. The "-rt" flag must b eset in that
- case. */
+ (-1), we assume real-time was wanted. Afterward, just in case
+ someone made Pd setuid in order to get permission to do this,
+ unset setuid and lose root priveliges after doing this. Starting
+ in Linux 2.6 this is accomplished by putting lines like:
+ @audio - rtprio 99
+ @audio - memlock unlimited
+ in the system limits file, perhaps /etc/limits.conf or
+ /etc/security/limits.conf */
+ fprintf(stderr, "was... %d\n", sys_hipriority);
if (sys_hipriority == -1)
- sys_hipriority = (!getuid() || !geteuid());
+ sys_hipriority = 1;
if (sys_hipriority)
{
@@ -1205,7 +1205,7 @@ int sys_startgui(const char *libdir)
setuid(getuid()); /* lose setuid priveliges */
#endif /* __linux__ */
-#ifdef MSW
+#ifdef _WIN32
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
fprintf(stderr, "pd: couldn't set high priority class\n");
#endif
@@ -1246,14 +1246,20 @@ int sys_startgui(const char *libdir)
sys_socketreceiver);
/* here is where we start the pinging. */
-#if defined(__linux__) || defined(IRIX)
+#if defined(__linux__) || defined(IRIX) || defined(__FreeBSD_kernel__)
if (sys_hipriority)
sys_gui("pdtk_watchdog\n");
#endif
sys_get_audio_apis(buf);
sys_get_midi_apis(buf2);
- sys_vgui("pdtk_pd_startup {%s} %s %s {%s} %s\n", pd_version, buf, buf2,
- sys_font, sys_fontweight);
+ sys_set_searchpath(); /* tell GUI about path and startup flags */
+ sys_set_extrapath();
+ sys_set_startup();
+ /* ... and about font, medio APIS, etc */
+ sys_vgui("pdtk_pd_startup %d %d %d {%s} %s %s {%s} %s\n",
+ PD_MAJOR_VERSION, PD_MINOR_VERSION,
+ PD_BUGFIX_VERSION, PD_TEST_VERSION,
+ buf, buf2, sys_font, sys_fontweight);
}
return (0);
@@ -1270,7 +1276,7 @@ void sys_bail(int n)
if (!reentered)
{
reentered = 1;
-#ifndef __linux__ /* sys_close_audio() hangs if you're in a signal? */
+#if !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) /* sys_close_audio() hangs if you're in a signal? */
fprintf(stderr, "closing audio...\n");
sys_close_audio();
fprintf(stderr, "closing MIDI...\n");
diff --git a/pd/src/s_loader.c b/pd/src/s_loader.c
index b708961c..c3e2d3a0 100644
--- a/pd/src/s_loader.c
+++ b/pd/src/s_loader.c
@@ -38,23 +38,22 @@ a fat binary or an indication of the instruction set. */
#ifdef __FreeBSD__
static char sys_dllextent[] = ".b_i386", sys_dllextent2[] = ".pd_freebsd";
-#endif
-#ifdef __linux__
-#ifdef __x86_64__
+#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+# ifdef __x86_64__
static char sys_dllextent[] = ".l_ia64", sys_dllextent2[] = ".pd_linux";
-#else
+# else
static char sys_dllextent[] = ".l_i386", sys_dllextent2[] = ".pd_linux";
-#endif
-#endif
-#ifdef __APPLE__
-#ifndef MACOSX3
+# endif
+#elif defined(__APPLE__)
+# ifndef MACOSX3
static char sys_dllextent[] = ".d_fat", sys_dllextent2[] = ".pd_darwin";
-#else
+# else
static char sys_dllextent[] = ".d_ppc", sys_dllextent2[] = ".pd_darwin";
-#endif
-#endif
-#ifdef MSW
+# endif
+#elif defined(_WIN32) || defined(__CYGWIN__)
static char sys_dllextent[] = ".m_i386", sys_dllextent2[] = ".dll";
+#elif defined(ANDROID)
+static char sys_dllextent[] = ".l_arm", sys_dllextent2[] = ".pd_linux";
#endif
/* maintain list of loaded modules to avoid repeating loads */
@@ -178,7 +177,7 @@ gotone:
return (0);
}
makeout = (t_xxx)dlsym(dlobj, symname);
- fprintf(stderr, "symbol %s\n", symname);
+ /* fprintf(stderr, "symbol %s\n", symname); */
#endif
#ifdef MSW
sys_bashfilename(filename, filename);
@@ -218,8 +217,10 @@ void sys_register_loader(loader_t loader)
{
loader_queue_t *q = &loaders;
while (1)
- {
- if (q->next)
+ {
+ if (q->loader == loader) /* already loaded - nothing to do */
+ return;
+ else if (q->next)
q = q->next;
else
{
diff --git a/pd/src/s_main.c b/pd/src/s_main.c
index a1e5af2a..24b5860e 100644
--- a/pd/src/s_main.c
+++ b/pd/src/s_main.c
@@ -25,7 +25,11 @@
#define snprintf sprintf_s
#endif
-char *pd_version;
+
+#define stringify(s) str(s)
+#define str(s) #s
+
+char *pd_version = "Pd-" stringify(PD_MAJOR_VERSION) "." stringify(PD_MINOR_VERSION) "." stringify(PD_BUGFIX_VERSION) " (" stringify(PD_TEST_VERSION) ")";
char pd_compiletime[] = __TIME__;
char pd_compiledate[] = __DATE__;
@@ -61,16 +65,17 @@ int sys_nmidiin = -1;
int sys_midiindevlist[MAXMIDIINDEV] = {1};
int sys_midioutdevlist[MAXMIDIOUTDEV] = {1};
-char sys_font[100] =
#ifdef __APPLE__
- "Monaco";
+char sys_font[100] = "Monaco";
+char sys_fontweight[10] = "normal";
#else
- "Courier";
+char sys_font[100] = "Courier";
+char sys_fontweight[10] = "bold";
#endif
-char sys_fontweight[] = "bold ";
static int sys_main_srate;
static int sys_main_advance;
static int sys_main_callback;
+static int sys_main_blocksize;
static int sys_listplease;
int sys_externalschedlib;
@@ -258,15 +263,6 @@ void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv)
static void sys_afterargparse(void);
-static void pd_makeversion(void)
-{
- char foo[100];
- sprintf(foo, "Pd version %d.%d-%d%s\n",PD_MAJOR_VERSION,
- PD_MINOR_VERSION,PD_BUGFIX_VERSION,PD_TEST_VERSION);
- pd_version = malloc(strlen(foo)+1);
- strcpy(pd_version, foo);
-}
-
/* this is called from main() in s_entry.c */
int sys_main(int argc, char **argv)
{
@@ -290,9 +286,7 @@ int sys_main(int argc, char **argv)
if (sys_argparse(argc-1, argv+1)) /* parse cmd line */
return (1);
sys_afterargparse(); /* post-argparse settings */
- /* build version string from defines in m_pd.h */
- pd_makeversion();
- if (sys_verbose || sys_version) fprintf(stderr, "%scompiled %s %s\n",
+ if (sys_verbose || sys_version) fprintf(stderr, "%s compiled %s %s\n",
pd_version, pd_compiletime, pd_compiledate);
if (sys_version) /* if we were just asked our version, exit here. */
return (0);
@@ -356,6 +350,15 @@ static char *(usagemessage[]) = {
#ifdef USEAPI_MMIO
"-mmio -- use MMIO audio API (default for Windows)\n",
#endif
+
+#ifdef USEAPI_AUDIOUNIT
+"-audiounit -- use Apple AudioUnit API\n",
+#endif
+
+#ifdef USEAPI_ESD
+"-esd -- use Enlightenment Sound Daemon (ESD) API\n",
+#endif
+
" (default audio API for this platform: ", API_DEFSTRING, ")\n\n",
"\nMIDI configuration flags:\n",
@@ -440,20 +443,19 @@ void sys_findprogdir(char *progname)
{
char sbuf[MAXPDSTRING], sbuf2[MAXPDSTRING], *sp;
char *lastslash;
-#ifdef HAVE_UNISTD_H
+#ifndef _WIN32
struct stat statbuf;
-#endif
+#endif /* NOT _WIN32 */
/* find out by what string Pd was invoked; put answer in "sbuf". */
-#ifdef MSW
+#ifdef _WIN32
GetModuleFileName(NULL, sbuf2, sizeof(sbuf2));
sbuf2[MAXPDSTRING-1] = 0;
sys_unbashfilename(sbuf2, sbuf);
-#endif /* MSW */
-#ifdef HAVE_UNISTD_H
+#else
strncpy(sbuf, progname, MAXPDSTRING);
sbuf[MAXPDSTRING-1] = 0;
-#endif
+#endif /* _WIN32 */
lastslash = strrchr(sbuf, '/');
if (lastslash)
{
@@ -483,12 +485,12 @@ void sys_findprogdir(char *progname)
"gui" directory. In "simple" unix installations, the layout is
.../bin/pd
.../bin/pd-watchdog (etc)
- .../tcl/pd-gui.tcl
+ .../bin/pd-gui.tcl
.../doc
and in "complicated" unix installations, it's:
.../bin/pd
.../lib/pd/bin/pd-watchdog
- .../lib/tcl/pd-gui.tcl
+ .../lib/pd/bin/pd-gui.tcl
.../lib/pd/doc
To decide which, we stat .../lib/pd; if that exists, we assume it's
the complicated layout. In MSW, it's the "simple" layout, but
@@ -578,7 +580,7 @@ int sys_argparse(int argc, char **argv)
}
else if (!strcmp(*argv, "-blocksize"))
{
- sys_setblocksize(atoi(argv[1]));
+ sys_main_blocksize = atoi(argv[1]);
argc -= 2; argv += 2;
}
else if (!strcmp(*argv, "-sleepgrain") && (argc > 1))
@@ -657,6 +659,20 @@ int sys_argparse(int argc, char **argv)
argc--; argv++;
}
#endif
+#ifdef USEAPI_AUDIOUNIT
+ else if (!strcmp(*argv, "-audiounit"))
+ {
+ sys_set_audio_api(API_AUDIOUNIT);
+ argc--; argv++;
+ }
+#endif
+#ifdef USEAPI_ESD
+ else if (!strcmp(*argv, "-esd"))
+ {
+ sys_set_audio_api(API_ESD);
+ argc--; argv++;
+ }
+#endif
else if (!strcmp(*argv, "-nomidiin"))
{
sys_nmidiin = 0;
@@ -909,7 +925,7 @@ static void sys_afterargparse(void)
int i;
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
- int nchindev, nchoutdev, rate, advance, callback;
+ int nchindev, nchoutdev, rate, advance, callback, blocksize;
int nmidiindev = 0, midiindev[MAXMIDIINDEV];
int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV];
/* add "extra" library to path */
@@ -945,7 +961,8 @@ static void sys_afterargparse(void)
else are the default. Overwrite them with any results
of argument parsing, and store them again. */
sys_get_audio_params(&naudioindev, audioindev, chindev,
- &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+ &naudiooutdev, audiooutdev, choutdev, &rate, &advance,
+ &callback, &blocksize);
if (sys_nchin >= 0)
{
nchindev = sys_nchin;
@@ -993,9 +1010,11 @@ static void sys_afterargparse(void)
rate = sys_main_srate;
if (sys_main_callback)
callback = sys_main_callback;
+ if (sys_main_blocksize)
+ blocksize = sys_main_blocksize;
sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance,
- callback);
+ callback, blocksize);
sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0);
}
diff --git a/pd/src/s_midi.c b/pd/src/s_midi.c
index 11669366..5ed54d8b 100644
--- a/pd/src/s_midi.c
+++ b/pd/src/s_midi.c
@@ -14,7 +14,7 @@
#include <bstring.h>
#endif
#endif
-#ifdef MSW
+#ifdef _WIN32
#include <winsock.h>
#include <sys/types.h>
#include <sys/timeb.h>
@@ -762,3 +762,17 @@ void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
}
}
+
+void sys_get_midi_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs,
+ int maxndevs, int devdescsize)
+{
+
+#ifdef USEAPI_ALSA
+ if (sys_midiapi == API_ALSA)
+ midi_alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs,
+ maxndevs, devdescsize);
+ else
+#endif /* ALSA */
+ midi_getdevs(indevlist, nindevs, outdevlist, noutdevs, maxndevs, devdescsize);
+}
diff --git a/pd/src/s_midi_alsa.c b/pd/src/s_midi_alsa.c
index d0d82f30..d6d1525e 100644
--- a/pd/src/s_midi_alsa.c
+++ b/pd/src/s_midi_alsa.c
@@ -28,16 +28,6 @@ static snd_seq_t *midi_handle;
static snd_midi_event_t *midiev;
-
-static unsigned short CombineBytes(unsigned char First, unsigned char Second)
-{
- unsigned short _14bit;
- _14bit = (unsigned short)Second;
- _14bit <<= 7;
- _14bit |= (unsigned short)First;
- return(_14bit);
-}
-
void sys_alsa_do_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec)
{
@@ -193,7 +183,7 @@ void sys_alsa_putmidimess(int portno, int a, int b, int c)
if (a >= 224) // pitchbend
{
channel = a-224;
- snd_seq_ev_set_pitchbend(&ev,channel,CombineBytes(b,c));
+ snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192)); /* b and c are already correct but alsa needs to recalculate them */
}
else if (a >= 208) // touch
{
diff --git a/pd/src/s_midi_dummy.c b/pd/src/s_midi_dummy.c
new file mode 100644
index 00000000..0ab463ef
--- /dev/null
+++ b/pd/src/s_midi_dummy.c
@@ -0,0 +1,34 @@
+/* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
+* Winfried Ritsch, Karl MacMillan, and others.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+
+ this file is a dummy for systems without any MIDI support
+
+*/
+
+void sys_do_open_midi(int nmidiin, int *midiinvec,
+ int nmidiout, int *midioutvec)
+{
+}
+
+void sys_close_midi( void)
+{
+}
+
+void sys_putmidimess(int portno, int a, int b, int c)
+{
+}
+
+void sys_putmidibyte(int portno, int byte)
+{
+}
+
+void sys_poll_midi(void)
+{
+}
+
+void midi_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int maxndev, int devdescsize)
+{
+}
diff --git a/pd/src/s_midi_pm.c b/pd/src/s_midi_pm.c
index e1c05b1a..fe123ff1 100644
--- a/pd/src/s_midi_pm.c
+++ b/pd/src/s_midi_pm.c
@@ -18,7 +18,6 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include "portaudio.h"
#include "portmidi.h"
#include "porttime.h"
diff --git a/pd/src/s_path.c b/pd/src/s_path.c
index f9c232a3..020db14a 100644
--- a/pd/src/s_path.c
+++ b/pd/src/s_path.c
@@ -20,6 +20,10 @@
#endif
#ifdef MSW
#include <io.h>
+#include <windows.h>
+#endif
+#ifdef _WIN32
+#include <malloc.h>
#endif
#include <string.h>
@@ -39,6 +43,7 @@
t_namelist *sys_externlist;
t_namelist *sys_searchpath;
+t_namelist *sys_staticpath;
t_namelist *sys_helppath;
/* change '/' characters to the system's native file separator */
@@ -86,6 +91,39 @@ int sys_isabsolutepath(const char *dir)
}
}
+/* expand env vars and ~ at the beginning of a path and make a copy to return */
+static void sys_expandpath(const char *from, char *to, int bufsize)
+{
+ if ((strlen(from) == 1 && from[0] == '~') || (strncmp(from,"~/", 2) == 0))
+ {
+#ifdef _WIN32
+ const char *home = getenv("USERPROFILE");
+#else
+ const char *home = getenv("HOME");
+#endif
+ if (home)
+ {
+ strncpy(to, home, bufsize);
+ to[bufsize-1] = 0;
+ strncpy(to + strlen(to), from + 1, bufsize - strlen(to));
+ to[bufsize-1] = 0;
+ }
+ }
+ else
+ {
+ strncpy(to, from, bufsize);
+ to[bufsize-1] = 0;
+ }
+#ifdef _WIN32
+ {
+ char *buf = alloca(bufsize);
+ ExpandEnvironmentStrings(to, buf, bufsize-1);
+ buf[bufsize-1] = 0;
+ strncpy(to, buf, bufsize);
+ to[bufsize-1] = 0;
+ }
+#endif
+}
/******************* Utility functions used below ******************/
@@ -187,14 +225,33 @@ char *namelist_get(t_namelist *namelist, int n)
return (nl ? nl->nl_string : 0);
}
-static t_namelist *pd_extrapath;
-
int sys_usestdpath = 1;
void sys_setextrapath(const char *p)
{
- namelist_free(pd_extrapath);
- pd_extrapath = namelist_append(0, p, 0);
+ char pathbuf[MAXPDSTRING];
+ namelist_free(sys_staticpath);
+ /* add standard place for users to install stuff first */
+#ifdef __gnu_linux__
+ sys_expandpath("~/pd-externals", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(0, pathbuf, 0);
+ sys_staticpath = namelist_append(sys_staticpath, "/usr/local/lib/pd-externals", 0);
+#endif
+
+#ifdef __APPLE__
+ sys_expandpath("~/Library/Pd", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(0, pathbuf, 0);
+ sys_staticpath = namelist_append(sys_staticpath, "/Library/Pd", 0);
+#endif
+
+#ifdef _WIN32
+ sys_expandpath("%ProgramFiles%/Common Files/Pd", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(0, pathbuf, 0);
+ sys_expandpath("%UserProfile%/Application Data/Pd", pathbuf, MAXPDSTRING);
+ sys_staticpath = namelist_append(sys_staticpath, pathbuf, 0);
+#endif
+ /* add built-in "extra" path last so its checked last */
+ sys_staticpath = namelist_append(sys_staticpath, p, 0);
}
#ifdef MSW
@@ -214,9 +271,11 @@ int sys_trytoopenone(const char *dir, const char *name, const char* ext,
char *dirresult, char **nameresult, unsigned int size, int bin)
{
int fd;
+ char buf[MAXPDSTRING];
if (strlen(dir) + strlen(name) + strlen(ext) + 4 > size)
return (-1);
- strcpy(dirresult, dir);
+ sys_expandpath(dir, buf, MAXPDSTRING);
+ strcpy(dirresult, buf);
if (*dirresult && dirresult[strlen(dirresult)-1] != '/')
strcat(dirresult, "/");
strcat(dirresult, name);
@@ -319,11 +378,12 @@ static int do_open_via_path(const char *dir, const char *name,
dirresult, nameresult, size, bin)) >= 0)
return (fd);
- /* next look in "extra" */
- if (sys_usestdpath &&
- (fd = sys_trytoopenone(pd_extrapath->nl_string, name, ext,
- dirresult, nameresult, size, bin)) >= 0)
- return (fd);
+ /* next look in built-in paths like "extra" */
+ if (sys_usestdpath)
+ for (nl = sys_staticpath; nl; nl = nl->nl_next)
+ if ((fd = sys_trytoopenone(nl->nl_string, name, ext,
+ dirresult, nameresult, size, bin)) >= 0)
+ return (fd);
*dirresult = 0;
*nameresult = dirresult;
@@ -338,6 +398,15 @@ int open_via_path(const char *dir, const char *name, const char *ext,
size, bin, sys_searchpath));
}
+ /* close a previsouly opened file
+ this is needed on platforms where you cannot open/close ressources
+ across dll-boundaries */
+int sys_close(int fd)
+{
+ return close(fd);
+}
+
+
/* Open a help file using the help search path. We expect the ".pd"
suffix here, even though we have to tear it back off for one of the
search attempts. */
@@ -450,7 +519,7 @@ int sys_rcfile(void)
}
if (sys_argparse(rcargc-1, rcargv+1))
{
- post("error parsing RC arguments");
+ error("error parsing RC arguments");
goto cleanup;
}
@@ -472,7 +541,7 @@ void sys_doflags( void)
char *rcargv[MAXPDSTRING];
if (len > MAXPDSTRING)
{
- post("flags: %s: too long", sys_flags->s_name);
+ error("flags: %s: too long", sys_flags->s_name);
return;
}
for (i = 0; i < len+1; i++)
@@ -504,7 +573,7 @@ void sys_doflags( void)
}
}
if (sys_argparse(rcargc, rcargv))
- post("error parsing startup arguments");
+ error("error parsing startup arguments");
}
/* undo pdtl_encodedialog. This allows dialogs to send spaces, commas,
@@ -540,17 +609,36 @@ t_symbol *sys_decodedialog(t_symbol *s)
return (gensym(buf));
}
-
- /* start a search path dialog window */
-void glob_start_path_dialog(t_pd *dummy)
+ /* send the user-specified search path to pd-gui */
+void sys_set_searchpath( void)
{
- char buf[MAXPDSTRING];
int i;
t_namelist *nl;
- sys_gui("global pd_path; set pd_path {}\n");
+ sys_gui("set ::tmp_path {}\n");
for (nl = sys_searchpath, i = 0; nl; nl = nl->nl_next, i++)
- sys_vgui("lappend pd_path {%s}\n", nl->nl_string);
+ sys_vgui("lappend ::tmp_path {%s}\n", nl->nl_string);
+ sys_gui("set ::sys_searchpath $::tmp_path\n");
+}
+
+ /* send the hard-coded search path to pd-gui */
+void sys_set_extrapath( void)
+{
+ int i;
+ t_namelist *nl;
+
+ sys_gui("set ::tmp_path {}\n");
+ for (nl = sys_staticpath, i = 0; nl; nl = nl->nl_next, i++)
+ sys_vgui("lappend ::tmp_path {%s}\n", nl->nl_string);
+ sys_gui("set ::sys_staticpath $::tmp_path\n");
+}
+
+ /* start a search path dialog window */
+void glob_start_path_dialog(t_pd *dummy)
+{
+ char buf[MAXPDSTRING];
+
+ sys_set_searchpath();
sprintf(buf, "pdtk_path_dialog %%s %d %d\n", sys_usestdpath, sys_verbose);
gfxstub_new(&glob_pdobject, (void *)glob_start_path_dialog, buf);
}
@@ -571,16 +659,24 @@ void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
}
}
- /* start a startup dialog window */
-void glob_start_startup_dialog(t_pd *dummy)
+ /* set the global list vars for startup libraries and flags */
+void sys_set_startup( void)
{
- char buf[MAXPDSTRING];
int i;
t_namelist *nl;
- sys_gui("global pd_startup; set pd_startup {}\n");
+ sys_vgui("set ::startup_flags {%s}\n", sys_flags->s_name);
+ sys_gui("set ::startup_libraries {}\n");
for (nl = sys_externlist, i = 0; nl; nl = nl->nl_next, i++)
- sys_vgui("lappend pd_startup {%s}\n", nl->nl_string);
+ sys_vgui("lappend ::startup_libraries {%s}\n", nl->nl_string);
+}
+
+ /* start a startup dialog window */
+void glob_start_startup_dialog(t_pd *dummy)
+{
+ char buf[MAXPDSTRING];
+
+ sys_set_startup();
sprintf(buf, "pdtk_startup_dialog %%s %d \"%s\"\n", sys_defeatrt,
sys_flags->s_name);
gfxstub_new(&glob_pdobject, (void *)glob_start_startup_dialog, buf);
diff --git a/pd/src/s_print.c b/pd/src/s_print.c
index 3aacd188..c82601a1 100644
--- a/pd/src/s_print.c
+++ b/pd/src/s_print.c
@@ -9,10 +9,43 @@
#include <string.h>
#include <errno.h>
#include "s_stuff.h"
+#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
+#define snprintf sprintf_s
+#endif
t_printhook sys_printhook;
int sys_printtostderr;
+/* escape characters for tcl/tk */
+static char* strnescape(char *dest, const char *src, size_t len)
+{
+ int ptin = 0;
+ unsigned ptout = 0;
+ for(; ptout < len; ptin++, ptout++)
+ {
+ int c = src[ptin];
+ if (c == '\\' || c == '{' || c == '}' || c == ';')
+ dest[ptout++] = '\\';
+ dest[ptout] = src[ptin];
+ if (c==0) break;
+ }
+
+ if(ptout < len)
+ dest[ptout]=0;
+ else
+ dest[len-1]=0;
+
+ return dest;
+}
+
+static char* strnpointerid(char *dest, const void *pointer, size_t len)
+{
+ *dest=0;
+ if(pointer)
+ snprintf(dest, len, ".x%lx", pointer);
+ return dest;
+}
+
static void dopost(const char *s)
{
if (sys_printhook)
@@ -22,25 +55,90 @@ static void dopost(const char *s)
else
{
char upbuf[MAXPDSTRING];
- int ptin = 0, ptout = 0, len = strlen(s);
- static int heldcr = 0;
- if (heldcr)
- upbuf[ptout++] = '\n', heldcr = 0;
- for (; ptin < len && ptout < MAXPDSTRING-3;
- ptin++, ptout++)
- {
- int c = s[ptin];
- if (c == '\\' || c == '{' || c == '}' || c == ';')
- upbuf[ptout++] = '\\';
- upbuf[ptout] = s[ptin];
- }
- if (ptout && upbuf[ptout-1] == '\n')
- upbuf[--ptout] = 0, heldcr = 1;
- upbuf[ptout] = 0;
- sys_vgui("pdtk_post {%s}\n", upbuf);
+ sys_vgui("::pdwindow::post {%s}\n", strnescape(upbuf, s, MAXPDSTRING));
}
}
+static void doerror(const void *object, const char *s)
+{
+ char upbuf[MAXPDSTRING];
+ upbuf[MAXPDSTRING-1]=0;
+
+ // what about sys_printhook_error ?
+ if (sys_printhook)
+ {
+ snprintf(upbuf, MAXPDSTRING-1, "error: %s", s);
+ (*sys_printhook)(upbuf);
+ }
+ else if (sys_printtostderr)
+ fprintf(stderr, "error: %s", s);
+ else
+ {
+ char obuf[MAXPDSTRING];
+ sys_vgui("::pdwindow::logpost {%s} 1 {%s}\n",
+ strnpointerid(obuf, object, MAXPDSTRING),
+ strnescape(upbuf, s, MAXPDSTRING));
+ }
+}
+
+static void dologpost(const void *object, const int level, const char *s)
+{
+ char upbuf[MAXPDSTRING];
+ upbuf[MAXPDSTRING-1]=0;
+
+ // what about sys_printhook_verbose ?
+ if (sys_printhook)
+ {
+ snprintf(upbuf, MAXPDSTRING-1, "verbose(%d): %s", level, s);
+ (*sys_printhook)(upbuf);
+ }
+ else if (sys_printtostderr)
+ {
+ fprintf(stderr, "verbose(%d): %s", level, s);
+ }
+ else
+ {
+ char obuf[MAXPDSTRING];
+ sys_vgui("::pdwindow::logpost {%s} %d {%s}\n",
+ strnpointerid(obuf, object, MAXPDSTRING),
+ level, strnescape(upbuf, s, MAXPDSTRING));
+ }
+}
+
+static void dobug(const char *s)
+{
+ char upbuf[MAXPDSTRING];
+ upbuf[MAXPDSTRING-1]=0;
+
+ // what about sys_printhook_bug ?
+ if (sys_printhook)
+ {
+ snprintf(upbuf, MAXPDSTRING-1, "consistency check failed: %s", s);
+ (*sys_printhook)(upbuf);
+ }
+ else if (sys_printtostderr)
+ fprintf(stderr, "consistency check failed: %s", s);
+ else
+ {
+ char upbuf[MAXPDSTRING];
+ sys_vgui("::pdwindow::bug {%s}\n", strnescape(upbuf, s, MAXPDSTRING));
+ }
+}
+
+void logpost(const void *object, const int level, const char *fmt, ...)
+{
+ char buf[MAXPDSTRING];
+ va_list ap;
+ t_int arg[8];
+ int i;
+ va_start(ap, fmt);
+ vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
+ va_end(ap);
+ strcat(buf, "\n");
+
+ dologpost(object, level, buf);
+}
+
void post(const char *fmt, ...)
{
char buf[MAXPDSTRING];
@@ -51,6 +149,7 @@ void post(const char *fmt, ...)
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
strcat(buf, "\n");
+
dopost(buf);
}
@@ -63,12 +162,14 @@ void startpost(const char *fmt, ...)
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
+
dopost(buf);
}
void poststring(const char *s)
{
dopost(" ");
+
dopost(s);
}
@@ -88,12 +189,17 @@ void postfloat(t_float f)
char buf[80];
t_atom a;
SETFLOAT(&a, f);
+
postatom(1, &a);
}
void endpost(void)
{
- dopost("\n");
+ if (sys_printhook)
+ (*sys_printhook)("\n");
+ else if (sys_printtostderr)
+ fprintf(stderr, "\n");
+ else post("");
}
void error(const char *fmt, ...)
@@ -102,12 +208,13 @@ void error(const char *fmt, ...)
va_list ap;
t_int arg[8];
int i;
- dopost("error: ");
+
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+
+ doerror(NULL, buf);
+ endpost();
}
void verbose(int level, const char *fmt, ...)
@@ -116,16 +223,15 @@ void verbose(int level, const char *fmt, ...)
va_list ap;
t_int arg[8];
int i;
+
if(level>sys_verbose)return;
- dopost("verbose(");
- postfloat((t_float)level);
- dopost("):");
-
+
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+ dologpost(NULL, level+4, buf);
+
+ endpost();
}
/* here's the good way to log errors -- keep a pointer to the
@@ -143,16 +249,19 @@ void pd_error(void *object, const char *fmt, ...)
t_int arg[8];
int i;
static int saidit;
- dopost("error: ");
+
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+
+ doerror(object, buf);
+ endpost();
+
error_object = object;
if (!saidit)
{
- post("... you might be able to track this down from the Find menu.");
+ logpost(NULL, 4,
+ "... you might be able to track this down from the Find menu.");
saidit = 1;
}
}
@@ -169,18 +278,29 @@ void glob_finderror(t_pd *dummy)
}
}
+void glob_findinstance(t_pd *dummy, t_symbol*s)
+{
+ // revert s to (potential) pointer to object
+ void*obj=NULL;
+ if(sscanf(s->s_name, ".x%lx", &obj)) {
+ if(obj) {
+ canvas_finderror(obj);
+ }
+ }
+}
+
void bug(const char *fmt, ...)
{
char buf[MAXPDSTRING];
va_list ap;
t_int arg[8];
int i;
- dopost("consistency check failed: ");
va_start(ap, fmt);
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
va_end(ap);
- strcat(buf, "\n");
- dopost(buf);
+
+ dobug(buf);
+ endpost();
}
/* this isn't worked out yet. */
@@ -203,4 +323,5 @@ void sys_ouch(void)
{
if (*errobject) error("%s: %s", errobject, errstring);
else error("%s", errstring);
+ sys_gui("bell\n");
}
diff --git a/pd/src/s_stuff.h b/pd/src/s_stuff.h
index 0fb2497e..b37b161a 100644
--- a/pd/src/s_stuff.h
+++ b/pd/src/s_stuff.h
@@ -75,12 +75,17 @@ extern int sys_blocksize; /* audio I/O block size in sample frames */
extern t_float sys_dacsr;
extern int sys_schedadvance;
extern int sys_sleepgrain;
-void sys_set_audio_settings(int naudioindev, int *audioindev,
+EXTERN void sys_set_audio_settings(int naudioindev, int *audioindev,
int nchindev, int *chindev,
int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
- int srate, int advance, int callback);
-void sys_reopen_audio( void);
-void sys_close_audio(void);
+ int srate, int advance, int callback, int blocksize);
+/* the same as above, but reopens the audio subsystem if needed */
+EXTERN void sys_set_audio_settings_reopen(int naudioindev, int *audioindev,
+ int nchindev, int *chindev,
+ int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
+ int srate, int advance, int callback, int blocksize);
+EXTERN void sys_reopen_audio( void);
+EXTERN void sys_close_audio(void);
int sys_send_dacs(void);
@@ -91,23 +96,32 @@ void sys_getmeters(t_sample *inmax, t_sample *outmax);
void sys_listdevs(void);
void sys_setblocksize(int n);
+EXTERN void sys_get_audio_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
+ int maxndev, int devdescsize);
+EXTERN void sys_get_audio_apis(char *buf);
+
/* s_midi.c */
#define MAXMIDIINDEV 16 /* max. number of input ports */
#define MAXMIDIOUTDEV 16 /* max. number of output ports */
+extern int sys_midiapi;
extern int sys_nmidiin;
extern int sys_nmidiout;
extern int sys_midiindevlist[];
extern int sys_midioutdevlist[];
-void sys_open_midi(int nmidiin, int *midiinvec,
+EXTERN void sys_open_midi(int nmidiin, int *midiinvec,
int nmidiout, int *midioutvec, int enable);
-void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
- int *pnmidioutdev, int *pmidioutdev);
-void sys_get_midi_apis(char *buf);
+EXTERN void sys_get_midi_apis(char *buf);
+EXTERN void sys_get_midi_devs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs,
+ int maxndev, int devdescsize);
+EXTERN void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
+ int *pnmidioutdev, int *pmidioutdev);
-void sys_reopen_midi( void);
-void sys_close_midi( void);
+EXTERN void sys_reopen_midi( void);
+EXTERN void sys_close_midi( void);
EXTERN void sys_putmidimess(int portno, int a, int b, int c);
EXTERN void sys_putmidibyte(int portno, int a);
EXTERN void sys_poll_midi(void);
@@ -171,9 +185,8 @@ EXTERN void sys_closesocket(int fd);
typedef void (*t_fdpollfn)(void *ptr, int fd);
EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
EXTERN void sys_rmpollfn(int fd);
-#ifdef UNIX
+#if defined(USEAPI_OSS) || defined(USEAPI_ALSA)
void sys_setalarm(int microsec);
-void sys_setvirtualalarm( void);
#endif
#define API_NONE 0
@@ -183,23 +196,41 @@ void sys_setvirtualalarm( void);
#define API_PORTAUDIO 4
#define API_JACK 5
#define API_SGI 6
+#define API_AUDIOUNIT 7
+#define API_ESD 8
+#define API_DUMMY 9
-#ifdef __linux__
-#define API_DEFAULT API_OSS
-#define API_DEFSTRING "OSS"
+#ifdef USEAPI_DUMMY
+#define API_DEFAULT API_DUMMY
+#define API_DEFSTRING "dummy audio"
+#else
+#if defined(__linux__) || defined(__FreeBSD_kernel__)
+# define API_DEFAULT API_OSS
+# define API_DEFSTRING "OSS"
#endif
-#ifdef MSW
-#define API_DEFAULT API_MMIO
-#define API_DEFSTRING "MMIO"
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define API_DEFAULT API_MMIO
+# define API_DEFSTRING "MMIO"
#endif
#ifdef __APPLE__
-#define API_DEFAULT API_PORTAUDIO
-#define API_DEFSTRING "portaudio"
+# ifdef __arm__
+# define API_DEFAULT API_AUDIOUNIT
+# define API_DEFSTRING "AudioUnit"
+# else
+# define API_DEFAULT API_PORTAUDIO
+# define API_DEFSTRING "portaudio"
+# endif /* __arm__ */
#endif
#ifdef IRIX
-#define API_DEFAULT API_SGI
-#define API_DEFSTRING "SGI Digital Media"
+# define API_DEFAULT API_SGI
+# define API_DEFSTRING "SGI Digital Media"
+#endif
+#ifdef __GNU__
+# define API_DEFAULT API_JACK
+# define API_DEFSTRING "Jack audio connection kit"
+#endif
#endif
+
#define DEFAULTAUDIODEV 0
#define MAXAUDIOINDEV 4
@@ -211,7 +242,7 @@ void sys_setvirtualalarm( void);
#ifdef MSW
#define DEFAULTADVANCE 70
#else
-#define DEFAULTADVANCE 50
+#define DEFAULTADVANCE 25
#endif
typedef void (*t_audiocallback)(void);
@@ -229,7 +260,7 @@ void pa_getdevs(char *indevlist, int *nindevs,
int oss_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate);
+ int *choutdev, int rate, int blocksize);
void oss_close_audio(void);
int oss_send_dacs(void);
void oss_reportidle(void);
@@ -239,7 +270,7 @@ void oss_getdevs(char *indevlist, int *nindevs,
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
- int *choutdev, int rate);
+ int *choutdev, int rate, int blocksize);
void alsa_close_audio(void);
int alsa_send_dacs(void);
void alsa_reportidle(void);
@@ -247,7 +278,8 @@ void alsa_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize);
-int jack_open_audio(int wantinchans, int wantoutchans, int srate);
+int jack_open_audio(int wantinchans, int wantoutchans, int srate,
+ t_audiocallback callback);
void jack_close_audio(void);
int jack_send_dacs(void);
void jack_reportidle(void);
@@ -266,25 +298,51 @@ void mmio_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
int maxndev, int devdescsize);
+int audiounit_open_audio(int naudioindev, int *audioindev, int nchindev,
+ int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+ int *choutdev, int rate);
+void audiounit_close_audio(void);
+int audiounit_send_dacs(void);
+void audiounit_listdevs(void);
+void audiounit_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize);
+
+int esd_open_audio(int naudioindev, int *audioindev, int nchindev,
+ int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+ int *choutdev, int rate);
+void esd_close_audio(void);
+int esd_send_dacs(void);
+void esd_listdevs(void);
+void esd_getdevs(char *indevlist, int *nindevs,
+ char *outdevlist, int *noutdevs, int *canmulti,
+ int maxndev, int devdescsize);
+
+int dummy_open_audio(int nin, int nout, int sr);
+int dummy_close_audio( void);
+int dummy_send_dacs( void);
+void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist,
+ int *noutdevs, int *canmulti, int maxndev, int devdescsize);
+void dummy_listdevs( void);
+
void sys_listmididevs(void);
-void sys_set_midi_api(int whichapi);
-void sys_set_audio_api(int whichapi);
-void sys_get_audio_apis(char *buf);
+EXTERN void sys_set_midi_api(int whichapi);
+EXTERN void sys_set_audio_api(int whichapi);
extern int sys_audioapi;
-void sys_set_audio_state(int onoff);
+EXTERN void sys_set_audio_state(int onoff);
/* API dependent audio flags and settings */
void oss_set32bit( void);
void linux_alsa_devname(char *devname);
-void sys_get_audio_params(
+EXTERN void sys_get_audio_params(
int *pnaudioindev, int *paudioindev, int *chindev,
int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
- int *prate, int *padvance, int *callback);
+ int *prate, int *padvance, int *callback, int *blocksize);
void sys_save_audio_params(
int naudioindev, int *audioindev, int *chindev,
int naudiooutdev, int *audiooutdev, int *choutdev,
- int rate, int advance, int callback);
+ int rate, int advance, int callback, int blocksize);
/* s_file.c */
diff --git a/pd/src/s_utf8.c b/pd/src/s_utf8.c
new file mode 100644
index 00000000..b50d0929
--- /dev/null
+++ b/pd/src/s_utf8.c
@@ -0,0 +1,280 @@
+/*
+ Basic UTF-8 manipulation routines
+ by Jeff Bezanson
+ placed in the public domain Fall 2005
+
+ This code is designed to provide the utilities you need to manipulate
+ UTF-8 as an internal string encoding. These functions do not perform the
+ error checking normally needed when handling UTF-8 data, so if you happen
+ to be from the Unicode Consortium you will want to flay me alive.
+ I do this because error checking can be performed at the boundaries (I/O),
+ with these routines reserved for higher performance on data known to be
+ valid.
+
+ modified by Bryan Jurish (moo) March 2009
+ + removed some unneeded functions (escapes, printf etc), added others
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef WIN32
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+#include "s_utf8.h"
+
+static const u_int32_t offsetsFromUTF8[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+};
+
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+
+/* returns length of next utf-8 sequence */
+int u8_seqlen(char *s)
+{
+ return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1;
+}
+
+/* conversions without error checking
+ only works for valid UTF-8, i.e. no 5- or 6-byte sequences
+ srcsz = source size in bytes, or -1 if 0-terminated
+ sz = dest size in # of wide characters
+
+ returns # characters converted
+ dest will always be L'\0'-terminated, even if there isn't enough room
+ for all the characters.
+ if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space.
+*/
+int u8_toucs(u_int32_t *dest, int sz, char *src, int srcsz)
+{
+ u_int32_t ch;
+ char *src_end = src + srcsz;
+ int nb;
+ int i=0;
+
+ while (i < sz-1) {
+ nb = trailingBytesForUTF8[(unsigned char)*src];
+ if (srcsz == -1) {
+ if (*src == 0)
+ goto done_toucs;
+ }
+ else {
+ if (src + nb >= src_end)
+ goto done_toucs;
+ }
+ ch = 0;
+ switch (nb) {
+ /* these fall through deliberately */
+#if UTF8_SUPPORT_FULL_UCS4
+ case 5: ch += (unsigned char)*src++; ch <<= 6;
+ case 4: ch += (unsigned char)*src++; ch <<= 6;
+#endif
+ case 3: ch += (unsigned char)*src++; ch <<= 6;
+ case 2: ch += (unsigned char)*src++; ch <<= 6;
+ case 1: ch += (unsigned char)*src++; ch <<= 6;
+ case 0: ch += (unsigned char)*src++;
+ }
+ ch -= offsetsFromUTF8[nb];
+ dest[i++] = ch;
+ }
+ done_toucs:
+ dest[i] = 0;
+ return i;
+}
+
+/* srcsz = number of source characters, or -1 if 0-terminated
+ sz = size of dest buffer in bytes
+
+ returns # characters converted
+ dest will only be '\0'-terminated if there is enough space. this is
+ for consistency; imagine there are 2 bytes of space left, but the next
+ character requires 3 bytes. in this case we could NUL-terminate, but in
+ general we can't when there's insufficient space. therefore this function
+ only NUL-terminates if all the characters fit, and there's space for
+ the NUL as well.
+ the destination string will never be bigger than the source string.
+*/
+int u8_toutf8(char *dest, int sz, u_int32_t *src, int srcsz)
+{
+ u_int32_t ch;
+ int i = 0;
+ char *dest_end = dest + sz;
+
+ while (srcsz<0 ? src[i]!=0 : i < srcsz) {
+ ch = src[i];
+ if (ch < 0x80) {
+ if (dest >= dest_end)
+ return i;
+ *dest++ = (char)ch;
+ }
+ else if (ch < 0x800) {
+ if (dest >= dest_end-1)
+ return i;
+ *dest++ = (ch>>6) | 0xC0;
+ *dest++ = (ch & 0x3F) | 0x80;
+ }
+ else if (ch < 0x10000) {
+ if (dest >= dest_end-2)
+ return i;
+ *dest++ = (ch>>12) | 0xE0;
+ *dest++ = ((ch>>6) & 0x3F) | 0x80;
+ *dest++ = (ch & 0x3F) | 0x80;
+ }
+ else if (ch < 0x110000) {
+ if (dest >= dest_end-3)
+ return i;
+ *dest++ = (ch>>18) | 0xF0;
+ *dest++ = ((ch>>12) & 0x3F) | 0x80;
+ *dest++ = ((ch>>6) & 0x3F) | 0x80;
+ *dest++ = (ch & 0x3F) | 0x80;
+ }
+ i++;
+ }
+ if (dest < dest_end)
+ *dest = '\0';
+ return i;
+}
+
+/* moo: get byte length of character number, or 0 if not supported */
+int u8_wc_nbytes(u_int32_t ch)
+{
+ if (ch < 0x80) return 1;
+ if (ch < 0x800) return 2;
+ if (ch < 0x10000) return 3;
+ if (ch < 0x200000) return 4;
+#if UTF8_SUPPORT_FULL_UCS4
+ /*-- moo: support full UCS-4 range? --*/
+ if (ch < 0x4000000) return 5;
+ if (ch < 0x7fffffffUL) return 6;
+#endif
+ return 0; /*-- bad input --*/
+}
+
+int u8_wc_toutf8(char *dest, u_int32_t ch)
+{
+ if (ch < 0x80) {
+ dest[0] = (char)ch;
+ return 1;
+ }
+ if (ch < 0x800) {
+ dest[0] = (ch>>6) | 0xC0;
+ dest[1] = (ch & 0x3F) | 0x80;
+ return 2;
+ }
+ if (ch < 0x10000) {
+ dest[0] = (ch>>12) | 0xE0;
+ dest[1] = ((ch>>6) & 0x3F) | 0x80;
+ dest[2] = (ch & 0x3F) | 0x80;
+ return 3;
+ }
+ if (ch < 0x110000) {
+ dest[0] = (ch>>18) | 0xF0;
+ dest[1] = ((ch>>12) & 0x3F) | 0x80;
+ dest[2] = ((ch>>6) & 0x3F) | 0x80;
+ dest[3] = (ch & 0x3F) | 0x80;
+ return 4;
+ }
+ return 0;
+}
+
+/*-- moo --*/
+int u8_wc_toutf8_nul(char *dest, u_int32_t ch)
+{
+ int sz = u8_wc_toutf8(dest,ch);
+ dest[sz] = '\0';
+ return sz;
+}
+
+/* charnum => byte offset */
+int u8_offset(char *str, int charnum)
+{
+ int offs=0;
+
+ while (charnum > 0 && str[offs]) {
+ (void)(isutf(str[++offs]) || isutf(str[++offs]) ||
+ isutf(str[++offs]) || ++offs);
+ charnum--;
+ }
+ return offs;
+}
+
+/* byte offset => charnum */
+int u8_charnum(char *s, int offset)
+{
+ int charnum = 0, offs=0;
+
+ while (offs < offset && s[offs]) {
+ (void)(isutf(s[++offs]) || isutf(s[++offs]) ||
+ isutf(s[++offs]) || ++offs);
+ charnum++;
+ }
+ return charnum;
+}
+
+/* reads the next utf-8 sequence out of a string, updating an index */
+u_int32_t u8_nextchar(char *s, int *i)
+{
+ u_int32_t ch = 0;
+ int sz = 0;
+
+ do {
+ ch <<= 6;
+ ch += (unsigned char)s[(*i)++];
+ sz++;
+ } while (s[*i] && !isutf(s[*i]));
+ ch -= offsetsFromUTF8[sz-1];
+
+ return ch;
+}
+
+/* number of characters */
+int u8_strlen(char *s)
+{
+ int count = 0;
+ int i = 0;
+
+ while (u8_nextchar(s, &i) != 0)
+ count++;
+
+ return count;
+}
+
+void u8_inc(char *s, int *i)
+{
+ (void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) ||
+ isutf(s[++(*i)]) || ++(*i));
+}
+
+void u8_dec(char *s, int *i)
+{
+ (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) ||
+ isutf(s[--(*i)]) || --(*i));
+}
+
+/*-- moo --*/
+void u8_inc_ptr(char **sp)
+{
+ (void)(isutf(*(++(*sp))) || isutf(*(++(*sp))) ||
+ isutf(*(++(*sp))) || ++(*sp));
+}
+
+/*-- moo --*/
+void u8_dec_ptr(char **sp)
+{
+ (void)(isutf(*(--(*sp))) || isutf(*(--(*sp))) ||
+ isutf(*(--(*sp))) || --(*sp));
+}
diff --git a/pd/src/s_utf8.h b/pd/src/s_utf8.h
new file mode 100644
index 00000000..56c40d48
--- /dev/null
+++ b/pd/src/s_utf8.h
@@ -0,0 +1,88 @@
+#ifndef S_UTF8_H
+#define S_UTF8_H
+
+/*--moo--*/
+#ifndef u_int32_t
+# define u_int32_t unsigned int
+#endif
+
+#ifndef UCS4
+# define UCS4 u_int32_t
+#endif
+
+/* UTF8_SUPPORT_FULL_UCS4
+ * define this to support the full potential range of UCS-4 codepoints
+ * (in anticipation of a future UTF-8 standard)
+ */
+/*#define UTF8_SUPPORT_FULL_UCS4 1*/
+#undef UTF8_SUPPORT_FULL_UCS4
+
+/* UTF8_MAXBYTES
+ * maximum number of bytes required to represent a single character in UTF-8
+ *
+ * UTF8_MAXBYTES1 = UTF8_MAXBYTES+1
+ * maximum bytes per character including NUL terminator
+ */
+#ifdef UTF8_SUPPORT_FULL_UCS4
+# ifndef UTF8_MAXBYTES
+# define UTF8_MAXBYTES 6
+# endif
+# ifndef UTF8_MAXBYTES1
+# define UTF8_MAXBYTES1 7
+# endif
+#else
+# ifndef UTF8_MAXBYTES
+# define UTF8_MAXBYTES 4
+# endif
+# ifndef UTF8_MAXBYTES1
+# define UTF8_MAXBYTES1 5
+# endif
+#endif
+/*--/moo--*/
+
+/* is c the start of a utf8 sequence? */
+#define isutf(c) (((c)&0xC0)!=0x80)
+
+/* convert UTF-8 data to wide character */
+int u8_toucs(u_int32_t *dest, int sz, char *src, int srcsz);
+
+/* the opposite conversion */
+int u8_toutf8(char *dest, int sz, u_int32_t *src, int srcsz);
+
+/* moo: get byte length of character number, or 0 if not supported */
+int u8_wc_nbytes(u_int32_t ch);
+
+/* moo: compute required storage for UTF-8 encoding of 's[0..n-1]' */
+int u8_wcs_nbytes(u_int32_t *ucs, int size);
+
+/* single character to UTF-8, no NUL termination */
+int u8_wc_toutf8(char *dest, u_int32_t ch);
+
+/* moo: single character to UTF-8, with NUL termination */
+int u8_wc_toutf8_nul(char *dest, u_int32_t ch);
+
+/* character number to byte offset */
+int u8_offset(char *str, int charnum);
+
+/* byte offset to character number */
+int u8_charnum(char *s, int offset);
+
+/* return next character, updating an index variable */
+u_int32_t u8_nextchar(char *s, int *i);
+
+/* move to next character */
+void u8_inc(char *s, int *i);
+
+/* move to previous character */
+void u8_dec(char *s, int *i);
+
+/* moo: move pointer to next character */
+void u8_inc_ptr(char **sp);
+
+/* moo: move pointer to previous character */
+void u8_dec_ptr(char **sp);
+
+/* returns length of next utf-8 sequence */
+int u8_seqlen(char *s);
+
+#endif /* S_UTF8_H */
diff --git a/pd/src/u_pdreceive.c b/pd/src/u_pdreceive.c
index e61397ed..8a193292 100644
--- a/pd/src/u_pdreceive.c
+++ b/pd/src/u_pdreceive.c
@@ -128,7 +128,7 @@ static void addport(int fd)
nfdpoll++;
if (fd >= maxfd) maxfd = fd + 1;
fp->fdp_outlen = fp->fdp_discard = fp->fdp_gotsemi = 0;
- if (!(fp->fdp_outbuf = malloc(BUFSIZE)))
+ if (!(fp->fdp_outbuf = (char*) malloc(BUFSIZE)))
{
fprintf(stderr, "out of memory");
exit(1);
diff --git a/pd/src/x_arithmetic.c b/pd/src/x_arithmetic.c
index 0dd19937..d89530f6 100644
--- a/pd/src/x_arithmetic.c
+++ b/pd/src/x_arithmetic.c
@@ -10,19 +10,6 @@ inputs to int and their outputs back to float. */
#include <math.h>
-/* MSW and OSX don't appear to have single-precision ANSI math */
-#if defined(MSW) || defined(__APPLE__)
-#define sinf sin
-#define cosf cos
-#define atanf atan
-#define atan2f atan2
-#define sqrtf sqrt
-#define logf log
-#define expf exp
-#define fabsf fabs
-#define powf pow
-#endif
-
typedef struct _binop
{
t_object x_obj;
diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
index b9093f46..abd09317 100644
--- a/pd/src/x_connective.c
+++ b/pd/src/x_connective.c
@@ -508,6 +508,8 @@ static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
{
t_float f;
if (!argc) return;
+ if (argv->a_type != A_FLOAT)
+ goto rejected;
f = atom_getfloat(argv);
for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
if (e->e_w.w_float == f)
@@ -569,6 +571,7 @@ static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
}
}
}
+ rejected:
outlet_list(x->x_rejectout, 0, argc, argv);
}
@@ -600,6 +603,12 @@ static void *route_new(t_symbol *s, int argc, t_atom *argv)
e->e_w.w_float = atom_getfloatarg(n, argc, argv);
else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv);
}
+ if (argc == 1)
+ {
+ if (argv->a_type == A_FLOAT)
+ floatinlet_new(&x->x_obj, &x->x_vec->e_w.w_float);
+ else symbolinlet_new(&x->x_obj, &x->x_vec->e_w.w_symbol);
+ }
x->x_rejectout = outlet_new(&x->x_obj, &s_list);
return (x);
}
@@ -1002,8 +1011,7 @@ static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv)
outlet_bang(u->u_outlet);
else if (u->u_type == TR_ANYTHING)
outlet_anything(u->u_outlet, s, argc, argv);
- else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'",
- s->s_name);
+ else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'");
}
}
@@ -1260,12 +1268,15 @@ static void makefilename_float(t_makefilename *x, t_floatarg f)
char buf[MAXPDSTRING];
if (x->x_accept == A_FLOAT) {
if (x->x_intconvert)
- sprintf(buf, x->x_format->s_name, (int)f);
- else
- sprintf(buf, x->x_format->s_name, f);
+ sprintf(buf, x->x_format->s_name, (int)f);
+ else sprintf(buf, x->x_format->s_name, f);
}
else
- sprintf(buf, x->x_format->s_name, "");
+ {
+ char buf2[MAXPDSTRING];
+ sprintf(buf2, "%g", f);
+ sprintf(buf, x->x_format->s_name, buf2);
+ }
if (buf[0]!=0)
outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
}
diff --git a/pd/src/x_gui.c b/pd/src/x_gui.c
index e83981bb..2409ca41 100644
--- a/pd/src/x_gui.c
+++ b/pd/src/x_gui.c
@@ -46,6 +46,9 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
{
char buf[4*MAXPDSTRING];
char namebuf[80];
+ char sprintfbuf[MAXPDSTRING];
+ char *afterpercent;
+ t_int afterpercentlen;
t_gfxstub *x;
t_symbol *s;
/* if any exists with matching key, burn it. */
@@ -55,7 +58,7 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
if (strlen(cmd) + 50 > 4*MAXPDSTRING)
{
bug("audio dialog too long");
- bug("%x", cmd);
+ bug("%s", cmd);
return;
}
x = (t_gfxstub *)pd_new(gfxstub_class);
@@ -68,7 +71,13 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
x->x_key = key;
x->x_next = gfxstub_list;
gfxstub_list = x;
- sprintf(buf, cmd, s->s_name);
+ /* only replace first %s so sprintf() doesn't crash */
+ afterpercent = strchr(cmd, '%') + 2;
+ afterpercentlen = afterpercent - cmd;
+ strncpy(sprintfbuf, cmd, afterpercentlen);
+ sprintfbuf[afterpercentlen] = '\0';
+ sprintf(buf, sprintfbuf, s->s_name);
+ strncat(buf, afterpercent, (4*MAXPDSTRING) - afterpercentlen);
sys_gui(buf);
}
diff --git a/pd/src/x_interface.c b/pd/src/x_interface.c
index 044961b1..ce685e57 100644
--- a/pd/src/x_interface.c
+++ b/pd/src/x_interface.c
@@ -19,12 +19,28 @@ typedef struct _print
static void *print_new(t_symbol *sel, int argc, t_atom *argv)
{
t_print *x = (t_print *)pd_new(print_class);
- t_symbol *s = atom_getsymbolarg(0, argc, argv);
- if (!*s->s_name)
+ if (argc == 0)
x->x_sym = gensym("print");
- else if (!strcmp(s->s_name, "-n"))
- x->x_sym = &s_;
- else x->x_sym = s;
+ else if (argc == 1 && argv->a_type == A_SYMBOL)
+ {
+ t_symbol *s = atom_getsymbolarg(0, argc, argv);
+ if (!strcmp(s->s_name, "-n"))
+ x->x_sym = &s_;
+ else x->x_sym = s;
+ }
+ else
+ {
+ int bufsize;
+ char *buf;
+ t_binbuf *bb = binbuf_new();
+ binbuf_add(bb, argc, argv);
+ binbuf_gettext(bb, &buf, &bufsize);
+ buf = resizebytes(buf, bufsize, bufsize+1);
+ buf[bufsize] = 0;
+ x->x_sym = gensym(buf);
+ freebytes(buf, bufsize+1);
+ binbuf_free(bb);
+ }
return (x);
}
diff --git a/pd/src/x_misc.c b/pd/src/x_misc.c
index 2d7860d9..13090f0d 100644
--- a/pd/src/x_misc.c
+++ b/pd/src/x_misc.c
@@ -9,24 +9,28 @@
#include <math.h>
#include <stdio.h>
#include <string.h>
-#ifdef HAVE_UNISTD_H
+#ifdef _WIN32
+#include <wtypes.h>
+#include <time.h>
+#else
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/param.h>
#include <unistd.h>
-#endif
-#ifdef MSW
-#include <wtypes.h>
-#include <time.h>
-#endif
+#endif /* _WIN32 */
#if defined (__APPLE__) || defined (__FreeBSD__)
#define CLOCKHZ CLK_TCK
#endif
-#if defined (__linux__)
+#if defined (__linux__) || defined (__CYGWIN__) || defined (ANDROID)
#define CLOCKHZ sysconf(_SC_CLK_TCK)
#endif
+#if defined (__FreeBSD_kernel__) || defined(__GNU__)
+#include <time.h>
+#define CLOCKHZ CLOCKS_PER_SEC
+#endif
+
/* -------------------------- random ------------------------------ */
/* this is strictly homebrew and untested. */
@@ -145,7 +149,7 @@ static void namecanvas_setup(void)
sizeof(t_namecanvas), CLASS_NOINLET, A_DEFSYM, 0);
}
-/* ---------------serial ports (MSW only -- hack) ------------------------- */
+/* ---------------serial ports (_WIN32 only -- hack) ------------------------- */
#define MAXSERIAL 100
static t_class *serial_class;
@@ -194,22 +198,18 @@ static t_class *cputime_class;
typedef struct _cputime
{
t_object x_obj;
-#ifdef HAVE_UNISTD_H
- struct tms x_setcputime;
-#endif
-#ifdef MSW
+#ifdef _WIN32
LARGE_INTEGER x_kerneltime;
LARGE_INTEGER x_usertime;
int x_warned;
-#endif
+#else
+ struct tms x_setcputime;
+#endif /* _WIN32 */
} t_cputime;
static void cputime_bang(t_cputime *x)
{
-#ifdef HAVE_UNISTD_H
- times(&x->x_setcputime);
-#endif
-#ifdef MSW
+#ifdef _WIN32
FILETIME ignorethis, ignorethat;
BOOL retval;
retval = GetProcessTimes(GetCurrentProcess(), &ignorethis, &ignorethat,
@@ -222,12 +222,14 @@ static void cputime_bang(t_cputime *x)
x->x_kerneltime.QuadPart = 0;
x->x_usertime.QuadPart = 0;
}
-#endif
+#else
+ times(&x->x_setcputime);
+#endif /* _WIN32 */
}
static void cputime_bang2(t_cputime *x)
{
-#ifdef HAVE_UNISTD_H
+#ifndef _WIN32
t_float elapsedcpu;
struct tms newcputime;
times(&newcputime);
@@ -235,8 +237,7 @@ static void cputime_bang2(t_cputime *x)
newcputime.tms_utime + newcputime.tms_stime -
x->x_setcputime.tms_utime - x->x_setcputime.tms_stime) / CLOCKHZ;
outlet_float(x->x_obj.ob_outlet, elapsedcpu);
-#endif
-#ifdef MSW
+#else
t_float elapsedcpu;
FILETIME ignorethis, ignorethat;
LARGE_INTEGER usertime, kerneltime;
@@ -250,7 +251,7 @@ static void cputime_bang2(t_cputime *x)
(usertime.QuadPart - x->x_usertime.QuadPart));
else elapsedcpu = 0;
outlet_float(x->x_obj.ob_outlet, elapsedcpu);
-#endif
+#endif /* NOT _WIN32 */
}
static void *cputime_new(void)
@@ -259,7 +260,7 @@ static void *cputime_new(void)
outlet_new(&x->x_obj, gensym("float"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
-#ifdef MSW
+#ifdef _WIN32
x->x_warned = 0;
#endif
cputime_bang(x);
diff --git a/pd/src/x_net.c b/pd/src/x_net.c
index 9d1aee0b..7e0d0be4 100644
--- a/pd/src/x_net.c
+++ b/pd/src/x_net.c
@@ -76,6 +76,10 @@ static void netsend_connect(t_netsend *x, t_symbol *hostname,
&intarg, sizeof(intarg)) < 0)
post("setsockopt (SO_RCVBUF) failed\n");
#endif
+ intarg = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+ (const void *)&intarg, sizeof(intarg)) < 0)
+ post("setting SO_BROADCAST");
/* for stream (TCP) sockets, specify "nodelay" */
if (x->x_protocol == SOCK_STREAM)
{
@@ -282,6 +286,10 @@ static void *netreceive_new(t_symbol *compatflag,
&intarg, sizeof(intarg)) < 0)
post("setsockopt (SO_RCVBUF) failed\n");
#endif
+ intarg = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+ (const void *)&intarg, sizeof(intarg)) < 0)
+ post("setting SO_BROADCAST");
/* Stream (TCP) sockets are set NODELAY */
if (!udp)
{
diff --git a/pd/src/x_time.c b/pd/src/x_time.c
index 5dc9d37f..c81c1ed1 100644
--- a/pd/src/x_time.c
+++ b/pd/src/x_time.c
@@ -139,6 +139,7 @@ static void metro_setup(void)
}
/* -------------------------- line ------------------------------ */
+#define DEFAULTLINEGRAIN 20
static t_class *line_class;
typedef struct _line
@@ -168,6 +169,8 @@ static void line_tick(t_line *x)
outlet_float(x->x_obj.ob_outlet,
x->x_setval + x->x_1overtimediff * (timenow - x->x_prevtime)
* (x->x_targetval - x->x_setval));
+ if (x->x_grain <= 0)
+ x->x_grain = DEFAULTLINEGRAIN;
clock_delay(x->x_clock,
(x->x_grain > msectogo ? msectogo : x->x_grain));
}
@@ -188,6 +191,8 @@ static void line_float(t_line *x, t_float f)
line_tick(x);
x->x_gotinlet = 0;
x->x_1overtimediff = 1./ (x->x_targettime - timenow);
+ if (x->x_grain <= 0)
+ x->x_grain = DEFAULTLINEGRAIN;
clock_delay(x->x_clock,
(x->x_grain > x->x_in1val ? x->x_in1val : x->x_grain));
@@ -232,10 +237,10 @@ static void *line_new(t_floatarg f, t_floatarg grain)
x->x_1overtimediff = 1;
x->x_clock = clock_new(x, (t_method)line_tick);
x->x_targettime = x->x_prevtime = clock_getsystime();
- if (grain <= 0) grain = 20;
x->x_grain = grain;
outlet_new(&x->x_obj, gensym("float"));
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
+ floatinlet_new(&x->x_obj, &x->x_grain);
return (x);
}
diff --git a/pd/tcl/AppMain.tcl b/pd/tcl/AppMain.tcl
index b170c6f5..7c68a9d0 100644
--- a/pd/tcl/AppMain.tcl
+++ b/pd/tcl/AppMain.tcl
@@ -3,17 +3,8 @@
# other configuration, like when 'pd' launches Wish.app or when 'pd' is using
# an X11 wish on Mac OS X. GNU/Linux and Windows will never use this file.
-
-puts --------------------------AppMain.tcl-----------------------------------
-catch {console show}
-
package require apple_events
-puts "AppMain.tcl"
-puts "argv0: $argv0"
-puts "executable: [info nameofexecutable]"
-puts "argc: $argc argv: $argv"
-
# TODO is there anything useful to do with the psn (Process Serial Number)?
if {[string first "-psn" [lindex $argv 0]] == 0} {
set argv [lrange $argv 1 end]
diff --git a/pd/tcl/Makefile.am b/pd/tcl/Makefile.am
new file mode 100644
index 00000000..65780ebf
--- /dev/null
+++ b/pd/tcl/Makefile.am
@@ -0,0 +1,16 @@
+AUTOMAKE_OPTIONS = foreign
+
+SUFFIXES = .tcl
+
+# we want these in the dist tarball
+#EXTRA_DIST = CHANGELOG.txt notes.txt makefile.mingw
+
+
+bin_SCRIPTS = pd-gui.tcl
+
+libpdtcldir = $(pkglibdir)/tcl
+dist_libpdtcl_SCRIPTS = pd-gui.tcl
+dist_libpdtcl_DATA = apple_events.tcl dialog_canvas.tcl dialog_gatom.tcl dialog_path.tcl pd_bindings.tcl pd_menus.tcl pdwindow.tcl scrollboxwindow.tcl AppMain.tcl dialog_data.tcl dialog_iemgui.tcl dialog_startup.tcl pd_connect.tcl pdtk_array.tcl pkgIndex.tcl wheredoesthisgo.tcl dialog_array.tcl dialog_find.tcl dialog_message.tcl helpbrowser.tcl pdtk_canvas.tcl pkg_mkIndex.tcl dialog_audio.tcl dialog_font.tcl dialog_midi.tcl opt_parser.tcl pd_menucommands.tcl pdtk_text.tcl scrollbox.tcl pd.ico
+
+etags: TAGS
+ etags --append --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl
diff --git a/pd/tcl/apple_events.tcl b/pd/tcl/apple_events.tcl
index cfc92982..0311add7 100644
--- a/pd/tcl/apple_events.tcl
+++ b/pd/tcl/apple_events.tcl
@@ -1,53 +1,65 @@
package provide apple_events 0.1
+package require pdwindow
package require wheredoesthisgo
# from http://wiki.tcl.tk/12987
set ::tk::mac::CGAntialiasLimit 0 ;# min line thickness to anti-alias (default: 3)
-set ::tk::mac::antialiasedtext 1 ;# enable/disable anti-aliased text
+set ::tk::mac::antialiasedtext 1 ;# enable anti-aliased text
# kAEOpenDocuments
proc ::tk::mac::OpenDocument {args} {
- foreach filename $args {
- puts "open_file $filename"
- open_file $filename
+ foreach filename $args {
+ if {$::done_init} {
+ open_file $filename
+ } else {
+ lappend ::filestoopen_list $filename
+ }
}
set ::pd_menucommands::menu_open_dir [file dirname $filename]
}
# kEventAppHidden
-proc ::tk::mac::OnHide {} {
- # TODO
+proc ::tk::mac::OnHide {args} {
+ ::pdwindow::verbose 1 "::tk::mac::OnHide $args +++++++++++++++++++++"
}
# kEventAppShown
-proc ::tk::mac::OnShow {} {
- # TODO
+proc ::tk::mac::OnShow {args} {
+ ::pdwindow::verbose 1 "::tk::mac::OnShow $args +++++++++++++++++++++"
+}
+
+# open About Pd... in Tk/Cocoa
+proc tkAboutDialog {} {
+ menu_aboutpd
}
# kAEShowPreferences
-proc ::tk::mac::ShowPreferences {} {
- menu_preferences_dialog
+proc ::tk::mac::ShowPreferences {args} {
+ ::pdwindow::verbose 1 "::tk::mac::ShowPreferences $args ++++++++++++"
+ pdsend "pd start-path-dialog"
}
# kAEQuitApplication
-#proc ::tk::mac::Quit {} {
-# # TODO sort this out... how to quit pd-gui after sending the message
-# puts stderr "Custom exit proc"
-# pdsend "pd verifyquit"
+proc ::tk::mac::Quit {args} {
+ pdsend "pd verifyquit"
+}
+
+# on Tk/Cocoa, override the Apple Help menu
+#proc tk::mac::ShowHelp {args} {
#}
# these I gleaned by reading the source (tkMacOSXHLEvents.c)
proc ::tk::mac::PrintDocument {args} {
- # TODO what's $mytoplevel here?. I am guessing args would be the same as
- # ::tk::mac::OpenDocument
- #menu_print $mytoplevel
+ menu_print $::focused_window
}
-proc ::tk::mac::OpenApplication {} {
+proc ::tk::mac::OpenApplication {args} {
+ ::pdwindow::verbose 1 "::tk::mac::OpenApplication $args ++++++++++++"
}
-proc ::tk::mac::ReopenApplication {} {
+proc ::tk::mac::ReopenApplication {args} {
+ ::pdwindow::verbose 1 "::tk::mac::ReopenApplication $args ++++++++++"
}
diff --git a/pd/tcl/dialog_array.tcl b/pd/tcl/dialog_array.tcl
index 87b2de8c..0f2696d2 100644
--- a/pd/tcl/dialog_array.tcl
+++ b/pd/tcl/dialog_array.tcl
@@ -239,7 +239,6 @@ proc ::dialog_array::ok {mytoplevel} {
}
proc ::dialog_array::pdtk_array_dialog {mytoplevel name size flags newone} {
-puts "::dialog_array::pdtk_array_dialog {$mytoplevel $name $size $flags $newone}"
if {[winfo exists $mytoplevel]} {
wm deiconify $mytoplevel
raise $mytoplevel
@@ -262,7 +261,11 @@ puts "::dialog_array::pdtk_array_dialog {$mytoplevel $name $size $flags $newone}
proc ::dialog_array::create_dialog {mytoplevel newone} {
toplevel $mytoplevel -class DialogWindow
wm title $mytoplevel [_ "Array Properties"]
- if {$::windowingsystem eq "aqua"} {$mytoplevel configure -menu .menubar}
+ wm group $mytoplevel .
+ wm resizable $mytoplevel 0 0
+ wm transient $mytoplevel $::focused_window
+ $mytoplevel configure -menu $::dialog_menubar
+ $mytoplevel configure -padx 0 -pady 0
::pd_bindings::dialog_bindings $mytoplevel "array"
frame $mytoplevel.name
@@ -315,14 +318,16 @@ proc ::dialog_array::create_dialog {mytoplevel newone} {
}
# end jsarlo
frame $mytoplevel.buttonframe
- pack $mytoplevel.buttonframe -side bottom -fill x -pady 2m
+ pack $mytoplevel.buttonframe -side bottom -expand 1 -fill x -pady 2m
button $mytoplevel.buttonframe.cancel -text [_ "Cancel"] \
-command "::dialog_array::cancel $mytoplevel"
- if {$newone == 0} {button $mytoplevel.buttonframe.apply -text [_ "Apply"] \
- -command "::dialog_array::apply $mytoplevel"}
+ pack $mytoplevel.buttonframe.cancel -side left -expand 1 -fill x -padx 10
+ if {$newone == 0 && $::windowingsystem ne "aqua"} {
+ button $mytoplevel.buttonframe.apply -text [_ "Apply"] \
+ -command "::dialog_array::apply $mytoplevel"
+ pack $mytoplevel.buttonframe.apply -side left -expand 1 -fill x -padx 10
+ }
button $mytoplevel.buttonframe.ok -text [_ "OK"]\
-command "::dialog_array::ok $mytoplevel"
- pack $mytoplevel.buttonframe.cancel -side left -expand 1
- if {$newone == 0} {pack $mytoplevel.buttonframe.apply -side left -expand 1}
- pack $mytoplevel.buttonframe.ok -side left -expand 1
+ pack $mytoplevel.buttonframe.ok -side left -expand 1 -fill x -padx 10
}
diff --git a/pd/tcl/dialog_audio.tcl b/pd/tcl/dialog_audio.tcl
index 1025f66e..56f18f45 100644
--- a/pd/tcl/dialog_audio.tcl
+++ b/pd/tcl/dialog_audio.tcl
@@ -4,19 +4,20 @@ namespace eval ::dialog_audio:: {
namespace export pdtk_audio_dialog
}
-# TODO this panel really needs some reworking, it works but the code is
-# very unreadable
+# TODO this panel really needs some reworking, it works but the code is very
+# unreadable. The panel could look a lot better too, like using menubuttons
+# instead of regular buttons with tk_popup for pulldown menus.
####################### audio dialog ##################3
-proc ::dialog_audio::apply {id} {
+proc ::dialog_audio::apply {mytoplevel} {
global audio_indev1 audio_indev2 audio_indev3 audio_indev4
global audio_inchan1 audio_inchan2 audio_inchan3 audio_inchan4
global audio_inenable1 audio_inenable2 audio_inenable3 audio_inenable4
global audio_outdev1 audio_outdev2 audio_outdev3 audio_outdev4
global audio_outchan1 audio_outchan2 audio_outchan3 audio_outchan4
global audio_outenable1 audio_outenable2 audio_outenable3 audio_outenable4
- global audio_sr audio_advance audio_callback
+ global audio_sr audio_advance audio_callback audio_blocksize
pdsend "pd audio-dialog \
$audio_indev1 \
@@ -37,16 +38,17 @@ proc ::dialog_audio::apply {id} {
[expr $audio_outchan4 * ( $audio_outenable4 ? 1 : -1 ) ]\
$audio_sr \
$audio_advance \
- $audio_callback"
+ $audio_callback \
+ $audio_blocksize"
}
-proc ::dialog_audio::cancel {id} {
- pdsend "$id cancel"
+proc ::dialog_audio::cancel {mytoplevel} {
+ pdsend "$mytoplevel cancel"
}
-proc ::dialog_audio::ok {id} {
- ::dialog_audio::apply $id
- ::dialog_audio::cancel $id
+proc ::dialog_audio::ok {mytoplevel} {
+ ::dialog_audio::apply $mytoplevel
+ ::dialog_audio::cancel $mytoplevel
}
# callback from popup menu
@@ -78,18 +80,19 @@ proc audio_popup {name buttonname varname devlist} {
# opening several devices; if not, we get an extra button to turn longform
# on and restart the dialog.
-proc ::dialog_audio::pdtk_audio_dialog {id indev1 indev2 indev3 indev4 \
+proc ::dialog_audio::pdtk_audio_dialog {mytoplevel \
+ indev1 indev2 indev3 indev4 \
inchan1 inchan2 inchan3 inchan4 \
outdev1 outdev2 outdev3 outdev4 \
outchan1 outchan2 outchan3 outchan4 sr advance multi callback \
- longform} {
+ longform blocksize} {
global audio_indev1 audio_indev2 audio_indev3 audio_indev4
global audio_inchan1 audio_inchan2 audio_inchan3 audio_inchan4
global audio_inenable1 audio_inenable2 audio_inenable3 audio_inenable4
global audio_outdev1 audio_outdev2 audio_outdev3 audio_outdev4
global audio_outchan1 audio_outchan2 audio_outchan3 audio_outchan4
global audio_outenable1 audio_outenable2 audio_outenable3 audio_outenable4
- global audio_sr audio_advance audio_callback
+ global audio_sr audio_advance audio_callback audio_blocksize
global audio_indevlist audio_outdevlist
global pd_indev pd_outdev
global audio_longform
@@ -125,174 +128,196 @@ proc ::dialog_audio::pdtk_audio_dialog {id indev1 indev2 indev3 indev4 \
set audio_sr $sr
set audio_advance $advance
set audio_callback $callback
-
- toplevel $id
- wm title $id [_ "Audio Settings"]
- if {$::windowingsystem eq "aqua"} {$id configure -menu .menubar}
- ::pd_bindings::dialog_bindings $id "audio"
-
- frame $id.buttonframe
- pack $id.buttonframe -side bottom -fill x -pady 2m
- button $id.buttonframe.cancel -text [_ "Cancel"]\
- -command "::dialog_audio::cancel $id"
- button $id.buttonframe.apply -text [_ "Apply"]\
- -command "::dialog_audio::apply $id"
- button $id.buttonframe.ok -text [_ "OK"]\
- -command "::dialog_audio::ok $id"
- button $id.buttonframe.save -text [_ "Save all settings"]\
- -command "::dialog_audio::apply $id \; pdsend \"pd save-preferences\""
- pack $id.buttonframe.cancel $id.buttonframe.apply $id.buttonframe.ok \
- $id.buttonframe.save -side left -expand 1
+ set audio_blocksize $blocksize
+
+ toplevel $mytoplevel -class DialogWindow
+ wm title $mytoplevel [_ "Audio Settings"]
+ wm group $mytoplevel .
+ wm resizable $mytoplevel 0 0
+ wm transient $mytoplevel
+ $mytoplevel configure -menu $::dialog_menubar
+ $mytoplevel configure -padx 10 -pady 5
+ ::pd_bindings::dialog_bindings $mytoplevel "audio"
+ # not all Tcl/Tk versions or platforms support -topmost, so catch the error
+ catch {wm attributes $mytoplevel -topmost 1}
+
+ frame $mytoplevel.buttonframe
+ pack $mytoplevel.buttonframe -side bottom -fill x -pady 2m
+ button $mytoplevel.buttonframe.cancel -text [_ "Cancel"]\
+ -command "::dialog_audio::cancel $mytoplevel"
+ pack $mytoplevel.buttonframe.cancel -side left -expand 1 -fill x -padx 15
+ button $mytoplevel.buttonframe.apply -text [_ "Apply"]\
+ -command "::dialog_audio::apply $mytoplevel"
+ pack $mytoplevel.buttonframe.apply -side left -expand 1 -fill x -padx 15
+ button $mytoplevel.buttonframe.ok -text [_ "OK"] \
+ -command "::dialog_audio::ok $mytoplevel"
+ pack $mytoplevel.buttonframe.ok -side left -expand 1 -fill x -padx 15
+
+ button $mytoplevel.saveall -text [_ "Save All Settings"]\
+ -command "::dialog_audio::apply $mytoplevel; pdsend {pd save-preferences}"
+ pack $mytoplevel.saveall -side bottom -expand 1 -pady 5
# sample rate and advance
- frame $id.srf
- pack $id.srf -side top
+ frame $mytoplevel.srf
+ pack $mytoplevel.srf -side top
- label $id.srf.l1 -text [_ "Sample rate:"]
- entry $id.srf.x1 -textvariable audio_sr -width 7
- label $id.srf.l2 -text [_ "Delay (msec):"]
- entry $id.srf.x2 -textvariable audio_advance -width 4
- pack $id.srf.l1 $id.srf.x1 $id.srf.l2 $id.srf.x2 -side left
+ label $mytoplevel.srf.l1 -text [_ "Sample rate:"]
+ entry $mytoplevel.srf.x1 -textvariable audio_sr -width 7
+ label $mytoplevel.srf.l2 -text [_ "Delay (msec):"]
+ entry $mytoplevel.srf.x2 -textvariable audio_advance -width 4
+
+ label $mytoplevel.srf.l3 -text [_ "Block size:"]
+ tk_optionMenu $mytoplevel.srf.x3 audio_blocksize 64 128 256 512 1024 2048
+
+ pack $mytoplevel.srf.l1 $mytoplevel.srf.x1 $mytoplevel.srf.l2 \
+ $mytoplevel.srf.x2 $mytoplevel.srf.l3 $mytoplevel.srf.x3 -side left
if {$audio_callback >= 0} {
- checkbutton $id.srf.x3 -variable audio_callback \
+ checkbutton $mytoplevel.srf.x4 -variable audio_callback \
-text [_ "Use callbacks"] -anchor e
- pack $id.srf.x3 -side left
+ pack $mytoplevel.srf.x4 -side left
}
# input device 1
- frame $id.in1f
- pack $id.in1f -side top
+ frame $mytoplevel.in1f
+ pack $mytoplevel.in1f -side top
- checkbutton $id.in1f.x0 -variable audio_inenable1 \
+ checkbutton $mytoplevel.in1f.x0 -variable audio_inenable1 \
-text [_ "Input device 1:"] -anchor e
- button $id.in1f.x1 -text [lindex $audio_indevlist $audio_indev1] \
- -command [list audio_popup $id $id.in1f.x1 audio_indev1 $audio_indevlist]
- label $id.in1f.l2 -text [_ "Channels:"]
- entry $id.in1f.x2 -textvariable audio_inchan1 -width 3
- pack $id.in1f.x0 $id.in1f.x1 $id.in1f.l2 $id.in1f.x2 -side left -fill x
+ button $mytoplevel.in1f.x1 -text [lindex $audio_indevlist $audio_indev1] \
+ -command [list audio_popup $mytoplevel $mytoplevel.in1f.x1 audio_indev1 $audio_indevlist]
+ label $mytoplevel.in1f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.in1f.x2 -textvariable audio_inchan1 -width 3
+ pack $mytoplevel.in1f.x0 $mytoplevel.in1f.x1 $mytoplevel.in1f.l2 \
+ $mytoplevel.in1f.x2 -side left -fill x
# input device 2
if {$longform && $multi > 1 && [llength $audio_indevlist] > 1} {
- frame $id.in2f
- pack $id.in2f -side top
+ frame $mytoplevel.in2f
+ pack $mytoplevel.in2f -side top
- checkbutton $id.in2f.x0 -variable audio_inenable2 \
+ checkbutton $mytoplevel.in2f.x0 -variable audio_inenable2 \
-text [_ "Input device 2:"] -anchor e
- button $id.in2f.x1 -text [lindex $audio_indevlist $audio_indev2] \
- -command [list audio_popup $id $id.in2f.x1 audio_indev2 \
+ button $mytoplevel.in2f.x1 -text [lindex $audio_indevlist $audio_indev2] \
+ -command [list audio_popup $mytoplevel $mytoplevel.in2f.x1 audio_indev2 \
$audio_indevlist]
- label $id.in2f.l2 -text [_ "Channels:"]
- entry $id.in2f.x2 -textvariable audio_inchan2 -width 3
- pack $id.in2f.x0 $id.in2f.x1 $id.in2f.l2 $id.in2f.x2 -side left -fill x
+ label $mytoplevel.in2f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.in2f.x2 -textvariable audio_inchan2 -width 3
+ pack $mytoplevel.in2f.x0 $mytoplevel.in2f.x1 $mytoplevel.in2f.l2 \
+ $mytoplevel.in2f.x2 -side left -fill x
}
# input device 3
if {$longform && $multi > 1 && [llength $audio_indevlist] > 2} {
- frame $id.in3f
- pack $id.in3f -side top
+ frame $mytoplevel.in3f
+ pack $mytoplevel.in3f -side top
- checkbutton $id.in3f.x0 -variable audio_inenable3 \
+ checkbutton $mytoplevel.in3f.x0 -variable audio_inenable3 \
-text [_ "Input device 3:"] -anchor e
- button $id.in3f.x1 -text [lindex $audio_indevlist $audio_indev3] \
- -command [list audio_popup $id $id.in3f.x1 audio_indev3 \
+ button $mytoplevel.in3f.x1 -text [lindex $audio_indevlist $audio_indev3] \
+ -command [list audio_popup $mytoplevel $mytoplevel.in3f.x1 audio_indev3 \
$audio_indevlist]
- label $id.in3f.l2 -text [_ "Channels:"]
- entry $id.in3f.x2 -textvariable audio_inchan3 -width 3
- pack $id.in3f.x0 $id.in3f.x1 $id.in3f.l2 $id.in3f.x2 -side left
+ label $mytoplevel.in3f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.in3f.x2 -textvariable audio_inchan3 -width 3
+ pack $mytoplevel.in3f.x0 $mytoplevel.in3f.x1 $mytoplevel.in3f.l2 $mytoplevel.in3f.x2 -side left
}
# input device 4
if {$longform && $multi > 1 && [llength $audio_indevlist] > 3} {
- frame $id.in4f
- pack $id.in4f -side top
+ frame $mytoplevel.in4f
+ pack $mytoplevel.in4f -side top
- checkbutton $id.in4f.x0 -variable audio_inenable4 \
+ checkbutton $mytoplevel.in4f.x0 -variable audio_inenable4 \
-text [_ "Input device 4:"] -anchor e
- button $id.in4f.x1 -text [lindex $audio_indevlist $audio_indev4] \
- -command [list audio_popup $id $id.in4f.x1 audio_indev4 \
+ button $mytoplevel.in4f.x1 -text [lindex $audio_indevlist $audio_indev4] \
+ -command [list audio_popup $mytoplevel $mytoplevel.in4f.x1 audio_indev4 \
$audio_indevlist]
- label $id.in4f.l2 -text [_ "Channels:"]
- entry $id.in4f.x2 -textvariable audio_inchan4 -width 3
- pack $id.in4f.x0 $id.in4f.x1 $id.in4f.l2 $id.in4f.x2 -side left
+ label $mytoplevel.in4f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.in4f.x2 -textvariable audio_inchan4 -width 3
+ pack $mytoplevel.in4f.x0 $mytoplevel.in4f.x1 $mytoplevel.in4f.l2 \
+ $mytoplevel.in4f.x2 -side left
}
# output device 1
- frame $id.out1f
- pack $id.out1f -side top
+ frame $mytoplevel.out1f
+ pack $mytoplevel.out1f -side top
- checkbutton $id.out1f.x0 -variable audio_outenable1 \
+ checkbutton $mytoplevel.out1f.x0 -variable audio_outenable1 \
-text [_ "Output device 1:"] -anchor e
if {$multi == 0} {
- label $id.out1f.l1 \
+ label $mytoplevel.out1f.l1 \
-text [_ "(same as input device) .............. "]
} else {
- button $id.out1f.x1 -text [lindex $audio_outdevlist $audio_outdev1] \
- -command [list audio_popup $id $id.out1f.x1 audio_outdev1 \
+ button $mytoplevel.out1f.x1 -text [lindex $audio_outdevlist $audio_outdev1] \
+ -command [list audio_popup $mytoplevel $mytoplevel.out1f.x1 audio_outdev1 \
$audio_outdevlist]
}
- label $id.out1f.l2 -text [_ "Channels:"]
- entry $id.out1f.x2 -textvariable audio_outchan1 -width 3
+ label $mytoplevel.out1f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.out1f.x2 -textvariable audio_outchan1 -width 3
if {$multi == 0} {
- pack $id.out1f.x0 $id.out1f.l1 $id.out1f.x2 -side left -fill x
+ pack $mytoplevel.out1f.x0 $mytoplevel.out1f.l1 $mytoplevel.out1f.x2 -side left -fill x
} else {
- pack $id.out1f.x0 $id.out1f.x1 $id.out1f.l2 $id.out1f.x2 -side left -fill x
+ pack $mytoplevel.out1f.x0 $mytoplevel.out1f.x1 $mytoplevel.out1f.l2\
+ $mytoplevel.out1f.x2 -side left -fill x
}
# output device 2
if {$longform && $multi > 1 && [llength $audio_outdevlist] > 1} {
- frame $id.out2f
- pack $id.out2f -side top
+ frame $mytoplevel.out2f
+ pack $mytoplevel.out2f -side top
- checkbutton $id.out2f.x0 -variable audio_outenable2 \
+ checkbutton $mytoplevel.out2f.x0 -variable audio_outenable2 \
-text [_ "Output device 2:"] -anchor e
- button $id.out2f.x1 -text [lindex $audio_outdevlist $audio_outdev2] \
+ button $mytoplevel.out2f.x1 -text [lindex $audio_outdevlist $audio_outdev2] \
-command \
- [list audio_popup $id $id.out2f.x1 audio_outdev2 $audio_outdevlist]
- label $id.out2f.l2 -text [_ "Channels:"]
- entry $id.out2f.x2 -textvariable audio_outchan2 -width 3
- pack $id.out2f.x0 $id.out2f.x1 $id.out2f.l2 $id.out2f.x2 -side left
+ [list audio_popup $mytoplevel $mytoplevel.out2f.x1 audio_outdev2 $audio_outdevlist]
+ label $mytoplevel.out2f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.out2f.x2 -textvariable audio_outchan2 -width 3
+ pack $mytoplevel.out2f.x0 $mytoplevel.out2f.x1 $mytoplevel.out2f.l2\
+ $mytoplevel.out2f.x2 -side left
}
# output device 3
if {$longform && $multi > 1 && [llength $audio_outdevlist] > 2} {
- frame $id.out3f
- pack $id.out3f -side top
+ frame $mytoplevel.out3f
+ pack $mytoplevel.out3f -side top
- checkbutton $id.out3f.x0 -variable audio_outenable3 \
+ checkbutton $mytoplevel.out3f.x0 -variable audio_outenable3 \
-text [_ "Output device 3:"] -anchor e
- button $id.out3f.x1 -text [lindex $audio_outdevlist $audio_outdev3] \
+ button $mytoplevel.out3f.x1 -text [lindex $audio_outdevlist $audio_outdev3] \
-command \
- [list audio_popup $id $id.out3f.x1 audio_outdev3 $audio_outdevlist]
- label $id.out3f.l2 -text [_ "Channels:"]
- entry $id.out3f.x2 -textvariable audio_outchan3 -width 3
- pack $id.out3f.x0 $id.out3f.x1 $id.out3f.l2 $id.out3f.x2 -side left
+ [list audio_popup $mytoplevel $mytoplevel.out3f.x1 audio_outdev3 $audio_outdevlist]
+ label $mytoplevel.out3f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.out3f.x2 -textvariable audio_outchan3 -width 3
+ pack $mytoplevel.out3f.x0 $mytoplevel.out3f.x1 $mytoplevel.out3f.l2 \
+ $mytoplevel.out3f.x2 -side left
}
# output device 4
if {$longform && $multi > 1 && [llength $audio_outdevlist] > 3} {
- frame $id.out4f
- pack $id.out4f -side top
+ frame $mytoplevel.out4f
+ pack $mytoplevel.out4f -side top
- checkbutton $id.out4f.x0 -variable audio_outenable4 \
+ checkbutton $mytoplevel.out4f.x0 -variable audio_outenable4 \
-text [_ "Output device 4:"] -anchor e
- button $id.out4f.x1 -text [lindex $audio_outdevlist $audio_outdev4] \
+ button $mytoplevel.out4f.x1 -text [lindex $audio_outdevlist $audio_outdev4] \
-command \
- [list audio_popup $id $id.out4f.x1 audio_outdev4 $audio_outdevlist]
- label $id.out4f.l2 -text [_ "Channels:"]
- entry $id.out4f.x2 -textvariable audio_outchan4 -width 3
- pack $id.out4f.x0 $id.out4f.x1 $id.out4f.l2 $id.out4f.x2 -side left
+ [list audio_popup $mytoplevel $mytoplevel.out4f.x1 audio_outdev4 $audio_outdevlist]
+ label $mytoplevel.out4f.l2 -text [_ "Channels:"]
+ entry $mytoplevel.out4f.x2 -textvariable audio_outchan4 -width 3
+ pack $mytoplevel.out4f.x0 $mytoplevel.out4f.x1 $mytoplevel.out4f.l2 \
+ $mytoplevel.out4f.x2 -side left
}
# if not the "long form" but if "multi" is 2, make a button to
# restart with longform set.
if {$longform == 0 && $multi > 1} {
- frame $id.longbutton
- pack $id.longbutton -side top
- button $id.longbutton.b -text [_ "Use multiple devices"] \
+ frame $mytoplevel.longbutton
+ pack $mytoplevel.longbutton -side top
+ button $mytoplevel.longbutton.b -text [_ "Use multiple devices"] \
-command {pdsend "pd audio-properties 1"}
- pack $id.longbutton.b
+ pack $mytoplevel.longbutton.b
}
- $id.srf.x1 select from 0
- $id.srf.x1 select adjust end
- focus $id.srf.x1
+ $mytoplevel.srf.x1 select from 0
+ $mytoplevel.srf.x1 select adjust end
+ focus $mytoplevel.srf.x1
}
diff --git a/pd/tcl/dialog_canvas.tcl b/pd/tcl/dialog_canvas.tcl
index 06444807..ea3f5d65 100644
--- a/pd/tcl/dialog_canvas.tcl
+++ b/pd/tcl/dialog_canvas.tcl
@@ -104,7 +104,6 @@ proc ::dialog_canvas::pdtk_canvas_dialog {mytoplevel xscale yscale graphmeflags
} else {
create_dialog $mytoplevel
}
- puts "canvas_dialog $mytoplevel"
switch -- $graphmeflags {
0 {
$mytoplevel.parent.graphme deselect
@@ -119,7 +118,7 @@ proc ::dialog_canvas::pdtk_canvas_dialog {mytoplevel xscale yscale graphmeflags
$mytoplevel.parent.graphme select
$mytoplevel.parent.hidetext select
} default {
- pdtk_post "Warning: unknown graphme flags received in pdtk_canvas_dialog"
+ ::pdwindow::error [_ "WARNING: unknown graphme flags received in pdtk_canvas_dialog"]
}
}
@@ -131,8 +130,8 @@ proc ::dialog_canvas::pdtk_canvas_dialog {mytoplevel xscale yscale graphmeflags
$mytoplevel.range.y.to_entry insert 0 $yto
$mytoplevel.range.x.size_entry insert 0 $xsize
$mytoplevel.range.y.size_entry insert 0 $ysize
- $mytoplevel.range.x.margin_entry insert 0 $xsize
- $mytoplevel.range.y.margin_entry insert 0 $ysize
+ $mytoplevel.range.x.margin_entry insert 0 $xmargin
+ $mytoplevel.range.y.margin_entry insert 0 $ymargin
::dialog_canvas::checkcommand $mytoplevel
}
@@ -140,7 +139,11 @@ proc ::dialog_canvas::pdtk_canvas_dialog {mytoplevel xscale yscale graphmeflags
proc ::dialog_canvas::create_dialog {mytoplevel} {
toplevel $mytoplevel -class DialogWindow
wm title $mytoplevel [_ "Canvas Properties"]
- if {$::windowingsystem eq "aqua"} {$mytoplevel configure -menu .menubar}
+ wm group $mytoplevel .
+ wm resizable $mytoplevel 0 0
+ wm transient $mytoplevel $::focused_window
+ $mytoplevel configure -menu $::dialog_menubar
+ $mytoplevel configure -padx 0 -pady 0
::pd_bindings::dialog_bindings $mytoplevel "canvas"
labelframe $mytoplevel.scale -text [_ "Scale"] -borderwidth 1
@@ -201,13 +204,16 @@ proc ::dialog_canvas::create_dialog {mytoplevel} {
-side left
frame $mytoplevel.buttons
- pack $mytoplevel.buttons -side bottom -fill x -pady 2m
+ pack $mytoplevel.buttons -side bottom -fill x -expand 1 -pady 2m
button $mytoplevel.buttons.cancel -text [_ "Cancel"] \
-command "::dialog_canvas::cancel $mytoplevel"
- button $mytoplevel.buttons.apply -text [_ "Apply"] \
- -command "::dialog_canvas::apply $mytoplevel"
+ pack $mytoplevel.buttons.cancel -side left -expand 1 -fill x -padx 10
+ if {$::windowingsystem ne "aqua"} {
+ button $mytoplevel.buttons.apply -text [_ "Apply"] \
+ -command "::dialog_canvas::apply $mytoplevel"
+ pack $mytoplevel.buttons.apply -side left -expand 1 -fill x -padx 10
+ }
button $mytoplevel.buttons.ok -text [_ "OK"] \
-command "::dialog_canvas::ok $mytoplevel"
- pack $mytoplevel.buttons.cancel $mytoplevel.buttons.apply \
- $mytoplevel.buttons.ok -side left -expand 1
+ pack $mytoplevel.buttons.ok -side left -expand 1 -fill x -padx 10
}
diff --git a/pd/tcl/dialog_data.tcl b/pd/tcl/dialog_data.tcl
new file mode 100644
index 00000000..0bc989f5
--- /dev/null
+++ b/pd/tcl/dialog_data.tcl
@@ -0,0 +1,53 @@
+
+package provide dialog_data 0.1
+
+namespace eval ::dialog_data:: {
+ namespace export pdtk_data_dialog
+}
+
+############ pdtk_data_dialog -- run a data dialog #########
+
+proc ::dialog_data::send {mytoplevel} {
+ for {set i 1} {[$mytoplevel.text compare [concat $i.0 + 3 chars] < end]} \
+ {incr i 1} {
+ pdsend "$mytoplevel data [$mytoplevel.text get $i.0 [expr $i + 1].0]"
+ }
+ pdsend "$mytoplevel end"
+}
+
+proc ::dialog_data::cancel {mytoplevel} {
+ pdsend "$mytoplevel cancel"
+}
+
+proc ::dialog_data::ok {mytoplevel} {
+ ::dialog_data::send $mytoplevel
+ ::dialog_data::cancel $mytoplevel
+}
+
+proc ::dialog_data::pdtk_data_dialog {mytoplevel stuff} {
+ toplevel $mytoplevel -class DialogWindow
+ wm title $mytoplevel [_ "Data Properties"]
+ wm group $mytoplevel $::focused_window
+ wm transient $mytoplevel $::focused_window
+ $mytoplevel configure -menu $::dialog_menubar
+ $mytoplevel configure -padx 0 -pady 0
+
+ frame $mytoplevel.buttonframe
+ pack $mytoplevel.buttonframe -side bottom -fill x -pady 2m
+ button $mytoplevel.buttonframe.send -text [_ "Send (Ctrl s)"] \
+ -command "::dialog_data::send $mytoplevel"
+ button $mytoplevel.buttonframe.ok -text [_ "OK (Ctrl t)"] \
+ -command "::dialog_data::ok $mytoplevel"
+ pack $mytoplevel.buttonframe.send -side left -expand 1
+ pack $mytoplevel.buttonframe.ok -side left -expand 1
+
+ text $mytoplevel.text -relief raised -bd 2 -height 40 -width 60 \
+ -yscrollcommand "$mytoplevel.scroll set"
+ scrollbar $mytoplevel.scroll -command "$mytoplevel.text yview"
+ pack $mytoplevel.scroll -side right -fill y
+ pack $mytoplevel.text -side left -fill both -expand 1
+ $mytoplevel.text insert end $stuff
+ focus $mytoplevel.text
+ bind $mytoplevel.text <Control-t> "::dialog_data::ok $mytoplevel"
+ bind $mytoplevel.text <Control-s> "::dialog_data::send $mytoplevel"
+}
diff --git a/pd/tcl/dialog_find.tcl b/pd/tcl/dialog_find.tcl
index c7a708ae..443bec3a 100644
--- a/pd/tcl/dialog_find.tcl
+++ b/pd/tcl/dialog_find.tcl
@@ -1,117 +1,182 @@
+# the find dialog panel is a bit unusual in that it is created directly by the
+# Tcl 'pd-gui'. Most dialog panels are created by sending a message to 'pd',
+# which then sends a message to 'pd-gui' to create the panel.
package provide dialog_find 0.1
package require pd_bindings
namespace eval ::dialog_find:: {
+ variable find_in_toplevel ".pdwindow"
# store the state of the "Match whole word only" check box
variable wholeword_button 0
# if the search hasn't changed, then the Find button sends "findagain"
variable previous_wholeword_button 0
variable previous_findstring ""
+ variable find_history {}
+ variable history_position 0
- namespace export menu_dialog_find
+ namespace export pdtk_couldnotfind
}
-# TODO make find panel as small as possible, being topmost means its findable
-# TODO (GNOME/Windows) find panel should retain focus after a find
-# TODO (Mac OS X) hide panel after success, but stay if the find was unsuccessful
+proc ::dialog_find::get_history {direction} {
+ variable find_history
+ variable history_position
+
+ incr history_position $direction
+ if {$history_position < 0} {set history_position 0}
+ if {$history_position > [llength $find_history]} {
+ set history_position [llength $find_history]
+ }
+ .find.entry delete 0 end
+ .find.entry insert 0 [lindex $find_history end-[expr $history_position - 1]]
+}
+# mytoplevel isn't used here, but is kept for compatibility with other dialog ok procs
proc ::dialog_find::ok {mytoplevel} {
+ variable find_in_window
variable wholeword_button
variable previous_wholeword_button
variable previous_findstring
- # find will be on top, so use the previous window that was on top
- set search_window [lindex [wm stackorder .] end-1]
- puts "search_window $search_window"
+ variable find_history
+
set findstring [.find.entry get]
- if {$findstring eq ""} {return}
- if {$search_window eq ".pdwindow"} {
- set matches [.pdwindow.text search -all -nocase -- $findstring 0.0]
+ if {$findstring eq ""} {
+ if {$::windowingsystem eq "aqua"} {bell}
+ return
+ }
+ if {$find_in_window eq ".pdwindow"} {
+ if {$::tcl_version < 8.5} {
+ # TODO implement in 8.4 style, without -all
+ set matches [.pdwindow.text search -nocase -- $findstring 0.0]
+ } else {
+ set matches [.pdwindow.text search -all -nocase -- $findstring 0.0]
+ }
.pdwindow.text tag delete sel
- foreach match $matches {
- .pdwindow.text tag add sel $match "$match wordend"
+ if {[llength $matches] > 0} {
+ foreach match $matches {
+ .pdwindow.text tag add sel $match "$match wordend"
+ }
+ .pdwindow.text see [lindex $matches 0]
+ lappend find_history $findstring
}
- .pdwindow.text see [lindex $matches 0]
} else {
if {$findstring eq $previous_findstring \
&& $wholeword_button == $previous_wholeword_button} {
- pdsend "$search_window findagain"
+ pdsend "$find_in_window findagain"
} else {
- # TODO switch back to this for 0.43:
- #pdsend "$search_window find $findstring $wholeword_button"
- pdsend "$search_window find $findstring"
+ pdsend [concat $find_in_window find [pdtk_encodedialog $findstring] \
+ $wholeword_button]
set previous_findstring $findstring
set previous_wholeword_button $wholeword_button
+ lappend find_history $findstring
}
}
+ if {$::windowingsystem eq "aqua"} {
+ # (Mac OS X) hide panel after success, but keep it if unsuccessful by
+ # having the couldnotfind proc reopen it
+ cancel $mytoplevel
+ } else {
+ # (GNOME/Windows) find panel should retain focus after a find
+ # (yes, a bit of a kludge)
+ after 100 "raise .find; focus .find.entry"
+ }
}
+# mytoplevel isn't used here, but is kept for compatibility with other dialog cancel procs
proc ::dialog_find::cancel {mytoplevel} {
wm withdraw .find
}
-proc ::dialog_find::set_canvas_to_search {mytoplevel} {
- # TODO rewrite using global $::focused_window
+proc ::dialog_find::set_window_to_search {mytoplevel} {
+ variable find_in_window $mytoplevel
if {[winfo exists .find.frame.targetlabel]} {
- set focusedtoplevel [winfo toplevel [lindex [wm stackorder .] end]]
- if {$focusedtoplevel eq ".find"} {
- set focusedtoplevel [winfo toplevel [lindex [wm stackorder .] end-1]]
+ if {$find_in_window eq ".find"} {
+ set find_in_window [winfo toplevel [lindex [wm stackorder .] end-1]]
}
- if {$focusedtoplevel eq ".pdwindow"} {
- .find.frame.targetlabel configure -text [wm title .pdwindow]
- } else {
- foreach window $::menu_windowlist {
- if {[lindex $window 1] eq $focusedtoplevel} {
- .find.frame.targetlabel configure -text [lindex $window 0]
- }
- }
+ # this has funny side effects in tcl 8.4 ???
+ if {$::tcl_version >= 8.5} {
+ wm transient .find $find_in_window
}
+ .find.frame.targetlabel configure -text \
+ [lookup_windowname $find_in_window]
}
}
+proc ::dialog_find::pdtk_couldnotfind {mytoplevel} {
+ bell
+ ::pdwindow::error [format [_ "Couldn't find '%s' in %s"] \
+ [.find.entry get] [lookup_windowname $mytoplevel] ]
+ if {$::windowingsystem eq "aqua"} {open_find_dialog $mytoplevel}
+}
+
# the find panel is opened from the menu and key bindings
-proc ::dialog_find::menu_find_dialog {mytoplevel} {
+proc ::dialog_find::open_find_dialog {mytoplevel} {
if {[winfo exists .find]} {
wm deiconify .find
raise .find
} else {
create_dialog $mytoplevel
}
+ .find.entry selection range 0 end
}
proc ::dialog_find::create_dialog {mytoplevel} {
toplevel .find -class DialogWindow
wm title .find [_ "Find"]
wm geometry .find =475x125+150+150
- .find configure
- if {$::windowingsystem eq "aqua"} {$mytoplevel configure -menu .menubar}
+ wm group .find .
+ wm resizable .find 0 0
+ wm transient .find
+ .find configure -menu $::dialog_menubar
+ .find configure -padx 10 -pady 5
::pd_bindings::dialog_bindings .find "find"
+ # sending these commands to the Find Dialog Panel should forward them to
+ # the currently focused patch
+ bind .find <$::modifier-Key-s> \
+ {menu_send $::focused_window menusave; break}
+ bind .find <$::modifier-Shift-Key-S> \
+ {menu_send $::focused_window menusaveas; break}
+ bind .find <$::modifier-Key-p> \
+ {menu_print $::focused_window; break}
frame .find.frame
pack .find.frame -side top -fill x -pady 1
label .find.frame.searchin -text [_ "Search in"]
- label .find.frame.targetlabel -font "TkTextFont 14"
+ label .find.frame.targetlabel -text [_ "Pd window"]
label .find.frame.for -text [_ "for:"]
pack .find.frame.searchin .find.frame.targetlabel .find.frame.for -side left
entry .find.entry -width 54 -font 18 -relief sunken \
- -highlightthickness 3 -highlightcolor blue
- focus .find.entry
+ -highlightthickness 1 -highlightcolor blue
pack .find.entry -side top -padx 10
+
+ bind .find.entry <Up> "::dialog_find::get_history 1"
+ bind .find.entry <Down> "::dialog_find::get_history -1"
checkbutton .find.wholeword -variable ::dialog_find::wholeword_button \
-text [_ "Match whole word only"] -anchor w
pack .find.wholeword -side top -padx 30 -pady 3 -fill x
frame .find.buttonframe -background yellow
+ pack .find.buttonframe -side right -pady 3
+ if {$::windowingsystem eq "win32"} {
+ button .find.cancel -text [_ "Cancel"] -default normal -width 9 \
+ -command "::dialog_find::cancel $mytoplevel"
+ pack .find.cancel -side right -padx 6 -pady 3
+ }
button .find.button -text [_ "Find"] -default active -width 9 \
-command "::dialog_find::ok $mytoplevel"
+ pack .find.button -side right -padx 6 -pady 3
if {$::windowingsystem eq "x11"} {
button .find.close -text [_ "Close"] -default normal -width 9 \
-command "::dialog_find::cancel $mytoplevel"
- pack .find.buttonframe .find.button .find.close -side right -padx 10 -pady 3
- } else {
- pack .find.buttonframe .find.button -side right -padx 10 -pady 3
+ pack .find.close -side right -padx 6 -pady 3
}
- ::dialog_find::set_canvas_to_search $mytoplevel
+ # on Mac OS X, the buttons shouldn't get Tab/keyboard focus
+ if {$::windowingsystem eq "aqua"} {
+ .find.wholeword configure -takefocus 0
+ .find.button configure -takefocus 0
+ }
+ ::dialog_find::set_window_to_search $mytoplevel
+ focus .find.entry
}
diff --git a/pd/tcl/dialog_font.tcl b/pd/tcl/dialog_font.tcl
index 578d155e..fce16000 100644
--- a/pd/tcl/dialog_font.tcl
+++ b/pd/tcl/dialog_font.tcl
@@ -7,17 +7,17 @@ namespace eval ::dialog_font:: {
variable whichstretch 1
variable canvaswindow
variable sizes {8 10 12 16 24 36}
- variable gfxstub
namespace export pdtk_canvas_dofont
}
# TODO this should use the pd_font_$size fonts created in pd-gui.tcl
+# TODO change pdtk_canvas_dofont to pdtk_font_dialog here and g_editor.c
# TODO this should really be changed on the C side so that it doesn't have to
# work around gfxstub/x_gui.c. The gfxstub stuff assumes that there are
# multiple panels, for properties panels like this, its much easier to use if
-# there is a single properties panel that adjusts based on which CanvasWindow
+# there is a single properties panel that adjusts based on which PatchWindow
# has focus
proc ::dialog_font::apply {mytoplevel myfontsize} {
@@ -30,44 +30,41 @@ proc ::dialog_font::apply {mytoplevel myfontsize} {
}
}
-proc ::dialog_font::cancel {mygfxstub} {
- if {$mygfxstub ne ".pdwindow"} {
- pdsend "$mygfxstub cancel"
+proc ::dialog_font::cancel {gfxstub} {
+ if {$gfxstub ne ".pdwindow"} {
+ pdsend "$gfxstub cancel"
}
destroy .font
}
-proc ::dialog_font::ok {mygfxstub} {
+proc ::dialog_font::ok {gfxstub} {
variable fontsize
- ::dialog_font::apply $mygfxstub $fontsize
- ::dialog_font::cancel $mygfxstub
+ apply $gfxstub $fontsize
+ cancel $gfxstub
}
proc ::dialog_font::update_font_dialog {mytoplevel} {
- set ::dialog_font::canvaswindow $mytoplevel
- if {$mytoplevel eq ".pdwindow"} {
- set windowname [_ "Pd window"]
- } else {
- set windowname [lookup_windowname $mytoplevel]
- }
+ variable canvaswindow $mytoplevel
if {[winfo exists .font]} {
- wm title .font [format [_ "%s Font"] $windowname]
+ wm title .font [format [_ "%s Font"] [lookup_windowname $mytoplevel]]
}
}
proc ::dialog_font::arrow_fontchange {change} {
variable sizes
- set position [expr [lsearch $sizes $::dialog_font::fontsize] + $change]
+ variable fontsize
+ variable canvaswindow
+ set position [expr [lsearch $sizes $fontsize] + $change]
if {$position < 0} {set position 0}
set max [llength $sizes]
if {$position >= $max} {set position [expr $max-1]}
- set ::dialog_font::fontsize [lindex $sizes $position]
- ::dialog_font::apply $::dialog_font::canvaswindow $::dialog_font::fontsize
+ set fontsize [lindex $sizes $position]
+ ::dialog_font::apply $canvaswindow $fontsize
}
# this should be called pdtk_font_dialog like the rest of the panels, but it
# is called from the C side, so we'll leave it be
-proc ::dialog_font::pdtk_canvas_dofont {mygfxstub initsize} {
+proc ::dialog_font::pdtk_canvas_dofont {gfxstub initsize} {
variable fontsize $initsize
variable whichstretch 1
variable stretchval 100
@@ -77,28 +74,34 @@ proc ::dialog_font::pdtk_canvas_dofont {mygfxstub initsize} {
# the gfxstub stuff expects multiple font windows, we only have one,
# so kill the new gfxstub requests as the come in. We'll save the
# original gfxstub for when the font panel gets closed
- pdsend "$mygfxstub cancel"
+ pdsend "$gfxstub cancel"
} else {
- create_dialog $mygfxstub
+ create_dialog $gfxstub
}
}
-proc ::dialog_font::create_dialog {mygfxstub} {
- variable gfxstub $mygfxstub
+proc ::dialog_font::create_dialog {gfxstub} {
toplevel .font -class DialogWindow
- if {$::windowingsystem eq "aqua"} {.font configure -menu .menubar}
+ .font configure -menu $::dialog_menubar
+ .font configure -padx 10 -pady 5
+ wm group .font .
+ wm resizable .font 0 0
+ wm transient .font $::focused_window
::pd_bindings::dialog_bindings .font "font"
- # replace standard bindings to work around the gfxstub stuff
- bind .font <KeyPress-Escape> "::dialog_font::cancel $mygfxstub"
- bind .font <KeyPress-Return> "::dialog_font::ok $mygfxstub"
- bind .font <$::pd_bindings::modifier-Key-w> "::dialog_font::cancel $mygfxstub"
+ # replace standard bindings to work around the gfxstub stuff and use
+ # break to prevent the close window command from going to other bindings.
+ # .font won't exist anymore, so it'll cause errors down the line...
+ bind .font <KeyPress-Return> "::dialog_font::ok $gfxstub; break"
+ bind .font <KeyPress-Escape> "::dialog_font::cancel $gfxstub; break"
+ bind .font <$::modifier-Key-w> "::dialog_font::cancel $gfxstub; break"
+ wm protocol .font WM_DELETE_WINDOW "dialog_font::cancel $gfxstub"
bind .font <Up> "::dialog_font::arrow_fontchange -1"
bind .font <Down> "::dialog_font::arrow_fontchange 1"
frame .font.buttonframe
pack .font.buttonframe -side bottom -fill x -pady 2m
button .font.buttonframe.ok -text [_ "OK"] \
- -command "::dialog_font::ok $mygfxstub"
+ -command "::dialog_font::ok $gfxstub"
pack .font.buttonframe.ok -side left -expand 1
labelframe .font.fontsize -text [_ "Font Size"] -padx 5 -pady 4 -borderwidth 1 \
diff --git a/pd/tcl/dialog_gatom.tcl b/pd/tcl/dialog_gatom.tcl
index b59751bf..200a631e 100644
--- a/pd/tcl/dialog_gatom.tcl
+++ b/pd/tcl/dialog_gatom.tcl
@@ -44,8 +44,8 @@ proc ::dialog_gatom::apply {mytoplevel} {
[$mytoplevel.limits.upper.entry get] \
[::dialog_gatom::escape [$mytoplevel.gatomlabel.name.entry get]] \
$gatomlabel_radio($mytoplevel) \
- [::dialog_gatom::escape [$mytoplevel.s_r.send.entry get]] \
- [::dialog_gatom::escape [$mytoplevel.s_r.receive.entry get]]"
+ [::dialog_gatom::escape [$mytoplevel.s_r.receive.entry get]] \
+ [::dialog_gatom::escape [$mytoplevel.s_r.send.entry get]]"
}
proc ::dialog_gatom::cancel {mytoplevel} {
@@ -60,7 +60,7 @@ proc ::dialog_gatom::ok {mytoplevel} {
# set up the panel with the info from pd
proc ::dialog_gatom::pdtk_gatom_dialog {mytoplevel initwidth initlower initupper \
initgatomlabel_radio \
- initgatomlabel initsend initreceive} {
+ initgatomlabel initreceive initsend} {
global gatomlabel_radio
set gatomlabel_radio($mytoplevel) $initgatomlabel_radio
@@ -91,7 +91,11 @@ proc ::dialog_gatom::create_dialog {mytoplevel} {
toplevel $mytoplevel -class DialogWindow
wm title $mytoplevel [_ "Atom Box Properties"]
- if {$::windowingsystem eq "aqua"} {$mytoplevel configure -menu .menubar}
+ wm group $mytoplevel .
+ wm resizable $mytoplevel 0 0
+ wm transient $mytoplevel $::focused_window
+ $mytoplevel configure -menu $::dialog_menubar
+ $mytoplevel configure -padx 0 -pady 0
::pd_bindings::dialog_bindings $mytoplevel "gatom"
frame $mytoplevel.width -height 7
@@ -149,16 +153,18 @@ proc ::dialog_gatom::create_dialog {mytoplevel} {
pack $mytoplevel.s_r.receive.entry $mytoplevel.s_r.receive.label -side right
frame $mytoplevel.buttonframe -pady 5
- pack $mytoplevel.buttonframe -side top -fill x -pady 2m
+ pack $mytoplevel.buttonframe -side top -fill x -expand 1 -pady 2m
button $mytoplevel.buttonframe.cancel -text [_ "Cancel"] \
-command "::dialog_gatom::cancel $mytoplevel"
- pack $mytoplevel.buttonframe.cancel -side left -expand 1
- button $mytoplevel.buttonframe.apply -text [_ "Apply"] \
- -command "::dialog_gatom::apply $mytoplevel"
- pack $mytoplevel.buttonframe.apply -side left -expand 1
+ pack $mytoplevel.buttonframe.cancel -side left -expand 1 -fill x -padx 10
+ if {$::windowingsystem ne "aqua"} {
+ button $mytoplevel.buttonframe.apply -text [_ "Apply"] \
+ -command "::dialog_gatom::apply $mytoplevel"
+ pack $mytoplevel.buttonframe.apply -side left -expand 1 -fill x -padx 10
+ }
button $mytoplevel.buttonframe.ok -text [_ "OK"] \
-command "::dialog_gatom::ok $mytoplevel"
- pack $mytoplevel.buttonframe.ok -side left -expand 1
+ pack $mytoplevel.buttonframe.ok -side left -expand 1 -fill x -padx 10
$mytoplevel.width.entry select from 0
$mytoplevel.width.entry select adjust end
diff --git a/pd/tcl/dialog_iemgui.tcl b/pd/tcl/dialog_iemgui.tcl
index 34ed4ccb..ed3a60bf 100644
--- a/pd/tcl/dialog_iemgui.tcl
+++ b/pd/tcl/dialog_iemgui.tcl
@@ -252,7 +252,7 @@ proc ::dialog_iemgui::toggle_font {mytoplevel gn_f} {
1 { set current_font "Helvetica" }
2 { set current_font "Times" }
}
- set current_font_spec "{$current_font} 12 $::font_weight"
+ set current_font_spec "{$current_font} 16 $::font_weight"
$mytoplevel.label.fontpopup_label configure -text $current_font \
-font $current_font_spec
@@ -362,7 +362,11 @@ proc ::dialog_iemgui::apply {mytoplevel} {
set hhhsnd [unspace_text $hhhsnd]
set hhhrcv [unspace_text $hhhrcv]
set hhhgui_nam [unspace_text $hhhgui_nam]
-
+
+# make sure the offset boxes have a value
+ if {[eval concat $$var_iemgui_gn_dx] eq ""} {set $var_iemgui_gn_dx 0}
+ if {[eval concat $$var_iemgui_gn_dy] eq ""} {set $var_iemgui_gn_dy 0}
+
pdsend [concat $mytoplevel dialog \
[eval concat $$var_iemgui_wdt] \
[eval concat $$var_iemgui_hgt] \
@@ -496,12 +500,16 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
toplevel $mytoplevel -class DialogWindow
wm title $mytoplevel [format [_ "%s Properties"] $mainheader]
- if {$::windowingsystem eq "aqua"} {$mytoplevel configure -menu .menubar}
+ wm group $mytoplevel .
+ wm resizable $mytoplevel 0 0
+ wm transient $mytoplevel $::focused_window
+ $mytoplevel configure -menu $::dialog_menubar
+ $mytoplevel configure -padx 0 -pady 0
::pd_bindings::dialog_bindings $mytoplevel "iemgui"
frame $mytoplevel.dim
pack $mytoplevel.dim -side top
- label $mytoplevel.dim.head -text $dim_header
+ label $mytoplevel.dim.head -text [_ $dim_header]
label $mytoplevel.dim.w_lab -text [_ $wdt_label] -width 6
entry $mytoplevel.dim.w_ent -textvariable $var_iemgui_wdt -width 5
label $mytoplevel.dim.dummy1 -text " " -width 10
@@ -514,7 +522,7 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
frame $mytoplevel.rng
pack $mytoplevel.rng -side top
- label $mytoplevel.rng.head -text $rng_header
+ label $mytoplevel.rng.head -text [_ $rng_header]
label $mytoplevel.rng.min_lab -text [_ $min_rng_label] -width 6
entry $mytoplevel.rng.min_ent -textvariable $var_iemgui_min_rng -width 9
label $mytoplevel.rng.dummy1 -text " " -width 1
@@ -544,21 +552,19 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
-command "::dialog_iemgui::lilo $mytoplevel" }
if {[eval concat $$var_iemgui_loadbang] == 0} {
button $mytoplevel.para.lb -text [_ "No init"] \
- -width [::msgcat::mcmax "No init"] \
-command "::dialog_iemgui::lb $mytoplevel" }
if {[eval concat $$var_iemgui_loadbang] == 1} {
button $mytoplevel.para.lb -text [_ "Save"] \
- -width [::msgcat::mcmax "Save"] \
-command "::dialog_iemgui::lb $mytoplevel" }
label $mytoplevel.para.num_lab -text [_ $num_label] -width 9
entry $mytoplevel.para.num_ent -textvariable $var_iemgui_num -width 4
if {[eval concat $$var_iemgui_steady] == 0} {
button $mytoplevel.para.stdy_jmp -command "::dialog_iemgui::stdy_jmp $mytoplevel" \
- -text [_ "Jump on click"] -width [::msgcat::mcmax "Jump on click"] }
+ -text [_ "Jump on click"] }
if {[eval concat $$var_iemgui_steady] == 1} {
button $mytoplevel.para.stdy_jmp -command "::dialog_iemgui::stdy_jmp $mytoplevel" \
- -text [_ "Steady on click"] -width [::msgcat::mcmax "Steady on click"] }
+ -text [_ "Steady on click"] }
if {[eval concat $$var_iemgui_lin0_log1] >= 0} {
pack $mytoplevel.para.lilo -side left -expand 1}
if {[eval concat $$var_iemgui_loadbang] >= 0} {
@@ -574,18 +580,22 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
labelframe $mytoplevel.s_r -borderwidth 1 -pady 4 -text [_ "Messages"]
pack $mytoplevel.s_r -side top -fill x -ipadx 5
frame $mytoplevel.s_r.send
- pack $mytoplevel.s_r.send -side top
- label $mytoplevel.s_r.send.lab -text [_ "Send symbol:"] -width 12 -justify right
+ pack $mytoplevel.s_r.send -side top -padx 4 -fill x -expand 1
+ label $mytoplevel.s_r.send.lab -text [_ "Send symbol:"] -justify left
entry $mytoplevel.s_r.send.ent -textvariable $var_iemgui_snd -width 22
if { $snd ne "nosndno" } {
- pack $mytoplevel.s_r.send.lab $mytoplevel.s_r.send.ent -side left}
+ pack $mytoplevel.s_r.send.lab $mytoplevel.s_r.send.ent -side left \
+ -fill x -expand 1
+ }
frame $mytoplevel.s_r.receive
- pack $mytoplevel.s_r.receive -side top
- label $mytoplevel.s_r.receive.lab -text [_ "Receive symbol:"] -width 12 -justify right
+ pack $mytoplevel.s_r.receive -side top -padx 4 -fill x -expand 1
+ label $mytoplevel.s_r.receive.lab -text [_ "Receive symbol:"] -justify left
entry $mytoplevel.s_r.receive.ent -textvariable $var_iemgui_rcv -width 22
if { $rcv ne "norcvno" } {
- pack $mytoplevel.s_r.receive.lab $mytoplevel.s_r.receive.ent -side left}
+ pack $mytoplevel.s_r.receive.lab $mytoplevel.s_r.receive.ent -side left \
+ -fill x -expand 1
+ }
# get the current font name from the int given from C-space (gn_f)
set current_font $::font_family
@@ -599,42 +609,40 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
labelframe $mytoplevel.label -borderwidth 1 -text [_ "Label"] -pady 4
pack $mytoplevel.label -side top -fill x
- entry $mytoplevel.label.name_entry -textvariable $var_iemgui_gui_nam -width 30 \
- -font [list $current_font 12 $::font_weight]
+ entry $mytoplevel.label.name_entry -textvariable $var_iemgui_gui_nam \
+ -width 30 -font [list $current_font 12 $::font_weight]
pack $mytoplevel.label.name_entry -side top -expand yes -fill both -padx 5
frame $mytoplevel.label.xy -padx 27 -pady 1
pack $mytoplevel.label.xy -side top
- label $mytoplevel.label.xy.x_lab -text [_ "X offset"] \
- -width [::msgcat::mcmax "X offset"]
+ label $mytoplevel.label.xy.x_lab -text [_ "X offset"]
entry $mytoplevel.label.xy.x_entry -textvariable $var_iemgui_gn_dx -width 5
label $mytoplevel.label.xy.dummy1 -text " " -width 2
- label $mytoplevel.label.xy.y_lab -text [_ "Y offset"] \
- -width [::msgcat::mcmax "Y offset"]
+ label $mytoplevel.label.xy.y_lab -text [_ "Y offset"]
entry $mytoplevel.label.xy.y_entry -textvariable $var_iemgui_gn_dy -width 5
pack $mytoplevel.label.xy.x_lab $mytoplevel.label.xy.x_entry $mytoplevel.label.xy.dummy1 \
$mytoplevel.label.xy.y_lab $mytoplevel.label.xy.y_entry -side left -anchor e
- label $mytoplevel.label.fontpopup_label -text $current_font \
- -relief groove -font [list $current_font 12 $::font_weight] -padx 5
- pack $mytoplevel.label.fontpopup_label -side left -anchor w -expand yes -fill x
- label $mytoplevel.label.fontsize_label -text [_ "Size:"] \
- -width [::msgcat::mcmax "Size:"]
+ button $mytoplevel.label.fontpopup_label -text $current_font \
+ -font [list $current_font 16 $::font_weight]
+ pack $mytoplevel.label.fontpopup_label -side left -anchor w \
+ -expand 1 -fill x -padx 5
+ label $mytoplevel.label.fontsize_label -text [_ "Size:"]
entry $mytoplevel.label.fontsize_entry -textvariable $var_iemgui_gn_fs -width 5
pack $mytoplevel.label.fontsize_entry $mytoplevel.label.fontsize_label \
-side right -anchor e -padx 5 -pady 5
menu $mytoplevel.popup
$mytoplevel.popup add command \
-label $::font_family \
- -font [format {{%s} 12 %s} $::font_family $::font_weight] \
+ -font [format {{%s} 16 %s} $::font_family $::font_weight] \
-command "::dialog_iemgui::toggle_font $mytoplevel 0"
$mytoplevel.popup add command \
-label "Helvetica" \
- -font [format {Helvetica 12 %s} $::font_weight] \
+ -font [format {Helvetica 16 %s} $::font_weight] \
-command "::dialog_iemgui::toggle_font $mytoplevel 1"
$mytoplevel.popup add command \
-label "Times" \
- -font [format {Times 12 %s} $::font_weight] \
+ -font [format {Times 16 %s} $::font_weight] \
-command "::dialog_iemgui::toggle_font $mytoplevel 2"
bind $mytoplevel.label.fontpopup_label <Button> \
[list tk_popup $mytoplevel.popup %X %Y]
@@ -648,14 +656,11 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
frame $mytoplevel.colors.select
pack $mytoplevel.colors.select -side top
radiobutton $mytoplevel.colors.select.radio0 -value 0 -variable \
- $var_iemgui_l2_f1_b0 -text [_ "Background"] -justify left \
- -width [::msgcat::mcmax "Background"]
+ $var_iemgui_l2_f1_b0 -text [_ "Background"] -justify left
radiobutton $mytoplevel.colors.select.radio1 -value 1 -variable \
- $var_iemgui_l2_f1_b0 -text [_ "Front"] -justify left \
- -width [::msgcat::mcmax "Front"]
+ $var_iemgui_l2_f1_b0 -text [_ "Front"] -justify left
radiobutton $mytoplevel.colors.select.radio2 -value 2 -variable \
- $var_iemgui_l2_f1_b0 -text [_ "Label"] -justify left \
- -width [::msgcat::mcmax "Label"]
+ $var_iemgui_l2_f1_b0 -text [_ "Label"] -justify left
if { [eval concat $$var_iemgui_fcol] >= 0 } {
pack $mytoplevel.colors.select.radio0 $mytoplevel.colors.select.radio1 \
$mytoplevel.colors.select.radio2 -side left
@@ -666,7 +671,6 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
frame $mytoplevel.colors.sections
pack $mytoplevel.colors.sections -side top
button $mytoplevel.colors.sections.but -text [_ "Compose color"] \
- -width [::msgcat::mcmax "Compose color"] \
-command "::dialog_iemgui::choose_col_bkfrlb $mytoplevel"
pack $mytoplevel.colors.sections.but -side left -anchor w -padx 10 -pady 5 \
-expand yes -fill x
@@ -686,7 +690,6 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
-font [list $current_font 12 $::font_weight] -padx 2 -pady 2 -relief ridge
}
label $mytoplevel.colors.sections.lb_bk -text [_ "Test label"] \
- -width [::msgcat::mcmax "Test label"] \
-background [format "#%6.6x" [eval concat $$var_iemgui_bcol]] \
-activebackground [format "#%6.6x" [eval concat $$var_iemgui_bcol]] \
-foreground [format "#%6.6x" [eval concat $$var_iemgui_lcol]] \
@@ -744,26 +747,18 @@ proc ::dialog_iemgui::pdtk_iemgui_dialog {mytoplevel mainheader dim_header \
$mytoplevel.colors.r3.c8 $mytoplevel.colors.r3.c9 -side left
frame $mytoplevel.cao -pady 10
- pack $mytoplevel.cao -side top
- button $mytoplevel.cao.cancel -text [_ "Cancel"] -width 6 \
+ pack $mytoplevel.cao -side top -expand 1 -fill x
+ button $mytoplevel.cao.cancel -text [_ "Cancel"] \
-command "::dialog_iemgui::cancel $mytoplevel"
- label $mytoplevel.cao.dummy1 -text "" -width 3
- button $mytoplevel.cao.apply -text [_ "Apply"] -width 6 \
- -command "::dialog_iemgui::apply $mytoplevel"
- label $mytoplevel.cao.dummy2 -text "" -width 3
- button $mytoplevel.cao.ok -text [_ "OK"] -width 6 \
- -command "::dialog_iemgui::ok $mytoplevel"
- pack $mytoplevel.cao.cancel $mytoplevel.cao.dummy1 -side left
- pack $mytoplevel.cao.apply $mytoplevel.cao.dummy2 -side left
- pack $mytoplevel.cao.ok -side left
-
- if {[info tclversion] < 8.4} {
- bind $mytoplevel <Key-Tab> {tkTabToWindow [tk_focusNext %W]}
- bind $mytoplevel <<PrevWindow>> {tkTabToWindow [tk_focusPrev %W]}
- } else {
- bind $mytoplevel <Key-Tab> {tk::TabToWindow [tk_focusNext %W]}
- bind $mytoplevel <<PrevWindow>> {tk::TabToWindow [tk_focusPrev %W]}
+ pack $mytoplevel.cao.cancel -side left -padx 10 -expand 1 -fill x
+ if {$::windowingsystem ne "aqua"} {
+ button $mytoplevel.cao.apply -text [_ "Apply"] \
+ -command "::dialog_iemgui::apply $mytoplevel"
+ pack $mytoplevel.cao.apply -side left -padx 10 -expand 1 -fill x
}
+ button $mytoplevel.cao.ok -text [_ "OK"] \
+ -command "::dialog_iemgui::ok $mytoplevel"
+ pack $mytoplevel.cao.ok -side left -padx 10 -expand 1 -fill x
$mytoplevel.dim.w_ent select from 0
$mytoplevel.dim.w_ent select adjust end
diff --git a/pd/tcl/dialog_message.tcl b/pd/tcl/dialog_message.tcl
new file mode 100644
index 00000000..107f1095
--- /dev/null
+++ b/pd/tcl/dialog_message.tcl
@@ -0,0 +1,85 @@
+# the message dialog panel is a bit unusual in that it is created directly by
+# the Tcl 'pd-gui'. Most dialog panels are created by sending a message to
+# 'pd', which then sends a message to 'pd-gui' to create the panel. This is
+# similar to the Find dialog panel.
+
+package provide dialog_message 0.1
+
+package require pd_bindings
+
+namespace eval ::dialog_message:: {
+ variable message_history {"pd dsp 1"}
+ variable history_position 0
+
+ namespace export open_message_dialog
+}
+
+proc ::dialog_message::get_history {direction} {
+ variable message_history
+ variable history_position
+
+ incr history_position $direction
+ if {$history_position < 0} {set history_position 0}
+ if {$history_position > [llength $message_history]} {
+ set history_position [llength $message_history]
+ }
+ .message.f.entry delete 0 end
+ .message.f.entry insert 0 \
+ [lindex $message_history end-[expr $history_position - 1]]
+}
+
+# mytoplevel isn't used here, but is kept for compatibility with other dialog ok procs
+proc ::dialog_message::ok {mytoplevel} {
+ variable message_history
+ set message [.message.f.entry get]
+ if {$message ne ""} {
+ pdsend $message
+ lappend message_history $message
+ .message.f.entry delete 0 end
+ }
+}
+
+# mytoplevel isn't used here, but is kept for compatibility with other dialog cancel procs
+proc ::dialog_message::cancel {mytoplevel} {
+ wm withdraw .message
+}
+
+# the message panel is opened from the menu and key bindings
+proc ::dialog_message::open_message_dialog {mytoplevel} {
+ if {[winfo exists .message]} {
+ wm deiconify .message
+ raise .message
+ } else {
+ create_dialog $mytoplevel
+ }
+}
+
+proc ::dialog_message::create_dialog {mytoplevel} {
+ toplevel .message -class DialogWindow
+ wm group .message .
+ wm transient .message
+ wm title .message [_ "Send a Pd message"]
+ wm geometry .message =400x80+150+150
+ wm resizable .message 1 0
+ wm minsize .message 250 80
+ .message configure -menu $::dialog_menubar
+ .message configure -padx 10 -pady 5
+ ::pd_bindings::dialog_bindings .message "message"
+ # not all Tcl/Tk versions or platforms support -topmost, so catch the error
+ catch {wm attributes $id -topmost 1}
+
+ # TODO this should use something like 'dialogfont' for the font
+ frame .message.f
+ pack .message.f -side top -fill x -expand 1
+ entry .message.f.entry -width 54 -font {Helvetica 18} -relief sunken \
+ -highlightthickness 1 -highlightcolor blue
+ label .message.f.semicolon -text ";" -font {Helvetica 24}
+ pack .message.f.semicolon -side left
+ pack .message.f.entry -side left -padx 10 -fill x -expand 1
+ focus .message.f.entry
+ label .message.label -text [_ "(use arrow keys for history)"]
+ pack .message.label -side bottom
+
+ bind .message.f.entry <Up> "::dialog_message::get_history 1"
+ bind .message.f.entry <Down> "::dialog_message::get_history -1"
+}
diff --git a/pd/tcl/dialog_midi.tcl b/pd/tcl/dialog_midi.tcl
index d8554665..450d2938 100644
--- a/pd/tcl/dialog_midi.tcl
+++ b/pd/tcl/dialog_midi.tcl
@@ -2,6 +2,7 @@ package provide dialog_midi 0.1
namespace eval ::dialog_midi:: {
namespace export pdtk_midi_dialog
+ namespace export pdtk_alsa_midi_dialog
}
# TODO this panel really needs some reworking, it works but the code is
@@ -81,10 +82,16 @@ proc ::dialog_midi::pdtk_midi_dialog {id indev1 indev2 indev3 indev4 \
set midi_alsain [llength $midi_indevlist]
set midi_alsaout [llength $midi_outdevlist]
- toplevel $id
+ toplevel $id -class DialogWindow
wm title $id [_ "MIDI Settings"]
- if {$::windowingsystem eq "aqua"} {$id configure -menu .menubar}
+ wm group $id .
+ wm resizable $id 0 0
+ wm transient $id
+ $id configure -menu $::dialog_menubar
+ $id configure -padx 10 -pady 5
::pd_bindings::dialog_bindings $id "midi"
+ # not all Tcl/Tk versions or platforms support -topmost, so catch the error
+ catch {wm attributes $id -topmost 1}
frame $id.buttonframe
pack $id.buttonframe -side bottom -fill x -pady 2m
@@ -165,7 +172,7 @@ proc ::dialog_midi::pdtk_midi_dialog {id indev1 indev2 indev3 indev4 \
}
# output device 3
- if {$longform && [llength $midi_midi_outdevlist] > 3} {
+ if {$longform && [llength $midi_outdevlist] > 3} {
frame $id.out3f
pack $id.out3f -side top
label $id.out3f.l1 -text [_ "Output device 3:"]
@@ -176,7 +183,7 @@ proc ::dialog_midi::pdtk_midi_dialog {id indev1 indev2 indev3 indev4 \
}
# output device 4
- if {$longform && [llength $midi_midi_outdevlist] > 4} {
+ if {$longform && [llength $midi_outdevlist] > 4} {
frame $id.out4f
pack $id.out4f -side top
label $id.out4f.l1 -text [_ "Output device 4:"]
diff --git a/pd/tcl/dialog_path.tcl b/pd/tcl/dialog_path.tcl
new file mode 100644
index 00000000..40a306ba
--- /dev/null
+++ b/pd/tcl/dialog_path.tcl
@@ -0,0 +1,70 @@
+
+package provide dialog_path 0.1
+
+namespace eval ::dialog_path:: {
+ variable use_standard_extensions_button 1
+ variable verbose_button 0
+
+ namespace export pdtk_path_dialog
+}
+
+############ pdtk_path_dialog -- run a path dialog #########
+
+# set up the panel with the info from pd
+proc ::dialog_path::pdtk_path_dialog {mytoplevel extrapath verbose} {
+ global use_standard_extensions_button
+ global verbose_button
+ set use_standard_extensions_button $extrapath
+ set verbose_button $verbose
+
+ if {[winfo exists $mytoplevel]} {
+ wm deiconify $mytoplevel
+ raise $mytoplevel
+ } else {
+ create_dialog $mytoplevel
+ }
+}
+
+proc ::dialog_path::create_dialog {mytoplevel} {
+
+ scrollboxwindow::make $mytoplevel $::sys_searchpath \
+ dialog_path::add dialog_path::edit dialog_path::commit \
+ [_ "Pd search path for objects, help, fonts, and other files"] \
+ 400 300
+
+ frame $mytoplevel.extraframe
+ pack $mytoplevel.extraframe -side bottom -pady 2m
+ checkbutton $mytoplevel.extraframe.extra -text [_ "Use standard extensions"] \
+ -variable use_standard_extensions_button -anchor w
+ checkbutton $mytoplevel.extraframe.verbose -text [_ "Verbose"] \
+ -variable verbose_button -anchor w
+ pack $mytoplevel.extraframe.extra $mytoplevel.extraframe.verbose \
+ -side left -expand 1
+}
+
+
+
+############ pdtk_path_dialog -- dialog window for search path #########
+proc ::dialog_path::choosePath { currentpath title } {
+ if {$currentpath == ""} {
+ set currentpath "~"
+ }
+ return [tk_chooseDirectory -initialdir $currentpath -title $title]
+}
+
+proc ::dialog_path::add {} {
+ return [::dialog_path::choosePath "" {Add a new path}]
+}
+
+proc ::dialog_path::edit { currentpath } {
+ return [::dialog_path::choosePath $currentpath "Edit existing path \[$currentpath\]"]
+}
+
+proc ::dialog_path::commit { new_path } {
+ global use_standard_extensions_button
+ global verbose_button
+
+ set ::sys_searchpath $new_path
+ pdsend "pd path-dialog $use_standard_extensions_button $verbose_button $::sys_searchpath"
+}
+
diff --git a/pd/tcl/dialog_startup.tcl b/pd/tcl/dialog_startup.tcl
new file mode 100644
index 00000000..52c5f647
--- /dev/null
+++ b/pd/tcl/dialog_startup.tcl
@@ -0,0 +1,96 @@
+
+package provide dialog_startup 0.1
+
+package require scrollboxwindow
+
+namespace eval dialog_startup {
+ variable defeatrt_flag 0
+
+ namespace export pdtk_startup_dialog
+}
+
+########## pdtk_startup_dialog -- dialog window for startup options #########
+# Create a simple modal window with an entry widget
+# for editing/adding a startup command
+# (the next-best-thing to in-place editing)
+proc ::dialog_startup::chooseCommand { prompt initialValue } {
+ global cmd
+ set cmd $initialValue
+
+ toplevel .inputbox
+ wm title .inputbox $prompt
+ wm group .inputbox .
+ wm minsize .inputbox 450 30
+ wm resizable .inputbox 0 0
+ wm geom .inputbox "450x30"
+ # not all Tcl/Tk versions or platforms support -topmost, so catch the error
+ catch {wm attributes $mytoplevel -topmost 1}
+
+ button .inputbox.button -text [_ "OK"] -command { destroy .inputbox } \
+ -width [::msgcat::mcmax [_ "OK"]]
+
+ entry .inputbox.entry -width 50 -textvariable cmd
+ pack .inputbox.button -side right
+ bind .inputbox.entry <KeyPress-Return> { destroy .inputbox }
+ bind .inputbox.entry <KeyPress-Escape> { destroy .inputbox }
+ pack .inputbox.entry -side right -expand 1 -fill x -padx 2m
+
+ focus .inputbox.entry
+
+ raise .inputbox
+ wm transient .inputbox
+ grab .inputbox
+ tkwait window .inputbox
+
+ return $cmd
+}
+
+proc ::dialog_startup::add {} {
+ return [chooseCommand [_ "Add new library"] ""]
+}
+
+proc ::dialog_startup::edit { current_library } {
+ return [chooseCommand [_ "Edit library"] $current_library]
+}
+
+proc ::dialog_startup::commit { new_startup } {
+ variable defeatrt_button
+ set ::startup_libraries $new_startup
+
+ pdsend "pd startup-dialog $defeatrt_button [pdtk_encodedialog $::startup_flags] $::startup_libraries"
+}
+
+# set up the panel with the info from pd
+proc ::dialog_startup::pdtk_startup_dialog {mytoplevel defeatrt flags} {
+ variable defeatrt_button $defeatrt
+ if {$flags ne ""} {variable ::startup_flags $flags}
+
+ if {[winfo exists $mytoplevel]} {
+ wm deiconify $mytoplevel
+ raise $mytoplevel
+ } else {
+ create_dialog $mytoplevel
+ }
+}
+
+proc ::dialog_startup::create_dialog {mytoplevel} {
+ ::scrollboxwindow::make $mytoplevel $::startup_libraries \
+ dialog_startup::add dialog_startup::edit dialog_startup::commit \
+ [_ "Pd libraries to load on startup"] \
+ 400 300
+
+ label $mytoplevel.entryname -text [_ "Startup flags:"]
+ entry $mytoplevel.entry -textvariable ::startup_flags -width 60
+ pack $mytoplevel.entryname $mytoplevel.entry -side left
+ pack $mytoplevel.entry -side right -padx 2m -fill x -expand 1
+
+ frame $mytoplevel.defeatrtframe
+ pack $mytoplevel.defeatrtframe -side bottom -fill x -pady 2m
+ if {$::windowingsystem ne "win32"} {
+ checkbutton $mytoplevel.defeatrtframe.defeatrt -anchor w \
+ -text [_ "Defeat real-time scheduling"] \
+ -variable ::dialog_startup::defeatrt_button
+ pack $mytoplevel.defeatrtframe.defeatrt -side left
+ }
+}
+
diff --git a/pd/tcl/helpbrowser.tcl b/pd/tcl/helpbrowser.tcl
new file mode 100644
index 00000000..bcec1fc5
--- /dev/null
+++ b/pd/tcl/helpbrowser.tcl
@@ -0,0 +1,272 @@
+
+package provide helpbrowser 0.1
+
+namespace eval ::helpbrowser:: {
+ variable libdirlist
+ variable helplist
+ variable reference_count
+ variable reference_paths
+ variable doctypes "*.{pd,pat,mxb,mxt,help,txt,htm,html,pdf}"
+
+ namespace export open_helpbrowser
+}
+
+# TODO remove the doc_ prefix on procs where its not needed
+# TODO rename .help_browser to .helpbrowser
+# TODO enter and up/down/left/right arrow key bindings for nav
+
+################## help browser and support functions #########################
+proc ::helpbrowser::open_helpbrowser {} {
+ if { [winfo exists .help_browser.frame] } {
+ wm deiconify .help_browser
+ raise .help_browser
+ } else {
+ toplevel .help_browser -class HelpBrowser
+ wm group .help_browser .
+ wm transient .help_browser
+ wm title .help_browser [_ "Help Browser"]
+ bind .help_browser <$::modifier-Key-w> "wm withdraw .help_browser"
+
+ if {$::windowingsystem eq "aqua"} {
+ .help_browser configure -menu $::dialog_menubar
+ }
+
+ wm resizable .help_browser 0 0
+ frame .help_browser.frame
+ pack .help_browser.frame -side top -fill both
+ build_references
+ make_rootlistbox .help_browser.frame
+ }
+}
+
+# make the root listbox of the help browser using the pre-built lists
+proc ::helpbrowser::make_rootlistbox {base} {
+ variable libdirlist
+ variable helplist
+ # exportselection 0 looks good, but selection gets easily out-of-sync
+ set current_listbox [listbox "[set b $base.root]" -yscrollcommand "$b-scroll set" \
+ -highlightbackground white -highlightthickness 5 \
+ -highlightcolor "#D6E5FC" -selectborderwidth 0 \
+ -height 20 -width 23 -exportselection 0 -bd 0]
+ pack $current_listbox [scrollbar "$b-scroll" -command [list $current_listbox yview]] \
+ -side left -fill both -expand 1
+ foreach item [concat [lsort [concat $libdirlist $helplist]]] {
+ $current_listbox insert end $item
+ }
+ bind $current_listbox <Button-1> \
+ [list ::helpbrowser::root_navigate %W %x %y]
+ bind $current_listbox <Key-Return> \
+ [list ::helpbrowser::root_navigate %W %x %y]
+ bind $current_listbox <Double-ButtonRelease-1> \
+ [list ::helpbrowser::root_doubleclick %W %x %y]
+ bind $current_listbox <$::modifier-Key-o> \
+ [list ::helpbrowser::root_doubleclick %W %x %y]
+}
+
+# navigate into a library/directory from the root
+proc ::helpbrowser::root_navigate {window x y} {
+ variable reference_paths
+ if {[set item [$window get [$window index "@$x,$y"]]] eq {}} {
+ return
+ }
+ set filename $reference_paths($item)
+ if {[file isdirectory $filename]} {
+ make_liblistbox [winfo parent $window] $filename
+ }
+}
+
+# double-click action to open the folder
+proc ::helpbrowser::root_doubleclick {window x y} {
+ variable reference_paths
+ if {[set listname [$window get [$window index "@$x,$y"]]] eq {}} {
+ return
+ }
+ set dir [file dirname $reference_paths($listname)]
+ set filename [file tail $reference_paths($listname)]
+ ::pdwindow::verbose 0 "menu_doc_open $dir $filename"
+ if { [catch {menu_doc_open $dir $filename} fid] } {
+ ::pdwindow::error "Could not open $dir/$filename\n"
+ }
+}
+
+# make the listbox to show the first level contents of a libdir
+proc ::helpbrowser::make_liblistbox {base dir} {
+ variable doctypes
+ catch { eval destroy [lrange [winfo children $base] 2 end] } errorMessage
+ # exportselection 0 looks good, but selection gets easily out-of-sync
+ set current_listbox [listbox "[set b $base.listbox0]" -yscrollcommand "$b-scroll set" \
+ -highlightbackground white -highlightthickness 5 \
+ -highlightcolor "#D6E5FC" -selectborderwidth 0 \
+ -height 20 -width 23 -exportselection 0 -bd 0]
+ pack $current_listbox [scrollbar "$b-scroll" -command [list $current_listbox yview]] \
+ -side left -fill both -expand 1
+ foreach item [lsort -dictionary [glob -directory $dir -nocomplain -types {d} -- *]] {
+ if {[glob -directory $item -nocomplain -types {f} -- $doctypes] ne "" ||
+ [glob -directory $item -nocomplain -types {d} -- *] ne ""} {
+ $current_listbox insert end "[file tail $item]/"
+ }
+ }
+ foreach item [lsort -dictionary [glob -directory $dir -nocomplain -types {f} -- \
+ *-{help,meta}.pd]] {
+ $current_listbox insert end [file tail $item]
+ }
+ $current_listbox insert end "___________________________"
+ foreach item [lsort -dictionary [glob -directory $dir -nocomplain -types {f} -- \
+ *.txt]] {
+ $current_listbox insert end [file tail $item]
+ }
+ bind $current_listbox <Button-1> \
+ [list ::helpbrowser::dir_navigate $dir 1 %W %x %y]
+ bind $current_listbox <Double-ButtonRelease-1> \
+ [list ::helpbrowser::dir_doubleclick $dir 1 %W %x %y]
+ bind $current_listbox <Key-Return> \
+ [list ::helpbrowser::dir_doubleclick $dir 1 %W %x %y]
+}
+
+proc ::helpbrowser::doc_make_listbox {base dir count} {
+ variable doctypes
+ # check for [file readable]?
+ # requires Tcl 8.5 but probably deals with special chars better:
+ # destroy {*}[lrange [winfo children $base] [expr {2 * $count}] end]
+ if { [catch { eval destroy [lrange [winfo children $base] \
+ [expr { 2 * $count }] end] } errorMessage] } {
+ ::pdwindow::error "doc_make_listbox: error listing $dir\n"
+ }
+ # exportselection 0 looks good, but selection gets easily out-of-sync
+ set current_listbox [listbox "[set b "$base.listbox$count"]-list" \
+ -yscrollcommand "$b-scroll set" \
+ -highlightbackground white -highlightthickness 5 \
+ -highlightcolor "#D6E5FC" -selectborderwidth 0 \
+ -height 20 -width 23 -exportselection 0 -bd 0]
+ pack $current_listbox [scrollbar "$b-scroll" -command "$current_listbox yview"] \
+ -side left -fill both -expand 1
+ foreach item [lsort -dictionary [glob -directory $dir -nocomplain -types {d} -- *]] {
+ $current_listbox insert end "[file tail $item]/"
+ }
+ foreach item [lsort -dictionary [glob -directory $dir -nocomplain -types {f} -- \
+ $doctypes]] {
+ $current_listbox insert end [file tail $item]
+ }
+ bind $current_listbox <Button-1> \
+ "::helpbrowser::dir_navigate {$dir} $count %W %x %y"
+ bind $current_listbox <Key-Right> \
+ "::helpbrowser::dir_navigate {$dir} $count %W %x %y"
+ bind $current_listbox <Double-ButtonRelease-1> \
+ "::helpbrowser::dir_doubleclick {$dir} $count %W %x %y"
+ bind $current_listbox <Key-Return> \
+ "::helpbrowser::dir_doubleclick {$dir} $count %W %x %y"
+}
+
+# navigate into an actual directory
+proc ::helpbrowser::dir_navigate {dir count window x y} {
+ if {[set newdir [$window get [$window index "@$x,$y"]]] eq {}} {
+ return
+ }
+ set dir_to_open [file join $dir $newdir]
+ if {[file isdirectory $dir_to_open]} {
+ doc_make_listbox [winfo parent $window] $dir_to_open [incr count]
+ }
+}
+
+proc ::helpbrowser::dir_doubleclick {dir count window x y} {
+ if {[set filename [$window get [$window index "@$x,$y"]]] eq {}} {
+ return
+ }
+ if { [catch {menu_doc_open $dir $filename} fid] } {
+ ::pdwindow::error "Could not open $dir/$filename\n"
+ }
+}
+
+proc ::helpbrowser::rightclickmenu {dir count window x y} {
+ if {[set filename [$window get [$window index "@$x,$y"]]] eq {}} {
+ return
+ }
+ if { [catch {menu_doc_open $dir $filename} fid] } {
+ ::pdwindow::error "Could not open $dir/$filename\n"
+ }
+}
+
+#------------------------------------------------------------------------------#
+# build help browser trees
+
+# TODO check file timestamp against timestamp of when tree was built
+
+proc ::helpbrowser::findfiles {basedir pattern} {
+ set basedir [string trimright [file join [file normalize $basedir] { }]]
+ set filelist {}
+
+ # Look in the current directory for matching files, -type {f r}
+ # means ony readable normal files are looked at, -nocomplain stops
+ # an error being thrown if the returned list is empty
+ foreach filename [glob -nocomplain -type {f r} -path $basedir $pattern] {
+ lappend filelist $filename
+ }
+
+ foreach dirName [glob -nocomplain -type {d r} -path $basedir *] {
+ set subdirlist [findfiles $dirName $pattern]
+ if { [llength $subdirlist] > 0 } {
+ foreach subdirfile $subdirlist {
+ lappend filelist $subdirfile
+ }
+ }
+ }
+ return $filelist
+}
+
+proc ::helpbrowser::add_entry {reflist entry} {
+ variable libdirlist
+ variable helplist
+ variable reference_paths
+ variable reference_count
+ set entryname [file tail $entry]
+ # if we are checking libdirs, then check to see if there is already a
+ # libdir with that name that has been discovered in the path. If so, dump
+ # a warning. The trailing slash on $entryname is added below when
+ # $entryname is a dir
+ if {$reflist eq "libdirlist" && [lsearch -exact $libdirlist $entryname/] > -1} {
+ ::pdwindow::error "WARNING: duplicate '$entryname' library found!\n"
+ ::pdwindow::error " '$reference_paths($entryname/)' is active\n"
+ ::pdwindow::error " '$entry' is duplicate\n"
+ incr reference_count($entryname)
+ append entryname "/ ($reference_count($entryname))"
+ } else {
+ set reference_count($entryname) 1
+ if {[file isdirectory $entry]} {
+ append entryname "/"
+ }
+ }
+ lappend $reflist $entryname
+ set reference_paths($entryname) $entry
+}
+
+proc ::helpbrowser::build_references {} {
+ variable libdirlist {" Pure Data/" "-----------------------"}
+ variable helplist {}
+ variable reference_count
+ variable reference_paths
+
+ array set reference_count {}
+ array set reference_paths [list \
+ " Pure Data/" $::sys_libdir/doc \
+ "-----------------------" "" \
+ ]
+ foreach pathdir [concat $::sys_searchpath $::sys_staticpath] {
+ if { ! [file isdirectory $pathdir]} {continue}
+ # Fix the directory name, this ensures the directory name is in the
+ # native format for the platform and contains a final directory seperator
+ set dir [string trimright [file join [file normalize $pathdir] { }]]
+ ## find the libdirs
+ foreach filename [glob -nocomplain -type d -path $dir "*"] {
+ add_entry libdirlist $filename
+ }
+ ## find the stray help patches
+ foreach filename [glob -nocomplain -type f -path $dir "*-help.pd"] {
+ add_entry helplist $filename
+ }
+ }
+}
+
+
+
+
+
diff --git a/pd/tcl/opt_parser.tcl b/pd/tcl/opt_parser.tcl
index d304e045..c34baf6d 100644
--- a/pd/tcl/opt_parser.tcl
+++ b/pd/tcl/opt_parser.tcl
@@ -3,35 +3,44 @@ package provide opt_parser 0.1
namespace eval opt_parser {
# list of option vars (keys are long option names)
variable optlist
+ # option behavior <set|lappend>
+ variable optbehavior
variable optprefix {-}
}
proc opt_parser::init {optdata} {
variable optlist
- array unset optlist
- array set optlist {}
+ variable optbehavior
+ array unset optlist ; array set optlist {}
+ array unset optbehavior ; array set optbehavior {}
foreach item $optdata {
- foreach {longname varlist} $item {
- if {[llength $varlist] < 1} {
- return -code error "usage: init { {optname {var1 var2 ...}} ... }"
+ foreach {optName behavior varlist} $item {
+ if {[llength $varlist] < 1 || [lsearch -exact {set lappend} $behavior] == -1} {
+ return -code error "usage: init { {optname <set|lappend> {var1 var2 ...}} ... }"
}
- set optlist($longname) $varlist
+ set optlist($optName) $varlist
+ set optbehavior($optName) $behavior
}
}
}
proc opt_parser::get_options {argv {opts {}}} {
- set ignore_unknown_flags 0
+ # second argument are internal options
+ # (like 'ignore_unknown_flags <0|1>')
foreach {k v} $opts {set $k $v}
+ set ignore_unknown_flags 0
variable optlist
+ variable optbehavior
variable optprefix
# zero all the options 1st var
foreach optName [array names optlist] {
uplevel [list set [lindex $optlist($optName) 0] 0]
- for {set i 1} {$i < [llength $optlist($optName)]} {incr i} {
- uplevel [list set [lindex $optlist($optName) $i] [list]]
+ if {$optbehavior($optName) == {lappend}} {
+ for {set i 1} {$i < [llength $optlist($optName)]} {incr i} {
+ uplevel [list set [lindex $optlist($optName) $i] [list]]
+ }
}
}
@@ -41,16 +50,15 @@ proc opt_parser::get_options {argv {opts {}}} {
set argc [llength $argv]
for {set i 0} {$i < $argc} {} {
# get i-th arg
- set argv_i [lindex $argv $i]
+ set optName [lindex $argv $i]
incr i
# if it's not an option, stop here, and add to residualArgs
- if {![regexp ^$optprefix $argv_i]} {
- lappend residualArgs $argv_i
+ if {![regexp ^$optprefix $optName]} {
+ lappend residualArgs $optName
continue
}
- set optName [regsub ^$optprefix $argv_i {}]
if {[info exists optlist($optName)]} {
set varlist $optlist($optName)
uplevel [list set [lindex $optlist($optName) 0] 1]
@@ -59,9 +67,9 @@ proc opt_parser::get_options {argv {opts {}}} {
while {$n_required_opt_args > 0} {
incr n_required_opt_args -1
if {$i >= $argc} {
- return -code error "not enough arguments for option $optprefix$optName"
+ return -code error "not enough arguments for option $optName"
}
- uplevel [list lappend [lindex $varlist $j] [lindex $argv $i]]
+ uplevel [list $optbehavior($optName) [lindex $varlist $j] [lindex $argv $i]]
incr j
incr i
}
@@ -70,7 +78,7 @@ proc opt_parser::get_options {argv {opts {}}} {
lappend residualArgs $argv_i
continue
} else {
- return -code error "unknown option: $optprefix$optName"
+ return -code error "unknown option: $optName"
}
}
}
diff --git a/pd/tcl/pd-gui.tcl b/pd/tcl/pd-gui.tcl
index 6dfe1663..39b260f5 100644
--- a/pd/tcl/pd-gui.tcl
+++ b/pd/tcl/pd-gui.tcl
@@ -8,15 +8,19 @@
# "." automatically gets a window, we don't want it. Withdraw it before doing
# anything else, so that we don't get the automatic window flashing for a
# second while pd loads.
-wm withdraw .
-
-puts -------------------------------pd-gui.tcl-----------------------------------
+if { [catch {wm withdraw .} fid] } { exit 2 }
package require Tcl 8.3
package require Tk
-package require Tk
-if {[tk windowingsystem] ne "win32"} {package require msgcat}
+#package require tile
+## replace Tk widgets with Ttk widgets on 8.5
+#namespace import -force ttk::*
+
+package require msgcat
# TODO figure out msgcat issue on Windows
+# TODO create a constructor in each package to create things at startup, that
+# way they can be easily be modified by startup scripts
+# TODO create alt-Enter/Cmd-I binding to bring up Properties panels
# Pd's packages are stored in the same directory as the main script (pd-gui.tcl)
set auto_path [linsert $auto_path 0 [file dirname [info script]]]
@@ -27,26 +31,52 @@ package require pdwindow
package require dialog_array
package require dialog_audio
package require dialog_canvas
+package require dialog_data
package require dialog_font
package require dialog_gatom
package require dialog_iemgui
+package require dialog_message
package require dialog_midi
+package require dialog_path
+package require dialog_startup
+package require helpbrowser
+package require pd_menucommands
+package require opt_parser
package require pdtk_canvas
package require pdtk_text
# TODO eliminate this kludge:
package require wheredoesthisgo
+#------------------------------------------------------------------------------#
+# import functions into the global namespace
+
+# make global since they are used throughout
+namespace import ::pd_menucommands::*
+
# import into the global namespace for backwards compatibility
namespace import ::pd_connect::pdsend
namespace import ::pdwindow::pdtk_post
+namespace import ::pdwindow::pdtk_pd_dio
+namespace import ::pdwindow::pdtk_pd_dsp
+namespace import ::pdwindow::pdtk_pd_meters
+namespace import ::pdtk_canvas::pdtk_canvas_popup
+namespace import ::pdtk_canvas::pdtk_canvas_editmode
+namespace import ::pdtk_canvas::pdtk_canvas_getscroll
+namespace import ::pdtk_canvas::pdtk_canvas_setparents
+namespace import ::pdtk_canvas::pdtk_canvas_reflecttitle
+namespace import ::pdtk_canvas::pdtk_canvas_menuclose
namespace import ::dialog_array::pdtk_array_dialog
namespace import ::dialog_audio::pdtk_audio_dialog
namespace import ::dialog_canvas::pdtk_canvas_dialog
+namespace import ::dialog_data::pdtk_data_dialog
+namespace import ::dialog_find::pdtk_couldnotfind
namespace import ::dialog_font::pdtk_canvas_dofont
namespace import ::dialog_gatom::pdtk_gatom_dialog
namespace import ::dialog_iemgui::pdtk_iemgui_dialog
namespace import ::dialog_midi::pdtk_midi_dialog
namespace import ::dialog_midi::pdtk_alsa_midi_dialog
+namespace import ::dialog_path::pdtk_path_dialog
+namespace import ::dialog_startup::pdtk_startup_dialog
# hack - these should be better handled in the C code
namespace import ::dialog_array::pdtk_array_listview_new
@@ -57,10 +87,16 @@ namespace import ::dialog_array::pdtk_array_listview_closeWindow
#------------------------------------------------------------------------------#
# global variables
+# this is a wide array of global variables that are used throughout the GUI.
+# they can be used in plugins to check the status of various things since they
+# should all have been properly initialized by the time startup plugins are
+# loaded.
+
set PD_MAJOR_VERSION 0
set PD_MINOR_VERSION 0
set PD_BUGFIX_VERSION 0
set PD_TEST_VERSION ""
+set done_init 0
set TCL_MAJOR_VERSION 0
set TCL_MINOR_VERSION 0
@@ -69,8 +105,13 @@ set TCL_BUGFIX_VERSION 0
# for testing which platform we are running on ("aqua", "win32", or "x11")
set windowingsystem ""
-# variable for vwait so that 'pd-gui' will timeout if 'pd' never shows up
-set wait4pd "init"
+# args about how much and where to log
+set loglevel 2
+set stderr 0
+
+# connection between 'pd' and 'pd-gui'
+set host ""
+set port 0
# canvas font, received from pd in pdtk_pd_startup, set in s_main.c
set font_family "courier"
@@ -78,45 +119,95 @@ set font_weight "normal"
# sizes of chars for each of the Pd fixed font sizes:
# fontsize width(pixels) height(pixels)
set font_fixed_metrics {
- 8 5 10
- 9 6 11
+ 8 5 11
+ 9 6 12
10 6 13
- 12 7 15
+ 12 7 16
14 8 17
- 16 10 20
+ 16 10 19
18 11 22
- 24 14 30
+ 24 14 29
30 18 37
- 36 22 45
+ 36 22 44
}
+set font_measured_metrics {}
# root path to lib of Pd's files, see s_main.c for more info
set sys_libdir {}
# root path where the pd-gui.tcl GUI script is located
set sys_guidir {}
-
-set audioapi_list {}
-set midiapi_list {}
+# user-specified search path for objects, help, fonts, etc.
+set sys_searchpath {}
+# hard-coded search patch for objects, help, plugins, etc.
+set sys_staticpath {}
+# the path to the folder where the current plugin is being loaded from
+set current_plugin_loadpath {}
+# list of command line flags set at startup
+set startup_flags {}
+# list of libraries loaded on startup
+set startup_libraries {}
+# start dirs for new files and open panels
+set filenewdir [pwd]
+set fileopendir [pwd]
+
+
+# lists of audio/midi devices and APIs for prefs dialogs
+set audio_apilist {}
+set audio_indevlist {}
+set audio_outdevlist {}
+set midi_apilist {}
+set midi_indevlist {}
+set midi_outdevlist {}
set pd_whichapi 0
set pd_whichmidiapi 0
# current state of the DSP
set dsp 0
+# state of the peak meters in the Pd window
+set meters 0
# the toplevel window that currently is on top and has focus
set focused_window .
-# TODO figure out how to get all windows into the menu_windowlist
-# store list of parent windows for Window menu
-set menu_windowlist {}
# store that last 10 files that were opened
set recentfiles_list {}
set total_recentfiles 10
-# keep track of the location of popup menu for CanvasWindows
-set popup_xpix 0
-set popup_ypix 0
+# keep track of the location of popup menu for PatchWindows, in canvas coords
+set popup_xcanvas 0
+set popup_ycanvas 0
+# modifier for key commands (Ctrl/Control on most platforms, Cmd/Mod1 on MacOSX)
+set modifier ""
+# current state of the Edit Mode menu item
+set editmode_button 0
+
## per toplevel/patch data
-# store editmode for each open canvas, starting with a blank array
-array set editmode {}
+# window location modifiers
+set menubarsize 0 ;# Mac OS X and other platforms have a menubar on top
+set windowframex 0 ;# different platforms have different window frames
+set windowframey 0 ;# different platforms have different window frames
+# patch properties
+array set editmode {} ;# store editmode for each open patch canvas
+array set editingtext {};# if an obj, msg, or comment is being edited, per patch
+array set loaded {} ;# store whether a patch has completed loading
+array set xscrollable {};# keep track of whether the scrollbars are present
+array set yscrollable {}
+# patch window tree, these might contain patch IDs without a mapped toplevel
+array set windowname {} ;# window names based on mytoplevel IDs
+array set childwindows {} ;# all child windows based on mytoplevel IDs
+array set parentwindows {} ;# topmost parent window ID based on mytoplevel IDs
+
+# variables for holding the menubar to allow for configuration by plugins
+set ::pdwindow_menubar ".menubar"
+set ::patch_menubar ".menubar"
+set ::dialog_menubar ""
+
+# minimum size of the canvas window of a patch
+set canvas_minwidth 50
+set canvas_minheight 20
+
+# undo states
+set ::undo_action "no"
+set ::redo_action "no"
+set ::undo_toplevel "."
#------------------------------------------------------------------------------#
# coding style
@@ -129,17 +220,23 @@ array set editmode {}
# - if a menu_* proc opens a dialog panel, that proc is called menu_*_dialog
# - use "eq/ne" for string comparison, NOT "==/!=" (http://wiki.tcl.tk/15323)
#
+#
## Names for Common Variables
#----------------------------
-#
# variables named after the Tk widgets they represent
+# $window = any kind of Tk widget that can be a Tk 'window'
# $mytoplevel = a window id made by a 'toplevel' command
-# $mygfxstub = a window id made by a 'toplevel' command via gfxstub/x_gui.c
-# $menubar = the 'menu' attached to each 'toplevel'
-# $mymenu = 'menu' attached to the menubar
-# $menuitem = 'menu' item
-# $mycanvas = 'canvas'
-# $canvasitem = 'canvas' item
+# $gfxstub = a 'toplevel' window id for dialogs made in gfxstub/x_gui.c
+# $menubar = the 'menu' attached to each 'toplevel'
+# $mymenu = 'menu' attached to the menubar, like the File menu
+# $tkcanvas = a Tk 'canvas', which is the root of each patch
+#
+#
+## Dialog Panel Types
+#----------------------------
+# global (only one): find, sendmessage, prefs, helpbrowser
+# per-canvas: font, canvas properties (created with a message from pd)
+# per object: gatom, iemgui, array, data structures (created with a message from pd)
#
#
## Prefix Names for procs
@@ -150,18 +247,6 @@ array set editmode {}
# ------------------------------------------------------------------------------
# init functions
-proc set_pd_version {versionstring} {
- regexp -- {.*([0-9])\.([0-9]+)[\.\-]([0-9]+)([^0-9]?.*)} $versionstring \
- wholematch \
- ::PD_MAJOR_VERSION ::PD_MINOR_VERSION ::PD_BUGFIX_VERSION ::PD_TEST_VERSION
-}
-
-proc set_tcl_version {} {
- regexp {([0-9])\.([0-9])\.([0-9]+)} [info patchlevel] \
- wholematch \
- ::TCL_MAJOR_VERSION ::TCL_MINOR_VERSION ::TCL_BUGFIX_VERSION
-}
-
# root paths to find Pd's files where they are installed
proc set_pd_paths {} {
set ::sys_guidir [file normalize [file dirname [info script]]]
@@ -175,6 +260,8 @@ proc init_for_platform {} {
switch -- $::windowingsystem {
"x11" {
+ set ::modifier "Control"
+ option add *PatchWindow*Canvas.background "white" startupFile
# add control to show/hide hidden files in the open panel (load
# the tk_getOpenFile dialog once, otherwise it will not work)
catch {tk_getOpenFile -with-invalid-argument}
@@ -188,8 +275,31 @@ proc init_for_platform {} {
[list [_ "Max Patch Files"] {.pat} ] \
[list [_ "Max Text Files"] {.mxt} ] \
]
+ # some platforms have a menubar on the top, so place below them
+ set ::menubarsize 0
+ # Tk handles the window placement differently on each
+ # platform. With X11, the x,y placement refers to the window
+ # frame's upper left corner. http://wiki.tcl.tk/11502
+ set ::windowframex 3
+ set ::windowframey 53
+ # TODO add wm iconphoto/iconbitmap here if it makes sense
+ # mouse cursors for all the different modes
+ set ::cursor_runmode_nothing "left_ptr"
+ set ::cursor_runmode_clickme "arrow"
+ set ::cursor_runmode_thicken "sb_v_double_arrow"
+ set ::cursor_runmode_addpoint "plus"
+ set ::cursor_editmode_nothing "hand2"
+ set ::cursor_editmode_connect "circle"
+ set ::cursor_editmode_disconnect "X_cursor"
}
"aqua" {
+ set ::modifier "Mod1"
+ option add *DialogWindow*background "#E8E8E8" startupFile
+ option add *DialogWindow*Entry.highlightBackground "#E8E8E8" startupFile
+ option add *DialogWindow*Button.highlightBackground "#E8E8E8" startupFile
+ option add *DialogWindow*Entry.background "white" startupFile
+ # Mac OS X needs a menubar all the time
+ set ::dialog_menubar ".menubar"
# set file types that open/save recognize
set ::filetypes \
[list \
@@ -197,10 +307,33 @@ proc init_for_platform {} {
[list [_ "Pd Files"] {.pd} ] \
[list [_ "Max Patch Files (.pat)"] {.pat} ] \
[list [_ "Max Text Files (.mxt)"] {.mxt} ] \
- ]
+ ]
+ # some platforms have a menubar on the top, so place below them
+ set ::menubarsize 22
+ # Tk handles the window placement differently on each platform, on
+ # Mac OS X, the x,y placement refers to the content window's upper
+ # left corner (not of the window frame) http://wiki.tcl.tk/11502
+ set ::windowframex 0
+ set ::windowframey 0
+ # mouse cursors for all the different modes
+ set ::cursor_runmode_nothing "arrow"
+ set ::cursor_runmode_clickme "center_ptr"
+ set ::cursor_runmode_thicken "sb_v_double_arrow"
+ set ::cursor_runmode_addpoint "plus"
+ set ::cursor_editmode_nothing "hand2"
+ set ::cursor_editmode_connect "circle"
+ set ::cursor_editmode_disconnect "X_cursor"
}
"win32" {
+ set ::modifier "Control"
+ option add *PatchWindow*Canvas.background "white" startupFile
+ # fix menu font size on Windows with tk scaling = 1
font create menufont -family Tahoma -size -11
+ option add *Menu.font menufont startupFile
+ option add *HelpBrowser*font menufont startupFile
+ option add *DialogWindow*font menufont startupFile
+ option add *PdWindow*font menufont startupFile
+ option add *ErrorDialog*font menufont startupFile
# set file types that open/save recognize
set ::filetypes \
[list \
@@ -209,6 +342,24 @@ proc init_for_platform {} {
[list [_ "Max Patch Files"] {.pat} ] \
[list [_ "Max Text Files"] {.mxt} ] \
]
+ # some platforms have a menubar on the top, so place below them
+ set ::menubarsize 0
+ # Tk handles the window placement differently on each platform, on
+ # Mac OS X, the x,y placement refers to the content window's upper
+ # left corner. http://wiki.tcl.tk/11502
+ # TODO this probably needs a script layer: http://wiki.tcl.tk/11291
+ set ::windowframex 0
+ set ::windowframey 0
+ # TODO use 'winico' package for full, hicolor icon support
+ wm iconbitmap . -default [file join $::sys_guidir pd.ico]
+ # mouse cursors for all the different modes
+ set ::cursor_runmode_nothing "right_ptr"
+ set ::cursor_runmode_clickme "arrow"
+ set ::cursor_runmode_thicken "sb_v_double_arrow"
+ set ::cursor_runmode_addpoint "plus"
+ set ::cursor_editmode_nothing "hand2"
+ set ::cursor_editmode_connect "circle"
+ set ::cursor_editmode_disconnect "X_cursor"
}
}
}
@@ -217,26 +368,32 @@ proc init_for_platform {} {
# locale handling
# official GNU gettext msgcat shortcut
-if {[tk windowingsystem] ne "win32"} {
- proc _ {s} {return [::msgcat::mc $s]}
-} else {
- proc _ {s} {return $s}
-}
+proc _ {s} {return [::msgcat::mc $s]}
proc load_locale {} {
- if {[tk windowingsystem] ne "win32"} {
- ::msgcat::mcload [file join [file dirname [info script]] .. po]
+ # on any UNIX-like environment, Tcl should automatically use LANG, LC_ALL,
+ # etc. otherwise we need to dig it up. Mac OS X only uses LANG, etc. from
+ # the Terminal, and Windows doesn't have LANG, etc unless you manually set
+ # it up yourself. Windows apps don't use the locale env vars usually.
+ if {$::tcl_platform(os) eq "Darwin" && ! [info exists ::env(LANG)]} {
+ # http://thread.gmane.org/gmane.comp.lang.tcl.mac/5215
+ # http://thread.gmane.org/gmane.comp.lang.tcl.mac/6433
+ if {![catch "exec defaults read com.apple.dock loc" lang]} {
+ ::msgcat::mclocale $lang
+ } elseif {![catch "exec defaults read NSGlobalDomain AppleLocale" lang]} {
+ ::msgcat::mclocale $lang
+ }
+ } elseif {$::tcl_platform(platform) eq "windows"} {
+ # using LANG on Windows is useful for easy debugging
+ if {[info exists ::env(LANG)] && $::env(LANG) ne "C" && $::env(LANG) ne ""} {
+ ::msgcat::mclocale $::env(LANG)
+ } elseif {![catch {package require registry}]} {
+ ::msgcat::mclocale [string tolower \
+ [string range \
+ [registry get {HKEY_CURRENT_USER\Control Panel\International} sLanguage] 0 1] ]
+ }
}
-
- # for Windows
- #set locale "en" ;# Use whatever is right for your app
- #if {[catch {package require registry}]} {
- # tk_messageBox -icon error -message "Could not get locale from registry"
- #} else {
- # set locale [string tolower \
- # [string range \
- # [registry get {HKEY_CURRENT_USER\Control Panel\International} sLanguage] 0 1] ]
- #}
+ ::msgcat::mcload [file join [file dirname [info script]] .. po]
##--moo: force default system and stdio encoding to UTF-8
encoding system utf-8
@@ -258,32 +415,32 @@ proc get_font_for_size {size} {
# always do a good job of choosing in respect to Pd's needs. So this chooses
# from a list of fonts that are known to work well with Pd.
proc find_default_font {} {
- set testfonts {Inconsolata "Courier New" "Liberation Mono" FreeMono \
- "DejaVu Sans Mono" "Bitstream Vera Sans Mono"}
+ set testfonts {"DejaVu Sans Mono" "Bitstream Vera Sans Mono" \
+ "Inconsolata" "Courier 10 Pitch" "Andale Mono" "Droid Sans Mono"}
foreach family $testfonts {
if {[lsearch -exact -nocase [font families] $family] > -1} {
set ::font_family $family
break
}
}
- puts "DEFAULT FONT: $::font_family"
+ ::pdwindow::verbose 0 "Default font: $::font_family\n"
}
proc set_base_font {family weight} {
if {[lsearch -exact [font families] $family] > -1} {
set ::font_family $family
} else {
- pdtk_post [format \
- [_ "WARNING: Font family '%s' not found, using default (%s)"] \
- $family $::font_family]
+ ::pdwindow::post [format \
+ [_ "WARNING: Font family '%s' not found, using default (%s)\n"] \
+ $family $::font_family]
}
if {[lsearch -exact {bold normal} $weight] > -1} {
set ::font_weight $weight
set using_defaults 0
} else {
- pdtk_post [format \
- [_ "WARNING: Font weight '%s' not found, using default (%s)"] \
- $weight $::font_weight]
+ ::pdwindow::post [format \
+ [_ "WARNING: Font weight '%s' not found, using default (%s)\n"] \
+ $weight $::font_weight]
}
}
@@ -297,17 +454,22 @@ proc fit_font_into_metrics {} {
-size [expr {-$height}]
set height2 $height
set giveup 0
- while {[font measure $myfont M] > $width} {
+ while {[font measure $myfont M] > $width || \
+ [font metrics $myfont -linespace] > $height} {
incr height2 -1
font configure $myfont -size [expr {-$height2}]
if {$height2 * 2 <= $height} {
set giveup 1
+ set ::font_measured_metrics $::font_fixed_metrics
break
}
}
+ set ::font_measured_metrics \
+ "$::font_measured_metrics $size\
+ [font measure $myfont M] [font metrics $myfont -linespace]"
if {$giveup} {
- pdtk_post [format \
- [_ "ERROR: %s failed to find font size (%s) that fits into %sx%s!"]\
+ ::pdwindow::post [format \
+ [_ "WARNING: %s failed to find font size (%s) that fits into %sx%s!\n"]\
[lindex [info level 0] 0] $size $width $height]
continue
}
@@ -318,46 +480,77 @@ proc fit_font_into_metrics {} {
# ------------------------------------------------------------------------------
# procs called directly by pd
-# this is only called when 'pd' starts 'pd-gui', not the other way around
-proc pdtk_pd_startup {versionstring audio_apis midi_apis sys_font sys_fontweight} {
-# pdtk_post "-------------- pdtk_pd_startup ----------------"
-# pdtk_post "version: $versionstring"
-# pdtk_post "audio_apis: $audio_apis"
-# pdtk_post "midi_apis: $midi_apis"
-# pdtk_post "sys_font: $sys_font"
-# pdtk_post "sys_fontweight: $sys_fontweight"
+proc pdtk_pd_startup {major minor bugfix test
+ audio_apis midi_apis sys_font sys_fontweight} {
+ set ::PD_MAJOR_VERSION $major
+ set ::PD_MINOR_VERSION $minor
+ set ::PD_BUGFIX_VERSION $bugfix
+ set ::PD_TEST_VERSION $test
set oldtclversion 0
- pdsend "pd init [enquote_path [pwd]] $oldtclversion $::font_fixed_metrics"
- set_pd_version $versionstring
- set ::audioapi_list $audio_apis
- set ::midiapi_list $midi_apis
+ set ::audio_apilist $audio_apis
+ set ::midi_apilist $midi_apis
if {$::tcl_version >= 8.5} {find_default_font}
set_base_font $sys_font $sys_fontweight
fit_font_into_metrics
- # TODO what else is needed from the original?
- set ::wait4pd "started"
+ pdsend "pd init [enquote_path [pwd]] $oldtclversion $::font_measured_metrics"
+ ::pd_bindings::class_bindings
+ ::pd_bindings::global_bindings
+ ::pd_menus::create_menubar
+ ::pdtk_canvas::create_popup
+ ::pdwindow::create_window
+ ::pd_menus::configure_for_pdwindow
+ load_startup_plugins
+ open_filestoopen
+ set ::done_init 1
}
##### routine to ask user if OK and, if so, send a message on to Pd ######
-# TODO add 'mytoplevel' once merged to 0.43, with -parent
-proc pdtk_check {message reply_to_pd default} {
- # TODO this should use -parent and -title, but the hard part is figuring
- # out how to get the values for those without changing g_editor.c
- set answer [tk_messageBox -type yesno -icon question -default $default \
- -message [_ $message]]
+proc pdtk_check {mytoplevel message reply_to_pd default} {
+ wm deiconify $mytoplevel
+ raise $mytoplevel
+ if {$::windowingsystem eq "win32"} {
+ set answer [tk_messageBox -message [_ $message] -type yesno -default $default \
+ -icon question -title [wm title $mytoplevel]]
+ } else {
+ set answer [tk_messageBox -message [_ $message] -type yesno \
+ -default $default -parent $mytoplevel -icon question]
+ }
if {$answer eq "yes"} {
pdsend $reply_to_pd
}
}
-proc pdtk_fixwindowmenu {} {
- # TODO canvas_updatewindowlist() sets up the menu_windowlist with all of
- # the parent CanvasWindows, we should then use [wm stackorder .] to get
- # the rest of the CanvasWindows to make sure that all CanvasWindows are in
- # the menu. This would probably be better handled on the C side of
- # things, since then, the menu_windowlist could be built with the proper
- # parent/child relationships.
- # pdtk_post "Running pdtk_fixwindowmenu"
+# ------------------------------------------------------------------------------
+# parse command line args when Wish/pd-gui.tcl is started first
+
+proc parse_args {argc argv} {
+ opt_parser::init {
+ {-stderr set {::stderr}}
+ {-open lappend {- ::filestoopen_list}}
+ }
+ set unflagged_files [opt_parser::get_options $argv]
+ # if we have a single arg that is not a file, its a port or host:port combo
+ if {$argc == 1 && ! [file exists $argv]} {
+ if { [string is int $argv] && $argv > 0} {
+ # 'pd-gui' got the port number from 'pd'
+ set ::host "localhost"
+ set ::port $argv
+ } else {
+ set hostport [split $argv ":"]
+ set ::host [lindex $hostport 0]
+ set ::port [lindex $hostport 1]
+ }
+ } elseif {$unflagged_files ne ""} {
+ foreach filename $unflagged_files {
+ lappend ::filestoopen_list $filename
+ }
+ }
+}
+
+proc open_filestoopen {} {
+ foreach filename $::filestoopen_list {
+ open_file $filename
+ }
}
# ------------------------------------------------------------------------------
@@ -384,28 +577,37 @@ proc first_lost {} {
selection own -command first_lost -selection PUREDATA .
}
-# all other instances
-proc send_args {offset maxChars} {
- return [string range $::argv $offset [expr {$offset+$maxChars}]]
-}
-
proc others_lost {} {
set ::singleton_state "exit"
destroy .
exit
}
+# all other instances
+proc send_args {offset maxChars} {
+ set sendargs {}
+ foreach filename $::filestoopen_list {
+ lappend sendargs [file normalize $filename]
+ }
+ return [string range $sendargs $offset [expr {$offset+$maxChars}]]
+}
-# ------------------------------------------------------------------------------
-# various startup related procs
+# this command will open files received from a 2nd instance of Pd
+proc receive_args {filelist} {
+ raise .
+ foreach filename $filelist {
+ open_file $filename
+ }
+}
proc check_for_running_instances {argc argv} {
- # pdtk_post "check_for_running_instances $argc $argv"
switch -- $::windowingsystem {
"aqua" {
# handled by ::tk::mac::OpenDocument in apple_events.tcl
} "x11" {
# http://wiki.tcl.tk/1558
+ # TODO replace PUREDATA name with path so this code is a singleton
+ # based on install location rather than this hard-coded name
if {![singleton PUREDATA_MANAGER]} {
# other instances called by wish/pd-gui (exempt 'pd' by 5400 arg)
if {$argc == 1 && [string is int $argv] && $argv >= 5400} {return}
@@ -425,32 +627,33 @@ proc check_for_running_instances {argc argv} {
}
}
-# this command will open files received from a 2nd instance of Pd
-proc receive_args args {
- # pdtk_post "receive_files $args"
- raise .
- foreach filename $args {
- open_file $filename
+
+# ------------------------------------------------------------------------------
+# load plugins on startup
+
+proc load_plugin_script {filename} {
+ global errorInfo
+
+ ::pdwindow::debug "Loading plugin: $filename\n"
+ set tclfile [open $filename]
+ set tclcode [read $tclfile]
+ close $tclfile
+ if {[catch {uplevel #0 $tclcode} errorname]} {
+ ::pdwindow::error "-----------\n"
+ ::pdwindow::error "UNHANDLED ERROR: $errorInfo\n"
+ ::pdwindow::error "FAILED TO LOAD $filename\n"
+ ::pdwindow::error "-----------\n"
}
}
-proc load_startup {} {
- global errorInfo
-# TODO search all paths for startup.tcl
- set startupdir [file normalize "$::sys_libdir/startup"]
- # pdtk_post "load_startup $startupdir"
- puts stderr "load_startup $startupdir"
- if { ! [file isdirectory $startupdir]} { return }
- foreach filename [glob -directory $startupdir -nocomplain -types {f} -- *.tcl] {
- puts "Loading $filename"
- set tclfile [open $filename]
- set tclcode [read $tclfile]
- close $tclfile
- if {[catch {uplevel #0 $tclcode} errorname]} {
- puts stderr "------------------------------------------------------"
- puts stderr "UNHANDLED ERROR: $errorInfo"
- puts stderr "FAILED TO LOAD $filename"
- puts stderr "------------------------------------------------------"
+proc load_startup_plugins {} {
+ foreach pathdir [concat $::sys_searchpath $::sys_staticpath] {
+ set dir [file normalize $pathdir]
+ if { ! [file isdirectory $dir]} {continue}
+ foreach filename [glob -directory $dir -nocomplain -types {f} -- \
+ *-plugin/*-plugin.tcl *-plugin.tcl] {
+ set ::current_plugin_loadpath [file dirname $filename]
+ load_plugin_script $filename
}
}
}
@@ -462,42 +665,27 @@ proc main {argc argv} {
set ::windowingsystem [tk windowingsystem]
tk appname pd-gui
load_locale
+ parse_args $argc $argv
check_for_running_instances $argc $argv
set_pd_paths
init_for_platform
- # post_tclinfo
- # set a timeout for how long 'pd-gui' should wait for 'pd' to start
- after 20000 set ::wait4pd "timeout"
- # TODO check args for -stderr and set pdtk_post accordingly
- if {$argc == 1 && [string is int $argv] && $argv >= 5400} {
+ # ::host and ::port are parsed from argv by parse_args
+ if { $::port > 0 && $::host ne "" } {
# 'pd' started first and launched us, so get the port to connect to
- ::pd_connect::to_pd [lindex $argv 0]
+ ::pd_connect::to_pd $::port $::host
} else {
# the GUI is starting first, so create socket and exec 'pd'
- set portnumber [::pd_connect::create_socket]
+ set ::port [::pd_connect::create_socket]
set pd_exec [file join [file dirname [info script]] ../bin/pd]
- exec -- $pd_exec -guiport $portnumber &
- }
- # wait for 'pd' to call pdtk_pd_startup, or exit on timeout
- vwait ::wait4pd
- if {$::wait4pd eq "timeout"} {
- puts stderr [_ "ERROR: 'pd' never showed up, 'pd-gui' quitting!"]
- exit 2
+ exec -- $pd_exec -guiport $::port &
+ if {$::windowingsystem eq "aqua"} {
+ # on Aqua, if 'pd-gui' first, then initial dir is home
+ set ::filenewdir $::env(HOME)
+ set ::fileopendir $::env(HOME)
+ }
}
- ::pd_bindings::class_bindings
- ::pd_menus::create_menubar
- ::pdtk_canvas::create_popup
- ::pdwindow::create_window
- ::pd_menus::configure_for_pdwindow
- load_startup
- # pdtk_post "------------------ done with main ----------------------"
+ ::pdwindow::verbose 0 "------------------ done with main ----------------------\n"
}
main $::argc $::argv
-
-
-
-
-
-
diff --git a/pd/tcl/pd.ico b/pd/tcl/pd.ico
new file mode 100755
index 00000000..2da5c243
--- /dev/null
+++ b/pd/tcl/pd.ico
Binary files differ
diff --git a/pd/tcl/pd_bindings.tcl b/pd/tcl/pd_bindings.tcl
index 0cef0474..82ac3509 100644
--- a/pd/tcl/pd_bindings.tcl
+++ b/pd/tcl/pd_bindings.tcl
@@ -4,83 +4,97 @@ package require pd_menucommands
package require dialog_find
namespace eval ::pd_bindings:: {
- variable modifier
-
- namespace export window_bindings
+ namespace export global_bindings
namespace export dialog_bindings
- namespace export canvas_bindings
+ namespace export patch_bindings
}
-# the commands are bound using "" quotations so that the $mytoplevel is
+# TODO rename pd_bindings to window_bindings after merge is done
+
+# Some commands are bound using "" quotations so that the $mytoplevel is
# interpreted immediately. Since the command is being bound to $mytoplevel,
# it makes sense to have value of $mytoplevel already in the command. This is
-# the opposite of the menu commands in pd_menus.tcl
+# the opposite of most menu/bind commands here and in pd_menus.tcl, which use
+# {} to force execution of any variables (i.e. $::focused_window) until later
+
-# binding by class is not recursive, so its useful for certain things
+# binding by class is not recursive, so its useful for window events
proc ::pd_bindings::class_bindings {} {
# and the Pd window is in a class to itself
- bind PdWindow <Configure> "::pd_bindings::window_configure %W"
bind PdWindow <FocusIn> "::pd_bindings::window_focusin %W"
- # bind to all the canvas windows
- bind CanvasWindow <Map> "::pd_bindings::map %W"
- bind CanvasWindow <Unmap> "::pd_bindings::unmap %W"
- bind CanvasWindow <Configure> "::pd_bindings::window_configure %W"
- bind CanvasWindow <FocusIn> "::pd_bindings::window_focusin %W"
- # bindings for dialog windows, which behave differently than canvas windows
+ # bind to all the windows dedicated to patch canvases
+ bind PatchWindow <FocusIn> "::pd_bindings::window_focusin %W"
+ bind PatchWindow <Map> "::pd_bindings::map %W"
+ bind PatchWindow <Unmap> "::pd_bindings::unmap %W"
+ bind PatchWindow <Configure> "::pd_bindings::patch_configure %W %w %h %x %y"
+ # dialog panel windows bindings, which behave differently than PatchWindows
bind DialogWindow <Configure> "::pd_bindings::dialog_configure %W"
bind DialogWindow <FocusIn> "::pd_bindings::dialog_focusin %W"
}
-proc ::pd_bindings::window_bindings {mytoplevel} {
- variable modifier
-
- # for key bindings
- if {$::windowingsystem eq "aqua"} {
- set modifier "Mod1"
- } else {
- set modifier "Control"
- }
-
- # File menu
- bind $mytoplevel <$modifier-Key-b> "menu_helpbrowser"
- bind $mytoplevel <$modifier-Key-f> "::dialog_find::menu_find_dialog $mytoplevel"
- bind $mytoplevel <$modifier-Key-n> "menu_new"
- bind $mytoplevel <$modifier-Key-o> "menu_open"
- bind $mytoplevel <$modifier-Key-p> "menu_print $mytoplevel"
- bind $mytoplevel <$modifier-Key-q> "pdsend \"pd verifyquit\""
- bind $mytoplevel <$modifier-Key-r> "menu_raise_pdwindow"
- bind $mytoplevel <$modifier-Shift-Key-L> "menu_clear_console"
- bind $mytoplevel <$modifier-Shift-Key-Q> "pdsend \"pd quit\""
- bind $mytoplevel <$modifier-Shift-Key-R> "menu_toggle_console"
-
- # DSP control
- bind $mytoplevel <$modifier-Key-slash> "pdsend \"pd dsp 1\""
- bind $mytoplevel <$modifier-Key-period> "pdsend \"pd dsp 0\""
-}
-
-proc ::pd_bindings::pdwindow_bindings {mytoplevel} {
- variable modifier
-
- window_bindings $mytoplevel
-
- # TODO update this to work with the console, if it is used
- bind $mytoplevel <$modifier-Key-a> ".pdwindow.text tag add sel 1.0 end"
- bind $mytoplevel <$modifier-Key-x> "tk_textCut .pdwindow.text"
- bind $mytoplevel <$modifier-Key-c> "tk_textCopy .pdwindow.text"
- bind $mytoplevel <$modifier-Key-v> "tk_textPaste .pdwindow.text"
- bind $mytoplevel <$modifier-Key-w> "wm iconify $mytoplevel"
+proc ::pd_bindings::global_bindings {} {
+ # we use 'bind all' everywhere to get as much of Tk's automatic binding
+ # behaviors as possible, things like not sending an event for 'O' when
+ # 'Control-O' is pressed.
+ bind all <$::modifier-Key-a> {menu_send %W selectall}
+ bind all <$::modifier-Key-b> {menu_helpbrowser}
+ bind all <$::modifier-Key-c> {menu_send %W copy}
+ bind all <$::modifier-Key-d> {menu_send %W duplicate}
+ bind all <$::modifier-Key-e> {menu_toggle_editmode}
+ bind all <$::modifier-Key-f> {menu_find_dialog}
+ bind all <$::modifier-Key-g> {menu_send %W findagain}
+ bind all <$::modifier-Key-n> {menu_new}
+ bind all <$::modifier-Key-o> {menu_open}
+ bind all <$::modifier-Key-p> {menu_print $::focused_window}
+ bind all <$::modifier-Key-q> {pdsend "pd verifyquit"}
+ bind all <$::modifier-Key-r> {menu_raise_pdwindow}
+ bind all <$::modifier-Key-s> {menu_send %W menusave}
+ bind all <$::modifier-Key-v> {menu_send %W paste}
+ bind all <$::modifier-Key-w> {menu_send_float %W menuclose 0}
+ bind all <$::modifier-Key-x> {menu_send %W cut}
+ bind all <$::modifier-Key-z> {menu_undo}
+ bind all <$::modifier-Key-1> {menu_send_float %W obj 0}
+ bind all <$::modifier-Key-2> {menu_send_float %W msg 0}
+ bind all <$::modifier-Key-3> {menu_send_float %W floatatom 0}
+ bind all <$::modifier-Key-4> {menu_send_float %W symbolatom 0}
+ bind all <$::modifier-Key-5> {menu_send_float %W text 0}
+ bind all <$::modifier-Key-slash> {pdsend "pd dsp 1"}
+ bind all <$::modifier-Key-period> {pdsend "pd dsp 0"}
+ # annoying, but Tk's bind needs uppercase letter to get the Shift
+ bind all <$::modifier-Shift-Key-B> {menu_send %W bng}
+ bind all <$::modifier-Shift-Key-C> {menu_send %W mycnv}
+ bind all <$::modifier-Shift-Key-D> {menu_send %W vradio}
+ bind all <$::modifier-Shift-Key-H> {menu_send %W hslider}
+ bind all <$::modifier-Shift-Key-I> {menu_send %W hradio}
+ bind all <$::modifier-Shift-Key-L> {menu_clear_console}
+ bind all <$::modifier-Shift-Key-N> {menu_send %W numbox}
+ bind all <$::modifier-Shift-Key-Q> {pdsend "pd quit"}
+ bind all <$::modifier-Shift-Key-S> {menu_send %W menusaveas}
+ bind all <$::modifier-Shift-Key-T> {menu_send %W toggle}
+ bind all <$::modifier-Shift-Key-U> {menu_send %W vumeter}
+ bind all <$::modifier-Shift-Key-V> {menu_send %W vslider}
+ bind all <$::modifier-Shift-Key-W> {menu_send_float %W menuclose 1}
+ bind all <$::modifier-Shift-Key-Z> {menu_redo}
+
+ # OS-specific bindings
if {$::windowingsystem eq "aqua"} {
- bind $mytoplevel <$modifier-Key-m> "menu_minimize $mytoplevel"
- bind $mytoplevel <$modifier-Key-t> "menu_font_dialog $mytoplevel"
- bind $mytoplevel <$modifier-quoteleft> "menu_raisenextwindow"
+ # Cmd-m = Minimize and Cmd-t = Font on Mac OS X for all apps
+ bind all <$::modifier-Key-m> {menu_minimize %W}
+ bind all <$::modifier-Key-t> {menu_font_dialog}
+ bind all <$::modifier-quoteleft> {menu_raisenextwindow}
+ bind all <$::modifier-Shift-Key-M> {menu_message_dialog}
} else {
- bind $mytoplevel <$modifier-Key-m> "menu_message_dialog"
- bind $mytoplevel <$modifier-Key-t> "menu_texteditor"
+ bind all <$::modifier-Key-m> {menu_message_dialog}
+ #bind all <$::modifier-Key-t> {menu_texteditor}
+ bind all <$::modifier-Next> {menu_raisenextwindow} ;# PgUp
+ bind all <$::modifier-Prior> {menu_raisepreviouswindow};# PageDown
}
- # Tcl event bindings
- wm protocol $mytoplevel WM_DELETE_WINDOW "pdsend \"pd verifyquit\""
+ bind all <KeyPress> {::pd_bindings::sendkey %W 1 %K %A 0}
+ bind all <KeyRelease> {::pd_bindings::sendkey %W 0 %K %A 0}
+ bind all <Shift-KeyPress> {::pd_bindings::sendkey %W 1 %K %A 1}
+ bind all <Shift-KeyRelease> {::pd_bindings::sendkey %W 0 %K %A 1}
}
# this is for the dialogs: find, font, sendmessage, gatom properties, array
@@ -89,135 +103,115 @@ proc ::pd_bindings::pdwindow_bindings {mytoplevel} {
proc ::pd_bindings::dialog_bindings {mytoplevel dialogname} {
variable modifier
- window_bindings $mytoplevel
-
bind $mytoplevel <KeyPress-Escape> "dialog_${dialogname}::cancel $mytoplevel"
bind $mytoplevel <KeyPress-Return> "dialog_${dialogname}::ok $mytoplevel"
- bind $mytoplevel <$modifier-Key-w> "dialog_${dialogname}::cancel $mytoplevel"
+ bind $mytoplevel <$::modifier-Key-w> "dialog_${dialogname}::cancel $mytoplevel"
+ # these aren't supported in the dialog, so alert the user, then break so
+ # that no other key bindings are run
+ bind $mytoplevel <$::modifier-Key-s> {bell; break}
+ bind $mytoplevel <$::modifier-Shift-Key-S> {bell; break}
+ bind $mytoplevel <$::modifier-Key-p> {bell; break}
- $mytoplevel configure -padx 10 -pady 5
- wm group $mytoplevel .
- wm resizable $mytoplevel 0 0
wm protocol $mytoplevel WM_DELETE_WINDOW "dialog_${dialogname}::cancel $mytoplevel"
- catch { # not all platforms/Tcls versions have these options
- wm attributes $mytoplevel -topmost 1
- #wm attributes $mytoplevel -transparent 1
- #$mytoplevel configure -highlightthickness 1
- }
}
-proc ::pd_bindings::canvas_bindings {mytoplevel} {
+proc ::pd_bindings::patch_bindings {mytoplevel} {
variable modifier
- set mycanvas $mytoplevel.c
-
- window_bindings $mytoplevel
+ set tkcanvas [tkcanvas_name $mytoplevel]
- # key bindings -------------------------------------------------------------
- bind $mytoplevel <$modifier-Key-1> "pdsend \"$mytoplevel obj\""
- bind $mytoplevel <$modifier-Key-2> "pdsend \"$mytoplevel msg\""
- bind $mytoplevel <$modifier-Key-3> "pdsend \"$mytoplevel floatatom\""
- bind $mytoplevel <$modifier-Key-4> "pdsend \"$mytoplevel symbolatom\""
- bind $mytoplevel <$modifier-Key-5> "pdsend \"$mytoplevel text\""
- bind $mytoplevel <$modifier-Key-a> "pdsend \"$mytoplevel selectall\""
- bind $mytoplevel <$modifier-Key-c> "pdsend \"$mytoplevel copy\""
- bind $mytoplevel <$modifier-Key-d> "pdsend \"$mytoplevel duplicate\""
- bind $mytoplevel <$modifier-Key-e> "pdsend \"$mytoplevel editmode 0\""
- bind $mytoplevel <$modifier-Key-g> "pdsend \"$mytoplevel findagain\""
- bind $mytoplevel <$modifier-Key-s> "pdsend \"$mytoplevel menusave\""
- bind $mytoplevel <$modifier-Key-v> "pdsend \"$mytoplevel paste\""
- bind $mytoplevel <$modifier-Key-w> "pdsend \"$mytoplevel menuclose 0\""
- bind $mytoplevel <$modifier-Key-x> "pdsend \"$mytoplevel cut\""
- bind $mytoplevel <$modifier-Key-z> "menu_undo $mytoplevel"
+ # TODO move mouse bindings to global and bind to 'all'
- # annoying, but Tk's bind needs uppercase letter to get the Shift
- bind $mytoplevel <$modifier-Shift-Key-B> "pdsend \"$mytoplevel bng 1\""
- bind $mytoplevel <$modifier-Shift-Key-C> "pdsend \"$mytoplevel mycnv 1\""
- bind $mytoplevel <$modifier-Shift-Key-D> "pdsend \"$mytoplevel vradio 1\""
- bind $mytoplevel <$modifier-Shift-Key-H> "pdsend \"$mytoplevel hslider 1\""
- bind $mytoplevel <$modifier-Shift-Key-I> "pdsend \"$mytoplevel hradio 1\""
- bind $mytoplevel <$modifier-Shift-Key-N> "pdsend \"$mytoplevel numbox 1\""
- bind $mytoplevel <$modifier-Shift-Key-S> "pdsend \"$mytoplevel menusaveas\""
- bind $mytoplevel <$modifier-Shift-Key-T> "pdsend \"$mytoplevel toggle 1\""
- bind $mytoplevel <$modifier-Shift-Key-U> "pdsend \"$mytoplevel vumeter 1\""
- bind $mytoplevel <$modifier-Shift-Key-V> "pdsend \"$mytoplevel vslider 1\""
- bind $mytoplevel <$modifier-Shift-Key-W> "pdsend \"$mytoplevel menuclose 1\""
- bind $mytoplevel <$modifier-Shift-Key-Z> "menu_redo $mytoplevel"
-
- if {$::windowingsystem eq "aqua"} {
- bind $mytoplevel <$modifier-Key-m> "menu_minimize $mytoplevel"
- bind $mytoplevel <$modifier-Key-t> "menu_font_dialog $mytoplevel"
- bind $mytoplevel <$modifier-quoteleft> "menu_raisenextwindow"
- } else {
- bind $mytoplevel <$modifier-Key-m> "menu_message_dialog"
- bind $mytoplevel <$modifier-Key-t> "menu_texteditor"
+ # mouse bindings -----------------------------------------------------------
+ # these need to be bound to $tkcanvas because %W will return $mytoplevel for
+ # events over the window frame and $tkcanvas for events over the canvas
+ bind $tkcanvas <Motion> "pdtk_canvas_motion %W %x %y 0"
+ bind $tkcanvas <$::modifier-Motion> "pdtk_canvas_motion %W %x %y 2"
+ bind $tkcanvas <ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 0"
+ bind $tkcanvas <ButtonRelease-1> "pdtk_canvas_mouseup %W %x %y %b"
+ bind $tkcanvas <$::modifier-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 2"
+ bind $tkcanvas <Shift-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 1"
+
+ if {$::windowingsystem eq "x11"} {
+ # from http://wiki.tcl.tk/3893
+ bind all <Button-4> \
+ {event generate [focus -displayof %W] <MouseWheel> -delta 1}
+ bind all <Button-5> \
+ {event generate [focus -displayof %W] <MouseWheel> -delta -1}
+ bind all <Shift-Button-4> \
+ {event generate [focus -displayof %W] <Shift-MouseWheel> -delta 1}
+ bind all <Shift-Button-5> \
+ {event generate [focus -displayof %W] <Shift-MouseWheel> -delta -1}
}
- bind $mytoplevel <KeyPress> "::pd_bindings::sendkey %W 1 %K %A 0"
- bind $mytoplevel <KeyRelease> "::pd_bindings::sendkey %W 0 %K %A 0"
- bind $mytoplevel <Shift-KeyPress> "::pd_bindings::sendkey %W 1 %K %A 1"
- bind $mytoplevel <Shift-KeyRelease> "::pd_bindings::sendkey %W 0 %K %A 1"
+ bind $tkcanvas <MouseWheel> {::pdtk_canvas::scroll %W y %D}
+ bind $tkcanvas <Shift-MouseWheel> {::pdtk_canvas::scroll %W x %D}
- # mouse bindings -----------------------------------------------------------
- # these need to be bound to $mycanvas because %W will return $mytoplevel for
- # events over the window frame and $mytoplevel.c for events over the canvas
- bind $mycanvas <Motion> "pdtk_canvas_motion %W %x %y 0"
- bind $mycanvas <$modifier-Motion> "pdtk_canvas_motion %W %x %y 2"
- bind $mycanvas <ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 0"
- bind $mycanvas <ButtonRelease-1> "pdtk_canvas_mouseup %W %x %y %b"
- bind $mycanvas <$modifier-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 2"
- # TODO look into "virtual events' for a means for getting Shift-Button, etc.
+ # "right clicks" are defined differently on each platform
switch -- $::windowingsystem {
"aqua" {
- bind $mycanvas <ButtonPress-2> "pdtk_canvas_rightclick %W %x %y %b"
+ bind $tkcanvas <ButtonPress-2> "pdtk_canvas_rightclick %W %x %y %b"
# on Mac OS X, make a rightclick with Ctrl-click for 1 button mice
- bind $mycanvas <Control-Button-1> "pdtk_canvas_rightclick %W %x %y %b"
- # TODO try replacing the above with this
- #bind all <Control-Button-1> {event generate %W <Button-2> \
- # -x %x -y %y -rootx %X -rooty %Y \
- # -button 2 -time %t}
+ bind $tkcanvas <Control-Button-1> "pdtk_canvas_rightclick %W %x %y %b"
+ bind $tkcanvas <Option-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 3"
} "x11" {
- bind $mycanvas <ButtonPress-3> "pdtk_canvas_rightclick %W %x %y %b"
+ bind $tkcanvas <ButtonPress-3> "pdtk_canvas_rightclick %W %x %y %b"
# on X11, button 2 "pastes" from the X windows clipboard
- bind $mycanvas <ButtonPress-2> "pdtk_canvas_clickpaste %W %x %y %b"
+ bind $tkcanvas <ButtonPress-2> "pdtk_canvas_clickpaste %W %x %y %b"
+ bind $tkcanvas <Alt-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 3"
} "win32" {
- bind $mycanvas <ButtonPress-3> "pdtk_canvas_rightclick %W %x %y %b"
+ bind $tkcanvas <ButtonPress-3> "pdtk_canvas_rightclick %W %x %y %b"
+ bind $tkcanvas <Alt-ButtonPress-1> "pdtk_canvas_mouse %W %x %y %b 3"
}
}
- #TODO bind $mytoplevel <MouseWheel>
# window protocol bindings
wm protocol $mytoplevel WM_DELETE_WINDOW "pdsend \"$mytoplevel menuclose 0\""
- bind $mycanvas <Destroy> "::pd_bindings::window_destroy %W"
+ bind $tkcanvas <Destroy> "::pd_bindings::window_destroy %W"
}
#------------------------------------------------------------------------------#
# event handlers
-proc ::pd_bindings::window_configure {mytoplevel} {
- pdtk_canvas_getscroll $mytoplevel
+proc ::pd_bindings::patch_configure {mytoplevel width height x y} {
+ # for some reason, when we create a window, we get an event with a
+ # widthXheight of 1x1 first, then we get the right values, so filter it out
+ if {$width == 1 && $height == 1} {return}
+ pdtk_canvas_getscroll [tkcanvas_name $mytoplevel]
+ # send the size/location of the window and canvas to 'pd' in the form of:
+ # left top right bottom
+ pdsend "$mytoplevel setbounds $x $y [expr $x + $width] [expr $y + $height]"
}
-proc ::pd_bindings::window_destroy {mycanvas} {
- set mytoplevel [winfo toplevel $mycanvas]
+proc ::pd_bindings::window_destroy {window} {
+ set mytoplevel [winfo toplevel $window]
unset ::editmode($mytoplevel)
+ unset ::editingtext($mytoplevel)
+ unset ::loaded($mytoplevel)
+ # unset my entries all of the window data tracking arrays
+ array unset ::windowname $mytoplevel
+ array unset ::parentwindows $mytoplevel
+ array unset ::childwindows $mytoplevel
}
# do tasks when changing focus (Window menu, scrollbars, etc.)
proc ::pd_bindings::window_focusin {mytoplevel} {
- # pdtk_post "::pd_bindings::window_focusin $mytoplevel"
+ # focused_window is used throughout for sending bindings, menu commands,
+ # etc. to the correct patch receiver symbol.
set ::focused_window $mytoplevel
- ::dialog_find::set_canvas_to_search $mytoplevel
- ::pd_menucommands::set_menu_new_dir $mytoplevel
+ ::dialog_find::set_window_to_search $mytoplevel
+ ::pd_menucommands::set_filenewdir $mytoplevel
::dialog_font::update_font_dialog $mytoplevel
if {$mytoplevel eq ".pdwindow"} {
::pd_menus::configure_for_pdwindow
} else {
::pd_menus::configure_for_canvas $mytoplevel
}
- # TODO handle enabling/disabling the Undo and Redo menu items in Edit
+ if {[winfo exists .font]} {wm transient .font $::focused_window}
+ # if we regain focus from another app, make sure to editmode cursor is right
+ if {$::editmode($mytoplevel)} {
+ $mytoplevel configure -cursor hand2
+ }
# TODO handle enabling/disabling the Cut/Copy/Paste menu items in Edit
- # TODO enable menu items that the Pd window or dialogs might have disabled
- # TODO update "Open Recent" menu
}
proc ::pd_bindings::dialog_configure {mytoplevel} {
@@ -233,6 +227,7 @@ proc ::pd_bindings::dialog_focusin {mytoplevel} {
# don't get a final "unmap" event when we destroy the window.
proc ::pd_bindings::map {mytoplevel} {
pdsend "$mytoplevel map 1"
+ ::pdtk_canvas::finished_loading_file $mytoplevel
}
proc ::pd_bindings::unmap {mytoplevel} {
@@ -243,7 +238,11 @@ proc ::pd_bindings::unmap {mytoplevel} {
#------------------------------------------------------------------------------#
# key usage
-proc ::pd_bindings::sendkey {mycanvas state key iso shift} {
+# canvas_key() expects to receive the patch's mytoplevel because key messages
+# are local to each patch. Therefore, key messages are not send for the
+# dialog panels, the Pd window, help browser, etc. so we need to filter those
+# events out.
+proc ::pd_bindings::sendkey {window state key iso shift} {
# TODO canvas_key on the C side should be refactored with this proc as well
switch -- $key {
"BackSpace" { set iso ""; set key 8 }
@@ -257,7 +256,13 @@ proc ::pd_bindings::sendkey {mycanvas state key iso shift} {
if {$iso ne ""} {
scan $iso %c key
}
- puts "::pd_bindings::sendkey {%W:$mycanvas $state %K$key %A$iso $shift}"
- # $mycanvas might be a toplevel, but [winfo toplevel] does the right thing
- pdsend "[winfo toplevel $mycanvas] key $state $key $shift"
+ # some pop-up panels also bind to keys like the enter, but then disappear,
+ # so ignore their events. The inputbox in the Startup dialog does this.
+ if {! [winfo exists $window]} {return}
+ #$window might be a toplevel or canvas, [winfo toplevel] does the right thing
+ set mytoplevel [winfo toplevel $window]
+ if {[winfo class $mytoplevel] eq "PatchWindow"} {
+ pdsend "$mytoplevel key $state $key $shift"
+ }
+ # TODO send to 'pd key' for global key events in Pd?
}
diff --git a/pd/tcl/pd_connect.tcl b/pd/tcl/pd_connect.tcl
index cdd3d91d..5bb3f29f 100644
--- a/pd/tcl/pd_connect.tcl
+++ b/pd/tcl/pd_connect.tcl
@@ -12,18 +12,17 @@ namespace eval ::pd_connect:: {
# TODO figure out how to escape { } properly
proc ::pd_connect::configure_socket {sock} {
- fconfigure $sock -blocking 0 -buffering line -encoding utf-8;
+ fconfigure $sock -blocking 0 -buffering none -encoding utf-8;
fileevent $sock readable {::pd_connect::pd_readsocket ""}
}
# if pd opens first, it starts pd-gui, then pd-gui connects to the port pd sent
-proc ::pd_connect::to_pd {port} {
- # puts "::pd_connect::to_pd"
+proc ::pd_connect::to_pd {port {host localhost}} {
variable pd_socket
- # puts stderr "Connecting to localhost $port ..."
- if {[catch {set pd_socket [socket localhost $port]}]} {
- puts stderr "WARNING: connect to pd failed, retrying port $port."
- after 1000 ::pd_connect::to_pd $port
+ ::pdwindow::debug "'pd-gui' connecting to 'pd' on localhost $port ...\n"
+ if {[catch {set pd_socket [socket $host $port]}]} {
+ puts stderr "WARNING: connect to pd failed, retrying port $host:$port."
+ after 1000 ::pd_connect::to_pd $port $host
return
}
::pd_connect::configure_socket $pd_socket
@@ -40,15 +39,15 @@ proc ::pd_connect::create_socket {} {
}
proc ::pd_connect::from_pd {channel clientaddr clientport} {
- puts "::pd_connect::from_pd"
variable pd_socket $channel
- puts "Connection from $clientaddr:$clientport registered"
+ ::pdwindow::debug "Connection from 'pd' to 'pd-gui' on $clientaddr:$clientport\n"
::pd_connect::configure_socket $pd_socket
}
# send a pd/FUDI message from Tcl to Pd. This function aims to behave like a
-# [; message( in Pd. Basically, whatever is in quotes after the proc name
-# will be sent as if it was sent from a message box with a leading semi-colon
+# [; message( in Pd or pdsend on the command line. Basically, whatever is in
+# quotes after the proc name will be sent as if it was sent from a message box
+# with a leading semi-colon.
proc ::pd_connect::pdsend {message} {
variable pd_socket
append message \;
@@ -74,18 +73,15 @@ proc ::pd_connect::pd_readsocket {cmd_from_pd} {
exit
}
}
-# puts stderr [concat CMD: $cmd_from_pd :CMD]
if {[catch {uplevel #0 $cmd_from_pd} errorname]} {
global errorInfo
- puts stderr "errorname: >>$errorname<<"
switch -regexp -- $errorname {
"missing close-brace" {
- # TODO consider using [info complete $cmd_from_pd] in a loop
pd_readsocket $cmd_from_pd
} "^invalid command name" {
- puts stderr "INVALID COMMAND NAME: $errorInfo"
+ ::pdwindow::fatal [concat [_ "(Tcl) INVALID COMMAND NAME: "] $errorInfo "\n"]
} default {
- puts stderr "UNHANDLED ERROR: $errorInfo"
+ ::pdwindow::fatal [concat [_ "(Tcl) UNHANDLED ERROR: "] $errorInfo "\n"]
}
}
}
diff --git a/pd/tcl/pd_menucommands.tcl b/pd/tcl/pd_menucommands.tcl
index e1373b84..d351c994 100644
--- a/pd/tcl/pd_menucommands.tcl
+++ b/pd/tcl/pd_menucommands.tcl
@@ -3,8 +3,6 @@ package provide pd_menucommands 0.1
namespace eval ::pd_menucommands:: {
variable untitled_number "1"
- variable menu_new_dir [pwd]
- variable menu_open_dir [pwd]
namespace export menu_*
}
@@ -14,27 +12,27 @@ namespace eval ::pd_menucommands:: {
proc ::pd_menucommands::menu_new {} {
variable untitled_number
- variable menu_new_dir
- if { ! [file isdirectory $menu_new_dir]} {set menu_new_dir $::env(HOME)}
- set untitled_name [_ "Untitled"]
- pdsend "pd filename $untitled_name-$untitled_number [enquote_path $menu_new_dir]"
+ if { ! [file isdirectory $::filenewdir]} {set ::filenewdir $::env(HOME)}
+ # to localize "Untitled" there will need to be changes in g_canvas.c and
+ # g_readwrite.c, where it tests for the string "Untitled"
+ set untitled_name "Untitled"
+ pdsend "pd filename $untitled_name-$untitled_number [enquote_path $::filenewdir]"
pdsend "#N canvas"
pdsend "#X pop 1"
incr untitled_number
}
proc ::pd_menucommands::menu_open {} {
- variable menu_open_dir
- if { ! [file isdirectory $menu_open_dir]} {set menu_open_dir $::env(HOME)}
+ if { ! [file isdirectory $::fileopendir]} {set ::fileopendir $::env(HOME)}
set files [tk_getOpenFile -defaultextension .pd \
-multiple true \
-filetypes $::filetypes \
- -initialdir $menu_open_dir]
+ -initialdir $::fileopendir]
if {$files ne ""} {
foreach filename $files {
open_file $filename
}
- set menu_open_dir [file dirname $filename]
+ set ::fileopendir [file dirname $filename]
}
}
@@ -43,54 +41,75 @@ proc ::pd_menucommands::menu_print {mytoplevel} {
-defaultextension .ps \
-filetypes { {{postscript} {.ps}} }]
if {$filename ne ""} {
- $mytoplevel.c postscript -file $filename
+ set tkcanvas [tkcanvas_name $mytoplevel]
+ $tkcanvas postscript -file $filename
}
}
-# dialog types:
-# global (only one): find, sendmessage, prefs, helpbrowser
-# per-canvas: font, canvas properties (created with a message from pd)
-# per object: gatom, iemgui, array, data structures (created with a message from pd)
+# ------------------------------------------------------------------------------
+# functions called from Edit menu
+
+proc ::pd_menucommands::menu_undo {} {
+ if {$::focused_window eq $::undo_toplevel && $::undo_action ne "no"} {
+ pdsend "$::focused_window undo"
+ }
+}
+proc ::pd_menucommands::menu_redo {} {
+ if {$::focused_window eq $::undo_toplevel && $::redo_action ne "no"} {
+ pdsend "$::focused_window redo"
+ }
+}
+
+proc ::pd_menucommands::menu_editmode {state} {
+ if {[winfo class $::focused_window] ne "PatchWindow"} {return}
+ set ::editmode_button $state
+# this shouldn't be necessary because 'pd' will reply with pdtk_canvas_editmode
+# set ::editmode($::focused_window) $state
+ pdsend "$::focused_window editmode $state"
+}
+
+proc ::pd_menucommands::menu_toggle_editmode {} {
+ menu_editmode [expr {! $::editmode_button}]
+}
# ------------------------------------------------------------------------------
-# functions called from Edit menu
+# generic procs for sending menu events
-proc menu_undo {mytoplevel} {
- # puts stderr "menu_undo $mytoplevel not implemented yet"
+# send a message to a pd canvas receiver
+proc ::pd_menucommands::menu_send {window message} {
+ set mytoplevel [winfo toplevel $window]
+ if {[winfo class $mytoplevel] eq "PatchWindow"} {
+ pdsend "$mytoplevel $message"
+ }
}
-proc menu_redo {mytoplevel} {
- # puts stderr "menu_redo $mytoplevel not implemented yet"
+# send a message to a pd canvas receiver with a float arg
+proc ::pd_menucommands::menu_send_float {window message float} {
+ set mytoplevel [winfo toplevel $window]
+ if {[winfo class $mytoplevel] eq "PatchWindow"} {
+ pdsend "$mytoplevel $message $float"
+ }
}
# ------------------------------------------------------------------------------
# open the dialog panels
proc ::pd_menucommands::menu_message_dialog {} {
- if {[winfo exists .send_message]} {
- wm deiconify .send_message
- raise .message
- } else {
- # TODO insert real message panel here
- toplevel .send_message
- wm group .send_message .
- wm title .send_message [_ "Send Message..."]
- wm resizable .send_message 0 0
- ::pd_bindings::dialog_bindings .send_message "send_message"
- frame .send_message.frame
- label .send_message.label -text [_ "Message"] -width 30 -height 15
- pack .send_message.label .send_message.frame -side top -expand yes -fill both
- }
+ ::dialog_message::open_message_dialog $::focused_window
+}
+
+proc ::pd_menucommands::menu_find_dialog {} {
+ ::dialog_find::open_find_dialog $::focused_window
}
-proc ::pd_menucommands::menu_font_dialog {mytoplevel} {
+proc ::pd_menucommands::menu_font_dialog {} {
if {[winfo exists .font]} {
raise .font
- } elseif {$mytoplevel eq ".pdwindow"} {
+ } elseif {$::focused_window eq ".pdwindow"} {
pdtk_canvas_dofont .pdwindow [lindex [.pdwindow.text cget -font] 1]
} else {
- pdsend "$mytoplevel menufont"
+ pdsend "$::focused_window menufont"
}
}
@@ -110,20 +129,27 @@ proc ::pd_menucommands::menu_startup_dialog {} {
}
}
+proc ::pd_menucommands::menu_helpbrowser {} {
+ ::helpbrowser::open_helpbrowser
+}
+
+proc ::pd_menucommands::menu_texteditor {} {
+ ::pdwindow::error "the text editor is not implemented"
+}
+
# ------------------------------------------------------------------------------
# window management functions
-proc ::pd_menucommands::menu_minimize {mytoplevel} {
- wm iconify $mytoplevel
+proc ::pd_menucommands::menu_minimize {window} {
+ wm iconify [winfo toplevel $window]
}
-proc ::pd_menucommands::menu_maximize {mytoplevel} {
- wm state $mytoplevel zoomed
+proc ::pd_menucommands::menu_maximize {window} {
+ wm state [winfo toplevel $window] zoomed
}
-proc menu_raise_pdwindow {} {
- set top_window [lindex [wm stackorder .pdwindow] end]
- if {.pdwindow eq $top_window} {
+proc ::pd_menucommands::menu_raise_pdwindow {} {
+ if {$::focused_window eq ".pdwindow" && [winfo viewable .pdwindow]} {
lower .pdwindow
} else {
wm deiconify .pdwindow
@@ -131,62 +157,89 @@ proc menu_raise_pdwindow {} {
}
}
+# used for cycling thru windows of an app
+proc ::pd_menucommands::menu_raisepreviouswindow {} {
+ lower [lindex [wm stackorder .] end] [lindex [wm stackorder .] 0]
+ focus [lindex [wm stackorder .] end]
+}
+
+# used for cycling thru windows of an app the other direction
+proc ::pd_menucommands::menu_raisenextwindow {} {
+ set mytoplevel [lindex [wm stackorder .] 0]
+ raise $mytoplevel
+ focus $mytoplevel
+}
+
+# ------------------------------------------------------------------------------
+# Pd window functions
+proc menu_clear_console {} {
+ ::pdwindow::clear_console
+}
+
# ------------------------------------------------------------------------------
# manage the saving of the directories for the new commands
# this gets the dir from the path of a window's title
-proc ::pd_menucommands::set_menu_new_dir {mytoplevel} {
- variable menu_new_dir
- variable menu_open_dir
+proc ::pd_menucommands::set_filenewdir {mytoplevel} {
# TODO add Aqua specifics once g_canvas.c has [wm attributes -titlepath]
if {$mytoplevel eq ".pdwindow"} {
- # puts "set_menu_new_dir $mytoplevel"
- set menu_new_dir $menu_open_dir
+ set ::filenewdir $::fileopendir
} else {
- regexp -- ".+ - (.+)" [wm title $mytoplevel] ignored menu_new_dir
+ regexp -- ".+ - (.+)" [wm title $mytoplevel] ignored ::filenewdir
}
}
-# ------------------------------------------------------------------------------
-# opening docs as menu items (like the Test Audio and MIDI patch and the manual)
-proc ::pd_menucommands::menu_doc_open {subdir basename} {
- set dirname "$::sys_libdir/$subdir"
-
- switch -- [string tolower [file extension $basename]] {
- ".txt" {::pd_menucommands::menu_opentext "$dirname/$basename"
- } ".c" {::pd_menucommands::menu_opentext "$dirname/$basename"
- } ".htm" {::pd_menucommands::menu_openhtml "$dirname/$basename"
- } ".html" {::pd_menucommands::menu_openhtml "$dirname/$basename"
- } default {
- pdsend "pd open [enquote_path $basename] [enquote_path $dirname]"
+# parse the textfile for the About Pd page
+proc ::pd_menucommands::menu_aboutpd {} {
+ set versionstring "Pd $::PD_MAJOR_VERSION.$::PD_MINOR_VERSION.$::PD_BUGFIX_VERSION$::PD_TEST_VERSION"
+ set filename "$::sys_libdir/doc/1.manual/1.introduction.txt"
+ if {[winfo exists .aboutpd]} {
+ wm deiconify .aboutpd
+ raise .aboutpd
+ } else {
+ toplevel .aboutpd -class TextWindow
+ wm title .aboutpd [_ "About Pd"]
+ wm group .aboutpd .
+ .aboutpd configure -menu $::dialog_menubar
+ text .aboutpd.text -relief flat -borderwidth 0 \
+ -yscrollcommand ".aboutpd.scroll set" -background white
+ scrollbar .aboutpd.scroll -command ".aboutpd.text yview"
+ pack .aboutpd.scroll -side right -fill y
+ pack .aboutpd.text -side left -fill both -expand 1
+ bind .aboutpd <$::modifier-Key-w> "wm withdraw .aboutpd"
+
+ set textfile [open $filename]
+ while {![eof $textfile]} {
+ set bigstring [read $textfile 1000]
+ regsub -all PD_BASEDIR $bigstring $::sys_guidir bigstring2
+ regsub -all PD_VERSION $bigstring2 $versionstring bigstring3
+ .aboutpd.text insert end $bigstring3
}
+ close $textfile
}
}
-# open text docs in a Pd window
-proc ::pd_menucommands::menu_opentext {filename} {
- global pd_myversion
- set mytoplevel [format ".help%d" [clock seconds]]
- toplevel $mytoplevel -class TextWindow
- text $mytoplevel.text -relief flat -borderwidth 0 \
- -yscrollcommand "$mytoplevel.scroll set" -background white
- scrollbar $mytoplevel.scroll -command "$mytoplevel.text yview"
- pack $mytoplevel.scroll -side right -fill y
- pack $mytoplevel.text -side left -fill both -expand 1
- ::pd_bindings::window_bindings $mytoplevel
-
- set textfile [open $filename]
- while {![eof $textfile]} {
- set bigstring [read $textfile 1000]
- regsub -all PD_BASEDIR $bigstring $::sys_guidir bigstring2
- regsub -all PD_VERSION $bigstring2 $pd_myversion bigstring3
- $mytoplevel.text insert end $bigstring3
+# ------------------------------------------------------------------------------
+# opening docs as menu items (like the Test Audio and MIDI patch and the manual)
+proc ::pd_menucommands::menu_doc_open {dir basename} {
+ if {[file pathtype $dir] eq "relative"} {
+ set dirname "$::sys_libdir/$dir"
+ } else {
+ set dirname $dir
+ }
+ set textextension "[string tolower [file extension $basename]]"
+ if {[lsearch -exact [lindex $::filetypes 0 1] $textextension] > -1} {
+ set fullpath [file normalize [file join $dirname $basename]]
+ set dirname [file dirname $fullpath]
+ set basename [file tail $fullpath]
+ pdsend "pd open [enquote_path $basename] [enquote_path $dirname]"
+ } else {
+ ::pd_menucommands::menu_openfile "$dirname/$basename"
}
- close $textfile
}
# open HTML docs from the menu using the OS-default HTML viewer
-proc ::pd_menucommands::menu_openhtml {filename} {
+proc ::pd_menucommands::menu_openfile {filename} {
if {$::tcl_platform(os) eq "Darwin"} {
exec sh -c [format "open '%s'" $filename]
} elseif {$::tcl_platform(platform) eq "windows"} {
diff --git a/pd/tcl/pd_menus.tcl b/pd/tcl/pd_menus.tcl
index 99b6be94..fc617dfa 100644
--- a/pd/tcl/pd_menus.tcl
+++ b/pd/tcl/pd_menus.tcl
@@ -4,33 +4,18 @@
package provide pd_menus 0.1
package require pd_menucommands
-package require Tk
-#package require tile
-## replace Tk widgets with Ttk widgets on 8.5
-#namespace import -force ttk::*
# TODO figure out Undo/Redo/Cut/Copy/Paste state changes for menus
-# TODO figure out parent window/window list for Window menu
-# TODO what is the Tcl package constructor or init()?
-# TODO $::pd_menus::menubar or .menubar globally?
# since there is one menubar that is used for all windows, the menu -commands
# use {} quotes so that $::focused_window is interpreted when the menu item
# is called, not when the command is mapped to the menu item. This is the
# opposite of the 'bind' commands in pd_bindings.tcl
-
-# ------------------------------------------------------------------------------
-# global variables
-
-# TODO this should properly be inside the pd_menus namespace, now it is global
-namespace import ::pd_menucommands::*
-
namespace eval ::pd_menus:: {
variable accelerator
variable menubar ".menubar"
- variable current_toplevel ".pdwindow"
-
+
namespace export create_menubar
namespace export configure_for_pdwindow
namespace export configure_for_canvas
@@ -52,32 +37,33 @@ proc ::pd_menus::create_menubar {} {
}
menu $menubar
set menulist "file edit put find media window help"
- if { $::windowingsystem eq "aqua" } {create_apple_menu $menubar}
- # FIXME why does the following (if uncommented) kill my menubar?
- # if { $::windowingsystem eq "win32" } {create_system_menu $menubar}
foreach mymenu $menulist {
menu $menubar.$mymenu
$menubar add cascade -label [_ [string totitle $mymenu]] \
-menu $menubar.$mymenu
- [format build_%s_menu $mymenu] $menubar.$mymenu .
- if {$::windowingsystem eq "win32"} {
- # fix menu font size on Windows with tk scaling = 1
- $menubar.$mymenu configure -font menufont
- }
+ [format build_%s_menu $mymenu] $menubar.$mymenu
}
+ if {$::windowingsystem eq "aqua"} {create_apple_menu $menubar}
+ if {$::windowingsystem eq "win32"} {create_system_menu $menubar}
+ . configure -menu $menubar
}
proc ::pd_menus::configure_for_pdwindow {} {
variable menubar
# these are meaningless for the Pd window, so disable them
- set file_items_to_disable {"Save" "Save As..." "Print..." "Close"}
- foreach menuitem $file_items_to_disable {
- $menubar.file entryconfigure [_ $menuitem] -state disabled
- }
- set edit_items_to_disable {"Undo" "Redo" "Duplicate" "Tidy Up" "Edit Mode"}
- foreach menuitem $edit_items_to_disable {
- $menubar.edit entryconfigure [_ $menuitem] -state disabled
- }
+ # File menu
+ $menubar.file entryconfigure [_ "Save"] -state disabled
+ $menubar.file entryconfigure [_ "Save As..."] -state disabled
+ $menubar.file entryconfigure [_ "Print..."] -state disabled
+ $menubar.file entryconfigure [_ "Close"] -state disabled
+ # Edit menu
+ $menubar.edit entryconfigure [_ "Duplicate"] -state disabled
+ $menubar.edit entryconfigure [_ "Tidy Up"] -state disabled
+ $menubar.edit entryconfigure [_ "Edit Mode"] -state disabled
+ pdtk_canvas_editmode .pdwindow 0
+ # Undo/Redo change names, they need to have the asterisk (*) after
+ $menubar.edit entryconfigure 0 -state disabled -label [_ "Undo"]
+ $menubar.edit entryconfigure 1 -state disabled -label [_ "Redo"]
# disable everything on the Put menu
for {set i 0} {$i <= [$menubar.put index end]} {incr i} {
# catch errors that happen when trying to disable separators
@@ -87,32 +73,45 @@ proc ::pd_menus::configure_for_pdwindow {} {
proc ::pd_menus::configure_for_canvas {mytoplevel} {
variable menubar
- set file_items_to_disable {"Save" "Save As..." "Print..." "Close"}
- foreach menuitem $file_items_to_disable {
- $menubar.file entryconfigure [_ $menuitem] -state normal
- }
- set edit_items_to_disable {"Undo" "Redo" "Duplicate" "Tidy Up" "Edit Mode"}
- foreach menuitem $edit_items_to_disable {
- $menubar.edit entryconfigure [_ $menuitem] -state normal
- }
+ # File menu
+ $menubar.file entryconfigure [_ "Save"] -state normal
+ $menubar.file entryconfigure [_ "Save As..."] -state normal
+ $menubar.file entryconfigure [_ "Print..."] -state normal
+ $menubar.file entryconfigure [_ "Close"] -state normal
+ # Edit menu
+ $menubar.edit entryconfigure [_ "Duplicate"] -state normal
+ $menubar.edit entryconfigure [_ "Tidy Up"] -state normal
+ $menubar.edit entryconfigure [_ "Edit Mode"] -state normal
+ pdtk_canvas_editmode $mytoplevel $::editmode($mytoplevel)
+ # Put menu
for {set i 0} {$i <= [$menubar.put index end]} {incr i} {
# catch errors that happen when trying to disable separators
- catch {$menubar.put entryconfigure $i -state normal }
+ if {[$menubar.put type $i] ne "separator"} {
+ $menubar.put entryconfigure $i -state normal
+ }
}
- # TODO set "Edit Mode" state using editmode($mytoplevel)
+ update_undo_on_menu $mytoplevel
}
proc ::pd_menus::configure_for_dialog {mytoplevel} {
variable menubar
- # these are meaningless for the dialog panels, so disable them
- set file_items_to_disable {"Save" "Save As..." "Print..." "Close"}
- foreach menuitem $file_items_to_disable {
- $menubar.file entryconfigure [_ $menuitem] -state disabled
- }
- set edit_items_to_disable {"Undo" "Redo" "Duplicate" "Tidy Up" "Edit Mode"}
- foreach menuitem $edit_items_to_disable {
- $menubar.edit entryconfigure [_ $menuitem] -state disabled
+ # these are meaningless for the dialog panels, so disable them except for
+ # the ones that make senes in the Find dialog panel
+ # File menu
+ if {$mytoplevel ne ".find"} {
+ $menubar.file entryconfigure [_ "Save"] -state disabled
+ $menubar.file entryconfigure [_ "Save As..."] -state disabled
+ $menubar.file entryconfigure [_ "Print..."] -state disabled
}
+ $menubar.file entryconfigure [_ "Close"] -state disabled
+ # Edit menu
+ $menubar.edit entryconfigure [_ "Duplicate"] -state disabled
+ $menubar.edit entryconfigure [_ "Tidy Up"] -state disabled
+ $menubar.edit entryconfigure [_ "Edit Mode"] -state disabled
+ pdtk_canvas_editmode $mytoplevel 0
+ # Undo/Redo change names, they need to have the asterisk (*) after
+ $menubar.edit entryconfigure 0 -state disabled -label [_ "Undo"]
+ $menubar.edit entryconfigure 1 -state disabled -label [_ "Redo"]
# disable everything on the Put menu
for {set i 0} {$i <= [$menubar.put index end]} {incr i} {
# catch errors that happen when trying to disable separators
@@ -123,19 +122,20 @@ proc ::pd_menus::configure_for_dialog {mytoplevel} {
# ------------------------------------------------------------------------------
# menu building functions
-proc ::pd_menus::build_file_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_file_menu {mymenu} {
+ # run the platform-specific build_file_menu_* procs first, the config them
[format build_file_menu_%s $::windowingsystem] $mymenu
$mymenu entryconfigure [_ "New"] -command {menu_new}
$mymenu entryconfigure [_ "Open"] -command {menu_open}
- $mymenu entryconfigure [_ "Save"] -command {pdsend "$::focused_window menusave"}
- $mymenu entryconfigure [_ "Save As..."] -command {pdsend "$::focused_window menusaveas"}
- #$mymenu entryconfigure [_ "Revert*"] -command {menu_revert $current_toplevel}
- $mymenu entryconfigure [_ "Close"] -command {pdsend "$::focused_window menuclose 0"}
- $mymenu entryconfigure [_ "Message"] -command {menu_message_dialog}
+ $mymenu entryconfigure [_ "Save"] -command {menu_send $::focused_window menusave}
+ $mymenu entryconfigure [_ "Save As..."] -command {menu_send $::focused_window menusaveas}
+ #$mymenu entryconfigure [_ "Revert*"] -command {menu_revert $::focused_window}
+ $mymenu entryconfigure [_ "Close"] -command {menu_send_float $::focused_window menuclose 0}
+ $mymenu entryconfigure [_ "Message..."] -command {menu_message_dialog}
$mymenu entryconfigure [_ "Print..."] -command {menu_print $::focused_window}
}
-proc ::pd_menus::build_edit_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_edit_menu {mymenu} {
variable accelerator
$mymenu add command -label [_ "Undo"] -accelerator "$accelerator+Z" \
-command {menu_undo $::focused_window}
@@ -143,165 +143,186 @@ proc ::pd_menus::build_edit_menu {mymenu mytoplevel} {
-command {menu_redo $::focused_window}
$mymenu add separator
$mymenu add command -label [_ "Cut"] -accelerator "$accelerator+X" \
- -command {pdsend "$::focused_window cut"}
+ -command {menu_send $::focused_window cut}
$mymenu add command -label [_ "Copy"] -accelerator "$accelerator+C" \
- -command {pdsend "$::focused_window copy"}
+ -command {menu_send $::focused_window copy}
$mymenu add command -label [_ "Paste"] -accelerator "$accelerator+V" \
- -command {pdsend "$::focused_window paste"}
+ -command {menu_send $::focused_window paste}
$mymenu add command -label [_ "Duplicate"] -accelerator "$accelerator+D" \
- -command {pdsend "$::focused_window duplicate"}
+ -command {menu_send $::focused_window duplicate}
$mymenu add command -label [_ "Select All"] -accelerator "$accelerator+A" \
- -command {pdsend "$::focused_window selectall"}
+ -command {menu_send $::focused_window selectall}
$mymenu add separator
if {$::windowingsystem eq "aqua"} {
- $mymenu add command -label [_ "Text Editor"] \
- -command {menu_texteditor $::focused_window}
+# $mymenu add command -label [_ "Text Editor"] \
+# -command {menu_texteditor}
$mymenu add command -label [_ "Font"] -accelerator "$accelerator+T" \
- -command {menu_font_dialog $::focused_window}
+ -command {menu_font_dialog}
} else {
- $mymenu add command -label [_ "Text Editor"] -accelerator "$accelerator+T"\
- -command {menu_texteditor $::focused_window}
+# $mymenu add command -label [_ "Text Editor"] -accelerator "$accelerator+T"\
+# -command {menu_texteditor}
$mymenu add command -label [_ "Font"] \
- -command {menu_font_dialog $::focused_window}
+ -command {menu_font_dialog}
}
$mymenu add command -label [_ "Tidy Up"] \
- -command {pdsend "$::focused_window tidy"}
- $mymenu add command -label [_ "Toggle Console"] -accelerator "Shift+$accelerator+R" \
- -command {.controls.switches.console invoke}
- $mymenu add command -label [_ "Clear Console"] -accelerator "Shift+$accelerator+L" \
- -command {menu_clear_console}
+ -command {menu_send $::focused_window tidy}
+ $mymenu add command -label [_ "Clear Console"] \
+ -accelerator "Shift+$accelerator+L" -command {menu_clear_console}
$mymenu add separator
- #TODO madness! how to do set the state of the check box without invoking the menu!
+ #TODO madness! how to set the state of the check box without invoking the menu!
$mymenu add check -label [_ "Edit Mode"] -accelerator "$accelerator+E" \
- -selectcolor grey85 \
- -command {pdsend "$::focused_window editmode 0"}
- #if { ! [catch {console hide}]} {
- # TODO set up menu item to show/hide the Tcl/Tk console, if it available
- #}
-
- if {$::windowingsystem ne "aqua"} {
- $mymenu add separator
- $mymenu add command -label [_ "Preferences"] \
- -command {menu_preferences_dialog}
- }
+ -selectcolor grey85 -variable ::editmode_button \
+ -command {menu_editmode $::editmode_button}
}
-proc ::pd_menus::build_put_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_put_menu {mymenu} {
variable accelerator
+ # The trailing 0 in menu_send_float basically means leave the object box
+ # sticking to the mouse cursor. The iemguis alway do that when created
+ # from the menu, as defined in canvas_iemguis()
$mymenu add command -label [_ "Object"] -accelerator "$accelerator+1" \
- -command {pdsend "$::focused_window obj 0"}
+ -command {menu_send_float $::focused_window obj 0}
$mymenu add command -label [_ "Message"] -accelerator "$accelerator+2" \
- -command {pdsend "$::focused_window msg 0"}
+ -command {menu_send_float $::focused_window msg 0}
$mymenu add command -label [_ "Number"] -accelerator "$accelerator+3" \
- -command {pdsend "$::focused_window floatatom 0"}
+ -command {menu_send_float $::focused_window floatatom 0}
$mymenu add command -label [_ "Symbol"] -accelerator "$accelerator+4" \
- -command {pdsend "$::focused_window symbolatom 0"}
+ -command {menu_send_float $::focused_window symbolatom 0}
$mymenu add command -label [_ "Comment"] -accelerator "$accelerator+5" \
- -command {pdsend "$::focused_window text 0"}
+ -command {menu_send_float $::focused_window text 0}
$mymenu add separator
$mymenu add command -label [_ "Bang"] -accelerator "Shift+$accelerator+B" \
- -command {pdsend "$::focused_window bng 0"}
+ -command {menu_send $::focused_window bng}
$mymenu add command -label [_ "Toggle"] -accelerator "Shift+$accelerator+T" \
- -command {pdsend "$::focused_window toggle 0"}
+ -command {menu_send $::focused_window toggle}
$mymenu add command -label [_ "Number2"] -accelerator "Shift+$accelerator+N" \
- -command {pdsend "$::focused_window numbox 0"}
+ -command {menu_send $::focused_window numbox}
$mymenu add command -label [_ "Vslider"] -accelerator "Shift+$accelerator+V" \
- -command {pdsend "$::focused_window vslider 0"}
+ -command {menu_send $::focused_window vslider}
$mymenu add command -label [_ "Hslider"] -accelerator "Shift+$accelerator+H" \
- -command {pdsend "$::focused_window hslider 0"}
+ -command {menu_send $::focused_window hslider}
$mymenu add command -label [_ "Vradio"] -accelerator "Shift+$accelerator+D" \
- -command {pdsend "$::focused_window vradio 0"}
+ -command {menu_send $::focused_window vradio}
$mymenu add command -label [_ "Hradio"] -accelerator "Shift+$accelerator+I" \
- -command {pdsend "$::focused_window hradio 0"}
+ -command {menu_send $::focused_window hradio}
$mymenu add command -label [_ "VU Meter"] -accelerator "Shift+$accelerator+U"\
- -command {pdsend "$::focused_window vumeter 0"}
+ -command {menu_send $::focused_window vumeter}
$mymenu add command -label [_ "Canvas"] -accelerator "Shift+$accelerator+C" \
- -command {pdsend "$::focused_window mycnv 0"}
+ -command {menu_send $::focused_window mycnv}
$mymenu add separator
- $mymenu add command -label [_ "Graph"] -command {pdsend "$::focused_window graph"}
- $mymenu add command -label [_ "Array"] -command {pdsend "$::focused_window menuarray"}
+ $mymenu add command -label [_ "Graph"] -command {menu_send $::focused_window graph}
+ $mymenu add command -label [_ "Array"] -command {menu_send $::focused_window menuarray}
}
-proc ::pd_menus::build_find_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_find_menu {mymenu} {
variable accelerator
$mymenu add command -label [_ "Find..."] -accelerator "$accelerator+F" \
- -command {::dialog_find::menu_find_dialog $::focused_window}
+ -command {menu_find_dialog}
$mymenu add command -label [_ "Find Again"] -accelerator "$accelerator+G" \
- -command {pdsend "$::focused_window findagain"}
+ -command {menu_send $::focused_window findagain}
$mymenu add command -label [_ "Find Last Error"] \
- -command {pdsend "$::focused_window finderror"}
+ -command {pdsend {pd finderror}}
}
-proc ::pd_menus::build_media_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_media_menu {mymenu} {
variable accelerator
$mymenu add radiobutton -label [_ "DSP On"] -accelerator "$accelerator+/" \
-variable ::dsp -value 1 -command {pdsend "pd dsp 1"}
$mymenu add radiobutton -label [_ "DSP Off"] -accelerator "$accelerator+." \
-variable ::dsp -value 0 -command {pdsend "pd dsp 0"}
+
$mymenu add separator
+ $mymenu add command -label [_ "Test Audio and MIDI..."] \
+ -command {menu_doc_open doc/7.stuff/tools testtone.pd}
+ $mymenu add command -label [_ "Load Meter"] \
+ -command {menu_doc_open doc/7.stuff/tools load-meter.pd}
- set audioapi_list_length [llength $::audioapi_list]
- for {set x 0} {$x<$audioapi_list_length} {incr x} {
- # pdtk_post "audio [lindex [lindex $::audioapi_list $x] 0]"
- $mymenu add radiobutton -label [lindex [lindex $::audioapi_list $x] 0] \
+ set audio_apilist_length [llength $::audio_apilist]
+ if {$audio_apilist_length > 0} {$mymenu add separator}
+ for {set x 0} {$x<$audio_apilist_length} {incr x} {
+ $mymenu add radiobutton -label [lindex [lindex $::audio_apilist $x] 0] \
-command {menu_audio 0} -variable ::pd_whichapi \
- -value [lindex [lindex $::audioapi_list $x] 1]\
+ -value [lindex [lindex $::audio_apilist $x] 1]\
-command {pdsend "pd audio-setapi $::pd_whichapi"}
}
- if {$audioapi_list_length > 0} {$mymenu add separator}
-
- set midiapi_list_length [llength $::midiapi_list]
- for {set x 0} {$x<$midiapi_list_length} {incr x} {
- # pdtk_post "midi [lindex [lindex $::midiapi_list $x] 0]"
- $mymenu add radiobutton -label [lindex [lindex $::midiapi_list $x] 0] \
+
+ set midi_apilist_length [llength $::midi_apilist]
+ if {$midi_apilist_length > 0} {$mymenu add separator}
+ for {set x 0} {$x<$midi_apilist_length} {incr x} {
+ $mymenu add radiobutton -label [lindex [lindex $::midi_apilist $x] 0] \
-command {menu_midi 0} -variable ::pd_whichmidiapi \
- -value [lindex [lindex $::midiapi_list $x] 1]\
+ -value [lindex [lindex $::midi_apilist $x] 1]\
-command {pdsend "pd midi-setapi $::pd_whichmidiapi"}
}
- if {$midiapi_list_length > 0} {$mymenu add separator}
-
if {$::windowingsystem ne "aqua"} {
- $mymenu add command -label [_ "Audio settings..."] \
- -command {pdsend "pd audio-properties"}
- $mymenu add command -label [_ "MIDI settings..."] \
- -command {pdsend "pd midi-properties"}
$mymenu add separator
+ create_preferences_menu $mymenu.preferences
+ $mymenu add cascade -label [_ "Preferences"] -menu $mymenu.preferences
}
- $mymenu add command -label [_ "Test Audio and MIDI..."] \
- -command {menu_doc_open doc/7.stuff/tools testtone.pd}
- $mymenu add command -label [_ "Load Meter"] \
- -command {menu_doc_open doc/7.stuff/tools load-meter.pd}
}
-proc ::pd_menus::build_window_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_window_menu {mymenu} {
variable accelerator
if {$::windowingsystem eq "aqua"} {
- $mymenu add command -label [_ "Minimize"] -command {menu_minimize .} \
- -accelerator "$accelerator+M"
- $mymenu add command -label [_ "Zoom"] -command {menu_zoom .}
+ $mymenu add command -label [_ "Minimize"] -accelerator "$accelerator+M"\
+ -command {menu_minimize $::focused_window}
+ $mymenu add command -label [_ "Zoom"] \
+ -command {menu_maximize $::focused_window}
$mymenu add separator
+ $mymenu add command -label [_ "Bring All to Front"] \
+ -command {menu_bringalltofront}
+ } else {
+ $mymenu add command -label [_ "Next Window"] \
+ -command {menu_raisenextwindow} \
+ -accelerator [_ "$accelerator+Page Down"]
+ $mymenu add command -label [_ "Previous Window"] \
+ -command {menu_raisepreviouswindow} \
+ -accelerator [_ "$accelerator+Page Up"]
}
- $mymenu add command -label [_ "Parent Window"] \
- -command {pdsend "$::focused_window findparent"}
+ $mymenu add separator
$mymenu add command -label [_ "Pd window"] -command {menu_raise_pdwindow} \
-accelerator "$accelerator+R"
+ $mymenu add command -label [_ "Parent Window"] \
+ -command {menu_send $::focused_window findparent}
$mymenu add separator
- if {$::windowingsystem eq "aqua"} {
- $mymenu add command -label [_ "Bring All to Front"] \
- -command {menu_bringalltofront}
- $mymenu add separator
- }
}
-proc ::pd_menus::build_help_menu {mymenu mytoplevel} {
+proc ::pd_menus::build_help_menu {mymenu} {
if {$::windowingsystem ne "aqua"} {
- $mymenu add command -label [_ "About Pd"] \
- -command {menu_doc_open doc/1.manual 1.introduction.txt}
+ $mymenu add command -label [_ "About Pd"] -command {menu_aboutpd}
}
$mymenu add command -label [_ "HTML Manual..."] \
-command {menu_doc_open doc/1.manual index.htm}
$mymenu add command -label [_ "Browser..."] \
- -command {placeholder menu_helpbrowser \$help_top_directory}
+ -command {menu_helpbrowser}
+ $mymenu add separator
+ $mymenu add command -label [_ "puredata.info"] \
+ -command {menu_openfile {http://puredata.info}}
+ $mymenu add command -label [_ "Report a bug"] -command {menu_openfile \
+ {http://sourceforge.net/tracker/?func=add&group_id=55736&atid=478070}}
+ $mymenu add separator
+ $mymenu add command -label [_ "Tcl prompt"] -command \
+ {::pdwindow::create_tcl_entry}
+
+}
+
+#------------------------------------------------------------------------------#
+# undo/redo menu items
+
+proc ::pd_menus::update_undo_on_menu {mytoplevel} {
+ variable menubar
+ if {$mytoplevel eq $::undo_toplevel && $::undo_action ne "no"} {
+ $menubar.edit entryconfigure 0 -state normal \
+ -label [_ "Undo $::undo_action"]
+ } else {
+ $menubar.edit entryconfigure 0 -state disabled -label [_ "Undo"]
+ }
+ if {$mytoplevel eq $::undo_toplevel && $::redo_action ne "no"} {
+ $menubar.edit entryconfigure 1 -state normal \
+ -label [_ "Redo $::redo_action"]
+ } else {
+ $menubar.edit entryconfigure 1 -state disabled -label [_ "Redo"]
+ }
}
# ------------------------------------------------------------------------------
@@ -323,14 +344,14 @@ proc ::pd_menus::clear_recentfiles_menu {} {
proc ::pd_menus::update_openrecent_menu_aqua {mymenu} {
if {! [winfo exists $mymenu]} {menu $mymenu}
$mymenu delete 0 end
- foreach filename $::recentfiles_list {
- puts "creating menu item for $filename"
- $mymenu add command -label [file tail $filename] \
- -command "open_file $filename"
- }
$mymenu add separator
$mymenu add command -label [_ "Clear Menu"] \
-command "::pd_menus::clear_recentfiles_menu"
+ # newest need to be on top, but the list in oldest first, so insert
+ foreach filename $::recentfiles_list {
+ $mymenu insert 0 command -label [file tail $filename] \
+ -command "open_file {$filename}"
+ }
}
# this expects to be run on the File menu, and to insert above the last separator
@@ -345,12 +366,98 @@ proc ::pd_menus::update_recentfiles_on_menu {mymenu} {
if {$top_separator < [expr $bottom_separator-1]} {
$mymenu delete [expr $top_separator+1] [expr $bottom_separator-1]
}
- set i 0
foreach filename $::recentfiles_list {
- $mymenu insert [expr $top_separator+$i+1] command \
- -label [file tail $filename] -command "open_file $filename"
- incr i
+ $mymenu insert [expr $top_separator+1] command \
+ -label [file tail $filename] -command "open_file {$filename}"
+ }
+}
+
+
+# ------------------------------------------------------------------------------
+# lots of crazy recursion to update the Window menu
+
+# find the first parent patch that has a mapped window
+proc ::pd_menus::find_mapped_parent {parentlist} {
+ if {[llength $parentlist] == 0} {return "none"}
+ set firstparent [lindex $parentlist 0]
+ if {[winfo exists $firstparent]} {
+ return $firstparent
+ } elseif {[llength $parentlist] > 1} {
+ return [find_mapped_parent [lrange $parentlist 1 end]]
+ } else {
+ # we must be the first menu item to be inserted
+ return "none"
+ }
+}
+
+# find the first parent patch that has a mapped window
+proc ::pd_menus::insert_into_menu {mymenu entry parent} {
+ set insertat [$mymenu index end]
+ for {set i 0} {$i <= [$mymenu index end]} {incr i} {
+ if {[$mymenu type $i] ne "command"} {continue}
+ set currentcommand [$mymenu entrycget $i -command]
+ if {$currentcommand eq "raise $entry"} {return} ;# it exists already
+ if {$currentcommand eq "raise $parent"} {
+ set insertat $i
+ }
+ }
+ incr insertat
+ set label ""
+ for {set i 0} {$i < [llength $::parentwindows($entry)]} {incr i} {
+ append label " "
}
+ append label $::windowname($entry)
+ $mymenu insert $insertat command -label $label -command "raise $entry"
+}
+
+# recurse through a list of parent windows and add to the menu
+proc ::pd_menus::add_list_to_menu {mymenu window parentlist} {
+ if {[llength $parentlist] == 0} {
+ insert_into_menu $mymenu $window {}
+ } else {
+ set entry [lindex $parentlist end]
+ if {[winfo exists $entry]} {
+ insert_into_menu $mymenu $entry \
+ [find_mapped_parent $::parentwindows($entry)]
+ }
+ }
+ if {[llength $parentlist] > 1} {
+ add_list_to_menu $mymenu $window [lrange $parentlist 0 end-1]
+ }
+}
+
+# update the list of windows on the Window menu. This expects run on the
+# Window menu, and to insert below the last separator
+proc ::pd_menus::update_window_menu {} {
+ set mymenu $::patch_menubar.window
+ # find the last separator and delete everything after that
+ for {set i 0} {$i <= [$mymenu index end]} {incr i} {
+ if {[$mymenu type $i] eq "separator"} {
+ set deleteat $i
+ }
+ }
+ $mymenu delete $deleteat end
+ $mymenu add separator
+ foreach window [array names ::parentwindows] {
+ set parentlist $::parentwindows($window)
+ add_list_to_menu $mymenu $window $parentlist
+ insert_into_menu $mymenu $window [find_mapped_parent $parentlist]
+ }
+}
+
+# ------------------------------------------------------------------------------
+# submenu for Preferences, now used on all platforms
+
+proc ::pd_menus::create_preferences_menu {mymenu} {
+ menu $mymenu
+ $mymenu add command -label [_ "Path..."] \
+ -command {pdsend "pd start-path-dialog"}
+ $mymenu add command -label [_ "Startup..."] \
+ -command {pdsend "pd start-startup-dialog"}
+ $mymenu add command -label [_ "Audio Settings..."] \
+ -command {pdsend "pd audio-properties"}
+ $mymenu add command -label [_ "MIDI Settings..."] \
+ -command {pdsend "pd midi-properties"}
}
# ------------------------------------------------------------------------------
@@ -360,16 +467,14 @@ proc ::pd_menus::update_recentfiles_on_menu {mymenu} {
proc ::pd_menus::create_apple_menu {mymenu} {
# TODO this should open a Pd patch called about.pd
menu $mymenu.apple
- $mymenu.apple add command -label [_ "About Pd"] \
- -command {menu_doc_open doc/1.manual 1.introduction.txt}
- $mymenu add cascade -label "Apple" -menu $mymenu.apple
+ $mymenu.apple add command -label [_ "About Pd"] -command {menu_aboutpd}
$mymenu.apple add separator
- # starting in 8.4.14, this is created automatically
- set patchlevel [split [info patchlevel] .]
- if {[lindex $patchlevel 1] < 5 && [lindex $patchlevel 2] < 14} {
- $mymenu.apple add command -label [_ "Preferences..."] \
- -command {menu_preferences_dialog" -accelerator "Cmd+,}
- }
+ create_preferences_menu $mymenu.apple.preferences
+ $mymenu.apple add cascade -label [_ "Preferences"] \
+ -menu $mymenu.apple.preferences
+ # this needs to be last for things to function properly
+ $mymenu add cascade -label "Apple" -menu $mymenu.apple
+
}
proc ::pd_menus::build_file_menu_aqua {mymenu} {
@@ -385,7 +490,7 @@ proc ::pd_menus::build_file_menu_aqua {mymenu} {
#$mymenu add command -label [_ "Save All"]
#$mymenu add command -label [_ "Revert to Saved"]
$mymenu add separator
- $mymenu add command -label [_ "Message"]
+ $mymenu add command -label [_ "Message..."]
$mymenu add separator
$mymenu add command -label [_ "Print..."] -accelerator "$accelerator+P"
}
@@ -412,7 +517,7 @@ proc ::pd_menus::build_file_menu_x11 {mymenu} {
$mymenu add command -label [_ "Save As..."] -accelerator "Shift+$accelerator+S"
# $mymenu add command -label "Revert"
$mymenu add separator
- $mymenu add command -label [_ "Message"] -accelerator "$accelerator+M"
+ $mymenu add command -label [_ "Message..."] -accelerator "$accelerator+M"
$mymenu add command -label [_ "Print..."] -accelerator "$accelerator+P"
$mymenu add separator
# the recent files get inserted in here by update_recentfiles_on_menu
@@ -436,10 +541,16 @@ proc ::pd_menus::build_window_menu_x11 {mymenu} {
# menu building functions for Windows/Win32
# for Windows only
-proc ::pd_menus::create_system_menu {mymenu} {
- $mymenu add cascade -menu [menu $mymenu.system]
+proc ::pd_menus::create_system_menu {mymenubar} {
+ set mymenu $mymenubar.system
+ $mymenubar add cascade -label System -menu $mymenu
+ menu $mymenu -tearoff 0
+ # placeholders
+ $mymenu add command -label [_ "Edit Mode"] -command "::pdwindow::verbose 0 systemmenu"
# TODO add Close, Minimize, etc and whatever else is on the little menu
# that is on the top left corner of the window frame
+ # http://wiki.tcl.tk/1006
+ # TODO add Edit Mode here
}
proc ::pd_menus::build_file_menu_win32 {mymenu} {
@@ -451,7 +562,9 @@ proc ::pd_menus::build_file_menu_win32 {mymenu} {
$mymenu add command -label [_ "Save As..."] -accelerator "Shift+$accelerator+S"
# $mymenu add command -label "Revert"
$mymenu add separator
- $mymenu add command -label [_ "Message"] -accelerator "$accelerator+M"
+ $mymenu add command -label [_ "Message..."] -accelerator "$accelerator+M"
+ create_preferences_menu $mymenu.preferences
+ $mymenu add cascade -label [_ "Preferences"] -menu $mymenu.preferences
$mymenu add command -label [_ "Print..."] -accelerator "$accelerator+P"
$mymenu add separator
# the recent files get inserted in here by update_recentfiles_on_menu
diff --git a/pd/tcl/pdtk_canvas.tcl b/pd/tcl/pdtk_canvas.tcl
index 31505cec..c1a85420 100644
--- a/pd/tcl/pdtk_canvas.tcl
+++ b/pd/tcl/pdtk_canvas.tcl
@@ -4,38 +4,103 @@ package provide pdtk_canvas 0.1
package require pd_bindings
namespace eval ::pdtk_canvas:: {
+ namespace export pdtk_canvas_popup
+ namespace export pdtk_canvas_editmode
+ namespace export pdtk_canvas_getscroll
+ namespace export pdtk_canvas_setparents
+ namespace export pdtk_canvas_reflecttitle
+ namespace export pdtk_canvas_menuclose
}
+# One thing that is tricky to understand is the difference between a Tk
+# 'canvas' and a 'canvas' in terms of Pd's implementation. They are similar,
+# but not the same thing. In Pd code, a 'canvas' is basically a patch, while
+# the Tk 'canvas' is the backdrop for drawing everything that is in a patch.
+# The Tk 'canvas' is contained in a 'toplevel' window. That window has a Tk
+# class of 'PatchWindow'.
+
# TODO figure out weird frameless window when you open a graph
+
+#TODO: http://wiki.tcl.tk/11502
+# MS Windows
+#wm geometry . returns contentswidthxcontentsheight+decorationTop+decorationLeftEdge.
+#and
+#winfo rooty . returns contentsTop
+#winfo rootx . returns contentsLeftEdge
+
+
#------------------------------------------------------------------------------#
# canvas new/saveas
proc pdtk_canvas_new {mytoplevel width height geometry editable} {
- # TODO check size of window
- toplevel $mytoplevel -width $width -height $height -class CanvasWindow
+ set screenwidth [winfo screenwidth .]
+ set screenheight [winfo screenheight .]
+
+ # read back the current geometry +posx+posy into variables
+ scan $geometry {%[+]%d%[+]%d} - x - y
+ # fit the geometry onto screen
+ set x [ expr $x % $screenwidth - $::windowframex]
+ set y [ expr $y % $screenheight - $::windowframey]
+ if {$width > $screenwidth} {
+ set width $screenwidth
+ set x 0
+ }
+ if {$height > $screenheight} {
+ set height [expr $screenheight - $::menubarsize - 30] ;# 30 for window framing
+ set y $::menubarsize
+ }
+ set geometry ${width}x$height+$x+$y
+
+ # release the window grab here so that the new window will
+ # properly get the Map and FocusIn events when its created
+ ::pdwindow::busyrelease
+ # set the loaded array for this new window so things can track state
+ set ::loaded($mytoplevel) 0
+ toplevel $mytoplevel -width $width -height $height -class PatchWindow
wm group $mytoplevel .
- $mytoplevel configure -menu .menubar
+ $mytoplevel configure -menu $::patch_menubar
+
+ # we have to wait until $mytoplevel exists before we can generate
+ # a <<Loading>> event for it, that's why this is here and not in the
+ # started_loading_file proc. Perhaps this doesn't make sense tho
+ event generate $mytoplevel <<Loading>>
- # TODO slide off screen windows into view
wm geometry $mytoplevel $geometry
- if {$::windowingsystem eq "aqua"} { # no menubar, it can be small
- wm minsize $mytoplevel 50 20
- } else { # leave room for the menubar
- wm minsize $mytoplevel 310 30
- }
-
- set ::editmode($mytoplevel) $editable
+ wm minsize $mytoplevel $::canvas_minwidth $::canvas_minheight
- set mycanvas $mytoplevel.c
- canvas $mycanvas -width $width -height $height -background white \
- -highlightthickness 0
- # TODO add scrollbars here
- pack $mycanvas -side left -expand 1 -fill both
+ set tkcanvas [tkcanvas_name $mytoplevel]
+ canvas $tkcanvas -width $width -height $height \
+ -highlightthickness 0 -scrollregion [list 0 0 $width $height] \
+ -xscrollcommand "$mytoplevel.xscroll set" \
+ -yscrollcommand "$mytoplevel.yscroll set"
+ scrollbar $mytoplevel.xscroll -orient horizontal -command "$tkcanvas xview"
+ scrollbar $mytoplevel.yscroll -orient vertical -command "$tkcanvas yview"
+ pack $tkcanvas -side left -expand 1 -fill both
+
+ ::pd_bindings::patch_bindings $mytoplevel
+
+ # give focus to the canvas so it gets the events rather than the window
+ focus $tkcanvas
- ::pd_bindings::canvas_bindings $mytoplevel
+ # let the scrollbar logic determine if it should make things scrollable
+ set ::xscrollable($tkcanvas) 0
+ set ::yscrollable($tkcanvas) 0
- # give focus to the canvas so it gets the events rather than the window
+ # init patch properties arrays
+ set ::editingtext($mytoplevel) 0
+ set ::childwindows($mytoplevel) {}
+
+ # this should be at the end so that the window and canvas are all ready
+ # before this variable changes.
+ set ::editmode($mytoplevel) $editable
+}
+
+# if the patch canvas window already exists, then make it come to the front
+proc pdtk_canvas_raise {mytoplevel} {
+ wm deiconify $mytoplevel
+ raise $mytoplevel
+ set mycanvas $mytoplevel.c
focus $mycanvas
}
@@ -61,36 +126,60 @@ proc pdtk_canvas_saveas {name initialfile initialdir} {
set dirname [file dirname $filename]
set basename [file tail $filename]
pdsend "$name savetofile [enquote_path $basename] [enquote_path $dirname]"
- set ::pd_menucommands::menu_new_dir $dirname
+ set ::filenewdir $dirname
+}
+
+##### ask user Save? Discard? Cancel?, and if so, send a message on to Pd ######
+proc ::pdtk_canvas::pdtk_canvas_menuclose {mytoplevel reply_to_pd} {
+ raise $mytoplevel
+ set filename [wm title $mytoplevel]
+ set message [format {Do you want to save the changes you made in "%s"?} $filename]
+ set answer [tk_messageBox -message $message -type yesnocancel -default "yes" \
+ -parent $mytoplevel -icon question]
+ switch -- $answer {
+ yes {
+ pdsend "$mytoplevel menusave"
+ if {[regexp {Untitled-[0-9]+} $filename]} {
+ # wait until pdtk_canvas_saveas finishes and writes to
+ # this var, otherwise the close command will be sent
+ # immediately and the file won't get saved
+ vwait ::filenewdir
+ }
+ pdsend $reply_to_pd
+ }
+ no {pdsend $reply_to_pd}
+ cancel {}
+ }
}
#------------------------------------------------------------------------------#
# mouse usage
-proc pdtk_canvas_motion {mycanvas x y mods} {
- set mytoplevel [winfo toplevel $mycanvas]
- pdsend "$mytoplevel motion [$mycanvas canvasx $x] [$mycanvas canvasy $y] $mods"
+# TODO put these procs into the pdtk_canvas namespace
+proc pdtk_canvas_motion {tkcanvas x y mods} {
+ set mytoplevel [winfo toplevel $tkcanvas]
+ pdsend "$mytoplevel motion [$tkcanvas canvasx $x] [$tkcanvas canvasy $y] $mods"
}
-proc pdtk_canvas_mouse {mycanvas x y b f} {
- set mytoplevel [winfo toplevel $mycanvas]
- pdsend "$mytoplevel mouse [$mycanvas canvasx $x] [$mycanvas canvasy $y] $b $f"
+proc pdtk_canvas_mouse {tkcanvas x y b f} {
+ set mytoplevel [winfo toplevel $tkcanvas]
+ pdsend "$mytoplevel mouse [$tkcanvas canvasx $x] [$tkcanvas canvasy $y] $b $f"
}
-proc pdtk_canvas_mouseup {mycanvas x y b} {
- set mytoplevel [winfo toplevel $mycanvas]
- pdsend "$mytoplevel mouseup [$mycanvas canvasx $x] [$mycanvas canvasy $y] $b"
+proc pdtk_canvas_mouseup {tkcanvas x y b} {
+ set mytoplevel [winfo toplevel $tkcanvas]
+ pdsend "$mytoplevel mouseup [$tkcanvas canvasx $x] [$tkcanvas canvasy $y] $b"
}
-proc pdtk_canvas_rightclick {mycanvas x y b} {
- set mytoplevel [winfo toplevel $mycanvas]
- pdsend "$mytoplevel mouse [$mycanvas canvasx $x] [$mycanvas canvasy $y] $b 8"
+proc pdtk_canvas_rightclick {tkcanvas x y b} {
+ set mytoplevel [winfo toplevel $tkcanvas]
+ pdsend "$mytoplevel mouse [$tkcanvas canvasx $x] [$tkcanvas canvasy $y] $b 8"
}
# on X11, button 2 pastes from X11 clipboard, so simulate normal paste actions
-proc pdtk_canvas_clickpaste {mycanvas x y b} {
- pdtk_canvas_mouse $mycanvas $x $y $b 0
- pdtk_canvas_mouseup $mycanvas $x $y $b
+proc pdtk_canvas_clickpaste {tkcanvas x y b} {
+ pdtk_canvas_mouse $tkcanvas $x $y $b 0
+ pdtk_canvas_mouseup $tkcanvas $x $y $b
pdtk_pastetext
}
@@ -107,21 +196,21 @@ proc ::pdtk_canvas::create_popup {} {
# the popup menu for the canvas
menu .popup -tearoff false
.popup add command -label [_ "Properties"] \
- -command {popup_action $::focused_window 0}
+ -command {::pdtk_canvas::done_popup $::focused_window 0}
.popup add command -label [_ "Open"] \
- -command {popup_action $::focused_window 1}
+ -command {::pdtk_canvas::done_popup $::focused_window 1}
.popup add command -label [_ "Help"] \
- -command {popup_action $::focused_window 2}
+ -command {::pdtk_canvas::done_popup $::focused_window 2}
}
}
-proc popup_action {mytoplevel action} {
- pdsend "$mytoplevel done-popup $action $::popup_xpix $::popup_ypix"
+proc ::pdtk_canvas::done_popup {mytoplevel action} {
+ pdsend "$mytoplevel done-popup $action $::popup_xcanvas $::popup_ycanvas"
}
-proc pdtk_canvas_popup {mytoplevel xpix ypix hasproperties hasopen} {
- set ::popup_xpix $xpix
- set ::popup_ypix $ypix
+proc ::pdtk_canvas::pdtk_canvas_popup {mytoplevel xcanvas ycanvas hasproperties hasopen} {
+ set ::popup_xcanvas $xcanvas
+ set ::popup_ycanvas $ycanvas
if {$hasproperties} {
.popup entryconfigure [_ "Properties"] -state normal
} else {
@@ -132,38 +221,144 @@ proc pdtk_canvas_popup {mytoplevel xpix ypix hasproperties hasopen} {
} else {
.popup entryconfigure [_ "Open"] -state disabled
}
- set mycanvas "$mytoplevel.c"
- tk_popup .popup [expr $xpix + [winfo rootx $mycanvas]] \
- [expr $ypix + [winfo rooty $mycanvas]] 0
+ set tkcanvas [tkcanvas_name $mytoplevel]
+ set scrollregion [$tkcanvas cget -scrollregion]
+ # get the canvas location that is currently the top left corner in the window
+ set left_xview_pix [expr [lindex [$tkcanvas xview] 0] * [lindex $scrollregion 2]]
+ set top_yview_pix [expr [lindex [$tkcanvas yview] 0] * [lindex $scrollregion 3]]
+ # take the mouse clicks in canvas coords, add the root of the canvas
+ # window, and subtract the area that is obscured by scrolling
+ set xpopup [expr int($xcanvas + [winfo rootx $tkcanvas] - $left_xview_pix)]
+ set ypopup [expr int($ycanvas + [winfo rooty $tkcanvas] - $top_yview_pix)]
+ tk_popup .popup $xpopup $ypopup 0
}
#------------------------------------------------------------------------------#
+# procs for when file loading starts/finishes
+
+proc ::pdtk_canvas::started_loading_file {patchname} {
+ ::pdwindow::busygrab
+}
+
+# things to run when a patch is finished loading. This is called when
+# the OS sends the "Map" event for this window.
+proc ::pdtk_canvas::finished_loading_file {mytoplevel} {
+ # ::pdwindow::busyrelease is in pdtk_canvas_new so that the grab
+ # is released before the new toplevel window gets created.
+ # Otherwise the grab blocks the new window from getting the
+ # FocusIn event on creation.
+
+ # set editmode to make sure the menu item is in the right state
+ pdtk_canvas_editmode $mytoplevel $::editmode($mytoplevel)
+ set ::loaded($mytoplevel) 1
+ # send the virtual events now that everything is loaded
+ event generate $mytoplevel <<Loaded>>
+}
+
+#------------------------------------------------------------------------------#
# procs for canvas events
# check or uncheck the "edit" menu item
-proc pdtk_canvas_editval {mytoplevel value} {
- set ::editmode($mytoplevel) $value
-# TODO figure how to change Edit Mode/Interact Mode text and have menu
-# enabling and disabling working still in pd_menus.tcl
-# if {$value == 0} {
-# $::pd_menus::menubar.edit entryconfigure [_ "Interact Mode"] -label [_ "Edit Mode"]
-# } else {
-# $::pd_menus::menubar.edit entryconfigure [_ "Edit Mode"] -label [_ "Interact Mode"]
-# }
- #$mytoplevel.menubar.edit entryconfigure [_ "Edit Mode"] -indicatoron $value
- # TODO make this work, probably with a proc in pd_menus, or maybe the menu
- # item can track the editmode variable
-}
-
-proc pdtk_undomenu {args} {
- # TODO make this work, probably with a proc in pd_menus
- puts "pdtk_undomenu $args"
-}
-
-proc pdtk_canvas_getscroll {mycanvas} {
- # TODO make this work
- # the C code still sends a .c canvas, so get the toplevel
- set mytoplevel [winfo toplevel $mycanvas]
- # puts stderr "pdtk_canvas_getscroll $mycanvas"
+proc ::pdtk_canvas::pdtk_canvas_editmode {mytoplevel state} {
+ set ::editmode_button $state
+ set ::editmode($mytoplevel) $state
+ event generate $mytoplevel <<EditMode>>
+ # can't change the menu background color on Aqua
+ if {$::windowingsystem eq "aqua"} {return}
+ if {$state == 0} {
+ $::pd_menus::menubar.edit entryconfigure [_ "Edit Mode"] -background {}
+ } else {
+ $::pd_menus::menubar.edit entryconfigure [_ "Edit Mode"] -background green
+ }
+}
+
+# message from Pd to update the currently available undo/redo action
+proc pdtk_undomenu {mytoplevel undoaction redoaction} {
+ set ::undo_toplevel $mytoplevel
+ set ::undo_action $undoaction
+ set ::redo_action $redoaction
+ if {$mytoplevel ne "nobody"} {
+ ::pd_menus::update_undo_on_menu $mytoplevel
+ }
+}
+
+# This proc configures the scrollbars whenever anything relevant has
+# been updated. It should always receive a tkcanvas, which is then
+# used to generate the mytoplevel, needed to address the scrollbars.
+proc ::pdtk_canvas::pdtk_canvas_getscroll {tkcanvas} {
+ set mytoplevel [winfo toplevel $tkcanvas]
+ set bbox [$tkcanvas bbox all]
+ if {$bbox eq "" || [llength $bbox] != 4} {return}
+ set xupperleft [lindex $bbox 0]
+ set yupperleft [lindex $bbox 1]
+ if {$xupperleft > 0} {set xupperleft 0}
+ if {$yupperleft > 0} {set yupperleft 0}
+ set scrollregion [concat $xupperleft $yupperleft [lindex $bbox 2] [lindex $bbox 3]]
+ $tkcanvas configure -scrollregion $scrollregion
+ # X scrollbar
+ if {[lindex [$tkcanvas xview] 0] == 0.0 && [lindex [$tkcanvas xview] 1] == 1.0} {
+ set ::xscrollable($tkcanvas) 0
+ pack forget $mytoplevel.xscroll
+ } else {
+ set ::xscrollable($tkcanvas) 1
+ pack $mytoplevel.xscroll -side bottom -fill x -before $tkcanvas
+ }
+ # Y scrollbar, it gets touchy at the limit, so say > 0.995
+ if {[lindex [$tkcanvas yview] 0] == 0.0 && [lindex [$tkcanvas yview] 1] > 0.995} {
+ set ::yscrollable($tkcanvas) 0
+ pack forget $mytoplevel.yscroll
+ } else {
+ set ::yscrollable($tkcanvas) 1
+ pack $mytoplevel.yscroll -side right -fill y -before $tkcanvas
+ }
+}
+
+proc ::pdtk_canvas::scroll {tkcanvas axis amount} {
+ if {$axis eq "x" && $::xscrollable($tkcanvas) == 1} {
+ $tkcanvas xview scroll [expr {- ($amount)}] units
+ }
+ if {$axis eq "y" && $::yscrollable($tkcanvas) == 1} {
+ $tkcanvas yview scroll [expr {- ($amount)}] units
+ }
+}
+
+#------------------------------------------------------------------------------#
+# get patch window child/parent relationships
+
+# add a child window ID to the list of children, if it isn't already there
+proc ::pdtk_canvas::addchild {mytoplevel child} {
+ # if either ::childwindows($mytoplevel) does not exist, or $child does not
+ # exist inside of the ::childwindows($mytoplevel list
+ if { [lsearch -exact [array names ::childwindows $mytoplevel]] == -1 \
+ || [lsearch -exact $::childwindows($mytoplevel) $child] == -1} {
+ set ::childwindows($mytoplevel) [lappend ::childwindows($mytoplevel) $child]
+ }
+}
+
+# receive a list of all my parent windows from 'pd'
+proc ::pdtk_canvas::pdtk_canvas_setparents {mytoplevel args} {
+ set ::parentwindows($mytoplevel) $args
+ foreach parent $args {
+ addchild $parent $mytoplevel
+ }
+}
+
+# receive information for setting the info the the title bar of the window
+proc ::pdtk_canvas::pdtk_canvas_reflecttitle {mytoplevel \
+ path name arguments dirty} {
+ set ::windowname($mytoplevel) $name ;# TODO add path to this
+ if {$::windowingsystem eq "aqua"} {
+ wm attributes $mytoplevel -modified $dirty
+ if {[file exists "$path/$name"]} {
+ # for some reason -titlepath can still fail so just catch it
+ if [catch {wm attributes $mytoplevel -titlepath "$path/$name"}] {
+ wm title $mytoplevel "$path/$name"
+ }
+ }
+ wm title $mytoplevel "$name$arguments"
+ } else {
+ if {$dirty} {set dirtychar "*"} else {set dirtychar " "}
+ wm title $mytoplevel "$name$dirtychar$arguments - $path"
+ }
}
diff --git a/pd/tcl/pdtk_text.tcl b/pd/tcl/pdtk_text.tcl
index bb37ccc3..5818926c 100644
--- a/pd/tcl/pdtk_text.tcl
+++ b/pd/tcl/pdtk_text.tcl
@@ -1,20 +1,53 @@
package provide pdtk_text 0.1
-############ pdtk_text_new -- create a new text object #2###########
-proc pdtk_text_new {mycanvas canvasitem x y text font_size color} {
- $mycanvas create text $x $y -tags $canvasitem -text $text -fill $color \
+# these procs are currently all in the global namespace because all of them
+# are used by 'pd' and therefore need to be in the global namespace.
+
+# create a new text object (ie. obj, msg, comment)
+proc pdtk_text_new {tkcanvas tags x y text font_size color} {
+ $tkcanvas create text $x $y -tags $tags -text $text -fill $color \
-anchor nw -font [get_font_for_size $font_size]
- $mycanvas bind $canvasitem <Home> "$mycanvas icursor $canvasitem 0"
- $mycanvas bind $canvasitem <End> "$mycanvas icursor $canvasitem end"
+ set mytag [lindex $tags 0]
+ $tkcanvas bind $mytag <Home> "$tkcanvas icursor $mytag 0"
+ $tkcanvas bind $mytag <End> "$tkcanvas icursor $mytag end"
+ # select all
+ $tkcanvas bind $mytag <Triple-ButtonRelease-1> \
+ "pdtk_text_selectall $tkcanvas $mytag"
if {$::windowingsystem eq "aqua"} { # emacs bindings for Mac OS X
- $mycanvas bind $canvasitem <Control-a> "$mycanvas icursor $canvasitem 0"
- $mycanvas bind $canvasitem <Control-e> "$mycanvas icursor $canvasitem end"
+ $tkcanvas bind $mytag <Control-a> "$tkcanvas icursor $mytag 0"
+ $tkcanvas bind $mytag <Control-e> "$tkcanvas icursor $mytag end"
+ }
+}
+
+# change the text in an existing text box
+proc pdtk_text_set {tkcanvas tag text} {
+ $tkcanvas itemconfig $tag -text $text
+}
+
+# paste into an existing text box by literally "typing" the contents of the
+# clipboard, i.e. send the contents one character at a time via 'pd key'
+proc pdtk_pastetext {args} {
+ catch {set pdtk_pastebuffer [clipboard get]}
+ for {set i 0} {$i < [string length $pdtk_pastebuffer]} {incr i 1} {
+ set cha [string index $pdtk_pastebuffer $i]
+ scan $cha %c keynum
+ pdsend "pd key 1 $keynum 0"
}
}
-################ pdtk_text_set -- change the text ##################
-proc pdtk_text_set {mycanvas canvasitem text} {
- $mycanvas itemconfig $canvasitem -text $text
+# select all of the text in an existing text box
+proc pdtk_text_selectall {tkcanvas mytag} {
+ if {$::editmode([winfo toplevel $tkcanvas])} {
+ $tkcanvas select from $mytag 0
+ $tkcanvas select to $mytag end
+ }
}
+# de/activate a text box for editing based on $editing flag
+proc pdtk_text_editing {mytoplevel tag editing} {
+ set tkcanvas [tkcanvas_name $mytoplevel]
+ if {$editing == 0} {selection clear $tkcanvas}
+ $tkcanvas focus $tag
+ set ::editingtext($mytoplevel) $editing
+}
diff --git a/pd/tcl/pdwindow.tcl b/pd/tcl/pdwindow.tcl
index d0c0c654..bb1e1d65 100644
--- a/pd/tcl/pdwindow.tcl
+++ b/pd/tcl/pdwindow.tcl
@@ -2,52 +2,387 @@
package provide pdwindow 0.1
namespace eval ::pdwindow:: {
- variable consolefont
- variable printout_buffer ""
- variable pdwindow_search_index
+ variable logbuffer {}
+ variable tclentry {}
+ variable tclentry_history {"console show"}
+ variable history_position 0
+ variable linecolor 0 ;# is toggled to alternate text line colors
+ variable logmenuitems
+ variable maxloglevel 4
+ variable lastlevel 0
+
+ namespace export create_window
namespace export pdtk_post
+ namespace export pdtk_pd_dsp
+ namespace export pdtk_pd_dio
+}
+
+# TODO make the Pd window save its size and location between running
+
+proc ::pdwindow::set_layout {} {
+ variable maxloglevel
+ .pdwindow.text.internal tag configure log0 -foreground "#d00" -background "#ffe0e8"
+ .pdwindow.text.internal tag configure log1 -foreground "#d00"
+ # log2 messages are normal black on white
+ .pdwindow.text.internal tag configure log3 -foreground "#484848"
+
+ # 0-20(4-24) is a rough useful range of 'verbose' levels for impl debugging
+ set start 4
+ set end 25
+ for {set i $start} {$i < $end} {incr i} {
+ set B [expr int(($i - $start) * (40 / ($end - $start))) + 50]
+ .pdwindow.text.internal tag configure log${i} -foreground grey${B}
+ }
+}
+
+
+# grab focus on part of the Pd window when Pd is busy
+proc ::pdwindow::busygrab {} {
+ # set the mouse cursor to look busy and grab focus so it stays that way
+ .pdwindow.text configure -cursor watch
+ grab set .pdwindow.text
+}
+
+# release focus on part of the Pd window when Pd is finished
+proc ::pdwindow::busyrelease {} {
+ .pdwindow.text configure -cursor xterm
+ grab release .pdwindow.text
+}
+
+# ------------------------------------------------------------------------------
+# pdtk functions for 'pd' to send data to the Pd window
+
+proc ::pdwindow::buffer_message {object_id level message} {
+ variable logbuffer
+ lappend logbuffer $object_id $level $message
+}
+
+proc ::pdwindow::insert_log_line {object_id level message} {
+ if {$object_id eq ""} {
+ .pdwindow.text.internal insert end $message log$level
+ } else {
+ .pdwindow.text.internal insert end $message [list log$level obj$object_id]
+ .pdwindow.text.internal tag bind obj$object_id <$::modifier-ButtonRelease-1> \
+ "::pdwindow::select_by_id $object_id; break"
+ .pdwindow.text.internal tag bind obj$object_id <Key-Return> \
+ "::pdwindow::select_by_id $object_id; break"
+ .pdwindow.text.internal tag bind obj$object_id <Key-KP_Enter> \
+ "::pdwindow::select_by_id $object_id; break"
+ }
+}
+
+# this has 'args' to satisfy trace, but its not used
+proc ::pdwindow::filter_buffer_to_text {args} {
+ variable logbuffer
+ variable maxloglevel
+ .pdwindow.text.internal delete 0.0 end
+ set i 0
+ foreach {object_id level message} $logbuffer {
+ if { $level <= $::loglevel || $maxloglevel == $::loglevel} {
+ insert_log_line $object_id $level $message
+ }
+ # this could take a while, so update the GUI every 10000 lines
+ if { [expr $i % 10000] == 0} {update idletasks}
+ incr i
+ }
+ .pdwindow.text.internal yview end
+ ::pdwindow::verbose 10 "The Pd window filtered $i lines\n"
+}
+
+proc ::pdwindow::select_by_id {args} {
+ if [llength $args] { # Is $args empty?
+ pdsend "pd findinstance $args"
+ }
+}
+
+# logpost posts to Pd window with an object to trace back to and a
+# 'log level'. The logpost and related procs are for generating
+# messages that are useful for debugging patches. They are messages
+# that are meant for the Pd programmer to see so that they can get
+# information about the patches they are building
+proc ::pdwindow::logpost {object_id level message} {
+ variable maxloglevel
+ variable lastlevel $level
+
+ buffer_message $object_id $level $message
+ if {[llength [info commands .pdwindow.text.internal]] &&
+ ($level <= $::loglevel || $maxloglevel == $::loglevel)} {
+ # cancel any pending move of the scrollbar, and schedule it
+ # after writing a line. This way the scrollbar is only moved once
+ # when the inserting has finished, greatly speeding things up
+ after cancel .pdwindow.text.internal yview end
+ insert_log_line $object_id $level $message
+ after idle .pdwindow.text.internal yview end
+ }
+ # -stderr only sets $::stderr if 'pd-gui' is started before 'pd'
+ if {$::stderr} {puts stderr $message}
+}
+
+# shortcuts for posting to the Pd window
+proc ::pdwindow::fatal {message} {logpost {} 0 $message}
+proc ::pdwindow::error {message} {logpost {} 1 $message}
+proc ::pdwindow::post {message} {logpost {} 2 $message}
+proc ::pdwindow::debug {message} {logpost {} 3 $message}
+# for backwards compatibility
+proc ::pdwindow::bug {message} {logpost {} 3 $message}
+proc ::pdwindow::pdtk_post {message} {post $message}
+
+proc ::pdwindow::endpost {} {
+ variable linecolor
+ variable lastlevel
+ logpost {} $lastlevel "\n"
+ set linecolor [expr ! $linecolor]
+}
+
+# this verbose proc has a separate numbering scheme since its for
+# debugging implementations, and therefore falls outside of the 0-3
+# numbering on the Pd window. They should only be shown in ALL mode.
+proc ::pdwindow::verbose {level message} {
+ incr level 4
+ logpost {} $level $message
+}
+
+# clear the log and the buffer
+proc ::pdwindow::clear_console {} {
+ variable logbuffer {}
+ .pdwindow.text.internal delete 0.0 end
+}
+
+#--compute audio/DSP checkbutton-----------------------------------------------#
+
+# set the checkbox on the "Compute Audio" menuitem and checkbox
+proc ::pdwindow::pdtk_pd_dsp {value} {
+ # TODO canvas_startdsp/stopdsp should really send 1 or 0, not "ON" or "OFF"
+ if {$value eq "ON"} {
+ set ::dsp 1
+ } else {
+ set ::dsp 0
+ }
+}
+
+proc ::pdwindow::pdtk_pd_dio {red} {
+ if {$red == 1} {
+ .pdwindow.header.dio configure -foreground red
+ } else {
+ .pdwindow.header.dio configure -foreground lightgray
+ }
+
}
+#--bindings specific to the Pd window------------------------------------------#
+proc ::pdwindow::pdwindow_bindings {} {
+ # these bindings are for the whole Pd window, minus the Tcl entry
+ foreach window {.pdwindow.text .pdwindow.header} {
+ bind $window <$::modifier-Key-x> "tk_textCut .pdwindow.text"
+ bind $window <$::modifier-Key-c> "tk_textCopy .pdwindow.text"
+ bind $window <$::modifier-Key-v> "tk_textPaste .pdwindow.text"
+ }
+ # Select All doesn't seem to work unless its applied to the whole window
+ bind .pdwindow <$::modifier-Key-a> ".pdwindow.text tag add sel 1.0 end"
+ # the "; break" part stops executing another binds, like from the Text class
+
+ # these don't do anything in the Pd window, so alert the user, then break
+ # so no more bindings run
+ bind .pdwindow <$::modifier-Key-s> "bell; break"
+ bind .pdwindow <$::modifier-Shift-Key-S> "bell; break"
+ bind .pdwindow <$::modifier-Key-p> "bell; break"
-proc ::pdwindow::pdtk_post {message} {
- variable printout_buffer
- # TODO this should be switchable between Pd window and stderr
- if { ! [winfo exists .pdwindow.text]} {
- set printout_buffer "$printout_buffer\n$message"
+ # ways of hiding/closing the Pd window
+ if {$::windowingsystem eq "aqua"} {
+ # on Mac OS X, you can close the Pd window, since the menubar is there
+ bind .pdwindow <$::modifier-Key-w> "wm withdraw .pdwindow"
+ wm protocol .pdwindow WM_DELETE_WINDOW "wm withdraw .pdwindow"
} else {
- if {$printout_buffer ne ""} {
- .pdwindow.text insert end "$printout_buffer\n"
- set printout_buffer ""
+ # TODO should it possible to close the Pd window and keep Pd open?
+ bind .pdwindow <$::modifier-Key-w> "wm iconify .pdwindow"
+ wm protocol .pdwindow WM_DELETE_WINDOW "pdsend \"pd verifyquit\""
+ }
+}
+
+#--Tcl entry procs-------------------------------------------------------------#
+
+# copied from ::pd_connect::pd_readsocket, so perhaps it could be merged
+proc ::pdwindow::eval_tclentry {} {
+ variable tclentry
+ variable tclentry_history
+ variable history_position 0
+ if {$tclentry eq ""} {return} ;# no need to do anything if empty
+ if {[catch {uplevel #0 $tclentry} errorname]} {
+ global errorInfo
+ switch -regexp -- $errorname {
+ "missing close-brace" {
+ ::pdwindow::error [concat [_ "(Tcl) MISSING CLOSE-BRACE '\}': "] $errorInfo]\n
+ } "missing close-bracket" {
+ ::pdwindow::error [concat [_ "(Tcl) MISSING CLOSE-BRACKET '\]': "] $errorInfo]\n
+ } "^invalid command name" {
+ ::pdwindow::error [concat [_ "(Tcl) INVALID COMMAND NAME: "] $errorInfo]\n
+ } default {
+ ::pdwindow::error [concat [_ "(Tcl) UNHANDLED ERROR: "] $errorInfo]\n
+ }
+ }
+ }
+ lappend tclentry_history $tclentry
+ set tclentry {}
+}
+
+proc ::pdwindow::get_history {direction} {
+ variable tclentry_history
+ variable history_position
+
+ incr history_position $direction
+ if {$history_position < 0} {set history_position 0}
+ if {$history_position > [llength $tclentry_history]} {
+ set history_position [llength $tclentry_history]
+ }
+ .pdwindow.tcl.entry delete 0 end
+ .pdwindow.tcl.entry insert 0 \
+ [lindex $tclentry_history end-[expr $history_position - 1]]
+}
+
+proc ::pdwindow::validate_tcl {} {
+ variable tclentry
+ if {[info complete $tclentry]} {
+ .pdwindow.tcl.entry configure -background "white"
+ } else {
+ .pdwindow.tcl.entry configure -background "#FFF0F0"
+ }
+}
+
+#--create tcl entry-----------------------------------------------------------#
+
+proc ::pdwindow::create_tcl_entry {} {
+# Tcl entry box frame
+ label .pdwindow.tcl.label -text [_ "Tcl:"] -anchor e
+ pack .pdwindow.tcl.label -side left
+ entry .pdwindow.tcl.entry -width 200 \
+ -exportselection 1 -insertwidth 2 -insertbackground blue \
+ -textvariable ::pdwindow::tclentry -font {$::font_family 12}
+ pack .pdwindow.tcl.entry -side left -fill x
+# bindings for the Tcl entry widget
+ bind .pdwindow.tcl.entry <$::modifier-Key-a> "%W selection range 0 end; break"
+ bind .pdwindow.tcl.entry <Return> "::pdwindow::eval_tclentry"
+ bind .pdwindow.tcl.entry <Up> "::pdwindow::get_history 1"
+ bind .pdwindow.tcl.entry <Down> "::pdwindow::get_history -1"
+ bind .pdwindow.tcl.entry <KeyRelease> +"::pdwindow::validate_tcl"
+
+ bind .pdwindow.text <Key-Tab> "focus .pdwindow.tcl.entry; break"
+}
+
+proc ::pdwindow::set_findinstance_cursor {widget key state} {
+ set triggerkeys [list Control_L Control_R Meta_L Meta_R]
+ if {[lsearch -exact $triggerkeys $key] > -1} {
+ if {$state == 0} {
+ $widget configure -cursor xterm
+ } else {
+ $widget configure -cursor based_arrow_up
}
- .pdwindow.text insert end "$message\n"
- .pdwindow.text yview end
}
- puts stderr $message
}
+#--create the window-----------------------------------------------------------#
+
proc ::pdwindow::create_window {} {
- variable consolefont
+ variable logmenuitems
+ set ::loaded(.pdwindow) 0
+
+ # colorize by class before creating anything
+ option add *PdWindow*Entry.highlightBackground "grey" startupFile
+ option add *PdWindow*Frame.background "grey" startupFile
+ option add *PdWindow*Label.background "grey" startupFile
+ option add *PdWindow*Checkbutton.background "grey" startupFile
+ option add *PdWindow*Menubutton.background "grey" startupFile
+ option add *PdWindow*Text.background "white" startupFile
+ option add *PdWindow*Entry.background "white" startupFile
+
toplevel .pdwindow -class PdWindow
- wm title .pdwindow [_ "Pd window"]
- wm geometry .pdwindow =500x450+20+50
+ wm title .pdwindow [_ "Pd"]
+ set ::windowname(.pdwindow) [_ "Pd"]
+ if {$::windowingsystem eq "x11"} {
+ wm minsize .pdwindow 400 75
+ } else {
+ wm minsize .pdwindow 400 51
+ }
+ wm geometry .pdwindow =500x400+20+50
.pdwindow configure -menu .menubar
- ::pd_menus::configure_for_pdwindow
- ::pd_bindings::pdwindow_bindings .pdwindow
- frame .pdwindow.header
- pack .pdwindow.header -side top -fill x -padx 30 -ipady 10
- # label .pdwindow.header.label -text "The Pd window wants you to make it look nice!"
- # pack .pdwindow.header.label -side left -fill y -anchor w
+ frame .pdwindow.header -borderwidth 1 -relief flat -background lightgray
+ pack .pdwindow.header -side top -fill x -ipady 5
+
+ frame .pdwindow.header.pad1
+ pack .pdwindow.header.pad1 -side left -padx 12
+
checkbutton .pdwindow.header.dsp -text [_ "DSP"] -variable ::dsp \
- -command "pdsend \"pd dsp 0\""
- pack .pdwindow.header.dsp -side right -fill y -anchor e
+ -font {$::font_family 18 bold} -takefocus 1 -background lightgray \
+ -borderwidth 0 -command {pdsend "pd dsp $::dsp"}
+ pack .pdwindow.header.dsp -side right -fill y -anchor e -padx 5 -pady 0
+# DIO button
+ label .pdwindow.header.dio -text [_ "audio I/O error"] -borderwidth 0 \
+ -background lightgray -foreground lightgray \
+ -takefocus 0 \
+ -font {$::font_family 14}
+ pack .pdwindow.header.dio -side right -fill y -padx 30 -pady 0
+
+ label .pdwindow.header.loglabel -text [_ "Log:"] -anchor e \
+ -background lightgray
+ pack .pdwindow.header.loglabel -side left
+
+ set loglevels {0 1 2 3 4}
+ lappend logmenuitems "0 [_ fatal]"
+ lappend logmenuitems "1 [_ error]"
+ lappend logmenuitems "2 [_ normal]"
+ lappend logmenuitems "3 [_ debug]"
+ lappend logmenuitems "4 [_ all]"
+ set logmenu \
+ [eval tk_optionMenu .pdwindow.header.logmenu ::loglevel $loglevels]
+ .pdwindow.header.logmenu configure -background lightgray
+ foreach i $loglevels {
+ $logmenu entryconfigure $i -label [lindex $logmenuitems $i]
+ }
+ trace add variable ::loglevel write ::pdwindow::filter_buffer_to_text
+
+ # TODO figure out how to make the menu traversable with the keyboard
+ #.pdwindow.header.logmenu configure -takefocus 1
+ pack .pdwindow.header.logmenu -side left
+ frame .pdwindow.tcl -borderwidth 0
+ pack .pdwindow.tcl -side bottom -fill x
# TODO this should use the pd_font_$size created in pd-gui.tcl
text .pdwindow.text -relief raised -bd 2 -font {-size 10} \
- -yscrollcommand ".pdwindow.scroll set" -width 60
- scrollbar .pdwindow.scroll -command ".pdwindow.text yview"
+ -highlightthickness 0 -borderwidth 1 -relief flat \
+ -yscrollcommand ".pdwindow.scroll set" -width 60 \
+ -undo false -autoseparators false -maxundo 1 -takefocus 0
+ scrollbar .pdwindow.scroll -command ".pdwindow.text.internal yview"
pack .pdwindow.scroll -side right -fill y
- pack .pdwindow.text -side bottom -fill both -expand 1
+ pack .pdwindow.text -side right -fill both -expand 1
raise .pdwindow
+ focus .pdwindow.text
+ # run bindings last so that .pdwindow.tcl.entry exists
+ pdwindow_bindings
+ # set cursor to show when clicking in 'findinstance' mode
+ bind .pdwindow <KeyPress> "+::pdwindow::set_findinstance_cursor %W %K %s"
+ bind .pdwindow <KeyRelease> "+::pdwindow::set_findinstance_cursor %W %K %s"
+
+ # hack to make a good read-only text widget from http://wiki.tcl.tk/1152
+ rename ::.pdwindow.text ::.pdwindow.text.internal
+ proc ::.pdwindow.text {args} {
+ switch -exact -- [lindex $args 0] {
+ "insert" {}
+ "delete" {}
+ "default" { return [eval ::.pdwindow.text.internal $args] }
+ }
+ }
+
+ # print whatever is in the queue
+ filter_buffer_to_text
+
+ set ::loaded(.pdwindow) 1
+
+ # set some layout variables
+ ::pdwindow::set_layout
+
+ # wait until .pdwindow.tcl.entry is visible before opening files so that
+ # the loading logic can grab it and put up the busy cursor
+ tkwait visibility .pdwindow.text
+# create_tcl_entry
}
diff --git a/pd/tcl/pkgIndex.tcl b/pd/tcl/pkgIndex.tcl
index cd28c6bd..5f4921b8 100644
--- a/pd/tcl/pkgIndex.tcl
+++ b/pd/tcl/pkgIndex.tcl
@@ -14,15 +14,22 @@ package ifneeded pd_connect 0.1 [list source [file join $dir pd_connect.tcl]]
package ifneeded dialog_array 0.1 [list source [file join $dir dialog_array.tcl]]
package ifneeded dialog_audio 0.1 [list source [file join $dir dialog_audio.tcl]]
package ifneeded dialog_canvas 0.1 [list source [file join $dir dialog_canvas.tcl]]
+package ifneeded dialog_data 0.1 [list source [file join $dir dialog_data.tcl]]
package ifneeded dialog_find 0.1 [list source [file join $dir dialog_find.tcl]]
package ifneeded dialog_font 0.1 [list source [file join $dir dialog_font.tcl]]
package ifneeded dialog_gatom 0.1 [list source [file join $dir dialog_gatom.tcl]]
package ifneeded dialog_iemgui 0.1 [list source [file join $dir dialog_iemgui.tcl]]
+package ifneeded dialog_message 0.1 [list source [file join $dir dialog_message.tcl]]
package ifneeded dialog_midi 0.1 [list source [file join $dir dialog_midi.tcl]]
+package ifneeded dialog_path 0.1 [list source [file join $dir dialog_path.tcl]]
+package ifneeded dialog_startup 0.1 [list source [file join $dir dialog_startup.tcl]]
+package ifneeded helpbrowser 0.1 [list source [file join $dir helpbrowser.tcl]]
package ifneeded opt_parser 0.1 [list source [file join $dir opt_parser.tcl]]
package ifneeded pdwindow 0.1 [list source [file join $dir pdwindow.tcl]]
package ifneeded pd_menucommands 0.1 [list source [file join $dir pd_menucommands.tcl]]
package ifneeded pd_menus 0.1 [list source [file join $dir pd_menus.tcl]]
package ifneeded pdtk_canvas 0.1 [list source [file join $dir pdtk_canvas.tcl]]
package ifneeded pdtk_text 0.1 [list source [file join $dir pdtk_text.tcl]]
+package ifneeded scrollbox 0.1 [list source [file join $dir scrollbox.tcl]]
+package ifneeded scrollboxwindow 0.1 [list source [file join $dir scrollboxwindow.tcl]]
package ifneeded wheredoesthisgo 0.1 [list source [file join $dir wheredoesthisgo.tcl]]
diff --git a/pd/tcl/scrollbox.tcl b/pd/tcl/scrollbox.tcl
new file mode 100644
index 00000000..b06670a0
--- /dev/null
+++ b/pd/tcl/scrollbox.tcl
@@ -0,0 +1,191 @@
+######### scrollbox -- utility scrollbar with default bindings #######
+# scrollbox is used in the Path and Startup dialogs to edit lists of options
+
+package provide scrollbox 0.1
+
+namespace eval scrollbox {
+ # This variable keeps track of the last list element we clicked on,
+ # used to implement drag-drop reordering of list items
+ variable lastIdx 0
+}
+
+proc ::scrollbox::get_curidx { mytoplevel } {
+ set idx [$mytoplevel.listbox.box index active]
+ if {$idx < 0 || \
+ $idx == [$mytoplevel.listbox.box index end]} {
+ return [expr {[$mytoplevel.listbox.box index end] + 1}]
+ }
+ return [expr $idx]
+}
+
+proc ::scrollbox::insert_item { mytoplevel idx name } {
+ if {$name != ""} {
+ $mytoplevel.listbox.box insert $idx $name
+ set activeIdx [expr {[$mytoplevel.listbox.box index active] + 1}]
+ $mytoplevel.listbox.box see $activeIdx
+ $mytoplevel.listbox.box activate $activeIdx
+ $mytoplevel.listbox.box selection clear 0 end
+ $mytoplevel.listbox.box selection set active
+ focus $mytoplevel.listbox.box
+ }
+}
+
+proc ::scrollbox::add_item { mytoplevel add_method } {
+ set dir [$add_method]
+ insert_item $mytoplevel [expr {[get_curidx $mytoplevel] + 1}] $dir
+}
+
+proc ::scrollbox::edit_item { mytoplevel edit_method } {
+ set idx [expr {[get_curidx $mytoplevel]}]
+ set initialValue [$mytoplevel.listbox.box get $idx]
+ if {$initialValue != ""} {
+ set dir [$edit_method $initialValue]
+
+ if {$dir != ""} {
+ $mytoplevel.listbox.box delete $idx
+ insert_item $mytoplevel $idx $dir
+ }
+ $mytoplevel.listbox.box activate $idx
+ $mytoplevel.listbox.box selection clear 0 end
+ $mytoplevel.listbox.box selection set active
+ focus $mytoplevel.listbox.box
+ }
+}
+
+proc ::scrollbox::delete_item { mytoplevel } {
+ set cursel [$mytoplevel.listbox.box curselection]
+ foreach idx $cursel {
+ $mytoplevel.listbox.box delete $idx
+ }
+}
+
+# Double-clicking on the listbox should edit the current item,
+# or add a new one if there is no current
+proc ::scrollbox::dbl_click { mytoplevel edit_method add_method x y } {
+ if { $x == "" || $y == "" } {
+ return
+ }
+
+ set curBB [$mytoplevel.listbox.box bbox @$x,$y]
+
+ # listbox bbox returns an array of 4 items in the order:
+ # left, top, width, height
+ set height [lindex $curBB 3]
+ set top [lindex $curBB 1]
+ if { $height == "" || $top == "" } {
+ # If for some reason we didn't get valid bbox info,
+ # we want to default to adding a new item
+ set height 0
+ set top 0
+ set y 1
+ }
+
+ set bottom [expr {$height + $top}]
+
+ if {$y > $bottom} {
+ add_item $mytoplevel $add_method
+ } else {
+ edit_item $mytoplevel $edit_method
+ }
+}
+
+proc ::scrollbox::click { mytoplevel x y } {
+ # record the index of the current element being
+ # clicked on
+ variable ::lastIdx [$mytoplevel.listbox.box index @$x,$y]
+
+ focus $mytoplevel.listbox.box
+}
+
+# For drag-and-drop reordering, recall the last-clicked index
+# and move it to the position of the item currently under the mouse
+proc ::scrollbox::release { mytoplevel x y } {
+ variable lastIdx
+ set curIdx [$mytoplevel.listbox.box index @$x,$y]
+
+ if { $curIdx != $::lastIdx } {
+ # clear any current selection
+ $mytoplevel.listbox.box selection clear 0 end
+
+ set oldIdx $::lastIdx
+ set newIdx [expr {$curIdx+1}]
+ set selIdx $curIdx
+
+ if { $curIdx < $::lastIdx } {
+ set oldIdx [expr {$::lastIdx + 1}]
+ set newIdx $curIdx
+ set selIdx $newIdx
+ }
+
+ $mytoplevel.listbox.box insert $newIdx [$mytoplevel.listbox.box get $::lastIdx]
+ $mytoplevel.listbox.box delete $oldIdx
+ $mytoplevel.listbox.box activate $newIdx
+ $mytoplevel.listbox.box selection set $selIdx
+ }
+}
+
+# Make a scrollbox widget in a given window and set of data.
+#
+# id - the parent window for the scrollbox
+# listdata - array of data to populate the scrollbox
+# add_method - method to be called when we add a new item
+# edit_method - method to be called when we edit an existing item
+proc ::scrollbox::make { mytoplevel listdata add_method edit_method } {
+ frame $mytoplevel.listbox
+ listbox $mytoplevel.listbox.box \
+ -selectmode browse -activestyle dotbox \
+ -yscrollcommand [list "$mytoplevel.listbox.scrollbar" set]
+
+ # Create a scrollbar and keep it in sync with the current
+ # listbox view
+ pack $mytoplevel.listbox.box [scrollbar "$mytoplevel.listbox.scrollbar" \
+ -command [list $mytoplevel.listbox.box yview]] \
+ -side left -fill y -anchor w
+
+ # Populate the listbox widget
+ foreach item $listdata {
+ $mytoplevel.listbox.box insert end $item
+ }
+
+ # Standard listbox key/mouse bindings
+ event add <<Delete>> <Delete>
+ if { $::windowingsystem eq "aqua" } { event add <<Delete>> <BackSpace> }
+
+ bind $mytoplevel.listbox.box <ButtonPress> "::scrollbox::click $mytoplevel %x %y"
+ bind $mytoplevel.listbox.box <Double-1> "::scrollbox::dbl_click $mytoplevel $edit_method $add_method %x %y"
+ bind $mytoplevel.listbox.box <ButtonRelease> "::scrollbox::release $mytoplevel %x %y"
+ bind $mytoplevel.listbox.box <Return> "::scrollbox::edit_item $mytoplevel $edit_method"
+ bind $mytoplevel.listbox.box <<Delete>> "::scrollbox::delete_item $mytoplevel"
+
+ # <Configure> is called when the user modifies the window
+ # We use it to capture resize events, to make sure the
+ # currently selected item in the listbox is always visible
+ bind $mytoplevel <Configure> "$mytoplevel.listbox.box see active"
+
+ # The listbox should expand to fill its containing window
+ # the "-fill" option specifies which direction (x, y or both) to fill, while
+ # the "-expand" option (false by default) specifies whether the widget
+ # should fill
+ pack $mytoplevel.listbox.box -side left -fill both -expand 1
+ pack $mytoplevel.listbox -side top -pady 2m -padx 2m -fill both -expand 1
+
+ # All widget interactions can be performed without buttons, but
+ # we still need a "New..." button since the currently visible window
+ # might be full (even though the user can still expand it)
+ frame $mytoplevel.actions
+ pack $mytoplevel.actions -side top -padx 2m -fill x
+ button $mytoplevel.actions.add_path -text {New...} \
+ -command "::scrollbox::add_item $mytoplevel $add_method"
+ button $mytoplevel.actions.edit_path -text {Edit...} \
+ -command "::scrollbox::edit_item $mytoplevel $edit_method"
+ button $mytoplevel.actions.delete_path -text {Delete} \
+ -command "::scrollbox::delete_item $mytoplevel"
+
+ pack $mytoplevel.actions.delete_path -side right -pady 2m
+ pack $mytoplevel.actions.edit_path -side right -pady 2m
+ pack $mytoplevel.actions.add_path -side right -pady 2m
+
+ $mytoplevel.listbox.box activate end
+ $mytoplevel.listbox.box selection set end
+ focus $mytoplevel.listbox.box
+}
diff --git a/pd/tcl/scrollboxwindow.tcl b/pd/tcl/scrollboxwindow.tcl
new file mode 100644
index 00000000..d78622c6
--- /dev/null
+++ b/pd/tcl/scrollboxwindow.tcl
@@ -0,0 +1,94 @@
+
+####### scrollboxwindow -- scrollbox window with default bindings #########
+## This is the base dialog behind the Path and Startup dialogs
+## This namespace specifies everything the two dialogs have in common,
+## with arguments specifying the differences
+##
+## By default, this creates a dialog centered on the viewing area of the screen
+## with cancel, apply, and OK buttons
+## which contains a scrollbox widget populated with the given data
+
+package provide scrollboxwindow 0.1
+
+package require scrollbox
+
+namespace eval scrollboxwindow {
+}
+
+
+proc ::scrollboxwindow::get_listdata {mytoplevel} {
+ return [$mytoplevel.listbox.box get 0 end]
+}
+
+proc ::scrollboxwindow::do_apply {mytoplevel commit_method listdata} {
+ $commit_method [pdtk_encode $listdata]
+ pdsend "pd save-preferences"
+}
+
+# Cancel button action
+proc ::scrollboxwindow::cancel {mytoplevel} {
+ pdsend "$mytoplevel cancel"
+}
+
+# Apply button action
+proc ::scrollboxwindow::apply {mytoplevel commit_method } {
+ do_apply $mytoplevel $commit_method [get_listdata $mytoplevel]
+}
+
+# OK button action
+# The "commit" action can take a second or more,
+# long enough to be noticeable, so we only write
+# the changes after closing the dialog
+proc ::scrollboxwindow::ok {mytoplevel commit_method } {
+ set listdata [get_listdata $mytoplevel]
+ cancel $mytoplevel
+ do_apply $mytoplevel $commit_method $listdata
+}
+
+# "Constructor" function for building the window
+# id -- the window id to use
+# listdata -- the data used to populate the scrollbox
+# add_method -- a reference to a proc to be called when the user adds a new item
+# edit_method -- same as above, for editing and existing item
+# commit_method -- same as above, to commit during the "apply" action
+# title -- top-level title for the dialog
+# width, height -- initial width and height dimensions for the window, also minimum size
+proc ::scrollboxwindow::make {mytoplevel listdata add_method edit_method commit_method title width height } {
+ wm deiconify .pdwindow
+ raise .pdwindow
+ toplevel $mytoplevel -class DialogWindow
+ wm title $mytoplevel $title
+ wm group $mytoplevel .
+ wm transient $mytoplevel .pdwindow
+ wm protocol $mytoplevel WM_DELETE_WINDOW "::scrollboxwindow::cancel $mytoplevel"
+
+ # Enforce a minimum size for the window
+ wm minsize $mytoplevel $width $height
+
+ # Set the current dimensions of the window
+ wm geometry $mytoplevel "${width}x${height}"
+
+ # Add the scrollbox widget
+ ::scrollbox::make $mytoplevel $listdata $add_method $edit_method
+
+ # Use two frames for the buttons, since we want them both
+ # bottom and right
+ frame $mytoplevel.nb
+ pack $mytoplevel.nb -side bottom -fill x -pady 2m
+
+ frame $mytoplevel.nb.buttonframe
+ pack $mytoplevel.nb.buttonframe -side right -padx 2m
+
+ button $mytoplevel.nb.buttonframe.cancel -text [_ "Cancel"]\
+ -command "::scrollboxwindow::cancel $mytoplevel"
+ button $mytoplevel.nb.buttonframe.apply -text [_ "Apply"]\
+ -command "::scrollboxwindow::apply $mytoplevel $commit_method"
+ button $mytoplevel.nb.buttonframe.ok -text [_ "OK"]\
+ -command "::scrollboxwindow::ok $mytoplevel $commit_method"
+
+ pack $mytoplevel.nb.buttonframe.cancel -side left -expand 1 -padx 2m
+ pack $mytoplevel.nb.buttonframe.apply -side left -expand 1 -padx 2m
+ pack $mytoplevel.nb.buttonframe.ok -side left -expand 1 -padx 2m
+}
+
+
diff --git a/pd/tcl/wheredoesthisgo.tcl b/pd/tcl/wheredoesthisgo.tcl
index 3fbb9d1f..1e9e0344 100644
--- a/pd/tcl/wheredoesthisgo.tcl
+++ b/pd/tcl/wheredoesthisgo.tcl
@@ -3,49 +3,89 @@ package provide wheredoesthisgo 0.1
# a place to temporarily store things until they find a home or go away
-set help_top_directory ""
-
-
-proc post_tclinfo {} {
- pdtk_post "Tcl library: [file normalize [info library]]"
- pdtk_post "executable: [file normalize [info nameofexecutable]]"
- pdtk_post "tclversion: [info tclversion]"
- pdtk_post "patchlevel: [info patchlevel]"
- pdtk_post "sharedlibextension: [info sharedlibextension]"
-}
-
-
-proc placeholder {args} {
- # PLACEHOLDER
- ::pdwindow::pdtk_post "PLACEHOLDER $args"
-}
-
-
proc open_file {filename} {
- set directory [file dirname $filename]
+ set directory [file normalize [file dirname $filename]]
set basename [file tail $filename]
if {[regexp -nocase -- "\.(pd|pat|mxt)$" $filename]} {
+ ::pdtk_canvas::started_loading_file [format "%s/%s" $basename $filename]
pdsend "pd open [enquote_path $basename] [enquote_path $directory]"
# remove duplicates first, then the duplicate added after to the top
set index [lsearch -exact $::recentfiles_list $filename]
set ::recentfiles_list [lreplace $::recentfiles_list $index $index]
- set ::recentfiles_list \
- "$filename [lrange $::recentfiles_list 0 $::total_recentfiles]"
+ lappend ::recentfiles_list $filename
+ set ::recentfiles_list [lrange $::recentfiles_list 0 $::total_recentfiles]
::pd_menus::update_recentfiles_menu
+ } {
+ ::pdwindow::post [format [_ "Ignoring '%s': doesn't look like a Pd-file"] $filename]
}
}
+
+# ------------------------------------------------------------------------------
+# procs for panels (openpanel, savepanel)
-proc lookup_windowname {mytoplevel} {
- foreach window $::menu_windowlist {
- if {[lindex $window 1] eq $mytoplevel} {
- return [lindex $window 0]
+proc pdtk_openpanel {target localdir} {
+ if {! [file isdirectory $localdir]} {
+ if { ! [file isdirectory $::fileopendir]} {
+ set ::fileopendir $::env(HOME)
+ }
+ set localdir $::fileopendir
+ }
+ set filename [tk_getOpenFile -initialdir $localdir]
+ if {$filename ne ""} {
+ set ::fileopendir [file dirname $filename]
+ pdsend "$target callback [enquote_path $filename]"
+ }
+}
+
+proc pdtk_savepanel {target localdir} {
+ if {! [file isdirectory $localdir]} {
+ if { ! [file isdirectory $::filenewdir]} {
+ set ::filenewdir $::env(HOME)
}
+ set localdir $::filenewdir
+ }
+ set filename [tk_getSaveFile -initialdir $localdir]
+ if {$filename ne ""} {
+ pdsend "$target callback [enquote_path $filename]"
}
}
-
+
+# ------------------------------------------------------------------------------
+# window info (name, path, parents, children, etc.)
+
+proc lookup_windowname {mytoplevel} {
+ set window [array get ::windowname $mytoplevel]
+ if { $window ne ""} {
+ return [lindex $window 1]
+ } else {
+ return ERROR
+ }
+}
+
+proc tkcanvas_name {mytoplevel} {
+ return "$mytoplevel.c"
+}
+
# ------------------------------------------------------------------------------
# quoting functions
+# enquote a string for find, path, and startup dialog panels, to be decoded by
+# sys_decodedialog()
+proc pdtk_encodedialog {x} {
+ concat +[string map {" " "+_" "$" "+d" ";" "+s" "," "+c" "+" "++"} $x]
+}
+
+# encode a list with pdtk_encodedialog
+proc pdtk_encode { listdata } {
+ set outlist {}
+ foreach this_path $listdata {
+ if {0==[string match "" $this_path]} {
+ lappend outlist [pdtk_encodedialog $this_path]
+ }
+ }
+ return $outlist
+}
+
# TODO enquote a filename to send it to pd, " isn't handled properly tho...
proc enquote_path {message} {
string map {"," "\\," ";" "\\;" " " "\\ "} $message
@@ -59,39 +99,14 @@ proc unspace_text {x} {
concat $y
}
-
# ------------------------------------------------------------------------------
-# lost pdtk functions...
-
-# set the checkbox on the "Compute Audio" menuitem and checkbox
-proc pdtk_pd_dsp {value} {
- # TODO canvas_startdsp/stopdsp should really send 1 or 0, not "ON" or "OFF"
- if {$value eq "ON"} {
- set ::dsp 1
- } else {
- set ::dsp 0
- }
-}
-
-proc pdtk_pd_dio {red} {
- # puts stderr [concat pdtk_pd_dio $red]
-}
-
+# watchdog functions
proc pdtk_watchdog {} {
pdsend "pd watchdog"
after 2000 {pdtk_watchdog}
}
-
proc pdtk_ping {} {
pdsend "pd ping"
}
-
-# ------------------------------------------------------------------------------
-# kludges to avoid changing C code
-
-proc .mbar.find {command number} {
- # this should be changed in g_canvas.c, around line 800
- .menubar.find $command $number
-}