pax_global_header00006660000000000000000000000064126507500460014517gustar00rootroot0000000000000052 comment=5567ea1735b5024ef615df04b23f21e4a38a74ee mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/000077500000000000000000000000001265075004600221135ustar00rootroot00000000000000mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/LICENSE.txt000066400000000000000000000013331265075004600237360ustar00rootroot00000000000000audiosettings - get/set audio settings within Pd Copyright © 2010-2012 IOhannes m zmoelnig (zmoelnig AT iem DOT at) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/Makefile000066400000000000000000000020701265075004600235520ustar00rootroot00000000000000#!/usr/bin/make -f # Makefile for pure data externals in lib creb. # Needs Makefile.pdlibbuilder to work (https://github.com/pure-data/pd-lib-builder) lib.name = mediasettings # special file that does not provide a class lib.setup.sources = # all other C and C++ files in subdirs are source files per class # (alternatively, enumerate them by hand) class.sources = audiosettings.c midisettings.c datafiles = \ audiosettings-help.pd midisettings-help.pd \ LICENSE.txt \ README.txt \ mediasettings-meta.pd cflags = -DVERSION='"$(lib.version)"' ################################################################################ ### pdlibbuilder ############################################################### ################################################################################ # This Makefile is based on the Makefile from pd-lib-builder written by # Katja Vetter. You can get it from: # https://github.com/pure-data/pd-lib-builder PDLIBBUILDER_DIR=pd-lib-builder/ include $(firstword $(wildcard $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder Makefile.pdlibbuilder)) mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/Makefile.pdlibbuilder000066400000000000000000001135411265075004600262200ustar00rootroot00000000000000# Makefile.pdlibbuilder version 0.0.1, dated 2015-10-31 # # 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 # - .class.sources # - .class.ldflags # - .class.ldlibs # - cflags # - ldflags # - ldlibs # - datafiles # - datadirs # - makefiles # - makefiledirs # - externalsdir # # Variables avaialable for (re)definition via command arguments: # # - pdbinpath (Windows only) # - pdincludepath # - DESTDIR # - prefix # - libdir # - pkglibdir # - CFLAGS # - 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. # # .class.sources: # Source file(s) (C or C++) specific to class . 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. # # .class.ldflags and .class.ldlibs: # Define ldflags resp. ldlibs specific to class . 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). # # 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. # # CFLAGS: # Compiler (notably optimization) flags which are defined by # Makefile.pdlibbuilder, but may be overriden via command argument. # # 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 the location where m_pd.h was found. # 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 classes (default) or library blob (if make-lib-executable=true) # alldebug: build all with -g option turned on for debug symbols # : force clean build of an individual class # .pre: make preprocessor output file in current working directory # .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 # # #=== 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 -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 ' to print debug details of the make process. # Use 'make -p ' 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 .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 .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. uname := $(shell uname) ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname)) system = Linux endif ifeq ($(uname), Darwin) system = Darwin endif ifeq ($(findstring MINGW, $(uname)), MINGW) system = Windows endif # TODO: Cygwin, Android #=== flags and paths for Linux ================================================= ifeq ($(system), Linux) prefix = /usr/local libdir := $(prefix)/lib pkglibdir = $(libdir)/pd-externals pdincludepath := $(firstword $(dir $(wildcard \ $(externalsdir)/../pd/src/m_pd.h \ /usr/include/pdextended/m_pd.h \ /usr/include/pd/m_pd.h))) 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 $(dir $(wildcard \ $(externalsdir)/../pd/src/m_pd.h \ /Applications/Pd-extended.app/Contents/Resources/include/pdextended/m_pd.h \ /Applications/Pd.app/Contents/Resources/src/m_pd.h))) 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 i386 -arch x86_64 -mmacosx-version-min=10.5 arch.ld.flags := -arch i386 -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 # check if m_pd.h is found and print info about it $(if $(shell ls "$(pdincludepath)m_pd.h"), \ $(info ++++ info: using Pd API $(pdincludepath)m_pd.h), \ $(warning Where is your m_pd.h? Do 'make help' for info.)) # 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 build-classes build-lib $(classes) $(makefiledirs) $(makefiles)\ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help ################################################################################ ### rules: build targets ####################################################### ################################################################################ # target all builds class executables plus optional shared lib # or alternatively a single lib executable when make-lib-executable=true all: $(executables) $(info ++++ info: $(if $(executables),executables in $(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 so we do not evaluate them in that case. ifndef pdincludepathwithspaces must-build-everything := $(filter all default lib, $(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) define declare-object-target $(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 mpdh := $(shell ls "$(pdincludepath)m_pd.h") mpdh := $(if $(mpdh), $(mpdh), m_pd.h not found. Is Pd(-extended) installed?) 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 " $(shell ls "$(pdincludepath)m_pd.h")" @echo " You may specify your preferred 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 " For detailed info read 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: mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/README.txt000066400000000000000000000003031265075004600236050ustar00rootroot00000000000000 mediasettings - get/set audio and MIDI settings within Pd NOTE: this library has been developed for the IntegraLive project http://integralive.org IOhannes m zmoelnig (zmoelnig AT iem DOT at) mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/audiosettings-help.pd000066400000000000000000000021201265075004600262430ustar00rootroot00000000000000#N canvas 172 173 473 417 10; #X obj 48 261 audiosettings; #X text 28 20 audiosettings - query and manipulate audio-settings; #X msg 98 58 listdrivers; #X msg 100 87 listdevices; #X msg 105 117 listparams; #X text 179 56 get available audio drivers; #X text 181 86 get available devices for current driver; #X text 183 119 get available parameters for current driver/device ; #X obj 48 283 print info; #N canvas 6 50 809 300 set 0; #X msg 123 54 driver ALSA; #X obj 61 259 outlet; #X text 207 55 set driver to "ALSA" (if possible); #X msg 130 119 params @samplerate 48000; #X text 288 118 set samplerate to 48kHz; #X text 432 165 choose (input-device #1) AND (output-device #2) AND (samplerate=48kHz); #X msg 135 168 params @input 0 2 @output 0 2 @samplerate 48000; #X connect 0 0 1 0; #X connect 3 0 1 0; #X connect 6 0 1 0; #X restore 114 181 pd set; #X msg 140 227 getdriver; #X msg 175 266 bang; #X msg 239 230 params @samplerate 48000; #X connect 0 0 8 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X connect 9 0 0 0; #X connect 10 0 0 0; #X connect 11 0 0 0; #X connect 12 0 0 0; mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/audiosettings.c000066400000000000000000000450061265075004600251460ustar00rootroot00000000000000/****************************************************** * * audiosettings - get/set audio preferences from within Pd-patches * Copyright (C) 2010-2012 IOhannes m zmölnig * * forum::für::umläute * * institute of electronic music and acoustics (iem) * university of music and dramatic arts, graz (kug) * * ****************************************************** * * license: GNU General Public License v.3 or later * ******************************************************/ #include "mediasettings.h" #if (!defined AUDIOSETTINGS_VERSION) && (defined VERSION) # define AUDIOSETTINGS_VERSION VERSION #endif #define MAXAUDIOINDEV 4 #define MAXAUDIOOUTDEV 4 static void as_get_audio_params( int *pnaudioindev, int *paudioindev, int *pchindev, int *pnaudiooutdev, int *paudiooutdev, int *pchoutdev, int *prate, int *padvance, int *pcallback, int *pblocksize) { #if (defined PD_MINOR_VERSION) && (PD_MINOR_VERSION >= 43) sys_get_audio_params(pnaudioindev , paudioindev , pchindev, pnaudiooutdev, paudiooutdev, pchoutdev, prate, padvance, pcallback, pblocksize); #else if(pblocksize) *pblocksize=-1; sys_get_audio_params(pnaudioindev , paudioindev , pchindev, pnaudiooutdev, paudiooutdev, pchoutdev, prate, padvance, pcallback); #endif } static t_class *audiosettings_class; t_symbol*s_pdsym=NULL; typedef struct _as_drivers { t_symbol*name; int id; struct _as_drivers *next; } t_as_drivers; typedef struct _as_params { int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; int rate, advance, callback; int blocksize; } t_as_params; t_as_drivers*as_finddriver(t_as_drivers*drivers, const t_symbol*name) { while(drivers) { if(name==drivers->name)return drivers; drivers=drivers->next; } return NULL; } t_as_drivers*as_finddriverid(t_as_drivers*drivers, const int id) { while(drivers) { if(id==drivers->id)return drivers; drivers=drivers->next; } return NULL; } t_as_drivers*as_adddriver(t_as_drivers*drivers, t_symbol*name, int id, int overwrite) { t_as_drivers*driver=as_finddriver(drivers, name); if(driver) { if(overwrite) { driver->name=name; driver->id =id; } return drivers; } driver=(t_as_drivers*)getbytes(sizeof(t_as_drivers)); driver->name=name; driver->id=id; driver->next=drivers; return driver; } t_as_drivers*as_driverparse(t_as_drivers*drivers, const char*buf) { int start=-1; int stop =-1; unsigned int index=0; int depth=0; const char*s; char substring[MAXPDSTRING]; for(index=0, s=buf; 0!=*s; s++, index++) { if('{'==*s) { start=index; depth++; } if('}'==*s) { depth--; stop=index; if(start>=0 && start=MAXPDSTRING)length=MAXPDSTRING-1; snprintf(substring, length, "%s", buf+start+1); if(common_parsedriver(substring, length, drivername, MAXPDSTRING, &driverid)) { drivers=as_adddriver(drivers, gensym(drivername), driverid, 0); } else { if((start+1)!=(stop)) post("unparseable: '%s' (%d-%d)", substring, start, stop); } } start=-1; stop=-1; } } return drivers; } static t_as_drivers*DRIVERS=NULL; static t_symbol*as_getdrivername(const int id) { t_as_drivers*driver=as_finddriverid(DRIVERS, id); if(driver) { return driver->name; } else { return gensym(""); } } static int as_getdriverid(const t_symbol*id) { t_as_drivers*driver=as_finddriver(DRIVERS, id); if(driver) { return driver->id; } return -1; /* unknown */ } static void as_params_print(t_as_params*parms) { int i=0; post("\n=================================<"); post("indevs: %d", parms->naudioindev); for(i=0; iaudioindev[i], parms->chindev[i]); } post("outdevs: %d", parms->naudiooutdev); for(i=0; iaudiooutdev[i], parms->choutdev[i]); } post("rate=%d", parms->rate); post("advance=%d", parms->advance); post("callback=%d", parms->callback); post(">=================================\n"); } static void as_params_get(t_as_params*parms) { int i=0; memset(parms, 0, sizeof(t_as_params)); parms->callback=-1; as_get_audio_params( &parms->naudioindev, parms->audioindev, parms->chindev, &parms->naudiooutdev, parms->audiooutdev, parms->choutdev, &parms->rate, &parms->advance, &parms->callback, &parms->blocksize); for(i=parms->naudioindev; iaudioindev[i]=0; parms->chindev[i]=0; } for(i=parms->naudiooutdev; iaudiooutdev[i]=0; parms->choutdev[i]=0; } // as_params_print(parms); } typedef struct _audiosettings { t_object x_obj; t_outlet*x_info; t_as_params x_params; } t_audiosettings; static void audiosettings_listparams(t_audiosettings *x); static void audiosettings_listdevices(t_audiosettings *x) { int i; char indevlist[MAXNDEV][DEVDESCSIZE], outdevlist[MAXNDEV][DEVDESCSIZE]; int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0; t_atom atoms[3]; sys_get_audio_devs((char*)indevlist, &indevs, (char*)outdevlist, &outdevs, &canmulti, &cancallback, MAXNDEV, DEVDESCSIZE); SETSYMBOL (atoms+0, gensym("driver")); SETSYMBOL (atoms+1, as_getdrivername(sys_audioapi)); outlet_anything(x->x_info, gensym("device"), 2, atoms); SETSYMBOL (atoms+0, gensym("multi")); SETFLOAT (atoms+1, (t_float)canmulti); outlet_anything(x->x_info, gensym("device"), 2, atoms); SETSYMBOL (atoms+0, gensym("callback")); SETFLOAT (atoms+1, (t_float)cancallback); outlet_anything(x->x_info, gensym("device"), 2, atoms); SETSYMBOL(atoms+0, gensym("in")); SETSYMBOL(atoms+1, gensym("devices")); SETFLOAT (atoms+2, (t_float)indevs); outlet_anything(x->x_info, gensym("device"), 3, atoms); for(i=0; ix_info, gensym("device"), 3, atoms); } SETSYMBOL(atoms+0, gensym("out")); SETSYMBOL(atoms+1, gensym("devices")); SETFLOAT (atoms+2, (t_float)outdevs); outlet_anything(x->x_info, gensym("device"), 3, atoms); for(i=0; ix_info, gensym("device"), 3, atoms); } } /* this is the actual settings used * */ static void audiosettings_listparams(t_audiosettings *x) { int i; t_atom atoms[4]; t_as_params params; as_params_get(¶ms); SETSYMBOL (atoms+0, gensym("rate")); SETFLOAT (atoms+1, (t_float)params.rate); outlet_anything(x->x_info, gensym("params"), 2, atoms); SETSYMBOL (atoms+0, gensym("advance")); SETFLOAT (atoms+1, (t_float)params.advance); outlet_anything(x->x_info, gensym("params"), 2, atoms); SETSYMBOL (atoms+0, gensym("callback")); SETFLOAT (atoms+1, (t_float)params.callback); outlet_anything(x->x_info, gensym("params"), 2, atoms); SETSYMBOL(atoms+0, gensym("in")); SETSYMBOL(atoms+1, gensym("devices")); SETFLOAT (atoms+2, (t_float)params.naudioindev); outlet_anything(x->x_info, gensym("params"), 3, atoms); for(i=0; ix_info, gensym("params"), 3, atoms); } SETSYMBOL(atoms+0, gensym("out")); SETSYMBOL(atoms+1, gensym("devices")); SETFLOAT (atoms+2, (t_float)params.naudiooutdev); outlet_anything(x->x_info, gensym("params"), 3, atoms); for(i=0; ix_info, gensym("params"), 3, atoms); } } static void audiosettings_params_init(t_audiosettings*x) { as_params_get(&x->x_params); } static void audiosettings_params_apply(t_audiosettings*x) { /* "pd audio-dialog ..." #00: indev[0] #01: indev[1] #02: indev[2] #03: indev[3] #04: inchan[0] #05: inchan[1] #06: inchan[2] #07: inchan[3] #08: outdev[0] #09: outdev[1] #10: outdev[2] #11: outdev[3] #12: outchan[0] #13: outchan[1] #14: outchan[2] #15: outchan[3] #16: rate #17: advance #18: callback */ t_atom argv [2*MAXAUDIOINDEV+2*MAXAUDIOOUTDEV+3]; int argc=2*MAXAUDIOINDEV+2*MAXAUDIOOUTDEV+3; int i=0; // as_params_print(&x->x_params); for(i=0; ix_params.audioindev[i])); SETFLOAT(argv+i+1*MAXAUDIOINDEV, (t_float)(x->x_params.chindev [i])); } for(i=0; ix_params.audiooutdev[i])); SETFLOAT(argv+i+2*MAXAUDIOINDEV+1*MAXAUDIOOUTDEV,(t_float)(x->x_params.choutdev [i])); } SETFLOAT(argv+2*MAXAUDIOINDEV+2*MAXAUDIOOUTDEV+0,(t_float)(x->x_params.rate)); SETFLOAT(argv+2*MAXAUDIOINDEV+2*MAXAUDIOOUTDEV+1,(t_float)(x->x_params.advance)); SETFLOAT(argv+2*MAXAUDIOINDEV+2*MAXAUDIOOUTDEV+2,(t_float)(x->x_params.callback)); if (s_pdsym->s_thing) typedmess(s_pdsym->s_thing, gensym("audio-dialog"), argc, argv); } /* find the beginning of the next parameter in the list */ typedef enum { PARAM_RATE, PARAM_ADVANCE, PARAM_CALLBACK, PARAM_INPUT, PARAM_OUTPUT, PARAM_INVALID } t_paramtype; static t_paramtype audiosettings_setparams_id(t_symbol*s) { if(gensym("@rate")==s) { return PARAM_RATE; } else if(gensym("@samplerate")==s) { return PARAM_RATE; } else if(gensym("@advance")==s) { return PARAM_ADVANCE; } else if(gensym("@buffersize")==s) { return PARAM_ADVANCE; } else if(gensym("@callback")==s) { return PARAM_CALLBACK; } else if(gensym("@input")==s) { return PARAM_INPUT; } else if(gensym("@output")==s) { return PARAM_OUTPUT; } return PARAM_INVALID; } /* find the beginning of the next parameter in the list */ static int audiosettings_setparams_next(int argc, t_atom*argv) { int i=0; for(i=0; is_name[0]) return i; } } return i; } /* ... */ static int audiosettings_setparams_rate(t_audiosettings*x, int argc, t_atom*argv) { if(argc<=0)return 1; t_int rate=atom_getint(argv); if(rate>0) x->x_params.rate=rate; return 1; } /* ... */ static int audiosettings_setparams_advance(t_audiosettings*x, int argc, t_atom*argv) { if(argc<=0)return 1; t_int advance=atom_getint(argv); if(advance>0) x->x_params.advance=advance; return 1; } /* ... */ static int audiosettings_setparams_callback(t_audiosettings*x, int argc, t_atom*argv) { if(argc<=0)return 1; t_int callback=atom_getint(argv); x->x_params.callback=callback; return 1; } /* [ ]* ... */ static int audiosettings_setparams_input(t_audiosettings*x, int argc, t_atom*argv) { int length=audiosettings_setparams_next(argc, argv); int i; int numpairs=length/2; if(length%2)return length; if(numpairs>MAXAUDIOINDEV) numpairs=MAXAUDIOINDEV; for(i=0; ix_params.audioindev[i]=dev; x->x_params.chindev[i]=ch; } return length; } static int audiosettings_setparams_output(t_audiosettings*x, int argc, t_atom*argv) { int length=audiosettings_setparams_next(argc, argv); int i; int numpairs=length/2; if(length%2)return length; if(numpairs>MAXAUDIOOUTDEV) numpairs=MAXAUDIOOUTDEV; for(i=0; ix_params.audiooutdev[i]=dev; x->x_params.choutdev[i]=ch; } return length; } static void audiosettings_setparams(t_audiosettings *x, t_symbol*s, int argc, t_atom*argv) { /* PLAN: several messages that accumulate to a certain settings, and then "apply" them */ int apply=1; int advance=0; t_paramtype param=PARAM_INVALID; audiosettings_params_init (x); /* re-initialize to what we got */ advance=audiosettings_setparams_next(argc, argv); while((argc-=advance)>0) { argv+=advance; s=atom_getsymbol(argv); param=audiosettings_setparams_id(s); argv++; argc--; switch(param) { case PARAM_RATE: advance=audiosettings_setparams_rate(x, argc, argv); break; case PARAM_ADVANCE: advance=audiosettings_setparams_advance(x, argc, argv); break; case PARAM_CALLBACK: advance=audiosettings_setparams_callback(x, argc, argv); break; case PARAM_INPUT: advance=audiosettings_setparams_input(x, argc, argv); break; case PARAM_OUTPUT: advance=audiosettings_setparams_output(x, argc, argv); break; default: pd_error(x, "unknown parameter"); postatom(1, argv);endpost(); break; } argc-=advance; argv+=advance; advance=audiosettings_setparams_next(argc, argv); } if(apply) { audiosettings_params_apply(x); } } static void audiosettings_testdevices(t_audiosettings *x); /* */ static void audiosettings_listdrivers(t_audiosettings *x) { t_as_drivers*driver=NULL; t_atom ap[2]; for(driver=DRIVERS; driver; driver=driver->next) { SETSYMBOL(ap+0, driver->name); SETFLOAT (ap+1, (t_float)(driver->id)); outlet_anything(x->x_info, gensym("driver"), 2, ap); } } static void audiosettings_setdriver(t_audiosettings *x, t_symbol*s, int argc, t_atom*argv) { int id=-1; s=gensym(""); /* just re-use the argument, which is not needed anyhow */ switch(argc) { case 0: audiosettings_listdrivers(x); return; case 1: if(A_FLOAT==argv->a_type) { s=as_getdrivername(atom_getint(argv)); break; } else if (A_SYMBOL==argv->a_type) { s=atom_getsymbol(argv); break; } } id=as_getdriverid(s); if(id<0) { pd_error(x, "invalid driver '%s'", s->s_name); return; } verbose(1, "setting driver '%s' (=%d)", s->s_name, id); #ifdef HAVE_SYS_CLOSE_AUDIO sys_close_audio(); sys_set_audio_api(id); sys_reopen_audio(); #else if (s_pdsym->s_thing) { t_atom ap[1]; SETFLOAT(ap, id); typedmess(s_pdsym->s_thing, gensym("audio-setapi"), 1, ap); } #endif } static void audiosettings_bang(t_audiosettings *x) { audiosettings_listdrivers(x); audiosettings_listdevices(x); audiosettings_listparams(x); } static void audiosettings_free(t_audiosettings *x){ } static void *audiosettings_new(void) { t_audiosettings *x = (t_audiosettings *)pd_new(audiosettings_class); x->x_info=outlet_new(&x->x_obj, 0); char buf[MAXPDSTRING]; sys_get_audio_apis(buf); DRIVERS=as_driverparse(DRIVERS, buf); audiosettings_params_init (x); return (x); } void audiosettings_setup(void) { s_pdsym=gensym("pd"); mediasettings_boilerplate("[audiosettings] audio settings manager", #ifdef AUDIOSETTINGS_VERSION AUDIOSETTINGS_VERSION #else 0 #endif ); #if (defined PD_MINOR_VERSION) && (PD_MINOR_VERSION < 43) if(1) { int major, minor, bugfix; sys_getversion(&major, &minor, &bugfix); if(0==major && minor>=43) { error("[audiosettings] have been compiled against an old version of Pd"); error(" that is incompatible with the one you are using!"); error(" recompile [audiosettings]"); } return; } #endif audiosettings_class = class_new(gensym("audiosettings"), (t_newmethod)audiosettings_new, (t_method)audiosettings_free, sizeof(t_audiosettings), 0, 0); class_addbang(audiosettings_class, (t_method)audiosettings_bang); class_addmethod(audiosettings_class, (t_method)audiosettings_listdrivers, gensym("listdrivers"), A_NULL); class_addmethod(audiosettings_class, (t_method)audiosettings_listdevices, gensym("listdevices"), A_NULL); class_addmethod(audiosettings_class, (t_method)audiosettings_listparams, gensym("listparams"), A_NULL); class_addmethod(audiosettings_class, (t_method)audiosettings_setdriver, gensym("driver"), A_GIMME, A_NULL); class_addmethod(audiosettings_class, (t_method)audiosettings_setparams, gensym("params"), A_GIMME, A_NULL); class_addmethod(audiosettings_class, (t_method)audiosettings_testdevices, gensym("testdevices"), A_NULL); } static void audiosettings_testdevices(t_audiosettings *x) { int i; char indevlist[MAXNDEV][DEVDESCSIZE], outdevlist[MAXNDEV][DEVDESCSIZE]; int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0; if(0) { pd_error(x, "this should never happen"); } sys_get_audio_devs((char*)indevlist, &indevs, (char*)outdevlist, &outdevs, &canmulti, &cancallback, MAXNDEV, DEVDESCSIZE); post("%d indevs", indevs); for(i=0; i #include #include #define MAXNDEV 20 #define DEVDESCSIZE 80 #ifndef BUILD_DATE # define BUILD_DATE "on " __DATE__ " at " __TIME__ #endif /** * find EOS of a string of tokens * where EOS might be indicated by \0, } */ unsigned int findEOT(const char*s, unsigned int length) { unsigned int len=0; do { char c=s[len]; len++; switch(c) { case '{': len+=findEOT(s+len, length-len); break; case '}': if('{'!=s[0]) return len; else return len-1; case '\0': return len; } } while(len=0) stop--; start=stop; while(start>=0) { char c=str[start]; if(c<48 || c>=57) break; start--; } if(start==stop || start<0) return ret; stop1=start; while(stop1>=0) { char c=str[stop1]; if(!isspace(c)) break; stop1--; } if(stop1<0) return ret; if(( str[start1]=='"' && str[stop1]=='"') || (str[start1]=='\'' && str[stop1]=='\'') || (str[start1]=='{' && str[stop1]=='}') ) { start1++; stop1--; } stop1+=2; if(stop1>=length)stop1=length-1; snprintf(name, stop1-start1, "%s", str+start1); ret=(1==sscanf(str+start, "%d", id)); return ret; } static void mediasettings_boilerplate(const char*name, const char*version) { post("%s%c%s", name, (version?' ':'\0'), version); verbose(0," compiled "BUILD_DATE""); verbose(0," Copyright © 2010-2016 IOhannes m zmölnig"); verbose(0," for the IntegraLive project"); verbose(0," institute of electronic music and acoustics (iem), KUG, Graz"); verbose(0," published under the GNU General Public License version 3 or later"); } mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/midisettings-help.pd000066400000000000000000000043221265075004600260720ustar00rootroot00000000000000#N canvas 643 220 611 530 10; #X obj 17 252 midisettings; #X msg 98 78 listdrivers; #X msg 100 107 listdevices; #X text 181 106 get available devices for current driver; #X text 179 76 get available MIDI drivers; #X text 28 20 midisettings - query and manipulate MIDI settings; #X msg 112 147 driver default-MIDI; #X msg 113 168 driver ALSA-MIDI; #X text 239 157 select one of the available MIDI drivers; #X msg 113 215 device @in ALSA-00 ALSA-01 @out ALSA-00; #X obj 272 297 route device devicelist; #X obj 17 323 route driver driverlist; #X obj 17 345 symbol; #X symbolatom 17 397 0 0 0 3 current - -; #X obj 84 345 route float; #X floatatom 84 366 5 0 0 0 - - -; #X obj 147 365 print MIDI-drivers; #X obj 272 321 route in out; #X obj 272 373 print MIDI-IN; #X obj 282 353 print MIDI-OUT; #X obj 339 404 route in out; #X obj 339 426 route float; #X floatatom 339 448 5 0 0 0 numINs - -; #X obj 392 447 print MIDI-indevices; #X obj 343 473 route float; #X floatatom 343 495 5 0 0 0 numOUTs - -; #X obj 396 494 print MIDI-outdevices; #X msg 17 47 bang; #X text 58 46 query current settings; #X obj 442 297 print oops; #X obj 17 274 t a a; #X obj 90 275 spigot; #X obj 90 297 print MIDI; #X obj 139 277 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 143 195 device @in UM-1 @out none; #X obj 467 211 r pd; #X obj 467 233 route midi-dialog; #X obj 467 255 print MD; #X obj 400 70 list prepend midi-dialog; #X obj 400 92 list trim; #X obj 400 114 s pd; #X msg 400 48 0 0 0 0 0 0 0 0 2 2; #X connect 0 0 30 0; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 6 0 0 0; #X connect 7 0 0 0; #X connect 9 0 0 0; #X connect 10 0 17 0; #X connect 10 1 20 0; #X connect 10 2 29 0; #X connect 11 0 12 0; #X connect 11 1 14 0; #X connect 11 2 10 0; #X connect 12 0 13 0; #X connect 14 0 15 0; #X connect 14 1 16 0; #X connect 17 0 18 0; #X connect 17 1 19 0; #X connect 20 0 21 0; #X connect 20 1 24 0; #X connect 20 2 29 0; #X connect 21 0 22 0; #X connect 21 1 23 0; #X connect 24 0 25 0; #X connect 24 1 26 0; #X connect 27 0 0 0; #X connect 30 0 11 0; #X connect 30 1 31 0; #X connect 31 0 32 0; #X connect 33 0 31 1; #X connect 34 0 0 0; #X connect 35 0 36 0; #X connect 36 0 37 0; #X connect 38 0 39 0; #X connect 39 0 40 0; #X connect 41 0 38 0; mediasettings-v0.1.1-5567ea1735b5024ef615df04b23f21e4a38a74ee/midisettings.c000066400000000000000000000463231265075004600247720ustar00rootroot00000000000000/****************************************************** * * midisettings - get/set midi preferences from within Pd-patches * Copyright (C) 2010-2012 IOhannes m zmölnig * * forum::für::umläute * * institute of electronic music and acoustics (iem) * university of music and dramatic arts, graz (kug) * * ****************************************************** * * license: GNU General Public License v.3 or later * ******************************************************/ #include "mediasettings.h" #if (!defined MIDISETTINGS_VERSION) && (defined VERSION) # define MIDISETTINGS_VERSION VERSION #endif #ifndef MAXMIDIINDEV # define MAXMIDIINDEV 4 #endif #ifndef MAXMIDIOUTDEV # define MAXMIDIOUTDEV 4 #endif #if MAXMIDIINDEV > MAXMIDIOUTDEV # define MAXMIDIDEV MAXMIDIINDEV #else # define MAXMIDIDEV MAXMIDIOUTDEV #endif extern int sys_midiapi; static t_class *midisettings_class; static t_symbol*s_pdsym=NULL; typedef struct _ms_symkeys { t_symbol*name; int id; struct _ms_symkeys *next; } t_ms_symkeys; typedef t_ms_symkeys t_ms_drivers ; static void ms_symkeys_print(t_ms_symkeys*symkeys) { while(symkeys) { post("symkey[%s]=%d", (symkeys->name)?symkeys->name->s_name:"", symkeys->id); symkeys=symkeys->next; } } static const char*ms_defaultdrivername(const int id) { switch (id) { case API_NONE: return NULL; case API_ALSA: return "ALSA-MIDI"; default: return "default-MIDI"; /* such a stupid name! */ } return NULL; } static t_ms_symkeys*ms_symkeys_find(t_ms_symkeys*symkeys, const t_symbol*name) { while(symkeys) { if(name==symkeys->name)return symkeys; symkeys=symkeys->next; } return NULL; } static t_ms_symkeys*ms_symkeys_findid(t_ms_symkeys*symkeys, const int id) { while(symkeys) { if(id==symkeys->id)return symkeys; symkeys=symkeys->next; } return NULL; } static t_ms_symkeys*ms_symkeys_add(t_ms_symkeys*symkeys, t_symbol*name, int id, int overwrite) { t_ms_symkeys*symkey=ms_symkeys_find(symkeys, name); if(symkey) { char buf[MAXPDSTRING+1]; buf[MAXPDSTRING]=0; if(!overwrite) return symkeys; #warning LATER check how to deal with multiple devices of the same name! // now this is a simple hack snprintf(buf, MAXPDSTRING, "%s[%d]", name->s_name, id); return ms_symkeys_add(symkeys, gensym(buf), id, overwrite); } symkey=(t_ms_symkeys*)getbytes(sizeof(t_ms_symkeys)); symkey->name=name; symkey->id=id; symkey->next=symkeys; return symkey; } static void ms_symkeys_clear(t_ms_symkeys*symkeys) { t_ms_symkeys*symkey=symkeys; while(symkey) { t_ms_symkeys*next=symkey->next; symkey->name=NULL; symkey->id=0; symkey->next=NULL; freebytes(symkey, sizeof(t_ms_symkeys)); symkey=next; } } static t_symbol*ms_symkeys_getname(t_ms_symkeys*symkeys, const int id) { t_ms_symkeys*driver=ms_symkeys_findid(symkeys, id); if(driver) return driver->name; return NULL; } static int ms_symkeys_getid(t_ms_symkeys*symkeys, const t_symbol*name) { t_ms_symkeys*symkey=ms_symkeys_find(symkeys, name); if(symkey) { return symkey->id; } return -1; /* unknown */ } t_ms_symkeys*ms_driverparse(t_ms_symkeys*drivers, const char*buf) { int start=-1; int stop =-1; unsigned int index=0; int depth=0; const char*s; char substring[MAXPDSTRING]; for(index=0, s=buf; 0!=*s; s++, index++) { if('{'==*s) { start=index; depth++; } if('}'==*s) { depth--; stop=index; if(start>=0 && start=MAXPDSTRING)length=MAXPDSTRING-1; snprintf(substring, length, "%s", buf+start+1); if(common_parsedriver(substring, length, drivername, MAXPDSTRING, &driverid)) { drivers=ms_symkeys_add(drivers, gensym(drivername), driverid, 0); } else { if((start+1)!=(stop)) /* empty APIs string */ post("unparseable: '%s'", substring); } } start=-1; stop=-1; } } return drivers; } static t_ms_symkeys*DRIVERS=NULL; static t_symbol*ms_getdrivername(const int id) { t_symbol*s=ms_symkeys_getname(DRIVERS, id); if(s) return s; else { const char*name=ms_defaultdrivername(id); if(name) return gensym(name); } return gensym(""); } static int ms_getdriverid(const t_symbol*id) { return ms_symkeys_getid(DRIVERS, id); } typedef struct _ms_params { int indev[MAXMIDIINDEV], outdev[MAXMIDIOUTDEV]; unsigned int num_indev, num_outdev; t_ms_symkeys*indevices, *outdevices; unsigned int num_indevices, num_outdevices; } t_ms_params; static void ms_params_print(t_ms_params*parms) { int i=0; #if 0 const int maxin =MAXMIDIINDEV; const int maxout=MAXMIDIOUTDEV; #else const int maxin =parms->num_indev; const int maxout=parms->num_outdev; #endif post("\n=================================<"); if(API_ALSA == sys_midiapi) { post("alsamidi: %d %d", parms->num_indev, parms->num_outdev); } else { for(i=0; iindev[i]); } for(i=0; ioutdev[i]); } } post(">=================================\n"); } static t_ms_symkeys*ms_params_adddevices(t_ms_symkeys*keys, unsigned int*number, char devlist[MAXNDEV][DEVDESCSIZE], unsigned int numdevs) { unsigned int num=0; if(number)num=*number; unsigned int i; for(i=0; iindevices); ms_symkeys_clear(parms->outdevices); memset(parms, 0, sizeof(t_ms_params)); sys_get_midi_devs((char*)indevlist, &indevs, (char*)outdevlist, &outdevs, MAXNDEV, DEVDESCSIZE); parms->num_indevices=0; parms->indevices=ms_params_adddevices(parms->indevices, &parms->num_indevices, indevlist, indevs); parms->num_outdevices=0; parms->outdevices=ms_params_adddevices(parms->outdevices, &parms->num_outdevices, outdevlist, outdevs); sys_get_midi_params(&indevs , parms->indev, &outdevs, parms->outdev); parms->num_indev =(indevs >0)?indevs:0; parms->num_outdev=(outdevs>0)?outdevs:0; // ms_params_print(parms); } typedef struct _midisettings { t_object x_obj; t_outlet*x_info; t_ms_params x_params; } t_midisettings; static void midisettings_params_init(t_midisettings*x) { int i=0; for(i=0; ix_params.indev [i]=0; for(i=0; ix_params.outdev[i]=0; x->x_params.num_indev = x->x_params.num_outdev = 0; ms_params_get(&x->x_params); } static void midisettings_debug(t_midisettings*x) { post("IN-DEVS");ms_symkeys_print(x->x_params.indevices); post("OUTDEVS");ms_symkeys_print(x->x_params.outdevices); } #define MS_ALSADEV_FORMAT "ALSA-%02d" static void midisettings_listdevices_devices(t_outlet *outlet, t_symbol*type, t_ms_symkeys*devices, const unsigned int numdevs ) { unsigned int count=0, i=0; t_atom atoms[MAXMIDIDEV+1]; SETSYMBOL(atoms+0, type); for(i=0; is_name; } } if(devname) { SETSYMBOL(atoms+count+1, gensym(devname)); count++; } } outlet_anything(outlet, gensym("device"), count+1, atoms); } static void midisettings_listdevices_devicelist(t_outlet *outlet, t_symbol*type, t_ms_symkeys*devices, const unsigned int numdevs, const unsigned int maxdevs ) { unsigned int i=0; t_atom atoms[MAXMIDIDEV+1]; SETSYMBOL(atoms+0, type); if(API_ALSA == sys_midiapi) { char dummy[MAXPDSTRING]; unsigned int iodevs=maxdevs; SETFLOAT (atoms+1, iodevs); outlet_anything(outlet, gensym("devicelist"), 2, atoms); for(i=0; inext) { if(NULL==devices->name) continue; SETSYMBOL(atoms+1, devices->name); SETFLOAT (atoms+2, (t_float)(devices->id)); outlet_anything(outlet, gensym("devicelist"), 3, atoms); } } } static void midisettings_listdevices(t_midisettings *x) { midisettings_listdevices_devices(x->x_info, gensym("in"), x->x_params.indevices, x->x_params.num_indev); midisettings_listdevices_devices(x->x_info, gensym("out"), x->x_params.outdevices, x->x_params.num_outdev); midisettings_listdevices_devicelist(x->x_info, gensym("in"), x->x_params.indevices, x->x_params.num_indevices, MAXMIDIINDEV); midisettings_listdevices_devicelist(x->x_info, gensym("out"), x->x_params.outdevices, x->x_params.num_outdevices, MAXMIDIOUTDEV); } static void midisettings_params_apply(t_midisettings*x) { /* "pd midi-dialog ..." #00: indev[0] #01: indev[1] #02: indev[2] #03: indev[3] #04: outdev[0] #05: outdev[1] #06: outdev[2] #07: outdev[3] #08: alsadevin #09: alsadevout */ #if 0 # define MIDIDIALOG_INDEVS MAXMIDIINDEV # define MIDIDIALOG_OUTDEVS MAXMIDIOUTDEV #else # define MIDIDIALOG_INDEVS 4 # define MIDIDIALOG_OUTDEVS 4 #endif int alsamidi=(API_ALSA==sys_midiapi); t_atom argv [MIDIDIALOG_INDEVS+MIDIDIALOG_OUTDEVS+2]; unsigned int argc= MIDIDIALOG_INDEVS+MIDIDIALOG_OUTDEVS+2; unsigned int i=0; ms_params_print(&x->x_params); for(i=0; ix_params.num_indev ); SETFLOAT(argv+1*MIDIDIALOG_INDEVS+1*MIDIDIALOG_OUTDEVS+1,(t_float)x->x_params.num_outdev); } else { unsigned int pos=0; for(i=0; ix_params.num_indev; i++) { pos=i+0*MIDIDIALOG_INDEVS; SETFLOAT(argv+pos, (t_float)x->x_params.indev[i]); } for(i=0; ix_params.num_indev; i++) { pos=i+1*MIDIDIALOG_INDEVS; SETFLOAT(argv+pos, (t_float)x->x_params.outdev[i]); } pos=MIDIDIALOG_INDEVS+MIDIDIALOG_OUTDEVS; SETFLOAT(argv+1*MIDIDIALOG_INDEVS+1*MIDIDIALOG_OUTDEVS+0,(t_float)x->x_params.num_indev ); SETFLOAT(argv+1*MIDIDIALOG_INDEVS+1*MIDIDIALOG_OUTDEVS+1,(t_float)x->x_params.num_outdev); } if (s_pdsym->s_thing) typedmess(s_pdsym->s_thing, gensym("midi-dialog"), argc, argv); } /* find the beginning of the next parameter in the list */ typedef enum { PARAM_INPUT, PARAM_OUTPUT, PARAM_INVALID } t_paramtype; static t_paramtype midisettings_setparams_id(t_symbol*s) { if(gensym("@input")==s) { return PARAM_INPUT; } else if(gensym("@output")==s) { return PARAM_OUTPUT; } else if(gensym("@in")==s) { return PARAM_INPUT; } else if(gensym("@out")==s) { return PARAM_OUTPUT; } return PARAM_INVALID; } /* find the beginning of the next parameter in the list */ static int midisettings_setparams_next(int argc, t_atom*argv) { int i=0; for(i=0; is_name[0]) return i; } } return i; } /* [ []*] ... */ static int midisettings_setparams_inout( int argc, t_atom*argv, t_ms_symkeys*devices, int*devicelist, unsigned int*numdevices, const unsigned int maxnumdevices ) { const unsigned int length=midisettings_setparams_next(argc, argv); unsigned int len=length; unsigned int i; if(len>maxnumdevices) len=maxnumdevices; *numdevices = len; for(i=0; ix_params.indevices, x->x_params.indev, &x->x_params.num_indev, MAXMIDIINDEV); return advance; } static int midisettings_setparams_output(t_midisettings*x, int argc, t_atom*argv) { return midisettings_setparams_inout(argc, argv, x->x_params.outdevices, x->x_params.outdev, &x->x_params.num_outdev, MAXMIDIOUTDEV); } static void midisettings_setparams(t_midisettings *x, t_symbol*s, int argc, t_atom*argv) { /* * PLAN: * several messages that accumulate to a certain settings, and then "apply" them * * normal midi: list up to four devices (each direction) * alsa midi: choose number of ports (each direction) */ int apply=1; int advance=0; t_paramtype param=PARAM_INVALID; enum { INPUT, OUTPUT, PARAM } type; type=PARAM; if(!argc) { midisettings_listdevices(x); return; } if(A_SYMBOL == argv->a_type ) { t_symbol*tsym=atom_getsymbol(argv); if(gensym("in")==tsym) type=INPUT; else if(gensym("out")==tsym) type=OUTPUT; if(PARAM!=type) { argc--; argv++; } } midisettings_params_init (x); /* re-initialize to what we got */ switch(type) { case INPUT: midisettings_setparams_input(x, argc, argv); break; case OUTPUT: midisettings_setparams_output(x, argc, argv); break; case PARAM: advance=midisettings_setparams_next(argc, argv); while((argc-=advance)>0) { argv+=advance; s=atom_getsymbol(argv); param=midisettings_setparams_id(s); argv++; argc--; switch(param) { case PARAM_INPUT: advance=midisettings_setparams_input(x, argc, argv); break; case PARAM_OUTPUT: advance=midisettings_setparams_output(x, argc, argv); break; default: pd_error(x, "unknown parameter %d:", param); postatom(1, argv);endpost(); break; } argc-=advance; argv+=advance; advance=midisettings_setparams_next(argc, argv); } break; } if(apply) { midisettings_params_apply (x); /* re-initialize to what we got */ } } static void midisettings_listdrivers(t_midisettings *x); static void midisettings_setdriver(t_midisettings *x, t_symbol*s, int argc, t_atom*argv) { int id=-1; s=gensym(""); /* just re-use the argument, which is not needed anyhow */ switch(argc) { case 0: midisettings_listdrivers(x); return; case 1: if(A_FLOAT==argv->a_type) { s=ms_getdrivername(atom_getint(argv)); break; } else if (A_SYMBOL==argv->a_type) { s=atom_getsymbol(argv); break; } } if(NULL==DRIVERS) { id=sys_midiapi; } else { id=ms_getdriverid(s); if(id<0) { pd_error(x, "invalid driver '%s'", s->s_name); return; } verbose(1, "setting driver '%s' (=%d)", s->s_name, id); } #ifdef HAVE_SYS_CLOSE_MIDI sys_close_midi(); sys_set_midi_api(id); sys_reopen_midi(); #else if (s_pdsym->s_thing) { t_atom ap[1]; SETFLOAT(ap, id); typedmess(s_pdsym->s_thing, gensym("midi-setapi"), 1, ap); } #endif } /* */ static void midisettings_listdrivers(t_midisettings *x) { t_ms_drivers*driver=NULL; t_atom ap[2]; size_t count=0; SETSYMBOL(ap+0, ms_getdrivername(sys_midiapi)); outlet_anything(x->x_info, gensym("driver"), 1, ap); for(driver=DRIVERS; driver; driver=driver->next) { count++; } SETFLOAT(ap+0, count); outlet_anything(x->x_info, gensym("driverlist"), 1, ap); for(driver=DRIVERS; driver; driver=driver->next) { SETSYMBOL(ap+0, driver->name); SETFLOAT (ap+1, (t_float)(driver->id)); outlet_anything(x->x_info, gensym("driverlist"), 2, ap); } } static void midisettings_bang(t_midisettings *x) { midisettings_listdrivers(x); midisettings_listdevices(x); } static void midisettings_free(t_midisettings *x){ #warning cleanup } static void *midisettings_new(void) { t_midisettings *x = (t_midisettings *)pd_new(midisettings_class); x->x_info=outlet_new(&x->x_obj, 0); x->x_params.indevices=NULL; x->x_params.outdevices=NULL; char buf[MAXPDSTRING]; sys_get_midi_apis(buf); DRIVERS=ms_driverparse(DRIVERS, buf); midisettings_params_init (x); /* re-initialize to what we got */ return (x); } static void midisettings_testdevices(t_midisettings *x); void midisettings_setup(void) { s_pdsym=gensym("pd"); mediasettings_boilerplate("[midisettings] midi settings manager", #ifdef MIDISETTINGS_VERSION MIDISETTINGS_VERSION #else 0 #endif ); midisettings_class = class_new(gensym("midisettings"), (t_newmethod)midisettings_new, (t_method)midisettings_free, sizeof(t_midisettings), 0, 0); class_addbang(midisettings_class, (t_method)midisettings_bang); class_addmethod(midisettings_class, (t_method)midisettings_listdrivers, gensym("listdrivers"), A_NULL); class_addmethod(midisettings_class, (t_method)midisettings_listdevices, gensym("listdevices"), A_NULL); class_addmethod(midisettings_class, (t_method)midisettings_setdriver, gensym("driver"), A_GIMME, A_NULL); class_addmethod(midisettings_class, (t_method)midisettings_setparams, gensym("device"), A_GIMME, A_NULL); class_addmethod(midisettings_class, (t_method)midisettings_debug, gensym("print"), A_NULL); } static void midisettings_testdevices(t_midisettings *x) { int i; char indevlist[MAXNDEV][DEVDESCSIZE], outdevlist[MAXNDEV][DEVDESCSIZE]; int indevs = 0, outdevs = 0; sys_get_midi_devs((char*)indevlist, &indevs, (char*)outdevlist, &outdevs, MAXNDEV, DEVDESCSIZE); post("%d midi indevs", indevs); for(i=0; i