diff --git a/externals/Makefile b/externals/Makefile index 363736cf580cf0f63198b8c36d8412b8140a0543..3cefc37fc5ed505805856f0ce57b20172a2eeba5 100644 --- a/externals/Makefile +++ b/externals/Makefile @@ -134,11 +134,9 @@ ifeq ($(LIGHT),yes) lib_targets = loaders-libdir pddp INCREMENTAL = yes else -lib_targets = adaptive arraysize autotune bassemu boids bsaylor comport creb cxc cyclone disis earplug ekext ext13 fftease fluid freeverb ggee hcs iem_ambi iem_bin_ambi iemlib iemgui iemguts iem_adaptfilt iemmatrix iemxmlrpc iem_delay iem_roomsim iem_spec2 iem_tab jasch_lib loaders-libdir lyonpotpourri mapping markex maxlib mjlib moocow moonlib motex mrpeach oscx pan pdcontainer pddp pdlua pdogg plugin pmpd rjlib sigpack smlib tof unauthorized vbap windowing zexy +lib_targets = adaptive arraysize autotune bassemu boids bsaylor comport creb cxc cyclone disis earplug ekext ext13 fftease flatgui fluid freeverb ggee hcs iem_ambi iem_bin_ambi iemlib iemgui iemguts iem_adaptfilt iemmatrix iemxmlrpc iem_delay iem_roomsim iem_spec2 iem_tab jasch_lib loaders-libdir lyonpotpourri mapping markex maxlib mjlib moocow moonlib motex mrpeach oscx pan pdcontainer pddp pdlua pdogg plugin pmpd rjlib sigpack smlib tof unauthorized vbap windowing zexy endif -# DISABLED: flatgui - # NEW (IN-PROGRESS): flext # this is for libraries that don't compile (yet) on all platforms @@ -538,16 +536,21 @@ fftease_clean: #------------------------------------------------------------------------------# # FLATGUI +# +# Right now we're just building footils/knob and throwing it in the flatgui +# external directory for compatibility +# flatgui: - make -C $(externals_src)/flatgui CFLAGS="$(CFLAGS)" \ - PD_PATH=$(pd_src) PD_INCLUDE=$(pd_src)/src + make -C $(externals_src)/footils/knob CFLAGS="$(CFLAGS)" \ + PD_PATH=$(pd_src) pdbinpath=$(pd_src)/src \ + PD_INCLUDE=$(pd_src)/src flatgui_install: - make -C $(externals_src)/flatgui STRIP="$(STRIP)" \ + make -C $(externals_src)/footils/knob STRIP="$(STRIP)" \ DESTDIR="$(DESTDIR)" objectsdir="$(objectsdir)" install flatgui_clean: - make -C $(externals_src)/flatgui clean + make -C $(externals_src)/footils/knob clean #------------------------------------------------------------------------------# # FLEXT and FLEXT externals diff --git a/externals/footils/knob/Makefile.pdlibbuilder.revised b/externals/footils/knob/Makefile.pdlibbuilder.revised new file mode 100644 index 0000000000000000000000000000000000000000..ed11b2259b0c5f674cd6005c810f9d9ff1e20379 --- /dev/null +++ b/externals/footils/knob/Makefile.pdlibbuilder.revised @@ -0,0 +1,1207 @@ +# Makefile.pdlibbuilder dated 2016-06-26 + +version = 0.2.5 + +# Helper makefile for Pure Data external libraries. +# Written by Katja Vetter March-June 2015 for the public domain. No warranties. +# Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's +# ShakeNMake. +# +# GNU make version >= 3.81 required. +# +# +#=== characteristics =========================================================== +# +# +# - defines build settings based on autodetected OS and architecture +# - defines rules to build Pd class- or lib executables from C or C++ sources +# - defines rules for libdir installation +# - defines convenience targets for developer and user +# - evaluates implicit dependencies for non-clean builds +# +# +#=== basic usage =============================================================== +# +# +# In your Makefile, define your Pd lib name and class files, and include +# Makefile.pdlibbuilder at the end of the Makefile. Like so: +# +# ________________________________________________________________________ +# +# # Makefile for mylib +# +# lib.name = mylib +# +# class.sources = myclass1.c myclass2.c +# +# datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt +# +# include Makefile.pdlibbuilder +# ________________________________________________________________________ +# +# +# For files in class.sources it is assumed that class basename == source file +# basename. The default target builds all classes as individual executables +# with Pd's default extension for the platform. For anything more than the +# most basic usage, continue reading. +# +# +#=== list of Makefile.pdlibbuilder API variables =============================== +# +# +# Variables available for definition in your library Makefile: +# +# - lib.name +# - lib.setup.sources +# - class.sources +# - common.sources +# - shared.sources +# - <classname>.class.sources +# - <classname>.class.ldflags +# - <classname>.class.ldlibs +# - cflags +# - ldflags +# - ldlibs +# - datafiles +# - datadirs +# - makefiles +# - makefiledirs +# - externalsdir +# +# Optional multiline defines evaluated per operating system: +# +# - forLinux +# - forDarwin +# - forWindows +# +# +# Variables avaialable for (re)definition via command arguments: +# +# - pdbinpath (Windows only) +# - pdincludepath +# - DESTDIR +# - prefix +# - libdir +# - pkglibdir +# - CPPFLAGS +# - CFLAGS +# - LDFLAGS +# - CC +# - CXX +# - INSTALL +# - INSTALL_PROGRAM +# - INSTALL_DATA +# - INSTALL_DIR +# +# Variables available for your makefile or as command argument: +# +# - objectsdir +# - make-lib-executable +# - suppress-wunused +# +# +#=== descriptions of Makefile.pdlibbuilder API variables ======================= +# +# +# lib.name: +# Name of the library directory as it will be installed / distributed. Also the +# name of the lib executable in the case where all classes are linked into +# a single binary. +# +# lib.setup.sources: +# Source file(s) (C or C++) which must be compiled only when linking all classes +# into a single lib binary. +# +# class.sources: +# All sources files (C or C++) for which the condition holds that +# class name == source file basename. +# +# <classname>.class.sources: +# Source file(s) (C or C++) specific to class <classname>. Use this for +# multiple-source classes or when class name != source file basename. +# +# common.sources: +# Source file(s) which must be statically linked to each class in the library. +# +# shared.sources: +# Source file(s) (C or C++) to build a shared dynamic link lib, to be linked +# with all class executables. +# +# cflags, ldflags, ldlibs: +# Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic +# link libs) for the whole library. These flags are added to platform-specific +# flags defined by Makefile.pdlibbuilder. +# +# <classname>.class.ldflags and <classname>.class.ldlibs: +# Define ldflags resp. ldlibs specific to class <classname>. These flags are +# added to platform-specific flags defined by Makefile.pdlibbuilder, and flags +# defined in your Makefile for the whole library. Note: cflags can not be +# defined per class in the current implementation. +# +# datafiles and datadirs: +# All extra files you want to include in binary distributions of the +# library: abstractions and help patches, example patches, meta patch, readme +# and license texts, manuals, sound files, etcetera. Use 'datafiles' for all +# files that should go into your lib rootdir and 'datadirs' for complete +# directories you want to copy from source to distribution. +# +# externalsdir: +# Relative path to directory 'externals' in the context of pd-extended SVN, or +# any other centralized build layout for multiple libraries. Default value +# is '..', meaning the direct parent. The value is used in search paths for +# pd core components (header files, and executable in the case of Windows). +# +# forLinux, forDarwin, forWindows: +# Shorthand for 'variable definitions for Linux only' etc. Use like: +# define forLinux +# cflags += -DLINUX +# class.sources += linuxthing.c +# endef +# +# makefiles and makefiledirs: +# Extra makefiles or directories with makefiles that should be made in sub-make +# processes. +# +# pdbinpath: +# For Windows only. Directory where pd.dll can be found for linking. +# +# pdincludepath: +# Directory where Pd API m_pd.h can be found, and other Pd header files. +# +# DESTDIR, prefix, libdir: +# Components of the path for installation as conventionally used on Linux. +# +# pkglibdir: +# Base path for installation of Pd library directories. Default is specified +# per OS, see section about paths below. +# +# objectsdir: +# Alias of pkglibdir. Can be defined in your makefile to enable project- +# dependent relative install locations. +# +# CPPFLAGS: +# Preprocessor flags which are not strictly required for building. +# +# CFLAGS: +# Compiler flags which are not strictly required for building. Compiler flags +# defined by Makefile.pdlibbuilder for warning, optimization and architecture +# specification are overriden by CFLAGS. +# +# LDFLAGS: +# Linker flags which are not strictly required for building. Linker flags +# defined by Makefile.pdlibbuilder for architecture specification are overriden +# by LDFLAGS. +# +# CC and CXX: +# C and C++ compiler programs as defined in your build environment. +# +# INSTALL, INSTALL_PROGRAM, INSTALL_DATA, INSTALL_DIR: +# Definitions of install program, may be overriden via command argument. +# +# make-lib-executable: +# When this variable is defined 'yes' in your makefile or as command argument, +# Makefile.pdlibbuilder will try to build all classes into a single library +# executable (but it will force exit if lib.setup.sources is undefined). +# If your makefile defines 'make-lib-executable=yes' as the library default, +# this can still be overriden with 'make-lib-executable=no' as command argument +# to build individual class executables (the Makefile.pdlibbuilder default.) +# +# suppress-wunused: +# When this variable is defined ('yes' or any other value), -Wunused-variable, +# -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed, +# but the other warnings from -Wall are retained. +# +# +#=== paths ===================================================================== +# +# +# Source files in directories other than current working directory must be +# prefixed with their relative path. Do not rely on VPATH or vpath. +# Object (.o) files are built in the directory of their source files. +# Executables are built in current working directory. +# +# Variable 'pdincludepath' stores a location where m_pd.h is expected to reside. +# Locations where Makefile.pdlibbuilder tries to find it, in order of priority: +# +# any OS: $(externalsdir)../pd/src +# +# Linux: /usr/include/pdextended +# /usr/include/pd +# +# OSX: /Applications/Pd-extended.app/Contents/Resources/include/pdextended +# /Applications/Pd.app/Contents/Resources/src +# +# Windows: %PROGRAMFILES%/pd/include/pdextended +# %PROGRAMFILES%/pd/src +# +# The path for installation of all library components is constructed as: +# +# installpath := $(DESTDIR)$(objectsdir)/$(lib.name) +# +# Default for 'objectsdir' is defined per platform and follows this convention: +# https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files +# +# Linux: /usr/local/lib/pd-externals +# OSX: ~/Library/Pd +# Windows: %APPDATA%/Pd +# +# The rationale for not installing to ~/pd-externals by default on Linux +# is that some people share the home dir between 32 and 64 bit installations. +# +# +#=== targets =================================================================== +# +# +# all: build $(executables) plus optional post target +# post: target to build after $(executables) +# alldebug: build all with -g option turned on for debug symbols +# <classname>: force clean build of an individual class +# <sourcefile>.pre: make preprocessor output file in current working directory +# <sourcefile>.lst: make asm/source output file in current working directory +# +# install: install executables and data files +# clean: remove build products from source tree +# +# help: print help text +# vars: print makefile variables +# allvars: print all variables +# depend: print generated prerequisites +# coffee: dummy target +# +# Variable $(executables) expands to class executables plus optional shared lib, +# or alternatively to single lib executable when make-lib-executable=true. +# Targets pre and post can be defined by library makefile. Make sure to include +# Makefile.pdlibbuilder first so default target all will not be redefined. +# +# +#=== Pd-extended libdir concept ================================================ +# +# +# For libdir layout as conceived by Hans-Christoph Steiner, see: +# +# https://puredata.info/docs/developer/Libdir +# +# Files README.txt, LICENSE.txt and <lib.name>-meta.pd are part of the libdir +# convention. Help patches for each class and abstraction are supposed to be +# available. Makefile.pdlibbuilder does not force the presence of these files +# however. It does not automatically include such files in libdir installations. +# Data files you want to include in distributions must be defined explicitly in +# your Makefile. +# +# +#=== Makefile.pdlibbuilder syntax conventions ================================== +# +# +# Makefile.pdlibbuilder variable names are lower case. Default make variables, +# environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR) +# are upper case. Use target 'allvars' to print all variables and their values. +# +# 'Fields' in data variables are separated by dots, like in 'foo.class.sources'. +# Words in variables expressing a function or command are separated by dashes, +# like in 'make-lib-executable'. +# +# +#=== useful make options ======================================================= +# +# +# Use 'make -d <target>' to print debug details of the make process. +# Use 'make -p <target>' to print make's database. +# +# +#=== TODO ====================================================================== +# +# +# - decide whether to use -static-libgcc or shared dll in MinGW +# - cygwin support +# - android support +# - Windows 64 bit support +# - figure out how to handle '$' in filenames +# - add makefile template targets dpkg-source dist libdir distclean tags? +# +# +#=== end of documentation sections ============================================= +# +# +################################################################################ +################################################################################ +################################################################################ + + +# GNU make version 3.81 (2006) or higher is required because of the following: +# - function 'info' +# - variable '.DEFAULT_GOAL' + +# force exit when make version is < 3.81 +ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81) + $(error GNU make version 3.81 or higher is required) +endif + +# Relative path to externals root dir in multi-lib source tree like +# pd-extended SVN. Default is parent of current working directory. May be +# defined differently in including makefile. This variable is used to probe for +# paths. +externalsdir ?= .. + +# variable you can use to check if Makefile.pdlibbuilder is already included +Makefile.pdlibbuilder = true + + +################################################################################ +### variables: library name and version ######################################## +################################################################################ + + +# strip possibles spaces from lib.name, they mess up calculated file names +lib.name := $(strip $(lib.name)) + +# if meta file exists, check library version +metafile := $(wildcard $(lib.name)-meta.pd) + +ifdef metafile + lib.version := $(shell sed -n \ + 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \ + $(metafile)) +endif + + +################################################################################ +### variables: files ########################################################### +################################################################################ + + +#=== sources =================================================================== + + +# (re)define <classname>.class.sources using file names in class.sources + +define add-class-source +$(notdir $(basename $v)).class.sources += $v +endef + +$(foreach v, $(class.sources), $(eval $(add-class-source))) + +# derive class names from <classname>.class.sources variables +sourcevariables := $(filter %.class.sources, $(.VARIABLES)) +classes := $(basename $(basename $(sourcevariables))) + +# accumulate all source files specified in makefile +classes.sources := $(sort $(foreach v, $(sourcevariables), $($v))) +all.sources := $(classes.sources) $(lib.setup.sources) \ + $(shared.sources) $(common.sources) + + +#=== object files ============================================================== + + +# construct object filenames from all C and C++ source file names +classes.objects := $(addsuffix .o, $(basename $(classes.sources))) +common.objects := $(addsuffix .o, $(basename $(common.sources))) +shared.objects := $(addsuffix .o, $(basename $(shared.sources))) +lib.setup.objects := $(addsuffix .o, $(basename $(lib.setup.sources))) +all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ + $(lib.setup.objects) + + +#=== executables =============================================================== + + +# use recursive variables here because executable extension is not yet known + +# construct class executable names from class names +classes.executables = $(addsuffix .$(extension), $(classes)) + +# construct shared lib executable name if shared sources are defined +ifdef shared.sources + shared.lib = lib$(lib.name).$(shared.extension) +else + shared.lib = +endif + + +################################################################################ +### variables per platform ##################################################### +################################################################################ + + +#=== flags per architecture ==================================================== + + +# Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, +# arch.c.flags are overriden below. + +machine := $(shell uname -m) + +# Raspberry Pi 1st generation +ifeq ($(machine), armv6l) + arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard +endif + +# Beagle, Udoo, RPi2 etc. +ifeq ($(machine), armv7l) + arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard +endif + +# Intel 32 bit, build with SSE and SSE2 instructions +ifeq ($(findstring $(machine), i386 i686), $(machine)) + arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 +endif + +# Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions +ifeq ($(findstring $(machine), ia64 x86_64), $(machine)) + arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 +endif + + +#=== operating system ========================================================== + + +# The following systems are defined: Linux, Darwin, Windows. GNU and +# GNU/kFreeBSD are treated as Linux to get the same options. System-specific +# multiline defines (optionally set in library makefile) are conditionally +# evaluated here. + +uname := $(shell uname) + +ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) + system = Linux + $(eval $(forLinux)) +endif + +ifeq ($(uname), Darwin) + system = Darwin + $(eval $(forDarwin)) +endif + +ifeq ($(findstring MINGW, $(uname)), MINGW) + system = Windows + $(eval $(forWindows)) +endif + +# TODO: Cygwin, Android + + +#=== flags and paths for Linux ================================================= + + +ifeq ($(system), Linux) + prefix = /usr/local + libdir := $(prefix)/lib + pkglibdir = $(libdir)/pd-externals + pdincludepath := $(firstword $(wildcard \ + $(externalsdir)/../pd/src \ + /usr/include/pdextended \ + /usr/include/pd)) + extension = pd_linux + cpp.flags := -DUNIX + c.flags := -fpic + c.ldflags := -rdynamic -shared -fpic -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags + c.ldlibs := -lc -lm + cxx.flags := -fpic -fcheck-new + cxx.ldflags := -rdynamic -shared -fpic -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags + cxx.ldlibs := -lc -lm -lstdc++ + shared.extension = so + shared.ldflags := -rdynamic -fpic -shared -Wl,-soname,$(shared.lib) + stripflags = --strip-unneeded -R .note -R .comment +endif + + +#=== flags and paths for Darwin ================================================ + + +# On OSX we try to build fat binaries by default. It is assumed that OSX i386 +# can build for ppc and OSX x86_64 can't. TODO: try to refine this condition. +# LLVM-clang doesn't support -fcheck-new, therefore this flag is omitted for +# OSX x86_64. + +ifeq ($(system), Darwin) + pkglibdir = $(HOME)/Library/Pd + pdincludepath := $(firstword $(wildcard \ + $(externalsdir)/../pd/src \ + /Applications/Pd-extended*.app/Contents/Resources/include/pdextended \ + /Applications/Pd*.app/Contents/Resources/src)) + extension = pd_darwin + cpp.flags := -DUNIX -DMACOSX -I /sw/include + c.flags := + c.ldflags := -undefined suppress -flat_namespace -bundle + c.ldlibs := -lc + cxx.ldflags := -undefined suppress -flat_namespace -bundle + cxx.ldlibs := -lc + shared.extension = dylib + shared.ldflags = -dynamiclib -undefined dynamic_lookup \ + -install_name @loader_path/$(shared.lib) \ + -compatibility_version 1 -current_version 1.0 + stripflags = -x + ifeq ($(machine), i386) + cxx.flags := -fcheck-new + arch.c.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + arch.ld.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + endif + ifeq ($(machine), x86_64) + arch.c.flags := -arch x86_64 -mmacosx-version-min=10.5 + arch.ld.flags := -arch x86_64 -mmacosx-version-min=10.5 + endif +endif + + +#=== flags and paths for Windows =============================================== + + +# Standard paths on Windows contain spaces, and GNU make functions treat such +# paths as lists, with unintended effects. Therefore we must use shell function +# ls instead of make's wildcard, and probe for each standard path individually. +# Using double quotes around paths with spaces is obligatory. Since some path +# variables are assembled or re-expanded later, great care must be taken to put +# quotes at appropriate points throughout the makefile. Thanks, Bill. + +# paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO) +ifeq ($(system), Windows) + pkglibdir := $(APPDATA)/Pd + pdbinpath := $(wildcard $(externalsdir)/../pd/bin) + pdincludepath := $(wildcard $(externalsdir)/../pd/src) + ifndef pdbinpath + pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin") + endif + ifndef pdincludepath + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/include/pdextended") + endif + ifndef pdincludepath + pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src") + endif +endif + +# On Windows we build 32 bit by default to match Pd(-extended) binary +# distributions. This may change in the future. +# TODO: decide whether -mms-bitfields should be specified. +ifeq ($(system), Windows) + extension = dll + CC = gcc + CXX = g++ + arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse + cpp.flags := -DMSW -DNT + c.flags := + c.ldflags := -static-libgcc -shared \ + -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" + c.ldlibs := + cxx.flags := -fcheck-new + cxx.ldflags := -static-libstdc++ -shared \ + -Wl,--enable-auto-import "$(pdbinpath)/pd.dll" + cxx.ldlibs := + shared.extension = dll + shared.ldflags := -static-libgcc -shared "$(pdbinpath)/pd.dll" + stripflags = --strip-unneeded -R .note -R .comment +endif + + +#=== paths ===================================================================== + + +# Default pkglibdir is specified above per operating system. It is aliased as +# 'objectsdir' to retain compatibility with pd-extended template. Assignment +# operator '?=' is used to enable a project-relative path definition in the +# including makefile. +objectsdir ?= $(pkglibdir) + +# base path where all components of the lib will be installed by default +installpath := $(DESTDIR)$(objectsdir)/$(lib.name) + +# check if pdincludepath contains spaces (as is often the case on Windows) +# if so, store the path so we can later do checks with it +pdincludepathwithspaces := $(if $(word 2, $(pdincludepath)), $(pdincludepath)) + + +#=== accumulated build flags =================================================== + + +# From GNU make docs: 'Users expect to be able to specify CFLAGS freely +# themselves.' So we use CFLAGS to define options which are not strictly +# required for compilation: optimizations, architecture specifications, and +# warnings. CFLAGS can be safely overriden using a make command argument. +# Variables cflags, ldflags and ldlibs may be defined in including makefile. + +optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer +warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing + +# suppress -Wunused-variable & Co if you don't want to clutter a build log +ifdef suppress-wunused + warn.flags += $(addprefix -Wno-unused-, function parameter value variable) +endif + +CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) + +# preprocessor flags +cpp.flags += -DPD -I "$(pdincludepath)" $(CPPFLAGS) + +# architecture specifications for linker are overridable by LDFLAGS +LDFLAGS := $(arch.ld.flags) + +# now add the same ld flags to shared dynamic lib +shared.ldflags := $(shared.ldflags) $(LDFLAGS) + +# accumulated flags for C compiler / linker +c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) +c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) +c.ldlibs := $(c.ldlibs) $(ldlibs) + +# accumulated flags for C++ compiler / linker +cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) +cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) +cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) + + +################################################################################ +### variables: tools ########################################################### +################################################################################ + + +# aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument +compile-c := $(CC) +compile-cxx := $(CXX) + + +################################################################################ +### checks ##################################################################### +################################################################################ + + +# At this point most variables are defined. Now do some checks and info's +# before rules begin. + +# 'forward declaration' of default target, needed to do checks +all: + +# To avoid unpredictable results, make sure the default target is not redefined +# by including makefile. +ifneq ($(.DEFAULT_GOAL), all) + $(error Default target must be 'all'.) +endif + +# find out which target(s) will be made +ifdef MAKECMDGOALS + goals := $(MAKECMDGOALS) +else + goals := all +endif + +# store path to Pd API m_pd.h if it is found +ifdef pdincludepath + mpdh := $(shell ls "$(pdincludepath)/m_pd.h") +endif + +# print Makefile.pdlibbuilder version +$(info ++++ info: using Makefile.pdlibbuilder version $(version)) + +# when making target all, check if m_pd.h is found and print info about it +ifeq ($(goals), all) + $(if $(mpdh), \ + $(info ++++ info: using Pd API $(mpdh)), \ + $(warning Where is Pd API m_pd.h? Do 'make help' for info.)) +endif + +# print target info +$(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name))) + +# when installing, print installpath info +$(if $(filter install install-lib, $(goals)), $(info ++++ info: \ + installpath is '$(installpath)')) + + +#=== define executables ======================================================== + + +# By default we build class executables, and optionally a shared dynamic link +# lib. When make-lib-executable=yes we build all classes into a single lib +# executable, on the condition that variable lib.setup.sources is defined. + +ifeq ($(make-lib-executable),yes) + $(if $(lib.setup.sources), ,\ + $(error Can not build library blob because lib.setup.sources is undefined)) + executables := $(lib.name).$(extension) +else + executables := $(classes.executables) $(shared.lib) +endif + + +################################################################################ +### rules: special targets ##################################################### +################################################################################ + + +# Disable built-in rules. If some target can't be built with the specified +# rules, it should not be built at all. +MAKEFLAGS += --no-builtin-rules + +.PRECIOUS: +.SUFFIXES: +.PHONY: all post build-lib \ + $(classes) $(makefiledirs) $(makefiles) \ + install install-executables install-datafiles install-datadirs \ + force clean vars allvars depend help + + +################################################################################ +### rules: build targets ####################################################### +################################################################################ + + +# Target all forces the build of targets [$(executables) post] in +# deterministic order. Target $(executables) builds class executables plus +# optional shared lib or alternatively a single lib executable when +# make-lib-executable=true. Target post is optionally defined by +# library makefile. + +all: post +post: $(executables) + +all: + $(info ++++info: target all in lib $(lib.name) completed) + +# build all with -g option turned on for debug symbols +alldebug: c.flags += -g +alldebug: cxx.flags += -g +alldebug: all + + +#=== class executable ========================================================== + + +# recipe for linking objects in class executable +# argument $1 = compiler type (c or cxx) +# argument $2 = class basename +define link-class + $(compile-$1) \ + $($1.ldflags) $($2.class.ldflags) \ + -o $2.$(extension) \ + $(addsuffix .o, $(basename $($2.class.sources))) \ + $(addsuffix .o, $(basename $(common.sources))) \ + $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) +endef + +# general rule for linking object files in class executable +%.$(extension): $(shared.lib) + $(info ++++ info: linking objects in $@ for lib $(lib.name)) + $(if $(filter %.cc %.cpp, $($*.class.sources)), \ + $(call link-class,cxx,$*), \ + $(call link-class,c,$*)) + + +#=== library blob ============================================================== + + +# build all classes into single executable +build-lib: $(lib.name).$(extension) + $(info ++++ info: library blob $(lib.name).$(extension) completed) + +# recipe for linking objects in lib executable +# argument $1 = compiler type (c or cxx) +define link-lib + $(compile-$1) \ + $($1.ldflags) $(lib.ldflags) \ + -o $(lib.name).$(extension) $(all.objects) \ + $($1.ldlibs) $(lib.ldlibs) +endef + +# rule for linking objects in lib executable +# declared conditionally to avoid name clashes +ifeq ($(make-lib-executable),yes) +$(lib.name).$(extension): $(all.objects) + $(if $(filter %.cc %.cpp, $(all.sources)), \ + $(call link-lib,cxx), \ + $(call link-lib,c)) +endif + + +#=== shared dynamic lib ======================================================== + + +# recipe for linking objects in shared executable +# argument $1 = compiler type (c or cxx) +define link-shared + $(compile-$1) \ + $(shared.ldflags) \ + -o lib$(lib.name).$(shared.extension) $(shared.objects) \ + $($1.ldlibs) $(shared.ldlibs) +endef + +# rule for linking objects in shared executable +# build recipe is in macro 'link-shared' +lib$(lib.name).$(shared.extension): $(shared.objects) + $(info ++++ info: linking objects in shared lib $@) + $(if $(filter %.cc %.cpp, $(shared.sources)), \ + $(call link-shared,cxx), \ + $(call link-shared,c)) + + +#=== object files ============================================================== + + +# recipe to make .o file from source +# argument $1 is compiler type (c or cxx) +define make-object-file + $(info ++++ info: making $@ in lib $(lib.name)) + $(compile-$1) \ + $($1.flags) \ + -o $@ -c $< +endef + +# Three rules to create .o files. These are double colon 'terminal' rules, +# meaning they are the last in a rules chain. + +%.o:: %.c + $(call make-object-file,c) + +%.o:: %.cc + $(call make-object-file,cxx) + +%.o:: %.cpp + $(call make-object-file,cxx) + + +#=== explicit prerequisites for class executables ============================== + + +# For class executables, prerequisite rules are declared in run time. Target +# 'depend' prints these rules for debugging purposes. + +# declare explicit prerequisites rule like 'class: class.extension' +# argument $v is class basename +define declare-class-target +$v: $v.$(extension) +endef + +# declare explicit prerequisites rule like 'class.extension: object1.o object2.o' +# argument $v is class basename +define declare-class-executable-target +$v.$(extension): $(addsuffix .o, $(basename $($v.class.sources))) \ + $(addsuffix .o, $(basename $(common.sources))) +endef + +# evaluate explicit prerequisite rules for all classes +$(foreach v, $(classes), $(eval $(declare-class-target))) +$(foreach v, $(classes), $(eval $(declare-class-executable-target))) + + +#=== implicit prerequisites for class executables ============================== + + +# Evaluating implicit prerequisites (header files) with help from the +# preprocessor is 'expensive' so this is done conditionally and selectively. +# Note that it is also possible to trigger a build via install targets, in +# which case implicit prerequisites are not checked. + +# When the Pd include path contains spaces it will mess up the implicit +# prerequisites rules. Also it is known that multiple arch flags are +# incompatible with preprocessor option -MM on OSX <= 10.5. Dependency +# tracking must be disabled in those cases. + +oldfat := $(and $(filter ppc i386, $(machine)), \ + $(filter-out 0 1, $(words $(filter -arch, $(c.flags))))) + +disable-dependency-tracking := $(strip $(pdincludepathwithspaces) $(oldfat)) + +ifndef disable-dependency-tracking + must-build-everything := $(filter all, $(goals)) + must-build-class := $(filter $(classes), $(goals)) + must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) +endif + +# declare implicit prerequisites rule like 'object.o: header1.h header2.h ...' +# argument $1 is input source file(s) +# dir is explicitly added because option -MM strips it by default +define declare-object-target +$(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(c.flags) -MM $1)) $(MAKEFILE_LIST) +endef + +# evaluate implicit prerequisite rules when rebuilding everything +ifdef must-build-everything + $(if $(wildcard $(all.objects)), \ + $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \ + $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v)))) +endif + +# evaluate implicit prerequisite rules when selectively building classes +ifdef must-build-class + $(foreach v, $(must-build-sources), \ + $(eval $(call declare-object-target, $v))) + $(foreach v, $(shared.sources), \ + $(eval $(call declare-object-target, $v))) +endif + + +################################################################################ +### rules: preprocessor and assembly files ##################################### +################################################################################ + + +# Preprocessor and assembly output files for bug tracing etc. They are not part +# of the build processes for executables. By default these files are created in +# the current working directory. Dependency tracking is not performed, the build +# is forced instead to make sure it's up to date. + +force: + + +#=== preprocessor file ========================================================= + + +# make preprocessor output file with extension .pre +# argument $1 = compiler type (c or cxx) +define make-preprocessor-file + $(info ++++ info: making preprocessor output file $(notdir $*.pre) \ + in current working directory) + $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre) +endef + +%.pre:: %.c force + $(call make-preprocessor-file,c) + +%.pre:: %.cc force + $(call make-preprocessor-file,cxx) + +%.pre:: %.cpp force + $(call make-preprocessor-file,cxx) + + +#=== assembly file ============================================================= + + +# make C / assembly interleaved output file with extension .lst +# argument $1 = compiler type (c or cxx) +define make-assembly-file + $(info ++++ info: making assembly output file $(notdir $*.lst) \ + in current working directory) + $(compile-$1) \ + -c -Wa,-a,-ad -fverbose-asm \ + $($1.flags) \ + $< > $(notdir $*.lst) +endef + +%.lst:: %.c force + $(call make-assembly-file,c) + +%.lst:: %.cc force + $(call make-assembly-file,cxx) + +%.lst:: %.cpp force + $(call make-assembly-file,cxx) + + +################################################################################ +### rules: installation targets ################################################ +################################################################################ + + +# Install targets depend on successful exit status of target all because nothing +# must be installed in case of a build error. + + +# -p = preserve time stamps +# -m = set permission mode (as in chmod) +# -d = create all components of specified directories +INSTALL = install +INSTALL_PROGRAM := $(INSTALL) -p -m 644 +INSTALL_DATA := $(INSTALL) -p -m 644 +INSTALL_DIR := $(INSTALL) -m 755 -d + +# strip spaces from file names +executables := $(strip $(executables)) +datafiles := $(strip $(datafiles)) +datadirs := $(strip $(datadirs)) + +# Do not make any install sub-target with empty variable definition because the +# install program would exit with an error. +install: $(if $(executables), install-executables) +install: $(if $(datafiles), install-datafiles) +install: $(if $(datadirs), install-datadirs) + +install-executables: all + $(INSTALL_DIR) -v "$(installpath)" + $(INSTALL_PROGRAM) $(executables) "$(installpath)" + $(info ++++ info: executables of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + +install-datafiles: all + $(INSTALL_DIR) -v "$(installpath)" + $(INSTALL_DATA) $(datafiles) "$(installpath)" + $(info ++++ info: data files of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + +install-datadirs: all + $(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";) + $(foreach v, $(datadirs), \ + $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";) + $(info ++++ info: data directories of lib $(lib.name) installed \ + from $(CURDIR) to $(installpath)) + + +################################################################################ +### rules: distribution targets ################################################ +################################################################################ + + +# TODO +# These targets are implemented in Makefile Template, but I have to figure out +# how to do it under the not-so-strict conditions of Makefile.pdlibbuilder. + +# make source package +dist: + @echo "target dist not yet implemented" + +# make Debian source package +dpkg-source: + @echo "target dpkg-source not yet implemented" + +$(ORIGDIR): + +$(DISTDIR): + + +################################################################################ +### rules: clean targets ####################################################### +################################################################################ + + +# delete build products from build tree +clean: + rm -f $(all.objects) + rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib) + rm -f *.pre *.lst + +# remove distribution directories and tarballs from build tree +distclean: clean + @echo "target distclean not yet implemented" + + +################################################################################ +### rules: submake targets ##################################################### +################################################################################ + + +# Iterate over sub-makefiles or makefiles in other directories. + +# When 'continue-make=yes' is set, sub-makes will report 'true' to the parent +# process regardless of their real exit status. This prevents the parent make +# from being aborted by a sub-make error. Useful when you want to quickly find +# out which sub-makes from a large set will succeed. +ifeq ($(continue-make),yes) + continue = || true +endif + +# These targets will trigger sub-make processes for entries in 'makefiledirs' +# and 'makefiles'. +all alldebug install clean distclean dist dkpg-source: \ + $(makefiledirs) $(makefiles) + +# this expands to identical rules for each entry in 'makefiledirs' +$(makefiledirs): + $(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue) + +# this expands to identical rules for each entry in 'makefiles' +$(makefiles): + $(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue) + + +################################################################################ +### rules: convenience targets ################################################# +################################################################################ + + +#=== show variables ============================================================ + + +# Several 'function' macro's cause errors when expanded within a rule or without +# proper arguments. Variables which are set with the define directive are only +# shown by name for that reason. +functions = \ +add-class-source \ +declare-class-target \ +declare-class-executable-target \ +declare-object-target \ +link-class \ +link-lib \ +link-shared \ +make-object-file \ +make-preprocessor-file \ +make-assembly-file + + +# show variables from makefiles +vars: + $(info ++++ info: showing makefile variables:) + $(foreach v,\ + $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\ + $(if $(filter file, $(origin $v)),\ + $(info variable $v = $($v)))) + $(foreach v, $(functions), $(info 'function' name: $v)) + @echo + +# show all variables +allvars: + $(info ++++ info: showing default, automatic and makefile variables:) + $(foreach v, \ + $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \ + $(info variable ($(origin $v)) $v = $($v))) + $(foreach v, $(functions), $(info 'function' name: $v)) + @echo + + +#=== show dependencies ========================================================= + + +# show generated prerequisites rules +depend: + $(info ++++ info: generated prerequisite rules) + $(foreach v, $(classes), $(info $(declare-class-target))) + $(foreach v, $(classes), $(info $(declare-class-executable-target))) + $(foreach v, $(all.sources), $(info $(call declare-object-target, $v))) + @echo + + +#=== show help text ============================================================ + + +# brief info about targets and paths + +ifdef mpdh + mpdhinfo := $(mpdh) +else + mpdhinfo := m_pd.h was not found. Is Pd(-extended) installed? +endif + +help: + @echo + @echo " Main targets:" + @echo " all: build executables (default target)" + @echo " install: install all components of the library" + @echo " vars: print makefile variables for troubleshooting" + @echo " allvars: print all variables for troubleshooting" + @echo " help: print this help text" + @echo + @echo " Pd API m_pd.h:" + @echo " $(mpdhinfo)" + @echo " You may specify your preferred Pd include path as argument to" + @echo " the make command, like 'pdincludepath=path/to/pd/src'." + @echo + @echo " Path for installation of your libdir(s):" + @echo " $(objectsdir)" + @echo " Alternatively you may specify your path for installation as argument" + @echo " to the make command, like 'objectsdir=path/to/pd-externals'." + @echo + @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." + @echo + + +#=== dummy target ============================================================== + + +coffee: + @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." + + +################################################################################ +### end of rules sections ###################################################### +################################################################################ + + +# for syntax highlighting in vim and github +# vim: set filetype=make: + diff --git a/externals/footils/knob/knob.c b/externals/footils/knob/knob.c index b3c0c2ca10818ee367cfbf3c618d1f45b27ce360..bdb953e032ee15222f3ef2b3190c766c9a899c0e 100644 --- a/externals/footils/knob/knob.c +++ b/externals/footils/knob/knob.c @@ -26,7 +26,7 @@ #include "g_canvas.h" -#include "../../old_g_all_guis.inc" +#include "g_all_guis.h" #include <math.h> #ifdef WIN32 @@ -47,13 +47,14 @@ t_widgetbehavior knob_widgetbehavior; static t_class *knob_class; t_symbol *iemgui_key_sym=0; /* taken from g_all_guis.c */ -typedef struct _knob /* taken from Frank's modyfied g_all_guis.h */ +typedef struct _knob /* taken from Frank's modified g_all_guis.h */ { t_iemgui x_gui; int x_pos; int x_val; int x_lin0_log1; int x_steady; + int x_explained_surprising_behavior; double x_min; double x_max; double x_k; @@ -63,34 +64,39 @@ typedef struct _knob /* taken from Frank's modyfied g_all_guis.h */ static void knob_draw_update(t_knob *x, t_glist *glist) { - if (glist_isvisible(glist)) - { + /* All this complicated data and no normalized value stored anywhere! + So we roll our own here for the sake of sanity... */ + double normalized_value = (double)(((x->x_val)*0.01*x->x_k + x->x_min) + / x->x_max); /* compute dial:*/ float radius = 0.5*(float)x->x_gui.x_h; - double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*( (double)x->x_val*0.01/(double)x->x_gui.x_h ); - int start = -80; - int extent = 350 - (int)(360.0*angle/(2.0*M_PI)); + double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*((double)x->x_val*0.01/(double)x->x_gui.x_h ); +// int start = -80; +// int extent = 350 - (int)(360.0*angle/(2.0*M_PI)); /* center point: */ - int x1 = text_xpix(&x->x_gui.x_obj, glist) + radius; - int y1 = text_ypix(&x->x_gui.x_obj, glist) + radius; - int x2 = text_xpix(&x->x_gui.x_obj, glist) + radius + radius * sin( -angle); - int y2 = text_ypix(&x->x_gui.x_obj, glist) + radius + radius * cos( angle); - - sys_vgui(".x%lx.c coords %xKNOB %d %d %d %d\n", - glist_getcanvas(glist), x, - x1, /* x1 */ - y1, /* y1 */ - x2, /* x2 */ - y2 /* y2 */ - ); - + int x1 = radius; + int y1 = radius; + int x2 = radius + radius * sin(-angle); + int y2 = radius + radius * cos(angle); + + gui_vmess("gui_turn_mknob", "xxiiiiif", + glist_getcanvas(glist), + x, + x1, + y1, + x2, + y2, + 1, + normalized_value + ); /* post("knob: (%d, %d) (%d, %d)", x1,y1,x2,y2); */ - sys_vgui(".x%lx.c itemconfigure %xBASE -start %d -extent %d \n", glist_getcanvas(glist), x, - start, extent); - } + //sys_vgui(".x%lx.c itemconfigure %xBASE -start %d -extent %d \n", + // glist_getcanvas(glist), x, + // start, extent); } +static void knob_draw_config(t_knob *x,t_glist *glist); static void knob_draw_new(t_knob *x, t_glist *glist) { int xpos=text_xpix(&x->x_gui.x_obj, glist); @@ -99,130 +105,101 @@ static void knob_draw_new(t_knob *x, t_glist *glist) t_canvas *canvas=glist_getcanvas(glist); /* compute dial:*/ - float radius = 0.5*(float)x->x_gui.x_h; +// float radius = 0.5*(float)x->x_gui.x_h; /* center point: */ - int x1 = xpos + radius; - int y1 = ypos + radius; +// int x1 = xpos + radius; +// int y1 = ypos + radius; /* dial */ - double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*((float)x->x_val*0.01/(float)(x->x_gui.x_h)); - int x2 = x1 + radius * sin(-angle); - int y2 = y1 + radius * cos(angle); +// double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*((float)x->x_val*0.01/(float)(x->x_gui.x_h)); +// int x2 = x1 + radius * sin(-angle); +// int y2 = y1 + radius * cos(angle); + /* reuse mknob drawing routine */ + gui_vmess("gui_mknob_new", "xxiiiiii", + canvas, + x, + xpos, + ypos, + glist_istoplevel(glist), + !iemgui_has_snd(&x->x_gui), + !iemgui_has_rcv(&x->x_gui), + 1 + ); + knob_draw_config(x, glist); /* BASE2 */ + /* sys_vgui(".x%lx.c create arc %d %d %d %d -outline #%6.6x -style arc -width 3 -start -80 -extent 340 -tags %xBASE2\n", canvas, - xpos, ypos, /* upper left */ - xpos + x->x_gui.x_h, ypos + x->x_gui.x_h, /* lower right */ + xpos, ypos, + xpos + x->x_gui.x_h, ypos + x->x_gui.x_h, x->x_gui.x_fcol, x); - + */ /* BASE */ + /* sys_vgui(".x%lx.c create arc %d %d %d %d -fill #%6.6x -style arc -width 3 -start -80 -extent 340 -tags %xBASE\n", - canvas, - xpos, ypos, /* upper left */ - xpos + x->x_gui.x_h, ypos + x->x_gui.x_h, /* lower right */ + canvas, + xpos, ypos, + xpos + x->x_gui.x_h, ypos + x->x_gui.x_h, x->x_gui.x_bcol, x); + */ /* LINE */ + /* sys_vgui(".x%lx.c create line %d %d %d %d -width 3 -fill #%6.6x -capstyle round -tags %xKNOB\n", - canvas, - x1, /* x1 */ - y1, /* y1 */ - x2, /* x2 */ - y2, /* y2 */ - x->x_gui.x_fcol, /* color */ - x); - + canvas, + x1, + y1, + x2, + y2, + x->x_gui.x_fcol, + x); + sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \ -font {%s %d bold} -fill #%6.6x -tags %xLABEL\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, x->x_gui.x_lcol, x); - if(!x->x_gui.x_fsf.x_snd_able) + iem_fstyletoint(&x->x_gui), x->x_gui.x_fontsize, x->x_gui.x_lcol, + x); + if (!iemgui_has_snd(&x->x_gui)) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xOUT%d\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) + if (!iemgui_has_rcv(&x->x_gui)) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xIN%d\n", canvas, xpos, ypos-2, xpos+7, ypos-1, x, 0); + */ } -static void knob_draw_move(t_knob *x, t_glist *glist) +static void knob_draw_config(t_knob *x,t_glist *glist) { - int xpos=text_xpix(&x->x_gui.x_obj, glist); - int ypos=text_ypix(&x->x_gui.x_obj, glist); - /* int r = ypos + x->x_gui.x_h - (x->x_val + 50)/100; */ - t_canvas *canvas=glist_getcanvas(glist); - /* compute dial:*/ - float radius = 0.5*(float)x->x_gui.x_h; - /* float angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*((float)x->x_val*0.01/(float)(x->x_gui.x_h)); */ - double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*( (double)x->x_val*0.01/(double)x->x_gui.x_h ); - /* center point: */ - int x1 = text_xpix(&x->x_gui.x_obj, glist) + radius; - int y1 = text_ypix(&x->x_gui.x_obj, glist) + radius; - int x2 = text_xpix(&x->x_gui.x_obj, glist) + radius + radius * sin( -angle); - int y2 = text_ypix(&x->x_gui.x_obj, glist) + radius + radius * cos( angle); - - - - sys_vgui(".x%lx.c coords %xKNOB %d %d %d %d\n", - canvas, x, - x1, /* x1 */ - y1, /* y1 */ - x2, /* x2 */ - y2 /* y2 */ - ); - /* post("knob: (%d, %d) (%d, %d)", x1,y1,x2,y2); */ - - sys_vgui(".x%lx.c coords %xBASE %d %d %d %d\n", - canvas, x, - xpos, ypos, - xpos + x->x_gui.x_h, ypos + x->x_gui.x_h); - - sys_vgui(".x%lx.c coords %xBASE2 %d %d %d %d\n", - canvas, x, - xpos, ypos, - xpos + x->x_gui.x_h, ypos + x->x_gui.x_h); - - sys_vgui(".x%lx.c coords %xLABEL %d %d\n", - canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy); - if(!x->x_gui.x_fsf.x_snd_able) - sys_vgui(".x%lx.c coords %xOUT%d %d %d %d %d\n", - canvas, x, 0, - xpos, ypos + x->x_gui.x_h+2, - xpos+7, ypos + x->x_gui.x_h+3); - if(!x->x_gui.x_fsf.x_rcv_able) - sys_vgui(".x%lx.c coords %xIN%d %d %d %d %d\n", - canvas, x, 0, - xpos, ypos-2, - xpos+7, ypos-1); -} + t_canvas *canvas = glist_getcanvas(glist); + char bcol[8], fcol[8], lcol[8]; -static void knob_draw_erase(t_knob* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); + sprintf(bcol, "#%6.6x", x->x_gui.x_bcol); + sprintf(fcol, "#%6.6x", x->x_gui.x_fcol); + sprintf(lcol, "#%6.6x", x->x_gui.x_lcol); - sys_vgui(".x%lx.c delete %xBASE\n", canvas, x); - sys_vgui(".x%lx.c delete %xBASE2\n", canvas, x); - sys_vgui(".x%lx.c delete %xKNOB\n", canvas, x); - sys_vgui(".x%lx.c delete %xLABEL\n", canvas, x); - if(!x->x_gui.x_fsf.x_snd_able) - sys_vgui(".x%lx.c delete %xOUT%d\n", canvas, x, 0); - if(!x->x_gui.x_fsf.x_rcv_able) - sys_vgui(".x%lx.c delete %xIN%d\n", canvas, x, 0); -} - -static void knob_draw_config(t_knob* x,t_glist* glist) -{ - t_canvas *canvas=glist_getcanvas(glist); + /* reuse mknob interface */ + gui_vmess("gui_configure_mknob", "xxissi", + canvas, + x, + x->x_gui.x_h, + bcol, + fcol, + 1 /* flag to tell we are a footils/knob */ + ); + knob_draw_update(x, glist); +/* sys_vgui(".x%lx.c itemconfigure %xLABEL -font {%s %d bold} -fill #%6.6x -text {%s} \n", - canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize, - x->x_gui.x_fsf.x_selected?IEM_GUI_COLOR_SELECTED:x->x_gui.x_lcol, + canvas, x, iem_fstyletoint(&x->x_gui), x->x_gui.x_fontsize, + glist_isselected(canvas, (t_gobj *)x) ? + 0 : x->x_gui.x_lcol, strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:""); sys_vgui(".x%lx.c itemconfigure %xKNOB -fill #%6.6x\n", canvas, x, x->x_gui.x_fcol); @@ -230,68 +207,77 @@ static void knob_draw_config(t_knob* x,t_glist* glist) x, x->x_gui.x_fcol); sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, x->x_gui.x_bcol); +*/ } +/* static void knob_draw_io(t_knob* x,t_glist* glist, int old_snd_rcv_flags) { int xpos=text_xpix(&x->x_gui.x_obj, glist); int ypos=text_ypix(&x->x_gui.x_obj, glist); t_canvas *canvas=glist_getcanvas(glist); - if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !iemgui_has_snd(&x->x_gui)) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xOUT%d\n", canvas, xpos, ypos + x->x_gui.x_h+2, xpos+7, ypos + x->x_gui.x_h+3, x, 0); - if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && iemgui_has_rcv(&x->x_gui)) sys_vgui(".x%lx.c delete %xOUT%d\n", canvas, x, 0); - if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !iemgui_has_rcv(&x->x_gui)) sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xIN%d\n", canvas, xpos, ypos-2, xpos+7, ypos-1, x, 0); - if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && iemgui_has_rcv(&x->x_gui)) sys_vgui(".x%lx.c delete %xIN%d\n", canvas, x, 0); } +*/ +/* static void knob_draw_select(t_knob *x, t_glist *glist) { t_canvas *canvas=glist_getcanvas(glist); - if(x->x_gui.x_fsf.x_selected) + if(glist_isselected(canvas, (t_gobj *)x)) { pd_bind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); - sys_vgui(".x%lx.c itemconfigure %xBASE2 -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); - sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); - sys_vgui(".x%lx.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%lx.c itemconfigure %xBASE2 -outline #%6.6x\n", canvas, x, 0); + sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, 0); + sys_vgui(".x%lx.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, 0); } else { pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); - sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, 0); sys_vgui(".x%lx.c itemconfigure %xBASE2 -outline #%6.6x\n", canvas, x, x->x_gui.x_fcol); sys_vgui(".x%lx.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, x->x_gui.x_lcol); } } +*/ -void knob_draw(t_knob *x, t_glist *glist, int mode) +static void knob_draw(t_knob *x, t_glist *glist, int mode) { if(mode == IEM_GUI_DRAW_MODE_UPDATE) knob_draw_update(x, glist); else if(mode == IEM_GUI_DRAW_MODE_MOVE) - knob_draw_move(x, glist); + iemgui_base_draw_move(&x->x_gui); else if(mode == IEM_GUI_DRAW_MODE_NEW) knob_draw_new(x, glist); +/* else if(mode == IEM_GUI_DRAW_MODE_SELECT) knob_draw_select(x, glist); else if(mode == IEM_GUI_DRAW_MODE_ERASE) knob_draw_erase(x, glist); +*/ else if(mode == IEM_GUI_DRAW_MODE_CONFIG) knob_draw_config(x, glist); +/* else if(mode >= IEM_GUI_DRAW_MODE_IO) knob_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO); +*/ } /* ------------------------ knob widgetbehaviour----------------------------- */ @@ -311,27 +297,25 @@ static void knob_getrect(t_gobj *z, t_glist *glist, static void knob_save(t_gobj *z, t_binbuf *b) { t_knob *x = (t_knob *)z; - int bflcol[3], *ip1, *ip2; + int bflcol[3]; t_symbol *srl[3]; iemgui_save(&x->x_gui, srl, bflcol); - ip1 = (int *)(&x->x_gui.x_isa); - ip2 = (int *)(&x->x_gui.x_fsf); binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", gensym("#X"),gensym("obj"), (t_int)x->x_gui.x_obj.te_xpix, (t_int)x->x_gui.x_obj.te_ypix, atom_getsymbol(binbuf_getvec(x->x_gui.x_obj.te_binbuf)), x->x_gui.x_h, x->x_gui.x_h, (float)x->x_min, (float)x->x_max, - x->x_lin0_log1, (*ip1)&IEM_INIT_ARGS_ALL, + x->x_lin0_log1, iem_symargstoint(&x->x_gui), srl[0], srl[1], srl[2], x->x_gui.x_ldx, x->x_gui.x_ldy, - (*ip2)&IEM_FSTYLE_FLAGS_ALL, x->x_gui.x_fontsize, + iem_fstyletoint(&x->x_gui), x->x_gui.x_fontsize, bflcol[0], bflcol[1], bflcol[2], x->x_val, x->x_steady); binbuf_addv(b, ";"); } -void knob_check_height(t_knob *x, int h) +static void knob_check_height(t_knob *x, int h) { if(h < IEM_SL_MINSIZE) h = IEM_SL_MINSIZE; @@ -347,7 +331,7 @@ void knob_check_height(t_knob *x, int h) x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_h - 1); } -void knob_check_minmax(t_knob *x, double min, double max) +static void knob_check_minmax(t_knob *x, double min, double max) { if(x->x_lin0_log1) { @@ -367,9 +351,9 @@ void knob_check_minmax(t_knob *x, double min, double max) x->x_min = min; x->x_max = max; if(x->x_min > x->x_max) /* bugfix */ - x->x_gui.x_isa.x_reverse = 1; + x->x_gui.x_reverse = 1; else - x->x_gui.x_isa.x_reverse = 0; + x->x_gui.x_reverse = 0; if(x->x_lin0_log1) x->x_k = log(x->x_max/x->x_min)/(double)(x->x_gui.x_h - 1); else @@ -379,11 +363,43 @@ void knob_check_minmax(t_knob *x, double min, double max) static void knob_properties(t_gobj *z, t_glist *owner) { t_knob *x = (t_knob *)z; - char buf[800]; +// char buf[800]; + char *gfx_tag; t_symbol *srl[3]; iemgui_properties(&x->x_gui, srl); - + gfx_tag = gfxstub_new2(&x->x_gui.x_obj.ob_pd, x); + + gui_start_vmess("gui_iemgui_dialog", "s", gfx_tag); + gui_start_array(); + + gui_s("type"); gui_s("knob"); + /* Since mknob reuses the iemgui dialog code, we just + use the "width" slot for "size" and the "height" slot + for the number of steps and re-label it on the GUI side. */ +// gui_s("width"); gui_i(x->x_gui.x_w); +// gui_s("height"); gui_i(x->x_gui.x_h); + gui_s("size"); gui_i(x->x_gui.x_h); + gui_s("minimum_range"); gui_f(x->x_min); + gui_s("maximum_range"); gui_f(x->x_max); + gui_s("log_scaling"); gui_i(x->x_lin0_log1); + gui_s("init"); gui_i(x->x_gui.x_loadinit); + gui_s("steady_on_click"); gui_i(x->x_steady); + gui_s("send_symbol"); gui_s(srl[0]->s_name); + gui_s("receive_symbol"); gui_s(srl[1]->s_name); + gui_s("label"); gui_s(srl[2]->s_name); + gui_s("x_offset"); gui_i(x->x_gui.x_ldx); + gui_s("y_offset"); gui_i(x->x_gui.x_ldy); + gui_s("font_style"); gui_i(x->x_gui.x_font_style); + gui_s("font_size"); gui_i(x->x_gui.x_fontsize); + gui_s("background_color"); gui_i(0xffffff & x->x_gui.x_bcol); + gui_s("foreground_color"); gui_i(0xffffff & x->x_gui.x_fcol); + gui_s("label_color"); gui_i(0xffffff & x->x_gui.x_lcol); + + gui_end_array(); + gui_end_vmess(); + +/* sprintf(buf, "pdtk_iemgui_dialog %%s KNOB \ --------dimensions(pix)(pix):-------- %d %d NONE: %d %d height: \ -----------output-range:----------- %g left: %g right: %g \ @@ -393,13 +409,14 @@ static void knob_properties(t_gobj *z, t_glist *owner) %d %d \ %d %d %d\n", x->x_gui.x_w, IEM_SL_MINSIZE, x->x_gui.x_h, IEM_GUI_MINSIZE, - x->x_min, x->x_max, 0.0,/*no_schedule*/ - x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/ + x->x_min, x->x_max, 0.0, //no_schedule + x->x_lin0_log1, x->x_gui.x_loadinit, x->x_steady, -1,//no multi, but iem-characteristic srl[0]->s_name, srl[1]->s_name, srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, - x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + iem_fstyletoint(&x->x_gui), x->x_gui.x_fontsize, 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +*/ } static void knob_bang(t_knob *x) @@ -415,15 +432,32 @@ static void knob_bang(t_knob *x) //post("knob_bang -- x_k: %f", x->x_k); outlet_float(x->x_gui.x_obj.ob_outlet, out); - if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + if(iemgui_has_snd(&x->x_gui) && x->x_gui.x_snd->s_thing) pd_float(x->x_gui.x_snd->s_thing, out); } +static void complain_about_surprising_behavior(t_knob *x) +{ + if (!x->x_explained_surprising_behavior) + { + pd_error(x, "knob: value is coupled to its height. This " + "means its output value can change when you change its size. " + "If you don't need to change the widget's size when running " + "your patch this is probably ok. Otherwise, " + "consider using moonlib/knob instead. " + "(Or perhaps question why audio interfaces are the only UIs " + "which still employ 'knob' widgets.)"); + x->x_explained_surprising_behavior = 1; + } +} + static void knob_dialog(t_knob *x, t_symbol *s, int argc, t_atom *argv) { - t_symbol *srl[3]; + if (atom_getintarg(19, argc, argv)) + canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x); int w = (int)atom_getintarg(0, argc, argv); int h = (int)atom_getintarg(1, argc, argv); + int old_h = x->x_gui.x_h; double min = (double)atom_getfloatarg(2, argc, argv); double max = (double)atom_getfloatarg(3, argc, argv); int lilo = (int)atom_getintarg(4, argc, argv); @@ -436,13 +470,20 @@ static void knob_dialog(t_knob *x, t_symbol *s, int argc, t_atom *argv) x->x_steady = 1; else x->x_steady = 0; - sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + sr_flags = iemgui_dialog(&x->x_gui, argc, argv); x->x_gui.x_h = iemgui_clip_size(w); knob_check_height(x, h); knob_check_minmax(x, min, max); - (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + if (old_h != x->x_gui.x_h) + complain_about_surprising_behavior(x); + iemgui_draw_config(&x->x_gui); +// (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + iemgui_draw_io(&x->x_gui, sr_flags); +/* (*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); +*/ +// (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + iemgui_io_draw_move(&x->x_gui); canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x); } @@ -450,7 +491,7 @@ static void knob_motion(t_knob *x, t_floatarg dx, t_floatarg dy) { int old = x->x_val; - if(x->x_gui.x_fsf.x_finemoved) + if(x->x_gui.x_finemoved) x->x_pos -= (int)dy; else x->x_pos -= 100*(int)dy; @@ -495,14 +536,14 @@ static int knob_newclick(t_gobj *z, struct _glist *glist, { t_knob* x = (t_knob *)z; - if(doit) + if (doit) { - knob_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + knob_click (x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt); - if(shift) - x->x_gui.x_fsf.x_finemoved = 1; + if (shift) + x->x_gui.x_finemoved = 1; else - x->x_gui.x_fsf.x_finemoved = 0; + x->x_gui.x_finemoved = 0; } return (1); } @@ -511,21 +552,21 @@ static void knob_set(t_knob *x, t_floatarg f) { double g; - if(x->x_gui.x_isa.x_reverse) /* bugfix */ + if (x->x_gui.x_reverse) /* bugfix */ { - if(f > x->x_min) + if (f > x->x_min) f = x->x_min; - if(f < x->x_max) + if (f < x->x_max) f = x->x_max; } else { - if(f > x->x_max) + if (f > x->x_max) f = x->x_max; - if(f < x->x_min) + if (f < x->x_min) f = x->x_min; } - if(x->x_lin0_log1) + if (x->x_lin0_log1) g = log(f/x->x_min)/x->x_k; else g = (f - x->x_min) / x->x_k; @@ -535,14 +576,15 @@ static void knob_set(t_knob *x, t_floatarg f) // x->x_val = (int)(100.0*g); x->x_pos = x->x_val; //post("knob_set x_val: %f", x->x_val ); - (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + if (glist_isvisible(x->x_gui.x_glist)) + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); } static void knob_float(t_knob *x, t_floatarg f) { - /* post("knob_set infloat f: %f", f ); */ + /* post("knob_set infloat f: %f", f ); */ knob_set(x, f); - if(x->x_gui.x_fsf.x_put_in2out) + if (x->x_gui.x_put_in2out) knob_bang(x); } @@ -550,15 +592,20 @@ static void knob_size(t_knob *x, t_symbol *s, int ac, t_atom *av) { x->x_gui.x_h = iemgui_clip_size((int)atom_getintarg(0, ac, av)); if(ac > 1) - knob_check_height(x, (int)atom_getintarg(1, ac, av)); - iemgui_size((void *)x, &x->x_gui); + knob_check_height(x, (int)atom_getintarg(1, ac, av)); + complain_about_surprising_behavior(x); + iemgui_size(&x->x_gui); } static void knob_delta(t_knob *x, t_symbol *s, int ac, t_atom *av) -{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} +{ + iemgui_delta(&x->x_gui, s, ac, av); +} static void knob_pos(t_knob *x, t_symbol *s, int ac, t_atom *av) -{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} +{ + iemgui_pos(&x->x_gui, s, ac, av); +} static void knob_range(t_knob *x, t_symbol *s, int ac, t_atom *av) { @@ -567,22 +614,34 @@ static void knob_range(t_knob *x, t_symbol *s, int ac, t_atom *av) } static void knob_color(t_knob *x, t_symbol *s, int ac, t_atom *av) -{iemgui_color((void *)x, &x->x_gui, s, ac, av);} +{ + iemgui_color(&x->x_gui, s, ac, av); +} static void knob_send(t_knob *x, t_symbol *s) -{iemgui_send(x, &x->x_gui, s);} +{ + iemgui_send(&x->x_gui, s); +} static void knob_receive(t_knob *x, t_symbol *s) -{iemgui_receive(x, &x->x_gui, s);} +{ + iemgui_receive(&x->x_gui, s); +} static void knob_label(t_knob *x, t_symbol *s) -{iemgui_label((void *)x, &x->x_gui, s);} +{ + iemgui_label(&x->x_gui, s); +} static void knob_label_pos(t_knob *x, t_symbol *s, int ac, t_atom *av) -{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} +{ + iemgui_label_pos(&x->x_gui, s, ac, av); +} static void knob_label_font(t_knob *x, t_symbol *s, int ac, t_atom *av) -{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} +{ + iemgui_label_font(&x->x_gui, s, ac, av); +} static void knob_log(t_knob *x) { @@ -598,7 +657,7 @@ static void knob_lin(t_knob *x) static void knob_init(t_knob *x, t_floatarg f) { - x->x_gui.x_isa.x_loadinit = (f==0.0)?0:1; + x->x_gui.x_loadinit = (f==0.0)?0:1; } static void knob_steady(t_knob *x, t_floatarg f) @@ -610,7 +669,7 @@ static void knob_steady(t_knob *x, t_floatarg f) static void knob_loadbang(t_knob *x, t_floatarg action) { - if (action == LB_LOAD && x->x_gui.x_isa.x_loadinit) + if (action == LB_LOAD && x->x_gui.x_loadinit) { (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); knob_bang(x); @@ -635,24 +694,101 @@ static void knob_list(t_knob *x, t_symbol *s, int ac, t_atom *av) } */ +/* we may no longer need h_dragon... */ +static void knob__clickhook(t_scalehandle *sh, int newstate) +{ + t_knob *x = (t_knob *)(sh->h_master); + if (newstate) + { + canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x); + if (!sh->h_scale) /* click on a label handle */ + scalehandle_click_label(sh); + } + /* We no longer need this "clickhook", as we can handle the dragging + either in the GUI (for the label handle) or or in canvas_doclick */ + //iemgui__clickhook3(sh,newstate); + sh->h_dragon = newstate; +} + +static void knob__motionhook(t_scalehandle *sh, + t_floatarg mouse_x, t_floatarg mouse_y) +{ + if (sh->h_scale) + { + t_knob *x = (t_knob *)(sh->h_master); + int width = x->x_gui.x_h, + height = x->x_gui.x_h; + int x1, y1, x2, y2, d; + x1 = text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist); + y1 = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist); + x2 = x1 + width; + y2 = y1 + height; + + /* This is convoluted, but I can't think of another + way to get this behavior... */ + if (mouse_x <= x2) + { + if (mouse_y > y2) + d = mouse_y - y2; + else if (abs(mouse_y - y2) < abs(mouse_x - x2)) + d = mouse_y - y2; + else + d = mouse_x - x2; + } + else + { + if (mouse_y <= y2) + d = mouse_x - x2; + else + d = maxi(mouse_y - y2, mouse_x - x2); + } + sh->h_dragx = d; + sh->h_dragy = d; + scalehandle_drag_scale(sh); + + width = maxi(width + d, IEM_GUI_MINSIZE); + height = width; + + /* Explain some suprising behavior to the user... */ + + x->x_gui.x_w = width; + x->x_gui.x_h = height; + /* recalculate x_k and stuff */ + knob_check_height(x, height); + knob_check_minmax(x, x->x_min, x->x_max); + + complain_about_surprising_behavior(x); + + if (glist_isvisible(x->x_gui.x_glist)) + { + knob_draw_config(x, x->x_gui.x_glist); + scalehandle_unclick_scale(sh); + } + + int properties = gfxstub_haveproperties((void *)x); + if (properties) + { + int new_w = x->x_gui.x_w + sh->h_dragx; + // This should actually be "size", but we're using the + // "width" input in dialog_iemgui and just relabelling it + // as a kluge. + properties_set_field_int(properties, "width", new_w); + } + } + scalehandle_dragon_label(sh, mouse_x, mouse_y); +} + static void *knob_new(t_symbol *s, int argc, t_atom *argv) { t_knob *x = (t_knob *)pd_new(knob_class); int bflcol[]={-262144, -1, -1}; - t_symbol *srl[3]; int w=IEM_KNOB_DEFAULTSIZE, h=IEM_KNOB_DEFAULTSIZE; int lilo=0, ldx=0, ldy=-8; int fs=8, v=0, steady=1; double min=0.0, max=(double)(IEM_SL_DEFAULTSIZE-1); - char str[144]; - - //srl[0] = gensym("empty"); - //srl[1] = gensym("empty"); - //srl[2] = gensym("empty"); - - iem_inttosymargs(&x->x_gui.x_isa, 0); - iem_inttofstyle(&x->x_gui.x_fsf, 0); + iem_inttosymargs(&x->x_gui, 0); + iem_inttofstyle(&x->x_gui, 0); if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3) @@ -669,11 +805,11 @@ static void *knob_new(t_symbol *s, int argc, t_atom *argv) min = (double)atom_getfloatarg(2, argc, argv); max = (double)atom_getfloatarg(3, argc, argv); lilo = (int)atom_getintarg(4, argc, argv); - iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv)); + iem_inttosymargs(&x->x_gui, atom_getintarg(5, argc, argv)); iemgui_new_getnames(&x->x_gui, 6, argv); ldx = (int)atom_getintarg(9, argc, argv); ldy = (int)atom_getintarg(10, argc, argv); - iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv)); + iem_inttofstyle(&x->x_gui, atom_getintarg(11, argc, argv)); fs = (int)atom_getintarg(12, argc, argv); bflcol[0] = (int)atom_getintarg(13, argc, argv); bflcol[1] = (int)atom_getintarg(14, argc, argv); @@ -681,16 +817,18 @@ static void *knob_new(t_symbol *s, int argc, t_atom *argv) v = (int)atom_getintarg(16, argc, argv); } else iemgui_new_getnames(&x->x_gui, 6, 0); - if((argc == 18)&&IS_A_FLOAT(argv,17)) + if ((argc == 18)&&IS_A_FLOAT(argv,17)) steady = (int)atom_getintarg(17, argc, argv); x->x_gui.x_draw = (t_iemfunptr)knob_draw; +/* x->x_gui.x_fsf.x_snd_able = 1; x->x_gui.x_fsf.x_rcv_able = 1; +*/ x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); - if(x->x_gui.x_isa.x_loadinit) + if (x->x_gui.x_loadinit) x->x_val = v; else x->x_val = 0; @@ -699,19 +837,30 @@ static void *knob_new(t_symbol *s, int argc, t_atom *argv) x->x_lin0_log1 = lilo; if(steady != 0) steady = 1; x->x_steady = steady; +/* if (!strcmp(x->x_gui.x_snd->s_name, "empty")) x->x_gui.x_fsf.x_snd_able = 0; if (!strcmp(x->x_gui.x_rcv->s_name, "empty")) x->x_gui.x_fsf.x_rcv_able = 0; - if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); - else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); - else { x->x_gui.x_fsf.x_font_style = 0; - strcpy(x->x_gui.x_font, "courier"); } - if(x->x_gui.x_fsf.x_rcv_able) +*/ + if (iem_fstyletoint(&x->x_gui) == 1) + { + //strcpy(x->x_gui.x_font, "helvetica"); + } + else if (iem_fstyletoint(&x->x_gui) == 2) + { + //strcpy(x->x_gui.x_font, "times"); + } + else + { + x->x_gui.x_font_style = 0; + //strcpy(x->x_gui.x_font, "courier"); + } + if (iemgui_has_rcv(&x->x_gui)) pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); x->x_gui.x_ldx = ldx; x->x_gui.x_ldy = ldy; - if(fs < 4) + if (fs < 4) fs = 4; x->x_gui.x_fontsize = fs; x->x_gui.x_h = iemgui_clip_size(h); @@ -721,6 +870,14 @@ static void *knob_new(t_symbol *s, int argc, t_atom *argv) //x->x_thick = 0; iemgui_verify_snd_ne_rcv(&x->x_gui); outlet_new(&x->x_gui.x_obj, &s_float); + x->x_gui.x_obj.te_iemgui = 1; + x->x_explained_surprising_behavior = 0; + + x->x_gui.x_handle = scalehandle_new((t_object *)x, + x->x_gui.x_glist, 1, knob__clickhook, knob__motionhook); + x->x_gui.x_lhandle = scalehandle_new((t_object *)x, + x->x_gui.x_glist, 0, knob__clickhook, knob__motionhook); + return (x); } @@ -728,9 +885,9 @@ static void *knob_new(t_symbol *s, int argc, t_atom *argv) static void knob_free(t_knob *x) { - if(x->x_gui.x_fsf.x_selected) + if (iemgui_has_snd(&x->x_gui)) pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); - if(x->x_gui.x_fsf.x_rcv_able) + if (iemgui_has_rcv(&x->x_gui)) pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); gfxstub_deleteforkey(x); } @@ -771,6 +928,7 @@ void knob_setup(void) iemgui_key_sym = gensym("#keyname"); knob_widgetbehavior.w_getrectfn = knob_getrect; knob_widgetbehavior.w_displacefn = iemgui_displace; + knob_widgetbehavior.w_displacefnwtag = iemgui_displace_withtag; knob_widgetbehavior.w_selectfn = iemgui_select; knob_widgetbehavior.w_activatefn = NULL; knob_widgetbehavior.w_deletefn = iemgui_delete; diff --git a/externals/footils/knob/makefile b/externals/footils/knob/makefile index 5fdf212db7d7c5c085d4f8b9ba88109f308eb96c..cdb8e075f5c344eff79071fc690d164e03a6b350 100644 --- a/externals/footils/knob/makefile +++ b/externals/footils/knob/makefile @@ -1,91 +1,13 @@ -NAME=knob -CSYM=knob - -# !!! -# change these two -PD_DIR=../../../pd -#current: pd_nt pd_linux -current: pd_linux - -# ----------------------- NT ----------------------- - -pd_nt: $(NAME).dll - -.SUFFIXES: .dll - -PDNTCFLAGS = /W3 /WX /O2 /G6 /DNT /DPD /nologo - -# where is VC++ ??? -VC="C:\Programme\Microsoft Visual Studio\VC98" - -# where is your m_pd.h ??? -PDNTINCLUDE = /I. /Ic:\pd\tcl\include /Ic:\pd\src /I$(VC)\include /Iinclude - -PDNTLDIR = $(VC)\Lib -PDNTLIB = $(PDNTLDIR)\libc.lib \ - $(PDNTLDIR)\oldnames.lib \ - $(PDNTLDIR)\kernel32.lib \ - $(PDNTLDIR)\user32.lib \ - $(PDNTLDIR)\uuid.lib \ - $(PDNTLDIR)\ws2_32.lib \ - c:\pd\bin\pd.lib - -.c.dll: - cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c - link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB) - -# ----------------------- IRIX 5.x ----------------------- - -pd_irix5: $(NAME).pd_irix5 - -.SUFFIXES: .pd_irix5 - -SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2 - -SGIINCLUDE = -I../../src - -.c.pd_irix5: - cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c - ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o - rm $*.o - -# ----------------------- IRIX 6.x ----------------------- - -pd_irix6: $(NAME).pd_irix6 - -.SUFFIXES: .pd_irix6 - -SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \ - -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ - -Ofast=ip32 - -.c.pd_irix6: - cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c - ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o - rm $*.o - -# ----------------------- LINUX i386 ----------------------- - -pd_linux: $(NAME).pd_linux - -.SUFFIXES: .pd_linux - -LINUXCFLAGS = -DPD -DUNIX -O2 -funroll-loops -fomit-frame-pointer \ - -Wall -W -Wshadow -Wstrict-prototypes -Werror \ - -Wno-unused -Wno-parentheses -Wno-switch - -# where is your m_pd.h ??? -LINUXINCLUDE = -I../../src -I$(PD_DIR)/src - -.c.pd_linux: - cc -O2 -Wall -DPD -fPIC $(LINUXINCLUDE) -c $*.c - ld --export-dynamic -shared -o $*.pd_linux $*.o -lc - strip $*.pd_linux - -# ---------------------------------------------------------- - -install: - cp help-*.pd ../../doc/5.reference - -clean: - rm -f *.o *.pd_* so_locations +# Makefile for mylib + +lib.name = flatgui + +class.sources = knob.c + +# ldlibs = -lfluidsynth + +datafiles = knob-help.pd clock.pd README + +externalsdir = ../../ + +include Makefile.pdlibbuilder.revised diff --git a/externals/moonlib/mknob.c b/externals/moonlib/mknob.c index bbba8d7ae3f5ba95e45c49f1f130b72f0a370536..f12edcf074f1e1726cf0b65bf2ab5c49113ce996 100644 --- a/externals/moonlib/mknob.c +++ b/externals/moonlib/mknob.c @@ -744,7 +744,7 @@ static void *mknob_new(t_symbol *s, int argc, t_atom *argv) x->x_thick = 0; iemgui_verify_snd_ne_rcv(&x->x_gui); outlet_new(&x->x_gui.x_obj, &s_float); - x->x_gui.x_obj.te_iemgui = 1; + x->x_gui.x_obj.te_iemgui = 1; x->x_gui.x_handle = scalehandle_new((t_object *)x, x->x_gui.x_glist, 1, mknob__clickhook, mknob__motionhook); diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index e40a3072c64c9bfdede723e6f138b894c7714e40..c27d0c0d87e1e514a3ebbad1bcf40c936483394d 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -1995,7 +1995,12 @@ function add_gobj_to_svg(svg, gobj) { var gui = (function() { var c = {}; // object to hold references to all our canvas closures - var last_thing; // last thing we got + // We store the last "thing" we fetched from the window. This is either + // the window itself or a "gobj". Regular old DOM elements that aren't + // a "gobj" container don't count. This way we can do a "get_gobj" then + // gang multiple element queries after it that work within our last + // "gobj." (Same for window.) + var last_thing; var null_fn, null_canvas; var create_canvas = function(cid, w) { var get = function(parent, sel, arg, suffix) { @@ -4152,7 +4157,8 @@ function gui_grid_point(cid, tag, x, y) { } // mknob from moonlib -function gui_mknob_new(cid, tag, x, y, is_toplevel, show_in, show_out) { +function gui_mknob_new(cid, tag, x, y, is_toplevel, show_in, show_out, + is_footils_knob) { gui(cid).get_elem("patchsvg", function(svg_elem) { gui_gobj_new(cid, tag, "obj", x, y, is_toplevel); }); @@ -4162,50 +4168,89 @@ function gui_mknob_new(cid, tag, x, y, is_toplevel, show_in, show_out) { class: "border" // now we can inherit the css border styles }), circle = create_item(cid, "circle", { - class: "circle" + //class: "circle" }), line = create_item(cid, "line", { - class: "dial" + //class: "dial" }); frag.appendChild(border); frag.appendChild(circle); + /* An extra circle for footils/knob */ + if (!!is_footils_knob) { + frag.appendChild(create_item(cid, "circle", { + class: "dial_frag" + })); + } frag.appendChild(line); return frag; }); } -function gui_configure_mknob(cid, tag, size, bg_color, fg_color) { - gui(cid).get_gobj(tag) +function knob_dashes(d, len) { + var c = d * 3.14159; + return (c * len) + " " + (c * (1 - len)); +} + +function knob_offset(d) { + return d * 3.14 * -0.28; +} + +function gui_configure_mknob(cid, tag, size, bg_color, fg_color, + is_footils_knob) { + var w = size, + h = !!is_footils_knob ? size + 5 : size; + var g = gui(cid).get_gobj(tag) .q(".border", { - d: ["M", 0, 0, size, 0, - "M", 0, size, size, size, - "M", 0, 0, 0, size, - "M", size, 0, size, size + d: ["M", 0, 0, w, 0, + "M", 0, h, w, h, + "M", 0, 0, 0, h, + "M", w, 0, w, h ].join(" "), fill: "none", }) - .q(".circle", { + .q("circle", { cx: size / 2, cy: size / 2, r: size / 2, - fill: bg_color, + fill: !!is_footils_knob ? "none" : bg_color, stroke: "black", - "stroke-width": 1 + "stroke-width": !!is_footils_knob ? 3 : 1, + "stroke-dasharray": !!is_footils_knob ? + knob_dashes(size, 0.94) : "none", + "stroke-dashoffset": !!is_footils_knob ? knob_offset(size) : "0" }) - .q(".dial", { + .q("line", { // indicator "stroke-width": 2, stroke: fg_color }); + + if (!!is_footils_knob) { + g.q(".dial_frag", { + cx: size / 2, + cy: size / 2, + r: size / 2, + fill: "none", + stroke: bg_color, + "stroke-width": 3, + "stroke-dasharray": knob_dashes(size, 0.94), + "stroke-dashoffset": knob_offset(size) + }); + } } -function gui_turn_mknob(cid, tag, x1, y1, x2, y2) { - gui(cid).get_gobj(tag) - .q(".dial", { +function gui_turn_mknob(cid, tag, x1, y1, x2, y2, is_footils_knob, val) { + var g = gui(cid).get_gobj(tag) + .q("line", { // indicator x1: x1, y1: y1, x2: x2, y2: y2 }); + if (!!is_footils_knob) { + g.q(".dial_frag", { + "stroke-dasharray": knob_dashes(x1 * 2, val * 0.94) + }); + } } function add_popup(cid, popup) { diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c index faaf731a41d081acede7293a0fd4f4d5642de81d..c2381e0f12f3d6d283868cf82e2c936143a31ef7 100644 --- a/pd/src/g_all_guis.c +++ b/pd/src/g_all_guis.c @@ -513,7 +513,6 @@ void iemgui_displace_withtag(t_gobj *z, t_glist *glist, int dx, int dy) canvas_fixlinesfor(glist_getcanvas(glist), (t_text *)z); } - void iemgui_select(t_gobj *z, t_glist *glist, int selected) { t_iemgui *x = (t_iemgui *)z;