From ceac394c2133d44e81db2eb633ff54a9ad6ce7c5 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 10 Nov 2005 05:52:11 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r3865, which included commits to RCS files with non-trunk default branches. svn path=/trunk/extensions/gripd/; revision=3866 --- src/Makefile.Linux | 48 + src/Makefile.NT | 86 ++ src/Makefile.midiioLibrary.ALSA | 205 +++++ src/Makefile.midiioLibrary.NT | 462 ++++++++++ src/Makefile.midiioLibrary.OSS | 205 +++++ src/gripd.c | 1031 +++++++++++++++++++++ src/gripd.h | 227 +++++ src/joystick.c | 296 ++++++ src/joystick_wrap.c | 692 ++++++++++++++ src/makefile | 44 + src/midi.cpp | 146 +++ src/midi_wrap.c | 723 +++++++++++++++ src/midiio/include/Array.cpp | 378 ++++++++ src/midiio/include/Array.h | 67 ++ src/midiio/include/CircularBuffer.cpp | 291 ++++++ src/midiio/include/CircularBuffer.h | 66 ++ src/midiio/include/Collection.cpp | 355 ++++++++ src/midiio/include/Collection.h | 70 ++ src/midiio/include/FileIO.h | 148 +++ src/midiio/include/MidiFile.h | 108 +++ src/midiio/include/MidiFileWrite.h | 61 ++ src/midiio/include/MidiIO.h | 58 ++ src/midiio/include/MidiInPort.h | 98 ++ src/midiio/include/MidiInPort_alsa.h | 107 +++ src/midiio/include/MidiInPort_alsa05.h | 107 +++ src/midiio/include/MidiInPort_linux.h | 94 ++ src/midiio/include/MidiInPort_oss.h | 105 +++ src/midiio/include/MidiInPort_unsupported.h | 89 ++ src/midiio/include/MidiInPort_visual.h | 114 +++ src/midiio/include/MidiInput.h | 53 ++ src/midiio/include/MidiMessage.h | 78 ++ src/midiio/include/MidiOutPort.h | 92 ++ src/midiio/include/MidiOutPort_alsa.h | 79 ++ src/midiio/include/MidiOutPort_linux.h | 80 ++ src/midiio/include/MidiOutPort_oss.h | 75 ++ src/midiio/include/MidiOutPort_unsupported.h | 71 ++ src/midiio/include/MidiOutPort_visual.h | 75 ++ src/midiio/include/MidiOutput.h | 140 +++ src/midiio/include/MidiPort.h | 49 + src/midiio/include/Options.h | 106 +++ src/midiio/include/Options_private.h | 73 ++ src/midiio/include/Sequencer_alsa.h | 139 +++ src/midiio/include/Sequencer_oss.h | 92 ++ src/midiio/include/SigTimer.h | 104 +++ src/midiio/include/Voice.h | 70 ++ src/midiio/include/gminstruments.h | 251 +++++ src/midiio/include/midichannels.h | 42 + src/midiio/include/mididefines.h | 34 + src/midiio/include/midiiolib.h | 57 ++ src/midiio/include/notenames.h | 219 +++++ src/midiio/include/sigConfiguration.h | 100 ++ src/midiio/src/FileIO.cpp | 761 ++++++++++++++++ src/midiio/src/MidiFile.cpp | 1200 ++++++++++++++++++++++++ src/midiio/src/MidiFileWrite.cpp | 259 ++++++ src/midiio/src/MidiIO.cpp | 283 ++++++ src/midiio/src/MidiInPort_alsa.cpp | 1038 +++++++++++++++++++++ src/midiio/src/MidiInPort_alsa05.cpp | 995 ++++++++++++++++++++ src/midiio/src/MidiInPort_linux.cpp | 491 ++++++++++ src/midiio/src/MidiInPort_oss.cpp | 1036 +++++++++++++++++++++ src/midiio/src/MidiInPort_unsupported.cpp | 487 ++++++++++ src/midiio/src/MidiInPort_visual.cpp | 1267 ++++++++++++++++++++++++++ src/midiio/src/MidiInput.cpp | 224 +++++ src/midiio/src/MidiMessage.cpp | 406 +++++++++ src/midiio/src/MidiOutPort_alsa.cpp | 469 ++++++++++ src/midiio/src/MidiOutPort_linux.cpp | 381 ++++++++ src/midiio/src/MidiOutPort_oss.cpp | 462 ++++++++++ src/midiio/src/MidiOutPort_unsupported.cpp | 402 ++++++++ src/midiio/src/MidiOutPort_visual.cpp | 532 +++++++++++ src/midiio/src/MidiOutput.cpp | 1082 ++++++++++++++++++++++ src/midiio/src/MidiPort.cpp | 189 ++++ src/midiio/src/Options.cpp | 887 ++++++++++++++++++ src/midiio/src/Options_private.cpp | 358 ++++++++ src/midiio/src/Sequencer_alsa.cpp | 643 +++++++++++++ src/midiio/src/Sequencer_alsa05.cpp | 518 +++++++++++ src/midiio/src/Sequencer_oss.cpp | 809 ++++++++++++++++ src/midiio/src/SigTimer.cpp | 498 ++++++++++ src/midiio/src/Voice.cpp | 334 +++++++ 77 files changed, 24571 insertions(+) create mode 100644 src/Makefile.Linux create mode 100644 src/Makefile.NT create mode 100644 src/Makefile.midiioLibrary.ALSA create mode 100644 src/Makefile.midiioLibrary.NT create mode 100644 src/Makefile.midiioLibrary.OSS create mode 100644 src/gripd.c create mode 100644 src/gripd.h create mode 100644 src/joystick.c create mode 100644 src/joystick_wrap.c create mode 100644 src/makefile create mode 100644 src/midi.cpp create mode 100644 src/midi_wrap.c create mode 100644 src/midiio/include/Array.cpp create mode 100644 src/midiio/include/Array.h create mode 100644 src/midiio/include/CircularBuffer.cpp create mode 100644 src/midiio/include/CircularBuffer.h create mode 100644 src/midiio/include/Collection.cpp create mode 100644 src/midiio/include/Collection.h create mode 100644 src/midiio/include/FileIO.h create mode 100644 src/midiio/include/MidiFile.h create mode 100644 src/midiio/include/MidiFileWrite.h create mode 100644 src/midiio/include/MidiIO.h create mode 100644 src/midiio/include/MidiInPort.h create mode 100644 src/midiio/include/MidiInPort_alsa.h create mode 100644 src/midiio/include/MidiInPort_alsa05.h create mode 100644 src/midiio/include/MidiInPort_linux.h create mode 100644 src/midiio/include/MidiInPort_oss.h create mode 100644 src/midiio/include/MidiInPort_unsupported.h create mode 100644 src/midiio/include/MidiInPort_visual.h create mode 100644 src/midiio/include/MidiInput.h create mode 100644 src/midiio/include/MidiMessage.h create mode 100644 src/midiio/include/MidiOutPort.h create mode 100644 src/midiio/include/MidiOutPort_alsa.h create mode 100644 src/midiio/include/MidiOutPort_linux.h create mode 100644 src/midiio/include/MidiOutPort_oss.h create mode 100644 src/midiio/include/MidiOutPort_unsupported.h create mode 100644 src/midiio/include/MidiOutPort_visual.h create mode 100644 src/midiio/include/MidiOutput.h create mode 100644 src/midiio/include/MidiPort.h create mode 100644 src/midiio/include/Options.h create mode 100644 src/midiio/include/Options_private.h create mode 100644 src/midiio/include/Sequencer_alsa.h create mode 100644 src/midiio/include/Sequencer_oss.h create mode 100644 src/midiio/include/SigTimer.h create mode 100644 src/midiio/include/Voice.h create mode 100644 src/midiio/include/gminstruments.h create mode 100644 src/midiio/include/midichannels.h create mode 100644 src/midiio/include/mididefines.h create mode 100644 src/midiio/include/midiiolib.h create mode 100644 src/midiio/include/notenames.h create mode 100644 src/midiio/include/sigConfiguration.h create mode 100644 src/midiio/src/FileIO.cpp create mode 100644 src/midiio/src/MidiFile.cpp create mode 100644 src/midiio/src/MidiFileWrite.cpp create mode 100644 src/midiio/src/MidiIO.cpp create mode 100644 src/midiio/src/MidiInPort_alsa.cpp create mode 100644 src/midiio/src/MidiInPort_alsa05.cpp create mode 100644 src/midiio/src/MidiInPort_linux.cpp create mode 100644 src/midiio/src/MidiInPort_oss.cpp create mode 100644 src/midiio/src/MidiInPort_unsupported.cpp create mode 100644 src/midiio/src/MidiInPort_visual.cpp create mode 100644 src/midiio/src/MidiInput.cpp create mode 100644 src/midiio/src/MidiMessage.cpp create mode 100644 src/midiio/src/MidiOutPort_alsa.cpp create mode 100644 src/midiio/src/MidiOutPort_linux.cpp create mode 100644 src/midiio/src/MidiOutPort_oss.cpp create mode 100644 src/midiio/src/MidiOutPort_unsupported.cpp create mode 100644 src/midiio/src/MidiOutPort_visual.cpp create mode 100644 src/midiio/src/MidiOutput.cpp create mode 100644 src/midiio/src/MidiPort.cpp create mode 100644 src/midiio/src/Options.cpp create mode 100644 src/midiio/src/Options_private.cpp create mode 100644 src/midiio/src/Sequencer_alsa.cpp create mode 100644 src/midiio/src/Sequencer_alsa05.cpp create mode 100644 src/midiio/src/Sequencer_oss.cpp create mode 100644 src/midiio/src/SigTimer.cpp create mode 100644 src/midiio/src/Voice.cpp (limited to 'src') diff --git a/src/Makefile.Linux b/src/Makefile.Linux new file mode 100644 index 0000000..999bc91 --- /dev/null +++ b/src/Makefile.Linux @@ -0,0 +1,48 @@ +include makefile + +current: all + +all: gripd.pd_linux joystickmodule.so midimodule.so + +LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch +MIDIDEFINES = -D$(MIDIOSSUBTYPE) -DLINUX +MIDICOMPILEFLAGS = -O6 -I./midiio/include $(MIDIDEFINES) +MIDILINKFLAGS = -L$(SYSTEMLIBDIR) -lpthread -L./midiio/lib -lmidiio +ifeq ($(MIDIOSSUBTYPE), ALSA) +MIDILINKFLAGS += -lasound +endif + +gripd.pd_linux: + cc $(LINUXCFLAGS) $(PDINCLUDE) -o gripd.o -c gripd.c + ld -export_dynamic -lm -shared -o gripd.pd_linux gripd.o -lc -lm + strip --strip-unneeded gripd.pd_linux + cp gripd.pd_linux .. + +joystickmodule.so: +ifeq ($(JOYSTICK), TRUE) + cc -c joystick.c + cc $(LINUXPYTHONINCLUDE) -c -DHAVE_CONFIG_H joystick_wrap.c + ld -shared joystick.o joystick_wrap.o -o joystickmodule.so + cp joystickmodule.so .. +endif + echo "joystick = "$(JOYSTICK) > ../gripd.opt + +midimodule.so: +ifeq ($(MIDI), TRUE) + make -f Makefile.midiioLibrary.$(MIDIOSSUBTYPE) + g++ -c $(MIDICOMPILEFLAGS) midi.cpp + g++ $(LINUXPYTHONINCLUDE) -c -DHAVE_CONFIG_H midi_wrap.c + g++ -shared midi.o midi_wrap.o $(MIDILINKFLAGS) -o midimodule.so + cp midimodule.so .. +endif + echo "midi = "$(MIDI) >> ../gripd.opt + +linux_clean: + rm *.o + rm gripd.pd_linux + rm joystickmodule.so + rm midimodule.so + make -f Makefile.midiioLibrary.$(MIDIOSSUBTYPE) clean + diff --git a/src/Makefile.NT b/src/Makefile.NT new file mode 100644 index 0000000..4974592 --- /dev/null +++ b/src/Makefile.NT @@ -0,0 +1,86 @@ +!INCLUDE makefile + +current: all +all: gripd.dll joystick.dll midi.dll + +PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo + +PDNTINCLUDE = /I. /I\tcl\include /I$(PDNTSRCDIR) /I$(VC)\include +JOYINCLUDE = /I$(PYTHONHOME)\include /I$(VC)\INCLUDE +MIDIINCLUDE = /I$(PYTHONHOME)\include /I$(VC)\INCLUDE /I.\midiio\include +PDNTLIB = $(VC)\lib\libc.lib \ + $(VC)\lib\oldnames.lib \ + $(VC)\lib\kernel32.lib \ + $(VC)\lib\wsock32.lib \ + $(VC)\lib\uuid.lib \ + $(PDNTLDIR)\pd.lib +JOYLIBS = $(VC)\LIB\kernel32.lib \ + $(VC)\LIB\advapi32.lib \ + $(VC)\LIB\user32.lib \ + $(VC)\LIB\gdi32.lib \ + $(VC)\LIB\libcmt.lib \ + $(VC)\LIB\comdlg32.lib \ + $(VC)\LIB\oldnames.lib \ + $(VC)\LIB\winmm.lib \ + $(VC)\LIB\winspool.lib \ + $(PYTHONHOME)\libs\python$(PYTHONVER).lib +MIDILIBS = midiio\lib\midiio.lib \ + $(PYTHONHOME)\libs\python$(PYTHONVER).lib \ + $(VC)\lib\kernel32.lib \ + $(VC)\lib\advapi32.lib \ + $(VC)\lib\user32.lib \ + $(VC)\lib\gdi32.lib \ + $(VC)\lib\comdlg32.lib \ + $(VC)\lib\oldnames.lib \ + $(VC)\lib\winmm.lib \ + $(VC)\lib\winspool.lib +JOYLOPT = -debug:full -debugtype:cv /NODEFAULTLIB /RELEASE /NOLOGO \ + /MACHINE:IX86 -entry:_DllMainCRTStartup@12 -dll +MIDILOPT = -debug:full -debugtype:cv /RELEASE /NOLOGO /NODEFAULTLIB:msvcrt.lib \ + /MACHINE:IX86 -entry:_DllMainCRTStartup@12 -dll + +gripd.dll: + cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c gripd.c + link /dll /export:gripd_setup gripd.obj $(PDNTLIB) + copy gripd.dll .. + +joystick.dll: +!IF "$(JOYSTICK)" == "TRUE" + cl /TP /DNT /c $(JOYINCLUDE) joystick.c + cl /Z7 /Od /c /nologo /D__WIN32__ $(JOYINCLUDE) joystick_wrap.c + link $(JOYLOPT) -out:joystick.dll $(JOYLIBS) joystick_wrap.obj \ + joystick.obj + copy joystick.dll .. +!ENDIF + echo joystick = $(JOYSTICK) > ..\gripd.opt + +midi.dll: +!IF "$(MIDI)" == "TRUE" + nmake -f Makefile.midiioLibrary.NT + cl /DVISUAL /TP /DNT /c /GX $(MIDIINCLUDE) midi.cpp + cl /TP /DVISUAL /Z7 /Od /c /nologo /D__WIN32__ $(MIDIINCLUDE) midi_wrap.c + link $(MIDILOPT) -out:midi.dll $(MIDILIBS) midi_wrap.obj midi.obj + copy midi.dll .. +!ENDIF + echo midi = $(MIDI) >> ..\gripd.opt + +nt_clean: + del gripd.obj + del gripd.exp + del gripd.lib + del joystick.pdb + del joystick.obj + del joystick.lib + del joystick.exp + del joystick_wrap.obj + del midi.pdb + del midi.obj + del midi.lib + del midi.exp + del midi_wrap.obj + del gripd.dll + del joystick.dll + del midi.dll + nmake -f Makefile.midiioLibrary.NT CLEAN + + diff --git a/src/Makefile.midiioLibrary.ALSA b/src/Makefile.midiioLibrary.ALSA new file mode 100644 index 0000000..5a5a7b2 --- /dev/null +++ b/src/Makefile.midiioLibrary.ALSA @@ -0,0 +1,205 @@ +## midiio library GNU makefile for linux. +## +## Programmer: Craig Stuart Sapp +## Creation Date: Sat Nov 2 19:49:57 PST 2002 +## Last Modified: Sat Nov 2 19:50:00 PST 2002 +## Filename: ...midiio/Makefile.library +## +## Description: This Makefile creates the midiio library lib/libmidiio.a +## for linux, using gcc 2.7.2.1 or higher +## +## To run this makefile, type (without quotes) "make -f Makefile.library" +## + +########################################################################### +# # +# # +# Operating System OSTYPEs available in the midiio library compilation: # +# +# LINUX = Linux running on intel computers +# VISUAL = Windows 95/NT using Microsoft Visual C++ 5/6 +# OSX = Apple Mac OS X (10.2 or higher when it is ready) +# +# The file "sigConfiguration.h" in the include directory contains additional +# defines which will be activated by the OS given by the OSTYPE variable +# below. Look at the sigConfiguration.h file for various things which need +# to be defined specifically for each OS. +# +OSTYPE = LINUX + +# The OSSUBTYPE is for determining which type of sound drivers +# are being used in linux. There are three possibilities: +# OSSUBTYPE = ALSA # ALSA 0.9 interface (http://www.alsa-project.org) +# OSSUBTYPE = ALSA05 # ALSA 0.5 interface (http://www.alsa-project.org) +# OSSUBTYPE = OSS # OSS interface (http://www.4front-tech.com) +# Note: The Improv library accesses the internal/external MIDI devices +# in OSS, but only the external MIDI devices in ALSA. OSS can be +# emulated in ALSA 0.9. +# +OSSUBTYPE = ALSA + +OBJDIR = ./midiio/obj +SRCDIR = ./midiio/src +INCDIR = ./midiio/include +LIBDIR = ./midiio/lib +LIBFILE = libmidiio.a + +COMPILER = g++ +# MAC OSX 10.2 needs this compiler: +# COMPILER = g++2 + +DEFINES = $(addprefix -D,$(OSTYPE)) $(addprefix -D,$(OSSUBTYPE)) +FLAGS = -Wall -c -O3 $(DEFINES) -I$(INCDIR) + +# # +# End of user-modifiable variables. # +# # +########################################################################### + + +# setting up the directory paths to search for dependency files +vpath %.h $(INCDIR):$(SRCDIR) +vpath %.cpp $(SRCDIR):$(INCDIR) +vpath %.o $(OBJDIR) + +# generating a list of the object files +OBJS = $(notdir $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp))) + +# targets which don't actually refer to files +.PHONY : all linux makeobjdir + + +########################################################################### +# # +# Hardware Configurations: # +# # + +all: makeobjdir $(OBJS) + + ifeq ($(OSTYPE),LINUX) + @echo Making midiio library file for linux ... + -mkdir -p $(LIBDIR) + -rm -f $(LIBDIR)/$(LIBFILE) + ar r $(LIBDIR)/$(LIBFILE) $(OBJDIR)/*.o + ranlib $(LIBDIR)/$(LIBFILE) + endif + + ifeq ($(OSTYPE),VISUAL) + echo "this makefile doesn't work with Visual C++." + endif + +clean: + @echo Erasing object files: + -rm -f $(OBJDIR)/*.o + @echo Erasing obj directory: + -rmdir $(OBJDIR) + +makeobjdir: + -mkdir -p $(OBJDIR) + +# defining an explicit rule for object file dependencies +%.o : %.cpp + $(COMPILER) $(FLAGS) -o $(OBJDIR)/$(notdir $@) $< + + +# # +########################################################################### + + + +########################################################################### +# # +# Dependencies -- generated with the following command in # +# the src directory (in csh shell): # +# # +# foreach i (*.cpp) # +# cc -I../include -MM $i | sed 's/\.\.\/include\///g' # +# echo "" # +# end # +# # + +FileIO.o: FileIO.cpp FileIO.h sigConfiguration.h + +MidiFile.o: MidiFile.cpp MidiFile.h FileIO.h Array.h Collection.h \ + Collection.cpp Array.cpp + +MidiFileWrite.o: MidiFileWrite.cpp MidiFileWrite.h FileIO.h SigTimer.h + +MidiIO.o: MidiIO.cpp MidiIO.h MidiInput.h MidiInPort.h MidiMessage.h \ + MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \ + Array.h Collection.h Collection.cpp Array.cpp MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h FileIO.h SigTimer.h + +MidiInPort_alsa.o: MidiInPort_alsa.cpp + +MidiInPort_alsa05.o: MidiInPort_alsa05.cpp + +MidiInPort_linux.o: MidiInPort_linux.cpp + +MidiInPort_oss.o: MidiInPort_oss.cpp + +MidiInPort_unsupported.o: MidiInPort_unsupported.cpp \ + MidiInPort_unsupported.h MidiMessage.h CircularBuffer.h \ + CircularBuffer.cpp Array.h Collection.h Collection.cpp \ + Array.cpp + +MidiInPort_visual.o: MidiInPort_visual.cpp + +MidiInput.o: MidiInput.cpp MidiInput.h MidiInPort.h MidiMessage.h \ + MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \ + Array.h Collection.h Collection.cpp Array.cpp + +MidiMessage.o: MidiMessage.cpp MidiMessage.h + +MidiOutPort_alsa.o: MidiOutPort_alsa.cpp + +MidiOutPort_linux.o: MidiOutPort_linux.cpp + +MidiOutPort_oss.o: MidiOutPort_oss.cpp + +MidiOutPort_unsupported.o: MidiOutPort_unsupported.cpp \ + MidiOutPort_unsupported.h + +MidiOutPort_visual.o: MidiOutPort_visual.cpp + +MidiOutput.o: MidiOutput.cpp MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \ + Collection.cpp Array.cpp + +MidiPerform.o: MidiPerform.cpp MidiPerform.h MidiFile.h FileIO.h Array.h \ + Collection.h Collection.cpp Array.cpp CircularBuffer.h \ + CircularBuffer.cpp SigTimer.h MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h + +MidiPort.o: MidiPort.cpp MidiPort.h MidiInPort.h MidiMessage.h \ + MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \ + Array.h Collection.h Collection.cpp Array.cpp MidiOutPort.h \ + MidiOutPort_unsupported.h + +MultiStageEvent.o: MultiStageEvent.cpp MultiStageEvent.h Event.h \ + OneStageEvent.h MidiEvent.h TwoStageEvent.h NoteEvent.h \ + EventBuffer.h CircularBuffer.h CircularBuffer.cpp MidiOutput.h \ + MidiOutPort.h MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h \ + Collection.h Collection.cpp Array.cpp FunctionEvent.h + +Options.o: Options.cpp Options.h Array.h Collection.h Collection.cpp \ + Array.cpp Options_private.h + +Options_private.o: Options_private.cpp Options_private.h + +Sequencer_alsa.o: Sequencer_alsa.cpp + +Sequencer_alsa05.o: Sequencer_alsa05.cpp + +Sequencer_oss.o: Sequencer_oss.cpp + +SigTimer.o: SigTimer.cpp SigTimer.h + +Voice.o: Voice.cpp Voice.h MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \ + Collection.cpp Array.cpp + + + + + diff --git a/src/Makefile.midiioLibrary.NT b/src/Makefile.midiioLibrary.NT new file mode 100644 index 0000000..a0900b0 --- /dev/null +++ b/src/Makefile.midiioLibrary.NT @@ -0,0 +1,462 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on midiio.dsp +!IF "$(CFG)" == "" +CFG = midiio - Win32 Release +!ENDIF + +!IF "$(CFG)" != "midiio - Win32 Release" && "$(CFG)" != "midiio - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "midiio.mak" CFG="midiio - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "midiio - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "midiio - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "midiio - Win32 Release" + +OUTDIR=.\midiio\lib +INTDIR=.\midiio\obj +# Begin Custom Macros +OutDir=.\midiio\lib +# End Custom Macros + +ALL : "$(OUTDIR)\midiio.lib" + + +CLEAN : + -@erase "$(INTDIR)\Array.obj" + -@erase "$(INTDIR)\CircularBuffer.obj" + -@erase "$(INTDIR)\Collection.obj" + -@erase "$(INTDIR)\FileIO.obj" + -@erase "$(INTDIR)\MidiFile.obj" + -@erase "$(INTDIR)\MidiFileWrite.obj" + -@erase "$(INTDIR)\MidiInPort_alsa.obj" + -@erase "$(INTDIR)\MidiInPort_alsa05.obj" + -@erase "$(INTDIR)\MidiInPort_linux.obj" + -@erase "$(INTDIR)\MidiInPort_oss.obj" + -@erase "$(INTDIR)\MidiInPort_unsupported.obj" + -@erase "$(INTDIR)\MidiInPort_visual.obj" + -@erase "$(INTDIR)\MidiInput.obj" + -@erase "$(INTDIR)\MidiIO.obj" + -@erase "$(INTDIR)\MidiMessage.obj" + -@erase "$(INTDIR)\MidiOutPort_alsa.obj" + -@erase "$(INTDIR)\MidiOutPort_linux.obj" + -@erase "$(INTDIR)\MidiOutPort_oss.obj" + -@erase "$(INTDIR)\MidiOutPort_unsupported.obj" + -@erase "$(INTDIR)\MidiOutPort_visual.obj" + -@erase "$(INTDIR)\MidiOutput.obj" + -@erase "$(INTDIR)\MidiPort.obj" + -@erase "$(INTDIR)\Options.obj" + -@erase "$(INTDIR)\Options_private.obj" + -@erase "$(INTDIR)\Sequencer_alsa.obj" + -@erase "$(INTDIR)\Sequencer_alsa05.obj" + -@erase "$(INTDIR)\Sequencer_oss.obj" + -@erase "$(INTDIR)\SigTimer.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\Voice.obj" + -@erase "$(INTDIR)\midiio.pch" + -@erase "$(OUTDIR)\midiio.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I ".\midiio\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "VISUAL" /Fp"$(INTDIR)\midiio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\midiio.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\midiio.lib" +LIB32_OBJS= \ + "$(INTDIR)\Array.obj" \ + "$(INTDIR)\CircularBuffer.obj" \ + "$(INTDIR)\Collection.obj" \ + "$(INTDIR)\FileIO.obj" \ + "$(INTDIR)\MidiFile.obj" \ + "$(INTDIR)\MidiFileWrite.obj" \ + "$(INTDIR)\MidiInPort_alsa.obj" \ + "$(INTDIR)\MidiInPort_alsa05.obj" \ + "$(INTDIR)\MidiInPort_linux.obj" \ + "$(INTDIR)\MidiInPort_oss.obj" \ + "$(INTDIR)\MidiInPort_unsupported.obj" \ + "$(INTDIR)\MidiInPort_visual.obj" \ + "$(INTDIR)\MidiInput.obj" \ + "$(INTDIR)\MidiIO.obj" \ + "$(INTDIR)\MidiMessage.obj" \ + "$(INTDIR)\MidiOutPort_alsa.obj" \ + "$(INTDIR)\MidiOutPort_linux.obj" \ + "$(INTDIR)\MidiOutPort_oss.obj" \ + "$(INTDIR)\MidiOutPort_unsupported.obj" \ + "$(INTDIR)\MidiOutPort_visual.obj" \ + "$(INTDIR)\MidiOutput.obj" \ + "$(INTDIR)\MidiPort.obj" \ + "$(INTDIR)\Options.obj" \ + "$(INTDIR)\Options_private.obj" \ + "$(INTDIR)\Sequencer_alsa.obj" \ + "$(INTDIR)\Sequencer_alsa05.obj" \ + "$(INTDIR)\Sequencer_oss.obj" \ + "$(INTDIR)\SigTimer.obj" \ + "$(INTDIR)\Voice.obj" + +"$(OUTDIR)\midiio.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ELSEIF "$(CFG)" == "midiio - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : "$(OUTDIR)\midiio.lib" + + +CLEAN : + -@erase "$(INTDIR)\Array.obj" + -@erase "$(INTDIR)\CircularBuffer.obj" + -@erase "$(INTDIR)\Collection.obj" + -@erase "$(INTDIR)\FileIO.obj" + -@erase "$(INTDIR)\MidiFile.obj" + -@erase "$(INTDIR)\MidiFileWrite.obj" + -@erase "$(INTDIR)\MidiInPort_alsa.obj" + -@erase "$(INTDIR)\MidiInPort_alsa05.obj" + -@erase "$(INTDIR)\MidiInPort_linux.obj" + -@erase "$(INTDIR)\MidiInPort_oss.obj" + -@erase "$(INTDIR)\MidiInPort_unsupported.obj" + -@erase "$(INTDIR)\MidiInPort_visual.obj" + -@erase "$(INTDIR)\MidiInput.obj" + -@erase "$(INTDIR)\MidiIO.obj" + -@erase "$(INTDIR)\MidiMessage.obj" + -@erase "$(INTDIR)\MidiOutPort_alsa.obj" + -@erase "$(INTDIR)\MidiOutPort_linux.obj" + -@erase "$(INTDIR)\MidiOutPort_oss.obj" + -@erase "$(INTDIR)\MidiOutPort_unsupported.obj" + -@erase "$(INTDIR)\MidiOutPort_visual.obj" + -@erase "$(INTDIR)\MidiOutput.obj" + -@erase "$(INTDIR)\MidiPort.obj" + -@erase "$(INTDIR)\Options.obj" + -@erase "$(INTDIR)\Options_private.obj" + -@erase "$(INTDIR)\Sequencer_alsa.obj" + -@erase "$(INTDIR)\Sequencer_alsa05.obj" + -@erase "$(INTDIR)\Sequencer_oss.obj" + -@erase "$(INTDIR)\SigTimer.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(INTDIR)\Voice.obj" + -@erase "$(OUTDIR)\midiio.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /I ".\midiio\include" /D "VISUAL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Fp"$(INTDIR)\midiio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\midiio.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\midiio.lib" +LIB32_OBJS= \ + "$(INTDIR)\Array.obj" \ + "$(INTDIR)\CircularBuffer.obj" \ + "$(INTDIR)\Collection.obj" \ + "$(INTDIR)\FileIO.obj" \ + "$(INTDIR)\MidiFile.obj" \ + "$(INTDIR)\MidiFileWrite.obj" \ + "$(INTDIR)\MidiInPort_alsa.obj" \ + "$(INTDIR)\MidiInPort_alsa05.obj" \ + "$(INTDIR)\MidiInPort_linux.obj" \ + "$(INTDIR)\MidiInPort_oss.obj" \ + "$(INTDIR)\MidiInPort_unsupported.obj" \ + "$(INTDIR)\MidiInPort_visual.obj" \ + "$(INTDIR)\MidiInput.obj" \ + "$(INTDIR)\MidiIO.obj" \ + "$(INTDIR)\MidiMessage.obj" \ + "$(INTDIR)\MidiOutPort_alsa.obj" \ + "$(INTDIR)\MidiOutPort_linux.obj" \ + "$(INTDIR)\MidiOutPort_oss.obj" \ + "$(INTDIR)\MidiOutPort_unsupported.obj" \ + "$(INTDIR)\MidiOutPort_visual.obj" \ + "$(INTDIR)\MidiOutput.obj" \ + "$(INTDIR)\MidiPort.obj" \ + "$(INTDIR)\Options.obj" \ + "$(INTDIR)\Options_private.obj" \ + "$(INTDIR)\Sequencer_alsa.obj" \ + "$(INTDIR)\Sequencer_alsa05.obj" \ + "$(INTDIR)\Sequencer_oss.obj" \ + "$(INTDIR)\SigTimer.obj" \ + "$(INTDIR)\Voice.obj" + +"$(OUTDIR)\midiio.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("midiiolib.dep") +!INCLUDE "midiiolib.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "midiio - Win32 Release" || "$(CFG)" == "midiio - Win32 Debug" +SOURCE=".\midiio\include\Array.cpp" + +"$(INTDIR)\Array.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\include\CircularBuffer.cpp" + +"$(INTDIR)\CircularBuffer.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\include\Collection.cpp" + +"$(INTDIR)\Collection.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\FileIO.cpp" + +"$(INTDIR)\FileIO.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiFile.cpp" + +"$(INTDIR)\MidiFile.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiFileWrite.cpp" + +"$(INTDIR)\MidiFileWrite.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInPort_alsa.cpp" + +"$(INTDIR)\MidiInPort_alsa.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInPort_alsa05.cpp" + +"$(INTDIR)\MidiInPort_alsa05.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInPort_linux.cpp" + +"$(INTDIR)\MidiInPort_linux.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInPort_oss.cpp" + +"$(INTDIR)\MidiInPort_oss.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInPort_unsupported.cpp" + +"$(INTDIR)\MidiInPort_unsupported.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\CircularBuffer.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInPort_visual.cpp" + +"$(INTDIR)\MidiInPort_visual.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiInput.cpp" + +"$(INTDIR)\MidiInput.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiIO.cpp" + +"$(INTDIR)\MidiIO.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiMessage.cpp" + +"$(INTDIR)\MidiMessage.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiOutPort_alsa.cpp" + +"$(INTDIR)\MidiOutPort_alsa.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiOutPort_linux.cpp" + +"$(INTDIR)\MidiOutPort_linux.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiOutPort_oss.cpp" + +"$(INTDIR)\MidiOutPort_oss.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiOutPort_unsupported.cpp" + +"$(INTDIR)\MidiOutPort_unsupported.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiOutPort_visual.cpp" + +"$(INTDIR)\MidiOutPort_visual.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiOutput.cpp" + +"$(INTDIR)\MidiOutput.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\MidiPort.cpp" + +"$(INTDIR)\MidiPort.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\Options.cpp" + +"$(INTDIR)\Options.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\Options_private.cpp" + +"$(INTDIR)\Options_private.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\Sequencer_alsa.cpp" + +"$(INTDIR)\Sequencer_alsa.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\Sequencer_alsa05.cpp" + +"$(INTDIR)\Sequencer_alsa05.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\Sequencer_oss.cpp" + +"$(INTDIR)\Sequencer_oss.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\SigTimer.cpp" + +"$(INTDIR)\SigTimer.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=".\midiio\src\Voice.cpp" + +"$(INTDIR)\Voice.obj" : $(SOURCE) "$(INTDIR)" ".\midiio\include\Array.cpp" ".\midiio\include\Collection.cpp" + $(CPP) $(CPP_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/src/Makefile.midiioLibrary.OSS b/src/Makefile.midiioLibrary.OSS new file mode 100644 index 0000000..2f1e6e2 --- /dev/null +++ b/src/Makefile.midiioLibrary.OSS @@ -0,0 +1,205 @@ +## midiio library GNU makefile for linux. +## +## Programmer: Craig Stuart Sapp +## Creation Date: Sat Nov 2 19:49:57 PST 2002 +## Last Modified: Sat Nov 2 19:50:00 PST 2002 +## Filename: ...midiio/Makefile.library +## +## Description: This Makefile creates the midiio library lib/libmidiio.a +## for linux, using gcc 2.7.2.1 or higher +## +## To run this makefile, type (without quotes) "make -f Makefile.library" +## + +########################################################################### +# # +# # +# Operating System OSTYPEs available in the midiio library compilation: # +# +# LINUX = Linux running on intel computers +# VISUAL = Windows 95/NT using Microsoft Visual C++ 5/6 +# OSX = Apple Mac OS X (10.2 or higher when it is ready) +# +# The file "sigConfiguration.h" in the include directory contains additional +# defines which will be activated by the OS given by the OSTYPE variable +# below. Look at the sigConfiguration.h file for various things which need +# to be defined specifically for each OS. +# +OSTYPE = LINUX + +# The OSSUBTYPE is for determining which type of sound drivers +# are being used in linux. There are three possibilities: +# OSSUBTYPE = ALSA # ALSA 0.9 interface (http://www.alsa-project.org) +# OSSUBTYPE = ALSA05 # ALSA 0.5 interface (http://www.alsa-project.org) +# OSSUBTYPE = OSS # OSS interface (http://www.4front-tech.com) +# Note: The Improv library accesses the internal/external MIDI devices +# in OSS, but only the external MIDI devices in ALSA. OSS can be +# emulated in ALSA 0.9. +# +OSSUBTYPE = OSS + +OBJDIR = ./midiio/obj +SRCDIR = ./midiio/src +INCDIR = ./midiio/include +LIBDIR = ./midiio/lib +LIBFILE = libmidiio.a + +COMPILER = g++ +# MAC OSX 10.2 needs this compiler: +# COMPILER = g++2 + +DEFINES = $(addprefix -D,$(OSTYPE)) $(addprefix -D,$(OSSUBTYPE)) +FLAGS = -Wall -c -O3 $(DEFINES) -I$(INCDIR) + +# # +# End of user-modifiable variables. # +# # +########################################################################### + + +# setting up the directory paths to search for dependency files +vpath %.h $(INCDIR):$(SRCDIR) +vpath %.cpp $(SRCDIR):$(INCDIR) +vpath %.o $(OBJDIR) + +# generating a list of the object files +OBJS = $(notdir $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp))) + +# targets which don't actually refer to files +.PHONY : all linux makeobjdir + + +########################################################################### +# # +# Hardware Configurations: # +# # + +all: makeobjdir $(OBJS) + + ifeq ($(OSTYPE),LINUX) + @echo Making midiio library file for linux ... + -mkdir -p $(LIBDIR) + -rm -f $(LIBDIR)/$(LIBFILE) + ar r $(LIBDIR)/$(LIBFILE) $(OBJDIR)/*.o + ranlib $(LIBDIR)/$(LIBFILE) + endif + + ifeq ($(OSTYPE),VISUAL) + echo "this makefile doesn't work with Visual C++." + endif + +clean: + @echo Erasing object files: + -rm -f $(OBJDIR)/*.o + @echo Erasing obj directory: + -rmdir $(OBJDIR) + +makeobjdir: + -mkdir -p $(OBJDIR) + +# defining an explicit rule for object file dependencies +%.o : %.cpp + $(COMPILER) $(FLAGS) -o $(OBJDIR)/$(notdir $@) $< + + +# # +########################################################################### + + + +########################################################################### +# # +# Dependencies -- generated with the following command in # +# the src directory (in csh shell): # +# # +# foreach i (*.cpp) # +# cc -I../include -MM $i | sed 's/\.\.\/include\///g' # +# echo "" # +# end # +# # + +FileIO.o: FileIO.cpp FileIO.h sigConfiguration.h + +MidiFile.o: MidiFile.cpp MidiFile.h FileIO.h Array.h Collection.h \ + Collection.cpp Array.cpp + +MidiFileWrite.o: MidiFileWrite.cpp MidiFileWrite.h FileIO.h SigTimer.h + +MidiIO.o: MidiIO.cpp MidiIO.h MidiInput.h MidiInPort.h MidiMessage.h \ + MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \ + Array.h Collection.h Collection.cpp Array.cpp MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h FileIO.h SigTimer.h + +MidiInPort_alsa.o: MidiInPort_alsa.cpp + +MidiInPort_alsa05.o: MidiInPort_alsa05.cpp + +MidiInPort_linux.o: MidiInPort_linux.cpp + +MidiInPort_oss.o: MidiInPort_oss.cpp + +MidiInPort_unsupported.o: MidiInPort_unsupported.cpp \ + MidiInPort_unsupported.h MidiMessage.h CircularBuffer.h \ + CircularBuffer.cpp Array.h Collection.h Collection.cpp \ + Array.cpp + +MidiInPort_visual.o: MidiInPort_visual.cpp + +MidiInput.o: MidiInput.cpp MidiInput.h MidiInPort.h MidiMessage.h \ + MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \ + Array.h Collection.h Collection.cpp Array.cpp + +MidiMessage.o: MidiMessage.cpp MidiMessage.h + +MidiOutPort_alsa.o: MidiOutPort_alsa.cpp + +MidiOutPort_linux.o: MidiOutPort_linux.cpp + +MidiOutPort_oss.o: MidiOutPort_oss.cpp + +MidiOutPort_unsupported.o: MidiOutPort_unsupported.cpp \ + MidiOutPort_unsupported.h + +MidiOutPort_visual.o: MidiOutPort_visual.cpp + +MidiOutput.o: MidiOutput.cpp MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \ + Collection.cpp Array.cpp + +MidiPerform.o: MidiPerform.cpp MidiPerform.h MidiFile.h FileIO.h Array.h \ + Collection.h Collection.cpp Array.cpp CircularBuffer.h \ + CircularBuffer.cpp SigTimer.h MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h + +MidiPort.o: MidiPort.cpp MidiPort.h MidiInPort.h MidiMessage.h \ + MidiInPort_unsupported.h CircularBuffer.h CircularBuffer.cpp \ + Array.h Collection.h Collection.cpp Array.cpp MidiOutPort.h \ + MidiOutPort_unsupported.h + +MultiStageEvent.o: MultiStageEvent.cpp MultiStageEvent.h Event.h \ + OneStageEvent.h MidiEvent.h TwoStageEvent.h NoteEvent.h \ + EventBuffer.h CircularBuffer.h CircularBuffer.cpp MidiOutput.h \ + MidiOutPort.h MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h \ + Collection.h Collection.cpp Array.cpp FunctionEvent.h + +Options.o: Options.cpp Options.h Array.h Collection.h Collection.cpp \ + Array.cpp Options_private.h + +Options_private.o: Options_private.cpp Options_private.h + +Sequencer_alsa.o: Sequencer_alsa.cpp + +Sequencer_alsa05.o: Sequencer_alsa05.cpp + +Sequencer_oss.o: Sequencer_oss.cpp + +SigTimer.o: SigTimer.cpp SigTimer.h + +Voice.o: Voice.cpp Voice.h MidiOutput.h MidiOutPort.h \ + MidiOutPort_unsupported.h FileIO.h SigTimer.h Array.h Collection.h \ + Collection.cpp Array.cpp + + + + + diff --git a/src/gripd.c b/src/gripd.c new file mode 100644 index 0000000..fce1aa5 --- /dev/null +++ b/src/gripd.c @@ -0,0 +1,1031 @@ +/* GrIPD v0.1. - Graphical Interface for Pure Data +** Copyright (C) 2003 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** 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, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#include "gripd.h" + +void gripd_setup(void) +{ + post (" \n"); + post (" .______________________________________."); + post (" | |"); + post (" | GrIPD: v%s |", VERSION); + post (" | Graphical Interface for Pure Data |"); + post (" | (C) Copyright 2003 Joseph A. Sarlo |"); + post (" | GNU General Public License |"); + post (" |______________________________________|"); + post (" \n"); +#ifndef NT + signal(SIGCHLD, gripd_sigChild); +#endif + gripd_class = class_new(gensym("gripd"), (t_newmethod)gripd_new, + (t_method)gripd_free, sizeof(t_gripd), 0, + A_DEFFLOAT, 0); + gripdRcvr_class = class_new(gensym("gripdRcvr"),0,0,sizeof(t_gripd), + 0, 0); + class_addmethod(gripd_class, (t_method)gripd_connect, + gensym("connect"), 0); + class_addmethod(gripd_class, (t_method)gripd_disconnect, + gensym("disconnect"), 0); + class_addmethod(gripd_class, (t_method)gripd_open, + gensym("open"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_openLocked, + gensym("open_locked"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_setPythonPath, + gensym("set_python_path"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_setPath, + gensym("set_path"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_setSTime, + gensym("poll_send"), A_DEFFLOAT, 0); + class_addmethod(gripd_class, (t_method)gripd_setRTime, + gensym("poll_receive"), A_DEFFLOAT, 0); + class_addmethod(gripd_class, (t_method)gripd_lock, + gensym("lock"), 0); + class_addmethod(gripd_class, (t_method)gripd_unlock, + gensym("unlock"), 0); + class_addmethod(gripd_class, (t_method)gripd_setTitle, + gensym("set_title"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_hide, + gensym("hide"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_show, + gensym("show"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_openpanel, + gensym("openpanel"), A_GIMME, 0); + class_addmethod(gripd_class, (t_method)gripd_savepanel, + gensym("savepanel"), A_GIMME, 0); + class_addbang(gripdRcvr_class, (t_method)gripdR_bang); + class_addfloat(gripdRcvr_class, (t_method)gripdR_float); + class_addsymbol(gripdRcvr_class, (t_method)gripdR_symbol); + class_addanything(gripdRcvr_class, (t_method)gripdR_anything); + class_addlist(gripdRcvr_class, (t_method)gripdR_list); +} + +void *gripd_new(t_floatarg port) +{ + t_gripd *x = (t_gripd *)pd_new(gripd_class); + + if (port == 0) + x->x_port = DEFPORT; + else + x->x_port = (int)port; + x->x_bound = 0; + x->x_connected = 0; +#ifdef NT + x->x_localOpened = (int *)malloc(sizeof(int)); +#else + x->x_childPID = 0; + x->x_localOpened = (int *)shmat(shmget(IPC_PRIVATE,sizeof(int), + IPC_CREAT | SHM_R | SHM_W), 0, + 0); +#endif + *(x->x_localOpened) = 0; + x->x_rdeltime = DEFRDELTIME; + x->x_sdeltime = DEFSDELTIME; + x->x_rclock = clock_new(x, (t_method)gripd_recv); + x->x_sclock = clock_new(x, (t_method)gripd_send); + x->x_connectionClock = clock_new(x, (t_method)gripd_trySocket); + x->x_bindClock = clock_new(x, (t_method)gripd_connect); +#ifdef NT + strcpy(x->x_pythExec, "c:\\program files\\python\\"); + strcpy(x->x_pythFile, "..\\gripd\\"); + x->x_wsockInitByMe = 0; +#else + strcpy(x->x_pythExec, ""); + strcpy(x->x_pythFile, "../gripd/"); +#endif + x->x_rcvrListMaxSize = DEFLISTSIZE; + x->x_rcvrs = (t_gripdRcvr **)calloc(x->x_rcvrListMaxSize, + sizeof(t_gripdRcvr *)); + x->x_rcvrListSize = 0; + x->x_sendBuffer[0] = '\0'; + outlet_new(&x->t_ob, &s_float); + x->x_outlet2 = outlet_new(&x->t_ob, &s_float); + gripd_getApplicationPath(x); + return (void *)x; +} + +void gripd_connect(t_gripd *x) +{ + gripd_openSocket(x); + clock_delay(x->x_rclock, x->x_rdeltime); + clock_delay(x->x_sclock, x->x_sdeltime); +} + +void gripd_openSocket(t_gripd *x) +{ +#ifdef NT + char my_name[DEFSTRSIZE]; + struct sockaddr_in my_addr; + struct sockaddr_in new_addr; + struct hostent *hp; + WSADATA wsaData; + int nSize, temp = 1; + unsigned long on = 1; + + if (!x->x_bound) + { + memset(&my_addr, 0, sizeof(struct sockaddr_in)); + memset(&new_addr, 0, sizeof(struct sockaddr_in)); + gethostname(my_name, sizeof(my_name)); + hp = gethostbyname(my_name); + if (hp == NULL) + { + if (WSAGetLastError() == WSANOTINITIALISED) + { + if (WSAStartup (MAKEWORD(1,1), &wsaData) != 0) + post("GrIPD: Failed to initialize winsock"); + else + { + x->x_wsockInitByMe = 1; + gripd_openSocket(x); + return; + } + } + else + { + post("GrIPD: Gethostname Error %d", WSAGetLastError()); + gripd_disconnect(x); + } + } + my_addr.sin_family = hp->h_addrtype; + my_addr.sin_port = htons(x->x_port); + x->x_sock = socket(AF_INET, SOCK_STREAM, 0); + if (x->x_sock == INVALID_SOCKET) + { + post("GrIPD: Socket Error %d", WSAGetLastError()); + gripd_disconnect(x); + } + else + { + ioctlsocket(x->x_sock, FIONBIO, &on); + setsockopt(x->x_sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&temp, sizeof(temp)); + } + if (bind(x->x_sock, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr)) == SOCKET_ERROR) + { + post("GrIPD: Bind Error %d", WSAGetLastError()); + post("GrIPD: Attempting to re-bind"); + clock_delay(x->x_bindClock, REBINDTIME); + } + else + { + nSize = sizeof(struct sockaddr_in); + getsockname(x->x_sock, (struct sockaddr *)&new_addr, &nSize); + x->x_port = (int)ntohs(new_addr.sin_port); + post("GrIPD: Using port %d", x->x_port); + x->x_bound = 1; + listen(x->x_sock, BACKLOG); + post("GrIPD: Waiting for a connection..."); + clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME); + } + } + else + post("GrIPD: Already waiting for a connection"); +#else + char portstr[MAXPORTSTRLEN]; + struct sockaddr_in my_addr, new_addr; + int nSize, temp = 1; + + if (!x->x_bound) + { + x->x_sock = -1; + if ((x->x_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + perror("GrIPD: Socket Error"); + gripd_disconnect(x); + } + setsockopt(x->x_sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&temp, sizeof(temp)); + fcntl(x->x_sock, F_SETFL, O_NONBLOCK); + my_addr.sin_family = AF_INET; + my_addr.sin_port = htons(x->x_port); + my_addr.sin_addr.s_addr = INADDR_ANY; + bzero(&(my_addr.sin_zero), 8); + if (bind(x->x_sock, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr)) == -1) + { + perror("GrIPD: Bind Error"); + clock_delay(x->x_bindClock, REBINDTIME); + } + else + { + nSize = sizeof(struct sockaddr_in); + getsockname(x->x_sock, (struct sockaddr *)&new_addr, &nSize); + x->x_port = ntohs(new_addr.sin_port); + post("GrIPD: Using port %d", x->x_port); + x->x_bound = 1; + if (listen(x->x_sock, BACKLOG) == -1) + { + perror("GrIPD: Listen Error"); + gripd_disconnect(x); + } + post("GrIPD: Waiting for a connection..."); + clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME); + } + } + else + post("GrIPD: Already waiting for a connection"); +#endif +} + +void gripd_disconnect(t_gripd *x) +{ + int numbytes; + char buf[MAXDATASIZE]; + + clock_unset(x->x_sclock); + clock_unset(x->x_rclock); + clock_unset(x->x_bindClock); + clock_unset(x->x_connectionClock); + if (*(x->x_localOpened)) + { + gripd_closePyth(x); + } + else + { + sprintf(buf, "%s%c0%c", CLOSECOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + numbytes = recv(x->x_newSock, buf, MAXDATASIZE, MSG_NOSIGNAL); + } + if (x->x_bound) + { + gripd_closeSocket(x); + } +} + +void gripd_trySocket(t_gripd *x) +{ +#ifdef NT + fd_set rfds; + struct timeval tv; + unsigned long on; + + on = 1; + tv.tv_sec = 0; + tv.tv_usec = WAITTIME; + FD_ZERO(&rfds); + FD_SET(x->x_sock, &rfds); + if (select(x->x_sock + 1, &rfds, NULL, NULL, &tv) > 0) + { + x->x_newSock = accept(x->x_sock, NULL, NULL); + if (x->x_newSock == INVALID_SOCKET) + { + post("GrIPD: Accept Error %d", WSAGetLastError()); + gripd_disconnect(x); + } + else + { + ioctlsocket(x->x_newSock, FIONBIO, &on); + x->x_connected = 1; + outlet_float(x->t_ob.ob_outlet, 1); + post("GrIPD: Connected"); + } + } + else + clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME); +#else + fd_set rfds; + struct timeval tv; + struct sockaddr_in their_addr; + int new_fd, sin_size; + + sin_size = sizeof(struct sockaddr_in); + tv.tv_sec = 0; + tv.tv_usec = WAITTIME; + FD_ZERO(&rfds); + FD_SET(x->x_sock, &rfds); + if (select(x->x_sock + 1, &rfds, NULL, NULL, &tv)) + { + if ((x->x_newSock = accept(x->x_sock, + (struct sockaddr *)&their_addr, + &sin_size)) == -1) + { + perror("GrIPD: Accept Error"); + gripd_disconnect(x); + } + else + { + x->x_connected = 1; + outlet_float(x->t_ob.ob_outlet, 1); + post("GrIPD: Connected"); + } + } + else + clock_delay(x->x_connectionClock, CONNECTIONPOLLTIME); +#endif +} + +void gripd_closeSocket(t_gripd *x) +{ +#ifdef NT + closesocket(x->x_newSock); + closesocket(x->x_sock); +#else + shutdown(x->x_newSock, 2); + close(x->x_newSock); + shutdown(x->x_sock, 2); + close(x->x_sock); +#endif + x->x_bound = 0; + x->x_connected = 0; + *(x->x_localOpened) = 0; + outlet_float(x->t_ob.ob_outlet, 0); + outlet_float(x->x_outlet2, 0); +} + +void gripd_recv(t_gripd *x) +{ + int numbytes, count, idx, i, j, argc; + char buf[MAXDATASIZE], symName[MAXSYMNAMELEN], + symValue[MAXSYMVALUELEN], + tempString[MAXDATASIZE]; + t_symbol *tempSym; + t_atom atomList[MAXALISTLEN]; + numbytes = count = idx = i = j = argc = 0; + tempSym = gensym(""); + + if (x->x_connected) + { + numbytes = recv(x->x_newSock, buf, MAXDATASIZE, + MSG_DONTWAIT | MSG_NOSIGNAL); + if (numbytes > 0) + { + buf[numbytes] = '\0'; + while (count <= numbytes) + { + while ((buf[count] != SYMMSGSEP) && (count <= numbytes)) + { + symName[i] = buf[count]; + count++; + i++; + } + symName[i] = '\0'; + i = 0; + count++; + while ((buf[count] != PAIRSEPCHAR) && (count <= numbytes)) + { + symValue[i] = buf[count]; + count ++; + i++; + } + symValue[i] = '\0'; + count++; + i = 0; + if (symName[0] == COMMANDCHAR) + { + if ((strcmp(SETRCVRSTRING, symName) == 0) \ + && (gripd_checkExistance(x, symValue) == 0)) + { + if (x->x_rcvrListSize \ + == (x->x_rcvrListMaxSize - 1)) + gripd_expandRcvrList(x); + gripd_makeGripdRcvr(x, gensym(symValue)); + x->x_rcvrListSize++; + } + if (strcmp(CLOSECOMMAND, symName) == 0) + { + post("GrIPD: Connection closed remotely"); + gripd_disconnect(x); + } + if (strcmp(HIDECOMMAND, symName) == 0) + { + outlet_float(x->x_outlet2, 0); + } + if (strcmp(SHOWCOMMAND, symName) == 0) + { + outlet_float(x->x_outlet2, 1); + } + if (strcmp(PINGCOMMAND, symName) == 0) + { + char pingCommandStr[64]; + + sprintf(pingCommandStr, + "%s%c0%c", + PINGCOMMAND, + SYMMSGSEP, + PAIRSEPCHAR); + gripd_appendSendBuffer(x, pingCommandStr); + gripd_send(x); + } + } + else + { + tempSym = gensym(symName); + if (tempSym->s_thing) + { + if (strcmp(BANGSTRING, symValue) == 0) + pd_bang(tempSym->s_thing); + else + { + if (strchr(symValue, ' ') == NULL) + { + if (gripd_isNumeric(symValue)) + pd_float(tempSym->s_thing, + (float)atof(symValue)); + else + typedmess(tempSym->s_thing, + gensym(symValue), + 0, + NULL); + } + else + { + idx = 0; + argc = 0; + for (j = 0; j < (int)strlen(symValue); j++) + { + if (symValue[j] != ' ') + { + tempString[idx] = symValue[j]; + idx++; + } + if ((symValue[j] == ' ') + || (j == (int)strlen(symValue) -1)) + { + tempString[idx] = '\0'; + if (gripd_isNumeric(tempString)) + { + atomList[argc].a_type = A_FLOAT; + atomList[argc].a_w.w_float = + (float)atof(tempString); + } + else + { + atomList[argc].a_type = A_SYMBOL; + atomList[argc].a_w.w_symbol + = gensym(tempString); + } + argc++; + idx = 0; + } + } + if (atomList[0].a_type == A_FLOAT) + pd_list(tempSym->s_thing, + atomList[0].a_w.w_symbol, + argc, atomList); + else + typedmess(tempSym->s_thing, + atomList[0].a_w.w_symbol, + argc - 1, &(atomList[1])); + } + } + } + } + } + } + } + clock_delay(x->x_rclock, x->x_rdeltime); +} + +void gripd_send(t_gripd *x) +{ + int charsSent, endPos; + if (x->x_connected && (strlen(x->x_sendBuffer) > 0)) + { + charsSent = send(x->x_newSock, x->x_sendBuffer, + strlen(x->x_sendBuffer), + MSG_DONTWAIT | MSG_NOSIGNAL); + if (charsSent == SOCKET_ERROR) + { + post("GrIPD: Client is not responding"); + gripd_disconnect(x); + return; + } + else if ((charsSent <= (signed int)strlen(x->x_sendBuffer)) && + (charsSent > -1)) + { + endPos = strlen(x->x_sendBuffer) - charsSent; + strcpy(x->x_sendBuffer, &(x->x_sendBuffer[charsSent])); + x->x_sendBuffer[endPos] = '\0'; + } + } + clock_delay(x->x_sclock, x->x_sdeltime); +} + +/* this does NOT take care of separator strings, sending function must + do that */ +void gripd_appendSendBuffer(t_gripd *x, char *aString) +{ + if (x->x_connected) + { + /* +1 below since strlen does not include '\0' */ + if ((strlen(x->x_sendBuffer) + strlen(aString)) + 1 > MAXDATASIZE) + post("GrIPD: Send buffer overflow"); + else + strcat(x->x_sendBuffer, aString); + } +} + +void gripd_open(t_gripd *x, t_symbol *sym, int argc, t_atom *argv) +{ + gripd_openPyth(x, sym, argc, argv, 0); +} +void gripd_openLocked(t_gripd *x, t_symbol *sym, int argc, t_atom *argv) +{ + gripd_openPyth(x, sym, argc, argv, 1); +} + +void gripd_openPyth(t_gripd *x, t_symbol *sym, int argc, + t_atom *argv, int locked) +{ +#ifdef NT + STARTUPINFO si; + PROCESS_INFORMATION pi; + char pythExec[DEFSTRSIZE], filename[DEFSTRSIZE], tempStr[DEFSTRSIZE]; + int i; + + if (!x->x_connected && !(*(x->x_localOpened))) + { + gripd_connect(x); + *(x->x_localOpened) = 1; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + if (argc > 0) + { + if (argv[0].a_type == A_SYMBOL) + { + strcpy(filename, argv[0].a_w.w_symbol->s_name); + for (i = 1; i < argc; i++) + if (argv[i].a_type == A_SYMBOL) + sprintf(filename, "%s %s", filename, + argv[i].a_w.w_symbol->s_name); + } + else + strcpy(filename, "0"); + } + else + strcpy(filename, "0"); + for (i = 0; i < (int)strlen(x->x_pythExec); i++) + if (x->x_pythExec[i] == '/') + x->x_pythExec[i] = '\\'; + for (i = 0; i < (int)strlen(x->x_pythFile); i++) + if (x->x_pythFile[i] == '/') + x->x_pythFile[i] = '\\'; + for (i = 0; i < (int)strlen(filename); i++) + if (filename[i] == '/') + filename[i] = '\\'; + if (filename[0] == '.' && + (filename[1] == '\\' || + (filename[1] == '.' && filename[2] == '\\'))) + { + sprintf(tempStr, "%s%s", x->x_appPath, filename); + strcpy(filename, tempStr); + } + if (x->x_pythFile[0] == '.' && + (x->x_pythFile[1] == '\\' || + (x->x_pythFile[1] == '.' && x->x_pythFile[2] == '\\'))) + { + sprintf(tempStr, "%s%s", x->x_appPath, x->x_pythFile); + strcpy(x->x_pythFile, tempStr); + } + sprintf(pythExec, "\"%sgripd.exe\" \"%s\" %d 1 %d", x->x_pythFile, + filename, x->x_port, locked); + if (!(CreateProcess(NULL, pythExec, NULL, NULL, FALSE, 0, NULL, NULL, + &si, &(x->x_childProcessInfo)) != 0)) + { + post("GrIPD: Failed to execute %sgripd.exe", x->x_pythFile); + sprintf(pythExec, "\"%spython.exe\" \"%sgripd.py\" \"%s\" %d 1 %d", + x->x_pythExec, x->x_pythFile, filename, x->x_port, locked); + if (!(CreateProcess(NULL, pythExec, NULL, NULL, FALSE, 0, NULL, + NULL, &si, &(x->x_childProcessInfo)) != 0)) + { + post("GrIPD: Failed to execute %spython.exe", x->x_pythExec); + gripd_disconnect(x); + *(x->x_localOpened) = 0; + } + } + } +#else + char pythExec[DEFSTRSIZE], filename[DEFSTRSIZE], portString[DEFSTRSIZE], + lockedString[DEFSTRSIZE], tempStr[DEFSTRSIZE]; + int i, pid; + + if (!x->x_connected && !(*(x->x_localOpened))) + { + gripd_connect(x); + pid = fork(); + if (pid == 0) + { + struct sched_param par; + int p1; + + /* Lose setuid priveliges */ + seteuid(getuid()); + *(x->x_localOpened) = 1; + /* set lowest priority, SCHED_OTHER policy, unlock mem*/ +#ifdef _POSIX_PRIORITY_SCHEDULING + p1 = sched_get_priority_min(SCHED_OTHER); + par.sched_priority = p1; + if (sched_setscheduler(0, SCHED_OTHER, &par) == -1) + post("GrIPD: unable to set priority %d scheduling.", p1); +#endif +#ifdef _POSIX_MEMLOCK + if ((munlockall() == -1) && (!getuid())) + post("GrIPD: unable to unlock memory."); +#endif + clock_free(x->x_rclock); + clock_free(x->x_sclock); + clock_free(x->x_connectionClock); + clock_free(x->x_bindClock); + for (i = 0; i < x->x_rcvrListSize; i++) + pd_unbind(&(x->x_rcvrs[i])->r_obj.ob_pd, + x->x_rcvrs[i]->r_sym); + free(x->x_rcvrs); + sprintf(pythExec, "%sgripd", x->x_pythFile); + if (argc > 0) + { + strcpy(filename, argv[0].a_w.w_symbol->s_name); + for (i = 1; i < argc; i++) + if (argv[i].a_type == A_SYMBOL) + sprintf(filename, "%s %s", filename, + argv[i].a_w.w_symbol->s_name); + } + else + strcpy(filename, "0"); + if (filename[0] == '.' && + (filename[1] == '/' || + (filename[1] == '.' && filename[2] == '/'))) + { + sprintf(tempStr, "%s%s", x->x_appPath, filename); + strcpy(filename, tempStr); + } + if (pythExec[0] == '.' && + (pythExec[1] == '/' || + (pythExec[1] == '.' && pythExec[2] == '/'))) + { + sprintf(tempStr, "%s%s", x->x_appPath, pythExec); + strcpy(pythExec, tempStr); + } + /* set x_localOpened before opened since execlp will exit + process on success */ + sprintf(portString, "%d", x->x_port); + sprintf(lockedString, "%d", locked); + if ((execlp(pythExec, pythExec, filename, portString, + "1", lockedString, (char *)0)) == -1) + { + post("GrIPD: Error launching %s", pythExec); + perror(" "); + *(x->x_localOpened) = 0; + exit(1); + } + exit(1); + } + else + { + x->x_childPID = pid; + } + } +#endif + else + { + gripd_show(x); + } +} + +void gripd_closePyth(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (*(x->x_localOpened)) + { + sprintf(buf, "%s%c0%c", CLOSECOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + *(x->x_localOpened) = 0; +#ifdef NT + TerminateProcess(x->x_childProcessInfo.hProcess, 0); +#else + kill(x->x_childPID, SIGKILL); + x->x_childPID = 0; +#endif + } +} + +void gripd_lock(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (x->x_connected) + { + sprintf(buf, "%s%c0%c", LOCKCOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_unlock(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (x->x_connected) + { + sprintf(buf, "%s%c0%c", UNLOCKCOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_hide(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (x->x_connected) + { + sprintf(buf, "%s%c0%c", HIDECOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_show(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (x->x_connected) + { + sprintf(buf, "%s%c0%c", SHOWCOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_openpanel(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (x->x_connected) + { + sprintf(buf, "%s%c0%c", OPENPANELCOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_savepanel(t_gripd *x) +{ + char buf[MAXDATASIZE]; + + if (x->x_connected) + { + sprintf(buf, "%s%c0%c", SAVEPANELCOMMAND, SYMMSGSEP, PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_setTitle(t_gripd *x, t_symbol *sym, int argc, t_atom *argv) +{ + int i; + char title[DEFSTRSIZE]; + char buf[MAXDATASIZE]; + + if (x->x_connected) { + if (argc > 0) + strcpy(title, argv[0].a_w.w_symbol->s_name); + for (i = 1; i < argc; i++) + if (argv[i].a_type == A_SYMBOL) + sprintf(title, "%s %s", title, + argv[i].a_w.w_symbol->s_name); + sprintf(buf, + "%s%c%s%c", + SETTITLECOMMAND, + SYMMSGSEP, + title, + PAIRSEPCHAR); + send(x->x_newSock, buf, strlen(buf), MSG_DONTWAIT | MSG_NOSIGNAL); + } +} + +void gripd_setPath(t_gripd *x, t_symbol *sym, int argc, t_atom *argv) +{ + int i; + if (argc > 0) + strcpy(x->x_pythFile, argv[0].a_w.w_symbol->s_name); + for (i = 1; i < argc; i++) + if (argv[i].a_type == A_SYMBOL) + sprintf(x->x_pythFile, "%s %s", x->x_pythFile, + argv[i].a_w.w_symbol->s_name); + sprintf(x->x_pythFile, "%s/", x->x_pythFile); +} + +void gripd_setPythonPath(t_gripd *x, t_symbol *sym, int argc, t_atom *argv) +{ + int i; + if (argc >0) + strcpy(x->x_pythExec, argv[0].a_w.w_symbol->s_name); + for (i = 1; i < argc; i++) + if (argv[i].a_type == A_SYMBOL) + sprintf(x->x_pythExec, "%s %s", x->x_pythExec, + argv[i].a_w.w_symbol->s_name); + sprintf(x->x_pythExec, "%s/", x->x_pythExec); +} + +void gripd_setSTime(t_gripd *x, t_floatarg val) +{ + if (val > 0) + x->x_sdeltime = val; + else + post("GrIPD: Illegal update time"); +} + +void gripd_setRTime(t_gripd *x, t_floatarg val) +{ + if (val > 0) + x->x_rdeltime = val; + else + post("GrIPD: Illegal update time"); +} + +void gripdR_bang(t_gripdRcvr *r) +{ + char aString[MAXDATASIZE]; + char valueString[MAXDATASIZE]; + + strcpy(aString, r->r_sym->s_name); + sprintf(valueString,"%cbang%c", SYMMSGSEP, PAIRSEPCHAR); + strcat(aString, valueString); + + gripd_appendSendBuffer((t_gripd *)(r->r_x), aString); +} + +void gripdR_float(t_gripdRcvr *r, t_float floatValue) +{ + char aString[MAXDATASIZE]; + char valueString[MAXDATASIZE]; + + strcpy(aString, r->r_sym->s_name); + sprintf(valueString,"%c%g%c", SYMMSGSEP, floatValue, PAIRSEPCHAR); + strcat(aString, valueString); + + gripd_appendSendBuffer((t_gripd *)(r->r_x), aString); +} + +void gripdR_symbol(t_gripdRcvr *r, t_symbol *sym) +{ + char aString[MAXDATASIZE]; + char valueString[MAXDATASIZE]; + + strcpy(aString, r->r_sym->s_name); + sprintf(valueString,"%c%s%c", SYMMSGSEP, sym->s_name, PAIRSEPCHAR); + strcat(aString, valueString); + + gripd_appendSendBuffer((t_gripd *)(r->r_x), aString); +} + +void gripdR_anything(t_gripdRcvr *r, t_symbol *sym, int argc, t_atom *argv) +{ + char aString[MAXDATASIZE]; + char valueString[MAXDATASIZE]; + int i; + + strcpy(aString, r->r_sym->s_name); + sprintf(valueString, "%c%s", SYMMSGSEP, sym->s_name); + strcat(aString, valueString); + for (i = 0; i < argc; i++) + { + if (argv[i].a_type == A_SYMBOL) + { + sprintf(valueString, " %s", argv[i].a_w.w_symbol->s_name); + strcat(aString, valueString); + } + else if (argv[i].a_type == A_FLOAT) + { + sprintf(valueString, " %g", argv[i].a_w.w_float); + strcat(aString, valueString); + } + } + sprintf(aString, "%s%c", aString, PAIRSEPCHAR); + gripd_appendSendBuffer((t_gripd *)(r->r_x), aString); +} + +void gripdR_list(t_gripdRcvr *r, t_symbol *sym, int argc, t_atom *argv) +{ + char aString[MAXDATASIZE]; + char valueString[MAXDATASIZE]; + int i; + + strcpy(aString, r->r_sym->s_name); + sprintf(valueString, "%c", SYMMSGSEP); + strcat(aString, valueString); + for (i = 0; i < argc; i++) + { + if (argv[i].a_type == A_SYMBOL) + { + sprintf(valueString, " %s", argv[i].a_w.w_symbol->s_name); + strcat(aString, valueString); + } + else if (argv[i].a_type == A_FLOAT) + { + sprintf(valueString, " %g", argv[i].a_w.w_float); + strcat(aString, valueString); + } + } + sprintf(aString, "%s%c", aString, PAIRSEPCHAR); + gripd_appendSendBuffer((t_gripd *)(r->r_x), aString); +} + +void gripd_makeGripdRcvr(t_gripd *x, t_symbol *s) +{ + t_gripdRcvr *r = (t_gripdRcvr *)pd_new(gripdRcvr_class); + r->r_sym = s; + pd_bind(&r->r_obj.ob_pd, s); + r->r_x = (t_gripd *)x; + x->x_rcvrs[x->x_rcvrListSize] = r; +} + +int gripd_checkExistance(t_gripd *x, char *name) +{ + int i, flag; + + flag = 0; + for (i = 0; i < x->x_rcvrListSize; i++) + { + if (strcmp(name, x->x_rcvrs[i]->r_sym->s_name) == 0) + flag = 1; + } + return flag; +} + +void gripd_expandRcvrList(t_gripd *x) +{ + x->x_rcvrListMaxSize *= 2; + x->x_rcvrs = (t_gripdRcvr **)realloc(x->x_rcvrs, + x->x_rcvrListMaxSize \ + * sizeof(t_gripdRcvr *)); +} + +void gripd_free(t_gripd *x) +{ + int i; + + if (*(x->x_localOpened)) + gripd_closePyth(x); + if (x->x_connected) + gripd_disconnect(x); + else if (x->x_bound) + gripd_closeSocket(x); + clock_free(x->x_rclock); + clock_free(x->x_sclock); + clock_free(x->x_connectionClock); + clock_free(x->x_bindClock); +#ifdef NT + free(x->x_localOpened); + if (x->x_wsockInitByMe != 0) + WSACleanup(); +#endif + for (i = 0; i < x->x_rcvrListSize; i++) + pd_unbind(&(x->x_rcvrs[i])->r_obj.ob_pd, x->x_rcvrs[i]->r_sym); + free(x->x_rcvrs); +} + +int gripd_isNumeric(char *string) +{ + if ((strspn(string, "0123456789.+-") == strlen(string)) && + (strchr(string, '+') == strrchr(string, '+')) && + (strchr(string, '-') == strrchr(string, '-')) && + (strchr(string, '.') == strrchr(string, '.')) && + (!((strchr(string, '+') != NULL) && + (strchr(string, '-') != NULL)))) + return 1; + else + return 0; +} + +#ifndef NT +void gripd_sigChild(int sig) +{ + wait(NULL); +} +#endif + +void gripd_getApplicationPath(t_gripd *x) +{ + char rawStr[MAXDATASIZE]; +#ifdef NT + GetModuleFileName(NULL, rawStr, sizeof(rawStr)); + rawStr[strrchr(rawStr, '\\') - rawStr + 1] = '\0'; + strcpy(x->x_appPath, rawStr); +#else + char *pathStr; + FILE *fp; + fp = fopen("/proc/self/maps", "r"); + fgets(rawStr, MAXDATASIZE, fp); + fclose(fp); + pathStr = index(rawStr, '/'); + pathStr[index(pathStr, '\n') - pathStr] = '\0'; + pathStr[rindex(pathStr, '/') - pathStr + 1] = '\0'; + strcpy(x->x_appPath, pathStr); +#endif +} + diff --git a/src/gripd.h b/src/gripd.h new file mode 100644 index 0000000..67ef16b --- /dev/null +++ b/src/gripd.h @@ -0,0 +1,227 @@ +/* GrIPD v0.1.1 - Graphical Interface for Pure Data +** Copyright (C) 2003 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** 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, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#include "m_pd.h" +#include +#include +#include +#include +#include +#ifdef NT +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#define VERSION "0.1.1" +#define DEFPORT 0 +/* maxiumum connections */ +#define BACKLOG 1 +/* max size of send buffer */ +#define MAXDATASIZE 16384 +#define MAXPORTSTRLEN 16 +#define MAXSYMNAMELEN 128 +#define MAXSYMVALUELEN 128 +/* separates send/recv object names from value they send/recv */ +#define SYMMSGSEP 31 +/* separates send/recv value pairs */ +#define PAIRSEPCHAR 29 +#define BANGSTRING "bang" +/* if 1st char, indicates send/recv name is actually a command */ +#define COMMANDCHAR '!' +/* command to add value to recv list */ +#define SETRCVRSTRING "!setRcvr" +/* command to close connection */ +#define CLOSECOMMAND "!disconnect" +/* command to close python app */ +#define EXITCOMMAND "!exit" +/* command to lock GUI */ +#define LOCKCOMMAND "!lock" +/* command to unlock GUI */ +#define UNLOCKCOMMAND "!unlock" +/* command to set title */ +#define SETTITLECOMMAND "!settitle" +/* command to hide GUI window */ +#define HIDECOMMAND "!hide" +/* command to show GUI window */ +#define SHOWCOMMAND "!show" +/* command for connection status */ +#define PINGCOMMAND "!ping" +// command to have GUI open a open file dialog +#define OPENPANELCOMMAND "!openpanel" +// command to have GUI open a save file dialog +#define SAVEPANELCOMMAND "!savepanel" +/* initial size of rcvr object list */ +#define DEFLISTSIZE 16 +/* poll time in ms to re-try accept() */ +#define CONNECTIONPOLLTIME 100 +/* blocking time us for accept() */ +#define WAITTIME 1 +/* poll time in ms to re-try bind after "address already in use" */ +#define REBINDTIME 1000 +/* default receive poll time in ms */ +#define DEFRDELTIME 5 +#define DEFSDELTIME 1 +/* default send poll time in ms */ +#define DEFSTRSIZE 256 +#define MAXALISTLEN 64 + +#ifdef NT +#define MSG_DONTWAIT 0 +#define MSG_NOSIGNAL 0 +#define MSG_WAITALL 0 +#else +#define SOCKET_ERROR -1 +#endif + +/* Individual "receive" class */ +typedef struct _gripdRcvr +{ + t_object r_obj; + t_symbol *r_sym; + /* gripd object, needed so recevied symbol functions can access + gripd data (socket)*/ + void *r_x; +}t_gripdRcvr; + +/* Main object class */ +typedef struct _gripd +{ + t_object t_ob; + t_outlet *x_outlet2; + unsigned short int x_port; +#ifdef NT + SOCKET x_sock; + SOCKET x_newSock; + /* for Windows, 1 if WSAStartup is called */ + int x_wsockInitByMe; + PROCESS_INFORMATION x_childProcessInfo; +#else + int x_sock; + int x_newSock; + int x_childPID; +#endif + /* 1 if socket has been bound, 0 otherwise */ + int x_bound; + /* 1 if currently connected, 0 otherwise */ + int x_connected; + /* 1 if PD opened python app, otherwise (shared mem for linux)*/ + int *x_localOpened; + /* timer for receiveing/sending */ + t_clock *x_rclock; + t_clock *x_sclock; + /* timer for polling accept() */ + t_clock *x_connectionClock; + /* timer for re-binding after "address already in use" error */ + t_clock *x_bindClock; + /* path to python.exe for Windows */ + char x_pythExec[DEFSTRSIZE]; + /* path to gripd.py (or gripd.exe and gripd.py in Windows) */ + char x_pythFile[DEFSTRSIZE]; + /* send/receive poll times */ + double x_sdeltime; + double x_rdeltime; + /* current number of receive "objects" being used */ + int x_rcvrListSize; + /* size currently allocated for receiver objects */ + int x_rcvrListMaxSize; + /* pointer to list of receiver objects */ + t_gripdRcvr **x_rcvrs; + /* buffer to be sent */ + char x_sendBuffer[MAXDATASIZE]; + /* path to application */ + char x_appPath[MAXDATASIZE]; +}t_gripd; + +t_class *gripd_class; +t_class *gripdRcvr_class; + +void gripd_setup(void); +void *gripd_new(t_floatarg port); +void gripd_connect(t_gripd *x); +/* initialize "server" */ +void gripd_openSocket(t_gripd *x); +/* shutdown server */ +void gripd_disconnect(t_gripd *x); +/* poll accept() */ +void gripd_trySocket(t_gripd *x); +void gripd_closeSocket(t_gripd *x); +void gripd_recv(t_gripd *x); +void gripd_send(t_gripd *x); +/* add name:value pair to send string */ +void gripd_appendSendBuffer(t_gripd *x, char *aString); +/* open gripd.py (or gripd.exe inWindows) unlocked mode*/ +void gripd_open(t_gripd *x, t_symbol *sym, int argc, t_atom *argv); +/* open gripd.py (or gripd.exe inWindows) locked mode*/ +void gripd_openLocked(t_gripd *x, t_symbol *sym, int argc, t_atom *argv); +/* actually open gripd.py (or gripd.exe inWindows)*/ +void gripd_openPyth(t_gripd *x, t_symbol *sym, int argc, + t_atom *argv, int locked); +/* tell python app to close itself */ +void gripd_closePyth(t_gripd *x); +/* lock GUI */ +void gripd_lock(t_gripd *x); +/* unlock GUI */ +void gripd_unlock(t_gripd *x); +/* hide GUI */ +void gripd_hide(t_gripd *x); +/* show GUI */ +void gripd_show(t_gripd *x); +/* set GUI window title */ +void gripd_setTitle(t_gripd *x, t_symbol *sym, int argc, t_atom *argv); +/* set path to gripd.py (or gripd.exe in Windows) */ +void gripd_setPath(t_gripd *x, t_symbol *sym, int argc, t_atom *argv); +/* set path to python.exe for Windows */ +void gripd_setPythonPath(t_gripd *x, t_symbol *sym, int argc, + t_atom *argv); +void gripd_setSTime(t_gripd *x, t_floatarg val); +void gripd_setRTime(t_gripd *x, t_floatarg val); +void gripd_openpanel(t_gripd *x); +void gripd_savepanel(t_gripd *x); +void gripdR_bang(t_gripdRcvr *r); +void gripdR_float(t_gripdRcvr *r, t_float floatValue); +void gripdR_symbol(t_gripdRcvr *r, t_symbol *sym); +void gripdR_anything(t_gripdRcvr *r, t_symbol *sym, int argc, + t_atom *argv); +void gripdR_list(t_gripdRcvr *r, t_symbol *sym, int argc, t_atom *argv); +/* instantiate new rcv object */ +void gripd_makeGripdRcvr(t_gripd *x, t_symbol *s); +/* check is rcv object has already been created */ +int gripd_checkExistance(t_gripd *x, char *name); +/* allocate more mem for recv objects */ +void gripd_expandRcvrList(t_gripd *x); +void gripd_free(t_gripd *x); +int gripd_isNumeric(char *string); +#ifndef NT +void gripd_sigChild(int signum); +#endif +void gripd_getApplicationPath(t_gripd *x); diff --git a/src/joystick.c b/src/joystick.c new file mode 100644 index 0000000..02fddb7 --- /dev/null +++ b/src/joystick.c @@ -0,0 +1,296 @@ +/* GrIPD v0.1.1 - Graphical Interface for Pure Data +** Copyright (C) 2002 Joseph A. Sarlo +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#include +#define MAXEVENTS 4096 +#define MAXDEVS 16 +#ifdef NT +#include +#include +#include +#include +#define MAX_AXIS_OUTS 10 +#define MAX_BUTTON_OUTS 32 +#else +#include +#include +#include +#include +#include +#include +#define JOYSTICK_DEVICE "/dev/js0" +#define JS_EVENT_BUTTON 0x01 +#define JS_EVENT_AXIS 0x02 +#define JS_EVENT_INTI 0x80 +#define DEFSCALE 1 +#define DEFTRANSLATION 0 +#define JSIOCGAXES _IOR('j', 0x11, unsigned char) +#define JSIOCGBUTTONS _IOR('j', 0x12, unsigned char) +#define MAXAXES 4 +#endif + +static int eventValue[MAXEVENTS][MAXDEVS]; +static int eventNumber[MAXEVENTS][MAXDEVS]; +static int eventType[MAXEVENTS][MAXDEVS]; +static int eventCount[MAXDEVS]; +static int devCount = 0; +static int devList[MAXDEVS]; +#ifdef NT +static JOYINFOEX joyInfoEx[MAXDEVS]; +static int joyDevNum[MAXDEVS]; +static int joy_buttons[MAXDEVS]; +static int joy_axes[MAXDEVS]; +static int button_val[MAX_BUTTON_OUTS][MAXDEVS]; +static int axis_val[MAX_AXIS_OUTS][MAXDEVS]; +/* FIXME */ +static DWORD *axes_ptr[MAX_AXIS_OUTS][MAXDEVS]; +#else +static int joy_fd[MAXDEVS]; +struct js_event +{ + unsigned int time; + signed short value; + unsigned char type; + unsigned char number; +}; +static struct js_event joy_e[MAXDEVS]; +#endif + +#ifdef NT +extern "C" { +#endif + +int closeDevice(int devno) +{ + if (devList[devno]) + { + devCount--; + devList[devno] = 0; +#ifdef NT + return (1); +#else + if (close(joy_fd[devno]) < 0) + return (0); + else + { + joy_fd[devno] = -1; + return(1); + } +#endif + } +} + +int openDevice(char *dev) +{ +#ifdef NT + int i, num_axes, num_buttons, devId; + JOYCAPS jscaps; + MMRESULT errCode; + if (devCount == 0) + { + for (i = 0; i < MAXDEVS; i++) + { + devList[i] = 0; + } + } + for (i = 0; i < MAXDEVS; i++) + { + if (devList[i] == 0) + { + devId = i; + i = MAXDEVS; + } + } + joyInfoEx[devId].dwSize = sizeof(joyInfoEx); + joyInfoEx[devId].dwFlags = JOY_RETURNALL; + joyDevNum[devId] = (JOYSTICKID1 - 1) + atoi(dev); + errCode = joyGetPosEx(joyDevNum[devId], &joyInfoEx[devId]); + if ((errCode == MMSYSERR_NOERROR) && (devCount < MAXDEVS)) + { + joyGetDevCaps(joyDevNum[devId], &jscaps, sizeof(jscaps)); + if (jscaps.wNumAxes > MAX_AXIS_OUTS) + joy_axes[devId] = MAX_AXIS_OUTS; + else + joy_axes[devId] = jscaps.wNumAxes; + if (jscaps.wNumButtons > MAX_BUTTON_OUTS) + joy_buttons[devId] = MAX_BUTTON_OUTS; + else + joy_buttons[devId] = jscaps.wNumButtons; + for (i = 0; i < joy_axes[devId]; i++) + axis_val[i][devId] = 0; + for (i = 0; i < joy_buttons[devId]; i++) + button_val[i][devId] = 0; + axes_ptr[0][devId] = &(joyInfoEx[devId].dwXpos); + axes_ptr[1][devId] = &(joyInfoEx[devId].dwYpos); + axes_ptr[2][devId] = &(joyInfoEx[devId].dwZpos); + axes_ptr[3][devId] = &(joyInfoEx[devId].dwRpos); + axes_ptr[4][devId] = &(joyInfoEx[devId].dwUpos); + axes_ptr[5][devId] = &(joyInfoEx[devId].dwVpos); + eventCount[devId] = 0; + devCount++; + devList[devId] = 1; + return (devId); + } + else + return (-1); +#else + int i, devId; + char joy_dev[256]; + + if (devCount == 0) + { + for (i = 0; i < MAXDEVS; i++) + { + devList[i] = 0; + } + } + for (i = 0; i < MAXDEVS; i++) + { + if (devList[i] == 0) + { + devId = i; + i = MAXDEVS; + } + } + if (strcmp(dev, "") == 0) + strcpy(joy_dev, JOYSTICK_DEVICE); + else + strcpy(joy_dev, dev); + joy_fd[devId] = open (joy_dev, O_RDONLY | O_NONBLOCK); + if ((joy_fd[devId] == -1) || (devCount >= MAXDEVS)) + { + return (-1); + } + else + { + devCount++; + eventCount[devId] = 0; + devList[devId] = 1; + return (devId); + } +#endif +} + +int readEvents(int devno) +{ +#ifdef NT + int i; + + eventCount[devno] = 0; + joyGetPosEx(joyDevNum[devno], &(joyInfoEx[devno])); + for (i = 0; i < joy_axes[devno]; i++) + if (((int)(*(axes_ptr[i][devno])) != axis_val[i][devno]) && + (eventCount[devno] < MAXEVENTS)) + { + eventType[eventCount[devno]][devno] = 0; + eventNumber[eventCount[devno]][devno] = i; + eventValue[eventCount[devno]][devno] = (int)(*(axes_ptr[i][devno])); + eventCount[devno]++; + axis_val[i][devno] = (int)(*(axes_ptr[i][devno])); + } + for (i = 0; i < joy_buttons[devno]; i ++) + { + if (joyInfoEx[devno].dwButtons & (1 << i)) + { + if ((button_val[i][devno] == 0) && (eventCount[devno] < MAXEVENTS)) + { + eventType[eventCount[devno]][devno] = 1; + eventNumber[eventCount[devno]][devno] = i; + eventValue[eventCount[devno]][devno] = 1; + eventCount[devno]++; + button_val[i][devno] = 1; + } + } + else + if ((button_val[i][devno] == 1) && (eventCount[devno] < MAXEVENTS)) + { + eventType[eventCount[devno]][devno] = 1; + eventNumber[eventCount[devno]][devno] = i; + eventValue[eventCount[devno]][devno] = 0; + eventCount[devno]++; + button_val[i][devno] = 0; + } + } + return (eventCount[devno]); +#else + int i; + + eventCount[devno] = 0; + if (joy_fd[devno] > -1) + { + while (read (joy_fd[devno], &(joy_e[devno]), sizeof(struct js_event)) > -1) + { + if (eventCount[devno] < MAXEVENTS) + { + if (joy_e[devno].type == JS_EVENT_AXIS) + eventType[eventCount[devno]][devno] = 0; + if (joy_e[devno].type == JS_EVENT_BUTTON) + eventType[eventCount[devno]][devno] = 1; + eventNumber[eventCount[devno]][devno] = joy_e[devno].number; + eventValue[eventCount[devno]][devno] = joy_e[devno].value; + eventCount[devno]++; + } + } + } + return eventCount[devno]; +#endif +} + +int getEventCount(int devno) +{ + return (eventCount[devno]); +} + +int getEventType(int devno, int eNum) +{ + int returnVal = 0; + + if (eNum >= 0 && eNum < eventCount[devno]) + { + returnVal = eventType[eNum][devno]; + } + return (returnVal); +} + +int getEventNumber(int devno, int eNum) +{ + int returnVal = 0; + + if (eNum >= 0 && eNum < eventCount[devno]) + { + returnVal = eventNumber[eNum][devno]; + } + return (returnVal); +} + +int getEventValue(int devno, int eNum) +{ + int returnVal = 0; + + if (eNum >= 0 && eNum < eventCount[devno]) + { + returnVal = eventValue[eNum][devno]; + } + return (returnVal); +} +#ifdef NT +} +#endif + diff --git a/src/joystick_wrap.c b/src/joystick_wrap.c new file mode 100644 index 0000000..b2e2087 --- /dev/null +++ b/src/joystick_wrap.c @@ -0,0 +1,692 @@ +/* + * FILE : joystick_wrap.c + * + * This file was automatically generated by : + * Simplified Wrapper and Interface Generator (SWIG) + * Version 1.1 (Patch 5) + * + * Portions Copyright (c) 1995-1998 + * The University of Utah and The Regents of the University of California. + * Permission is granted to distribute this file in any manner provided + * this notice remains intact. + * + * Do not make changes to this file--changes will be lost! + * + */ + + +#define SWIGCODE +/* Implementation : PYTHON */ + +#define SWIGPYTHON +#include +#include +/*********************************************************************** + * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/joystick_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $ + * swig_lib/python/python.cfg + * + * This file contains coded needed to add variable linking to the + * Python interpreter. C variables are added as a new kind of Python + * datatype. + * + * Also contains supporting code for building python under Windows + * and things like that. + * + * $Log: not supported by cvs2svn $ + ************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif +#include "Python.h" +#ifdef __cplusplus +} +#endif + +/* Definitions for Windows/Unix exporting */ +#if defined(__WIN32__) +# if defined(_MSC_VER) +# define SWIGEXPORT(a,b) __declspec(dllexport) a b +# else +# if defined(__BORLANDC__) +# define SWIGEXPORT(a,b) a _export b +# else +# define SWIGEXPORT(a,b) a b +# endif +# endif +#else +# define SWIGEXPORT(a,b) a b +#endif + +#ifdef SWIG_GLOBAL +#ifdef __cplusplus +#define SWIGSTATIC extern "C" +#else +#define SWIGSTATIC +#endif +#endif + +#ifndef SWIGSTATIC +#define SWIGSTATIC static +#endif + +typedef struct { + char *name; + PyObject *(*get_attr)(void); + int (*set_attr)(PyObject *); +} swig_globalvar; + +typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar **vars; + int nvars; + int maxvars; +} swig_varlinkobject; + +/* ---------------------------------------------------------------------- + swig_varlink_repr() + + Function for python repr method + ---------------------------------------------------------------------- */ + +static PyObject * +swig_varlink_repr(swig_varlinkobject *v) +{ + v = v; + return PyString_FromString(""); +} + +/* --------------------------------------------------------------------- + swig_varlink_print() + + Print out all of the global variable names + --------------------------------------------------------------------- */ + +static int +swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) +{ + + int i = 0; + flags = flags; + fprintf(fp,"Global variables { "); + while (v->vars[i]) { + fprintf(fp,"%s", v->vars[i]->name); + i++; + if (v->vars[i]) fprintf(fp,", "); + } + fprintf(fp," }\n"); + return 0; +} + +/* -------------------------------------------------------------------- + swig_varlink_getattr + + This function gets the value of a variable and returns it as a + PyObject. In our case, we'll be looking at the datatype and + converting into a number or string + -------------------------------------------------------------------- */ + +static PyObject * +swig_varlink_getattr(swig_varlinkobject *v, char *n) +{ + int i = 0; + char temp[128]; + + while (v->vars[i]) { + if (strcmp(v->vars[i]->name,n) == 0) { + return (*v->vars[i]->get_attr)(); + } + i++; + } + sprintf(temp,"C global variable %s not found.", n); + PyErr_SetString(PyExc_NameError,temp); + return NULL; +} + +/* ------------------------------------------------------------------- + swig_varlink_setattr() + + This function sets the value of a variable. + ------------------------------------------------------------------- */ + +static int +swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) +{ + char temp[128]; + int i = 0; + while (v->vars[i]) { + if (strcmp(v->vars[i]->name,n) == 0) { + return (*v->vars[i]->set_attr)(p); + } + i++; + } + sprintf(temp,"C global variable %s not found.", n); + PyErr_SetString(PyExc_NameError,temp); + return 1; +} + +statichere PyTypeObject varlinktype = { +/* PyObject_HEAD_INIT(&PyType_Type) Note : This doesn't work on some machines */ + PyObject_HEAD_INIT(0) + 0, + "varlink", /* Type name */ + sizeof(swig_varlinkobject), /* Basic size */ + 0, /* Itemsize */ + 0, /* Deallocator */ + (printfunc) swig_varlink_print, /* Print */ + (getattrfunc) swig_varlink_getattr, /* get attr */ + (setattrfunc) swig_varlink_setattr, /* Set attr */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_mapping*/ + 0, /* tp_hash */ +}; + +/* Create a variable linking object for use later */ + +SWIGSTATIC PyObject * +SWIG_newvarlink(void) +{ + swig_varlinkobject *result = 0; + result = PyMem_NEW(swig_varlinkobject,1); + varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */ + result->ob_type = &varlinktype; + /* _Py_NewReference(result); Does not seem to be necessary */ + result->nvars = 0; + result->maxvars = 64; + result->vars = (swig_globalvar **) malloc(64*sizeof(swig_globalvar *)); + result->vars[0] = 0; + result->ob_refcnt = 0; + Py_XINCREF((PyObject *) result); + return ((PyObject*) result); +} + +SWIGSTATIC void +SWIG_addvarlink(PyObject *p, char *name, + PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) +{ + swig_varlinkobject *v; + v= (swig_varlinkobject *) p; + + if (v->nvars >= v->maxvars -1) { + v->maxvars = 2*v->maxvars; + v->vars = (swig_globalvar **) realloc(v->vars,v->maxvars*sizeof(swig_globalvar *)); + if (v->vars == NULL) { + fprintf(stderr,"SWIG : Fatal error in initializing Python module.\n"); + exit(1); + } + } + v->vars[v->nvars] = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + v->vars[v->nvars]->name = (char *) malloc(strlen(name)+1); + strcpy(v->vars[v->nvars]->name,name); + v->vars[v->nvars]->get_attr = get_attr; + v->vars[v->nvars]->set_attr = set_attr; + v->nvars++; + v->vars[v->nvars] = 0; +} + + + +/***************************************************************************** + * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/joystick_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $ + * + * swigptr.swg + * + * This file contains supporting code for the SWIG run-time type checking + * mechanism. The following functions are available : + * + * SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *)); + * + * Registers a new type-mapping with the type-checker. origtype is the + * original datatype and newtype is an equivalent type. cast is optional + * pointer to a function to cast pointer values between types (this + * is typically used to cast pointers from derived classes to base classes in C++) + * + * SWIG_MakePtr(char *buffer, void *ptr, char *typestring); + * + * Makes a pointer string from a pointer and typestring. The result is returned + * in buffer which is assumed to hold enough space for the result. + * + * char * SWIG_GetPtr(char *buffer, void **ptr, char *type) + * + * Gets a pointer value from a string. If there is a type-mismatch, returns + * a character string to the received type. On success, returns NULL. + * + * + * You can remap these functions by making a file called "swigptr.swg" in + * your the same directory as the interface file you are wrapping. + * + * These functions are normally declared static, but this file can be + * can be used in a multi-module environment by redefining the symbol + * SWIGSTATIC. + *****************************************************************************/ + +#include + +#ifdef SWIG_GLOBAL +#ifdef __cplusplus +#define SWIGSTATIC extern "C" +#else +#define SWIGSTATIC +#endif +#endif + +#ifndef SWIGSTATIC +#define SWIGSTATIC static +#endif + + +/* SWIG pointer structure */ + +typedef struct SwigPtrType { + char *name; /* Datatype name */ + int len; /* Length (used for optimization) */ + void *(*cast)(void *); /* Pointer casting function */ + struct SwigPtrType *next; /* Linked list pointer */ +} SwigPtrType; + +/* Pointer cache structure */ + +typedef struct { + int stat; /* Status (valid) bit */ + SwigPtrType *tp; /* Pointer to type structure */ + char name[256]; /* Given datatype name */ + char mapped[256]; /* Equivalent name */ +} SwigCacheType; + +/* Some variables */ + +static int SwigPtrMax = 64; /* Max entries that can be currently held */ + /* This value may be adjusted dynamically */ +static int SwigPtrN = 0; /* Current number of entries */ +static int SwigPtrSort = 0; /* Status flag indicating sort */ +static int SwigStart[256]; /* Starting positions of types */ + +/* Pointer table */ +static SwigPtrType *SwigPtrTable = 0; /* Table containing pointer equivalences */ + +/* Cached values */ + +#define SWIG_CACHESIZE 8 +#define SWIG_CACHEMASK 0x7 +static SwigCacheType SwigCache[SWIG_CACHESIZE]; +static int SwigCacheIndex = 0; +static int SwigLastCache = 0; + +/* Sort comparison function */ +static int swigsort(const void *data1, const void *data2) { + SwigPtrType *d1 = (SwigPtrType *) data1; + SwigPtrType *d2 = (SwigPtrType *) data2; + return strcmp(d1->name,d2->name); +} + +/* Binary Search function */ +static int swigcmp(const void *key, const void *data) { + char *k = (char *) key; + SwigPtrType *d = (SwigPtrType *) data; + return strncmp(k,d->name,d->len); +} + +/* Register a new datatype with the type-checker */ + +SWIGSTATIC +void SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *)) { + + int i; + SwigPtrType *t = 0,*t1; + + /* Allocate the pointer table if necessary */ + + if (!SwigPtrTable) { + SwigPtrTable = (SwigPtrType *) malloc(SwigPtrMax*sizeof(SwigPtrType)); + SwigPtrN = 0; + } + /* Grow the table */ + if (SwigPtrN >= SwigPtrMax) { + SwigPtrMax = 2*SwigPtrMax; + SwigPtrTable = (SwigPtrType *) realloc((char *) SwigPtrTable,SwigPtrMax*sizeof(SwigPtrType)); + } + for (i = 0; i < SwigPtrN; i++) + if (strcmp(SwigPtrTable[i].name,origtype) == 0) { + t = &SwigPtrTable[i]; + break; + } + if (!t) { + t = &SwigPtrTable[SwigPtrN]; + t->name = origtype; + t->len = strlen(t->name); + t->cast = 0; + t->next = 0; + SwigPtrN++; + } + + /* Check for existing entry */ + + while (t->next) { + if ((strcmp(t->name,newtype) == 0)) { + if (cast) t->cast = cast; + return; + } + t = t->next; + } + + /* Now place entry (in sorted order) */ + + t1 = (SwigPtrType *) malloc(sizeof(SwigPtrType)); + t1->name = newtype; + t1->len = strlen(t1->name); + t1->cast = cast; + t1->next = 0; + t->next = t1; + SwigPtrSort = 0; +} + +/* Make a pointer value string */ + +SWIGSTATIC +void SWIG_MakePtr(char *_c, const void *_ptr, char *type) { + static char _hex[16] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + unsigned long _p, _s; + char _result[20], *_r; /* Note : a 64-bit hex number = 16 digits */ + _r = _result; + _p = (unsigned long) _ptr; + if (_p > 0) { + while (_p > 0) { + _s = _p & 0xf; + *(_r++) = _hex[_s]; + _p = _p >> 4; + } + *_r = '_'; + while (_r >= _result) + *(_c++) = *(_r--); + } else { + strcpy (_c, "NULL"); + } + if (_ptr) + strcpy (_c, type); +} + +/* Define for backwards compatibility */ + +#define _swig_make_hex SWIG_MakePtr + +/* Function for getting a pointer value */ + +SWIGSTATIC +char *SWIG_GetPtr(char *_c, void **ptr, char *_t) +{ + unsigned long _p; + char temp_type[256]; + char *name; + int i, len; + SwigPtrType *sp,*tp; + SwigCacheType *cache; + int start, end; + _p = 0; + + /* Pointer values must start with leading underscore */ + if (*_c == '_') { + _c++; + /* Extract hex value from pointer */ + while (*_c) { + if ((*_c >= '0') && (*_c <= '9')) + _p = (_p << 4) + (*_c - '0'); + else if ((*_c >= 'a') && (*_c <= 'f')) + _p = (_p << 4) + ((*_c - 'a') + 10); + else + break; + _c++; + } + + if (_t) { + if (strcmp(_t,_c)) { + if (!SwigPtrSort) { + qsort((void *) SwigPtrTable, SwigPtrN, sizeof(SwigPtrType), swigsort); + for (i = 0; i < 256; i++) { + SwigStart[i] = SwigPtrN; + } + for (i = SwigPtrN-1; i >= 0; i--) { + SwigStart[(int) (SwigPtrTable[i].name[1])] = i; + } + for (i = 255; i >= 1; i--) { + if (SwigStart[i-1] > SwigStart[i]) + SwigStart[i-1] = SwigStart[i]; + } + SwigPtrSort = 1; + for (i = 0; i < SWIG_CACHESIZE; i++) + SwigCache[i].stat = 0; + } + + /* First check cache for matches. Uses last cache value as starting point */ + cache = &SwigCache[SwigLastCache]; + for (i = 0; i < SWIG_CACHESIZE; i++) { + if (cache->stat) { + if (strcmp(_t,cache->name) == 0) { + if (strcmp(_c,cache->mapped) == 0) { + cache->stat++; + *ptr = (void *) _p; + if (cache->tp->cast) *ptr = (*(cache->tp->cast))(*ptr); + return (char *) 0; + } + } + } + SwigLastCache = (SwigLastCache+1) & SWIG_CACHEMASK; + if (!SwigLastCache) cache = SwigCache; + else cache++; + } + /* We have a type mismatch. Will have to look through our type + mapping table to figure out whether or not we can accept this datatype */ + + start = SwigStart[(int) _t[1]]; + end = SwigStart[(int) _t[1]+1]; + sp = &SwigPtrTable[start]; + while (start < end) { + if (swigcmp(_t,sp) == 0) break; + sp++; + start++; + } + if (start >= end) sp = 0; + /* Try to find a match for this */ + if (sp) { + while (swigcmp(_t,sp) == 0) { + name = sp->name; + len = sp->len; + tp = sp->next; + /* Try to find entry for our given datatype */ + while(tp) { + if (tp->len >= 255) { + return _c; + } + strcpy(temp_type,tp->name); + strncat(temp_type,_t+len,255-tp->len); + if (strcmp(_c,temp_type) == 0) { + + strcpy(SwigCache[SwigCacheIndex].mapped,_c); + strcpy(SwigCache[SwigCacheIndex].name,_t); + SwigCache[SwigCacheIndex].stat = 1; + SwigCache[SwigCacheIndex].tp = tp; + SwigCacheIndex = SwigCacheIndex & SWIG_CACHEMASK; + + /* Get pointer value */ + *ptr = (void *) _p; + if (tp->cast) *ptr = (*(tp->cast))(*ptr); + return (char *) 0; + } + tp = tp->next; + } + sp++; + /* Hmmm. Didn't find it this time */ + } + } + /* Didn't find any sort of match for this data. + Get the pointer value and return the received type */ + *ptr = (void *) _p; + return _c; + } else { + /* Found a match on the first try. Return pointer value */ + *ptr = (void *) _p; + return (char *) 0; + } + } else { + /* No type specified. Good luck */ + *ptr = (void *) _p; + return (char *) 0; + } + } else { + if (strcmp (_c, "NULL") == 0) { + *ptr = (void *) 0; + return (char *) 0; + } + *ptr = (void *) 0; + return _c; + } +} + +/* Compatibility mode */ + +#define _swig_get_hex SWIG_GetPtr + +#define SWIG_init initjoystick + +#define SWIG_name "joystick" + +extern int closeDevice(int); +extern int openDevice(char *); +extern int readEvents(int); +extern int getEventCount(int); +extern int getEventType(int, int); +extern int getEventNumber(int, int); +extern int getEventValue(int, int); +static PyObject *_wrap_closeDevice(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:closeDevice",&_arg0)) + return NULL; + _result = (int )closeDevice(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_openDevice(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + char * _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"s:openDevice",&_arg0)) + return NULL; + _result = (int )openDevice(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_readEvents(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:readEvents",&_arg0)) + return NULL; + _result = (int )readEvents(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventCount(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:getEventCount",&_arg0)) + return NULL; + _result = (int )getEventCount(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventType(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventType",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventType(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventNumber(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventNumber",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventNumber(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventValue(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventValue",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventValue(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyMethodDef joystickMethods[] = { + { "getEventValue", _wrap_getEventValue, 1 }, + { "getEventNumber", _wrap_getEventNumber, 1 }, + { "getEventType", _wrap_getEventType, 1 }, + { "getEventCount", _wrap_getEventCount, 1 }, + { "readEvents", _wrap_readEvents, 1 }, + { "openDevice", _wrap_openDevice, 1 }, + { "closeDevice", _wrap_closeDevice, 1 }, + { NULL, NULL } +}; +static PyObject *SWIG_globals; +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT(void,initjoystick)() { + PyObject *m, *d; + SWIG_globals = SWIG_newvarlink(); + m = Py_InitModule("joystick", joystickMethods); + d = PyModule_GetDict(m); +/* + * These are the pointer type-equivalency mappings. + * (Used by the SWIG pointer type-checker). + */ + SWIG_RegisterMapping("_signed_long","_long",0); + SWIG_RegisterMapping("_long","_unsigned_long",0); + SWIG_RegisterMapping("_long","_signed_long",0); + SWIG_RegisterMapping("_unsigned_long","_long",0); + SWIG_RegisterMapping("_signed_int","_int",0); + SWIG_RegisterMapping("_unsigned_short","_short",0); + SWIG_RegisterMapping("_signed_short","_short",0); + SWIG_RegisterMapping("_unsigned_int","_int",0); + SWIG_RegisterMapping("_short","_unsigned_short",0); + SWIG_RegisterMapping("_short","_signed_short",0); + SWIG_RegisterMapping("_int","_unsigned_int",0); + SWIG_RegisterMapping("_int","_signed_int",0); +} diff --git a/src/makefile b/src/makefile new file mode 100644 index 0000000..8930736 --- /dev/null +++ b/src/makefile @@ -0,0 +1,44 @@ +#-------------------------------------------------------------- + +current: gripd_linux +clean: clean_linux + +#----------- Options (all OS) -------------------------------- + +MIDI = TRUE +#MIDI = FALSE +JOYSTICK = TRUE +#JOYSTICK = FALSE + +#----------- Settings (Linux) -------------------------------- + +MIDIOSSUBTYPE = ALSA +#MIDIOSSUBTYPE = OSS +PDINCLUDE = -I../../src +LINUXPYTHONINCLUDE = -I/usr/include/python2.2 +SYSTEMLIBDIR = /usr/lib + +#----------- Settings (Windows) ------------------------------- + +VC = "C:\Program Files\Microsoft Visual Studio\VC98" +PYTHONHOME = C:\python22 +PYTHONVER = 22 +PDNTSRCDIR = C:\pd-37\src +PDNTLDIR = C:\pd-37\bin + +#----------- Linux -------------------------------------------- + +gripd_linux: + make -f Makefile.Linux all +clean_linux: + make -f Makefile.Linux linux_clean + +#----------- Win32--------------------------------------------- + +gripd_nt: + nmake -f Makefile.NT all +clean_nt: + nmake -f Makefile.NT nt_clean + + + diff --git a/src/midi.cpp b/src/midi.cpp new file mode 100644 index 0000000..1d63446 --- /dev/null +++ b/src/midi.cpp @@ -0,0 +1,146 @@ +/* GrIPD v0.1.1 - Graphical Interface for Pure Data +** Copyright (C) 2003 Joseph A. Sarlo +** +** 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 2 +** 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, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#include "midiiolib.h" +#include +#ifndef NT +#include +#endif +#define MAXDEVS 16 +#define MAXEVENTS 4096 + +#ifndef VISUAL +using namespace std; +#endif + +static int eventCount[MAXDEVS]; +static int eventCommand[MAXEVENTS][MAXDEVS]; +static int eventP0[MAXEVENTS][MAXDEVS]; +static int eventP1[MAXEVENTS][MAXDEVS]; +static int eventP2[MAXEVENTS][MAXDEVS]; +static int eventP3[MAXEVENTS][MAXDEVS]; +static MidiInput mInput[MAXDEVS]; +static int devCount = 0; +static int devList[MAXDEVS]; + +int openDevice(int dev) { + int i, devId, numPorts; + + numPorts = MidiInPort::getNumPorts(); + if (dev >= numPorts || dev < 0) { + return (-1); + } + else { + if (devCount == 0) { + for (i = 0; i < MAXDEVS; i++) { + devList[i] = 0; + } + } + for (i = 0; i < MAXDEVS; i++) { + if (devList[i] == 0) { + devId = i; + i = MAXDEVS; + } + } + devCount++; + eventCount[devId] = 0; + devList[devId] = 1; + mInput[devId].setPort(dev); + mInput[devId].open(); + return (devId); + } +} + +int closeDevice(int devno) { + if (devList[devno]) { + devCount--; + devList[devno] = 0; +#ifndef LINUX + mInput[devno].close(); +#endif + return (1); + } + else + return (-1); +} + +int readEvents(int devno) { + int i; + MidiMessage message; + + if (devno < 0 || devno >= MAXDEVS) + return (-1); + eventCount[devno] = mInput[devno].getCount(); + if (eventCount[devno] > MAXEVENTS) { + eventCount[devno] = MAXEVENTS; + } + for (i = 0; i < eventCount[devno]; i++) { + message = mInput[devno].extract(); + eventCommand[i][devno] = message.getCommand(); + eventP0[i][devno] = message.getP0(); + eventP1[i][devno] = message.getP1(); + eventP2[i][devno] = message.getP2(); + eventP3[i][devno] = message.getP3(); + } + return (eventCount[devno]); +} + +int getEventCount(int devno) { + if (devno < 0 || devno >= MAXDEVS) + return (-1); + else + return (eventCount[devno]); +} + +int getEventCommand(int devno, int eNum) { + if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS) + return (-1); + else + return eventCommand[eNum][devno]; +} + +int getEventP0(int devno, int eNum) { + if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS) + return (-1); + else + return eventP0[eNum][devno]; +} + +int getEventP1(int devno, int eNum) { + if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS) + return (-1); + else + return eventP1[eNum][devno]; +} + +int getEventP2(int devno, int eNum) { + if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS) + return (-1); + else + return eventP2[eNum][devno]; +} + +int getEventP3(int devno, int eNum) { + if (eNum < 0 || eNum >= eventCount[devno] || devno < 0 || devno >= MAXDEVS) + return (-1); + else + return eventP3[eNum][devno]; +} + diff --git a/src/midi_wrap.c b/src/midi_wrap.c new file mode 100644 index 0000000..7b4ad15 --- /dev/null +++ b/src/midi_wrap.c @@ -0,0 +1,723 @@ +/* + * FILE : midi_wrap.c + * + * This file was automatically generated by : + * Simplified Wrapper and Interface Generator (SWIG) + * Version 1.1 (Patch 5) + * + * Portions Copyright (c) 1995-1998 + * The University of Utah and The Regents of the University of California. + * Permission is granted to distribute this file in any manner provided + * this notice remains intact. + * + * Do not make changes to this file--changes will be lost! + * + */ + + +#define SWIGCODE +/* Implementation : PYTHON */ + +#define SWIGPYTHON +#include +#include +/*********************************************************************** + * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/midi_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $ + * swig_lib/python/python.cfg + * + * This file contains coded needed to add variable linking to the + * Python interpreter. C variables are added as a new kind of Python + * datatype. + * + * Also contains supporting code for building python under Windows + * and things like that. + * + * $Log: not supported by cvs2svn $ + ************************************************************************/ + +#ifdef __cplusplus +#include "Python.h" +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +/* Definitions for Windows/Unix exporting */ +#if defined(__WIN32__) +# if defined(_MSC_VER) +# define SWIGEXPORT(a,b) __declspec(dllexport) a b +# else +# if defined(__BORLANDC__) +# define SWIGEXPORT(a,b) a _export b +# else +# define SWIGEXPORT(a,b) a b +# endif +# endif +#else +# define SWIGEXPORT(a,b) a b +#endif + +#ifdef SWIG_GLOBAL +#ifdef __cplusplus +#define SWIGSTATIC extern "C" +#else +#define SWIGSTATIC +#endif +#endif + +#ifndef SWIGSTATIC +#define SWIGSTATIC static +#endif + +typedef struct { + char *name; + PyObject *(*get_attr)(void); + int (*set_attr)(PyObject *); +} swig_globalvar; + +typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar **vars; + int nvars; + int maxvars; +} swig_varlinkobject; + +/* ---------------------------------------------------------------------- + swig_varlink_repr() + + Function for python repr method + ---------------------------------------------------------------------- */ + +static PyObject * +swig_varlink_repr(swig_varlinkobject *v) +{ + v = v; + return PyString_FromString(""); +} + +/* --------------------------------------------------------------------- + swig_varlink_print() + + Print out all of the global variable names + --------------------------------------------------------------------- */ + +static int +swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) +{ + + int i = 0; + flags = flags; + fprintf(fp,"Global variables { "); + while (v->vars[i]) { + fprintf(fp,"%s", v->vars[i]->name); + i++; + if (v->vars[i]) fprintf(fp,", "); + } + fprintf(fp," }\n"); + return 0; +} + +/* -------------------------------------------------------------------- + swig_varlink_getattr + + This function gets the value of a variable and returns it as a + PyObject. In our case, we'll be looking at the datatype and + converting into a number or string + -------------------------------------------------------------------- */ + +static PyObject * +swig_varlink_getattr(swig_varlinkobject *v, char *n) +{ + int i = 0; + char temp[128]; + + while (v->vars[i]) { + if (strcmp(v->vars[i]->name,n) == 0) { + return (*v->vars[i]->get_attr)(); + } + i++; + } + sprintf(temp,"C global variable %s not found.", n); + PyErr_SetString(PyExc_NameError,temp); + return NULL; +} + +/* ------------------------------------------------------------------- + swig_varlink_setattr() + + This function sets the value of a variable. + ------------------------------------------------------------------- */ + +static int +swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) +{ + char temp[128]; + int i = 0; + while (v->vars[i]) { + if (strcmp(v->vars[i]->name,n) == 0) { + return (*v->vars[i]->set_attr)(p); + } + i++; + } + sprintf(temp,"C global variable %s not found.", n); + PyErr_SetString(PyExc_NameError,temp); + return 1; +} + +statichere PyTypeObject varlinktype = { +/* PyObject_HEAD_INIT(&PyType_Type) Note : This doesn't work on some machines */ + PyObject_HEAD_INIT(0) + 0, + "varlink", /* Type name */ + sizeof(swig_varlinkobject), /* Basic size */ + 0, /* Itemsize */ + 0, /* Deallocator */ + (printfunc) swig_varlink_print, /* Print */ + (getattrfunc) swig_varlink_getattr, /* get attr */ + (setattrfunc) swig_varlink_setattr, /* Set attr */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_mapping*/ + 0, /* tp_hash */ +}; + +/* Create a variable linking object for use later */ + +SWIGSTATIC PyObject * +SWIG_newvarlink(void) +{ + swig_varlinkobject *result = 0; + result = PyMem_NEW(swig_varlinkobject,1); + varlinktype.ob_type = &PyType_Type; /* Patch varlinktype into a PyType */ + result->ob_type = &varlinktype; + /* _Py_NewReference(result); Does not seem to be necessary */ + result->nvars = 0; + result->maxvars = 64; + result->vars = (swig_globalvar **) malloc(64*sizeof(swig_globalvar *)); + result->vars[0] = 0; + result->ob_refcnt = 0; + Py_XINCREF((PyObject *) result); + return ((PyObject*) result); +} + +SWIGSTATIC void +SWIG_addvarlink(PyObject *p, char *name, + PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) +{ + swig_varlinkobject *v; + v= (swig_varlinkobject *) p; + + if (v->nvars >= v->maxvars -1) { + v->maxvars = 2*v->maxvars; + v->vars = (swig_globalvar **) realloc(v->vars,v->maxvars*sizeof(swig_globalvar *)); + if (v->vars == NULL) { + fprintf(stderr,"SWIG : Fatal error in initializing Python module.\n"); + exit(1); + } + } + v->vars[v->nvars] = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + v->vars[v->nvars]->name = (char *) malloc(strlen(name)+1); + strcpy(v->vars[v->nvars]->name,name); + v->vars[v->nvars]->get_attr = get_attr; + v->vars[v->nvars]->set_attr = set_attr; + v->nvars++; + v->vars[v->nvars] = 0; +} + + + +/***************************************************************************** + * $Header: /home/zmoelnig/cvs2svn/pure-data/puredata_cvsbackup/extensions/gripd/src/midi_wrap.c,v 1.1.1.1 2005-11-10 05:52:09 eighthave Exp $ + * + * swigptr.swg + * + * This file contains supporting code for the SWIG run-time type checking + * mechanism. The following functions are available : + * + * SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *)); + * + * Registers a new type-mapping with the type-checker. origtype is the + * original datatype and newtype is an equivalent type. cast is optional + * pointer to a function to cast pointer values between types (this + * is typically used to cast pointers from derived classes to base classes in C++) + * + * SWIG_MakePtr(char *buffer, void *ptr, char *typestring); + * + * Makes a pointer string from a pointer and typestring. The result is returned + * in buffer which is assumed to hold enough space for the result. + * + * char * SWIG_GetPtr(char *buffer, void **ptr, char *type) + * + * Gets a pointer value from a string. If there is a type-mismatch, returns + * a character string to the received type. On success, returns NULL. + * + * + * You can remap these functions by making a file called "swigptr.swg" in + * your the same directory as the interface file you are wrapping. + * + * These functions are normally declared static, but this file can be + * can be used in a multi-module environment by redefining the symbol + * SWIGSTATIC. + *****************************************************************************/ + +#include + +#ifdef SWIG_GLOBAL +#ifdef __cplusplus +#define SWIGSTATIC extern "C" +#else +#define SWIGSTATIC +#endif +#endif + +#ifndef SWIGSTATIC +#define SWIGSTATIC static +#endif + + +/* SWIG pointer structure */ + +typedef struct SwigPtrType { + char *name; /* Datatype name */ + int len; /* Length (used for optimization) */ + void *(*cast)(void *); /* Pointer casting function */ + struct SwigPtrType *next; /* Linked list pointer */ +} SwigPtrType; + +/* Pointer cache structure */ + +typedef struct { + int stat; /* Status (valid) bit */ + SwigPtrType *tp; /* Pointer to type structure */ + char name[256]; /* Given datatype name */ + char mapped[256]; /* Equivalent name */ +} SwigCacheType; + +/* Some variables */ + +static int SwigPtrMax = 64; /* Max entries that can be currently held */ + /* This value may be adjusted dynamically */ +static int SwigPtrN = 0; /* Current number of entries */ +static int SwigPtrSort = 0; /* Status flag indicating sort */ +static int SwigStart[256]; /* Starting positions of types */ + +/* Pointer table */ +static SwigPtrType *SwigPtrTable = 0; /* Table containing pointer equivalences */ + +/* Cached values */ + +#define SWIG_CACHESIZE 8 +#define SWIG_CACHEMASK 0x7 +static SwigCacheType SwigCache[SWIG_CACHESIZE]; +static int SwigCacheIndex = 0; +static int SwigLastCache = 0; + +/* Sort comparison function */ +static int swigsort(const void *data1, const void *data2) { + SwigPtrType *d1 = (SwigPtrType *) data1; + SwigPtrType *d2 = (SwigPtrType *) data2; + return strcmp(d1->name,d2->name); +} + +/* Binary Search function */ +static int swigcmp(const void *key, const void *data) { + char *k = (char *) key; + SwigPtrType *d = (SwigPtrType *) data; + return strncmp(k,d->name,d->len); +} + +/* Register a new datatype with the type-checker */ + +SWIGSTATIC +void SWIG_RegisterMapping(char *origtype, char *newtype, void *(*cast)(void *)) { + + int i; + SwigPtrType *t = 0,*t1; + + /* Allocate the pointer table if necessary */ + + if (!SwigPtrTable) { + SwigPtrTable = (SwigPtrType *) malloc(SwigPtrMax*sizeof(SwigPtrType)); + SwigPtrN = 0; + } + /* Grow the table */ + if (SwigPtrN >= SwigPtrMax) { + SwigPtrMax = 2*SwigPtrMax; + SwigPtrTable = (SwigPtrType *) realloc((char *) SwigPtrTable,SwigPtrMax*sizeof(SwigPtrType)); + } + for (i = 0; i < SwigPtrN; i++) + if (strcmp(SwigPtrTable[i].name,origtype) == 0) { + t = &SwigPtrTable[i]; + break; + } + if (!t) { + t = &SwigPtrTable[SwigPtrN]; + t->name = origtype; + t->len = strlen(t->name); + t->cast = 0; + t->next = 0; + SwigPtrN++; + } + + /* Check for existing entry */ + + while (t->next) { + if ((strcmp(t->name,newtype) == 0)) { + if (cast) t->cast = cast; + return; + } + t = t->next; + } + + /* Now place entry (in sorted order) */ + + t1 = (SwigPtrType *) malloc(sizeof(SwigPtrType)); + t1->name = newtype; + t1->len = strlen(t1->name); + t1->cast = cast; + t1->next = 0; + t->next = t1; + SwigPtrSort = 0; +} + +/* Make a pointer value string */ + +SWIGSTATIC +void SWIG_MakePtr(char *_c, const void *_ptr, char *type) { + static char _hex[16] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + unsigned long _p, _s; + char _result[20], *_r; /* Note : a 64-bit hex number = 16 digits */ + _r = _result; + _p = (unsigned long) _ptr; + if (_p > 0) { + while (_p > 0) { + _s = _p & 0xf; + *(_r++) = _hex[_s]; + _p = _p >> 4; + } + *_r = '_'; + while (_r >= _result) + *(_c++) = *(_r--); + } else { + strcpy (_c, "NULL"); + } + if (_ptr) + strcpy (_c, type); +} + +/* Define for backwards compatibility */ + +#define _swig_make_hex SWIG_MakePtr + +/* Function for getting a pointer value */ + +SWIGSTATIC +char *SWIG_GetPtr(char *_c, void **ptr, char *_t) +{ + unsigned long _p; + char temp_type[256]; + char *name; + int i, len; + SwigPtrType *sp,*tp; + SwigCacheType *cache; + int start, end; + _p = 0; + + /* Pointer values must start with leading underscore */ + if (*_c == '_') { + _c++; + /* Extract hex value from pointer */ + while (*_c) { + if ((*_c >= '0') && (*_c <= '9')) + _p = (_p << 4) + (*_c - '0'); + else if ((*_c >= 'a') && (*_c <= 'f')) + _p = (_p << 4) + ((*_c - 'a') + 10); + else + break; + _c++; + } + + if (_t) { + if (strcmp(_t,_c)) { + if (!SwigPtrSort) { + qsort((void *) SwigPtrTable, SwigPtrN, sizeof(SwigPtrType), swigsort); + for (i = 0; i < 256; i++) { + SwigStart[i] = SwigPtrN; + } + for (i = SwigPtrN-1; i >= 0; i--) { + SwigStart[(int) (SwigPtrTable[i].name[1])] = i; + } + for (i = 255; i >= 1; i--) { + if (SwigStart[i-1] > SwigStart[i]) + SwigStart[i-1] = SwigStart[i]; + } + SwigPtrSort = 1; + for (i = 0; i < SWIG_CACHESIZE; i++) + SwigCache[i].stat = 0; + } + + /* First check cache for matches. Uses last cache value as starting point */ + cache = &SwigCache[SwigLastCache]; + for (i = 0; i < SWIG_CACHESIZE; i++) { + if (cache->stat) { + if (strcmp(_t,cache->name) == 0) { + if (strcmp(_c,cache->mapped) == 0) { + cache->stat++; + *ptr = (void *) _p; + if (cache->tp->cast) *ptr = (*(cache->tp->cast))(*ptr); + return (char *) 0; + } + } + } + SwigLastCache = (SwigLastCache+1) & SWIG_CACHEMASK; + if (!SwigLastCache) cache = SwigCache; + else cache++; + } + /* We have a type mismatch. Will have to look through our type + mapping table to figure out whether or not we can accept this datatype */ + + start = SwigStart[(int) _t[1]]; + end = SwigStart[(int) _t[1]+1]; + sp = &SwigPtrTable[start]; + while (start < end) { + if (swigcmp(_t,sp) == 0) break; + sp++; + start++; + } + if (start >= end) sp = 0; + /* Try to find a match for this */ + if (sp) { + while (swigcmp(_t,sp) == 0) { + name = sp->name; + len = sp->len; + tp = sp->next; + /* Try to find entry for our given datatype */ + while(tp) { + if (tp->len >= 255) { + return _c; + } + strcpy(temp_type,tp->name); + strncat(temp_type,_t+len,255-tp->len); + if (strcmp(_c,temp_type) == 0) { + + strcpy(SwigCache[SwigCacheIndex].mapped,_c); + strcpy(SwigCache[SwigCacheIndex].name,_t); + SwigCache[SwigCacheIndex].stat = 1; + SwigCache[SwigCacheIndex].tp = tp; + SwigCacheIndex = SwigCacheIndex & SWIG_CACHEMASK; + + /* Get pointer value */ + *ptr = (void *) _p; + if (tp->cast) *ptr = (*(tp->cast))(*ptr); + return (char *) 0; + } + tp = tp->next; + } + sp++; + /* Hmmm. Didn't find it this time */ + } + } + /* Didn't find any sort of match for this data. + Get the pointer value and return the received type */ + *ptr = (void *) _p; + return _c; + } else { + /* Found a match on the first try. Return pointer value */ + *ptr = (void *) _p; + return (char *) 0; + } + } else { + /* No type specified. Good luck */ + *ptr = (void *) _p; + return (char *) 0; + } + } else { + if (strcmp (_c, "NULL") == 0) { + *ptr = (void *) 0; + return (char *) 0; + } + *ptr = (void *) 0; + return _c; + } +} + +/* Compatibility mode */ + +#define _swig_get_hex SWIG_GetPtr + +#define SWIG_init initmidi + +#define SWIG_name "midi" +extern int openDevice(int ); +extern int closeDevice(int ); +extern int readEvents(int ); +extern int getEventCount(int ); +extern int getEventCommand(int ,int ); +extern int getEventP0(int ,int ); +extern int getEventP1(int ,int ); +extern int getEventP2(int ,int ); +extern int getEventP3(int ,int ); +static PyObject *_wrap_openDevice(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:openDevice",&_arg0)) + return NULL; + _result = (int )openDevice(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_closeDevice(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:closeDevice",&_arg0)) + return NULL; + _result = (int )closeDevice(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_readEvents(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:readEvents",&_arg0)) + return NULL; + _result = (int )readEvents(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventCount(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + + self = self; + if(!PyArg_ParseTuple(args,"i:getEventCount",&_arg0)) + return NULL; + _result = (int )getEventCount(_arg0); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventCommand(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventCommand",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventCommand(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventP0(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventP0",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventP0(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventP1(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventP1",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventP1(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventP2(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventP2",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventP2(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyObject *_wrap_getEventP3(PyObject *self, PyObject *args) { + PyObject * _resultobj; + int _result; + int _arg0; + int _arg1; + + self = self; + if(!PyArg_ParseTuple(args,"ii:getEventP3",&_arg0,&_arg1)) + return NULL; + _result = (int )getEventP3(_arg0,_arg1); + _resultobj = Py_BuildValue("i",_result); + return _resultobj; +} + +static PyMethodDef midiMethods[] = { + { "getEventP3", _wrap_getEventP3, 1 }, + { "getEventP2", _wrap_getEventP2, 1 }, + { "getEventP1", _wrap_getEventP1, 1 }, + { "getEventP0", _wrap_getEventP0, 1 }, + { "getEventCommand", _wrap_getEventCommand, 1 }, + { "getEventCount", _wrap_getEventCount, 1 }, + { "readEvents", _wrap_readEvents, 1 }, + { "closeDevice", _wrap_closeDevice, 1 }, + { "openDevice", _wrap_openDevice, 1 }, + { NULL, NULL } +}; +static PyObject *SWIG_globals; +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT(void,initmidi)() { + PyObject *m, *d; + SWIG_globals = SWIG_newvarlink(); + m = Py_InitModule("midi", midiMethods); + d = PyModule_GetDict(m); +/* + * These are the pointer type-equivalency mappings. + * (Used by the SWIG pointer type-checker). + */ + SWIG_RegisterMapping("_signed_long","_long",0); + SWIG_RegisterMapping("_long","_unsigned_long",0); + SWIG_RegisterMapping("_long","_signed_long",0); + SWIG_RegisterMapping("_unsigned_long","_long",0); + SWIG_RegisterMapping("_signed_int","_int",0); + SWIG_RegisterMapping("_unsigned_short","_short",0); + SWIG_RegisterMapping("_signed_short","_short",0); + SWIG_RegisterMapping("_unsigned_int","_int",0); + SWIG_RegisterMapping("_short","_unsigned_short",0); + SWIG_RegisterMapping("_short","_signed_short",0); + SWIG_RegisterMapping("_int","_unsigned_int",0); + SWIG_RegisterMapping("_int","_signed_int",0); +} diff --git a/src/midiio/include/Array.cpp b/src/midiio/include/Array.cpp new file mode 100644 index 0000000..044ed2d --- /dev/null +++ b/src/midiio/include/Array.cpp @@ -0,0 +1,378 @@ +// +// Copyright 1997-1999 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Feb 5 19:42:53 PST 1997 +// Last Modified: Sun May 11 20:41:28 GMT-0800 1997 +// Last Modified: Wed Jul 7 11:44:50 PDT 1999 (added setAll() function) +// Filename: ...sig/maint/code/base/Array/Array.cpp +// Web Address: http://sig.sapp.org/src/sigBase/Array.cpp +// Syntax: C++ +// +// Description: An array which can grow dynamically. Array is derived from +// the Collection class and adds various mathematical operators +// to the Collection class. The Array template class is used for +// storing numbers of any type which can be added, multiplied +// and divided into one another. +// + +#ifndef _ARRAY_CPP_INCLUDED +#define _ARRAY_CPP_INCLUDED + +#include "Array.h" +#include +#include + + +////////////////////////////// +// +// Array::Array +// + +template +Array::Array(void) : Collection(4) { } + +template +Array::Array(int arraySize) : Collection(arraySize) { } + +template +Array::Array(Array& anArray) : Collection(anArray) { } + +template +Array::Array(int arraySize, type *anArray) : + Collection(arraySize, anArray) { } + + + + +////////////////////////////// +// +// Array::~Array +// + +template +Array::~Array() { } + + + +////////////////////////////// +// +// Array::setAll -- sets the contents of each element to the +// specified value +// + +template +void Array::setAll(type aValue) { + for (int i=0; i +type Array::sum(void) { + type theSum = 0; + for (int i=0; i +type Array::sum(int loIndex, int hiIndex) { + type theSum = 0; + for (int i=loIndex; i<=hiIndex; i++) { + theSum += array[i]; + } + return theSum; +} + + + +////////////////////////////// +// +// Array::zero(-1, -1) +// + +template +void Array::zero(int minIndex, int maxIndex) { + if (size == 0) return; + if (minIndex == -1) minIndex = 0; + if (maxIndex == -1) maxIndex = size-1; + + if (minIndex < 0 || maxIndex < 0 || minIndex > maxIndex || + maxIndex >= size) { + cerr << "Error in zero function: min = " << minIndex + << " max = " << maxIndex << " size = " << size << endl; + exit(1); + } + + for (int i=minIndex; i<=maxIndex; i++) { + array[i] = 0; + } +} + + +//////////////////////////////////////////////////////////////////////////// +// +// operators +// + + +template +int Array::operator==(const Array& aArray) { + if (getSize() != aArray.getSize()) { + return 0; + } + Array& t = *this; + int i; + for (i=0; i +Array& Array::operator=(const Array& anArray) { + if (allocSize < anArray.size) { + if (allocSize != 0) { + delete [] array; + } + allocSize = anArray.size; + size = anArray.size; + array = new type[size]; + allowGrowthQ = anArray.allowGrowthQ; + growthAmount = anArray.growthAmount; + maxSize = anArray.maxSize; + } + size = anArray.size; + for (int i=0; i +Array& Array::operator+=(const Array& anArray) { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + for (int i=0; i +Array Array::operator+(const Array& anArray) const { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + Array bArray(*this); + bArray += anArray; + return bArray; +} + + +template +Array Array::operator+(type aNumber) const { + Array anArray(*this); + for (int i=0; i +Array& Array::operator-=(const Array& anArray) { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + for (int i=0; i +Array Array::operator-(const Array& anArray) const { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + Array bArray(*this); + bArray -= anArray; + return bArray; +} + + +template +Array Array::operator-(void) const { + Array anArray(*this); + for (int i=0; i +Array Array::operator-(type aNumber) const { + Array anArray(*this); + for (int i=0; i +Array& Array::operator*=(const Array& anArray) { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + for (int i=0; i +Array Array::operator*(const Array& anArray) const { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + Array bArray(*this); + bArray *= anArray; + return bArray; +} + + +template +Array Array::operator*(type aNumber) const { + Array anArray(*this); + for (int i=0; i +Array& Array::operator/=(const Array& anArray) { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + for (int i=0; i +Array Array::operator/(const Array& anArray) const { + if (size != anArray.size) { + cerr << "Error: different size arrays " << size << " and " + << anArray.size << endl; + exit(1); + } + + Array bArray(*this); + bArray /= anArray; + return bArray; +} + + +#endif /* _ARRAY_CPP_INCLUDED */ + + + +// md5sum: 8f52a167c93f51702ce316204fd6e722 - Array.cpp =css= 20030102 diff --git a/src/midiio/include/Array.h b/src/midiio/include/Array.h new file mode 100644 index 0000000..75e08eb --- /dev/null +++ b/src/midiio/include/Array.h @@ -0,0 +1,67 @@ +// +// Copyright 1997-1999 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Feb 5 19:42:53 PST 1997 +// Last Modified: Sun May 11 20:33:13 GMT-0800 1997 +// Last Modified: Wed Jul 7 11:44:50 PDT 1999 (added setAll() function) +// Last Modified: Mon Jul 29 22:08:32 PDT 2002 (added operator==) +// Filename: ...sig/maint/code/base/Array/Array.h +// Web Address: http://sig.sapp.org/include/sigBase/Array.h +// Documentation: http://sig.sapp.org/doc/classes/Array +// Syntax: C++ +// +// Description: An array which can grow dynamically. Array is derived from +// the Collection class and adds various mathematical operators +// to the Collection class. The Array template class is used for +// storing numbers of any type which can be added, multiplied +// and divided into one another. +// + +#ifndef _ARRAY_H_INCLUDED +#define _ARRAY_H_INCLUDED + +#include "Collection.h" + + +template +class Array : public Collection { + public: + Array (void); + Array (int arraySize); + Array (Array& aArray); + Array (int arraySize, type *anArray); + ~Array (); + + void setAll (type aValue); + type sum (void); + type sum (int lowIndex, int hiIndex); + void zero (int minIndex = -1, int maxIndex = -1); + + int operator== (const Array& aArray); + Array& operator= (const Array& aArray); + Array& operator+= (const Array& aArray); + Array& operator-= (const Array& aArray); + Array& operator*= (const Array& aArray); + Array& operator/= (const Array& aArray); + + Array operator+ (const Array& aArray) const; + Array operator+ (type aNumber) const; + Array operator- (const Array& aArray) const; + Array operator- (void) const; + + Array operator- (type aNumber) const; + Array operator* (const Array& aArray) const; + Array operator* (type aNumber) const; + Array operator/ (const Array& aArray) const; +}; + + +#include "Array.cpp" /* necessary for templates */ + + + +#endif /* _ARRAY_H_INCLUDED */ + + + +// md5sum: 09d1b1f8e70ecde53f484548e48f33c3 - Array.h =css= 20030102 diff --git a/src/midiio/include/CircularBuffer.cpp b/src/midiio/include/CircularBuffer.cpp new file mode 100644 index 0000000..9f4aca6 --- /dev/null +++ b/src/midiio/include/CircularBuffer.cpp @@ -0,0 +1,291 @@ +// +// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: 19 December 1997 +// Last Modified: Wed Jan 21 23:16:54 GMT-0800 1998 +// Filename: ...sig/maint/code/base/CircularBuffer/CircularBuffer.cpp +// Web Address: http://sig.sapp.org/src/sigBase/CircularBuffer.cpp +// Syntax: C++ +// +// Description: A Circular buffer designed to handle MIDI input, +// but able to store any type of object. Elements +// can be read out of the buffer in two ways. +// (1) from a read pointer which extracts the +// elements in order by following the write pointer, +// and (2) from an index operator related to the +// write pointer's location, for example, +// object[0] is the last value written into the +// buffer and object[-1] (or object[1]) is the +// item written just before that. +// +// + +#ifndef _CIRCULARBUFFER_CPP_INCLUDED +#define _CIRCULARBUFFER_CPP_INCLUDED + +#include "CircularBuffer.h" +#include +#include + + +////////////////////////////// +// +// CircularBuffer::CircularBuffer -- Constructor. +// + +template +CircularBuffer::CircularBuffer(void) { + size = 0; + buffer = NULL; + reset(); +} + + +template +CircularBuffer::CircularBuffer(int maxElements) { + if (maxElements < 0) { + std::cerr << "Error: cannot have a negative number of elements: " + << maxElements << std::endl; + exit(1); + } + if (maxElements == 0) { + size = 0; + buffer = NULL; + reset(); + } else { + size = maxElements; + buffer = new type[maxElements]; + reset(); + } +} + + +template +CircularBuffer::CircularBuffer(const CircularBuffer& anotherBuffer) { + size = anotherBuffer.size; + if (getSize() == 0) { + buffer = NULL; + reset(); + } else { + buffer = new type[getSize()]; + writeIndex = anotherBuffer.writeIndex; + readIndex = anotherBuffer.readIndex; + itemCount = anotherBuffer.itemCount; + for (int i=0; i +CircularBuffer::~CircularBuffer() { + if (buffer != NULL) { + delete [] buffer; + } +} + + + +////////////////////////////// +// +// CircularBuffer::capacity -- returns the number of items which +// can be added to the buffer. Returns a positive number +// if the buffer has empty locations available. Returns 0 if the +// buffer is 100% full. Returns a negative number if the +// buffer has overflowed. + +template +int CircularBuffer::capacity(void) const { + return getSize() - getCount(); +} + + + +////////////////////////////// +// +// CircularBuffer::extract -- reads the next value from the buffer. +// + +template +type CircularBuffer::extract(void) { + itemCount--; + if (itemCount < 0) { + std::cerr << "Error: no elements in buffer to extract." << std::endl; + exit(1); + } + increment(readIndex); + return buffer[readIndex]; +} + + + +////////////////////////////// +// +// CircularBuffer::getCount -- returns the number of elements +// between the write index and the read index. +// + +template +int CircularBuffer::getCount(void) const { + return itemCount; +} + + + +////////////////////////////// +// +// CircularBuffer::getSize -- returns the allocated size of the buffer. +// + +template +int CircularBuffer::getSize(void) const { + return size; +} + + + +////////////////////////////// +// +// CircularBuffer::insert -- add an element to the circular buffer +// + +template +void CircularBuffer::insert(const type& anItem) { + itemCount++; + increment(writeIndex); + buffer[writeIndex] = anItem; +} + + + +////////////////////////////// +// +// CircularBuffer::operator[] -- access an element relative to the +// currently written element +// + +template +type& CircularBuffer::operator[](int index) { + if (buffer == NULL) { + std::cerr << "Error: buffer has no allocated space" << std::endl; + exit(1); + } + int realIndex = (index < 0) ? -index : index; + if (realIndex >= getSize()) { + std::cerr << "Error: Invalid access: " << realIndex << ", maximum is " + << getSize()-1 << std::endl; + exit(1); + } + realIndex = writeIndex - realIndex; + + // should need to go through this loop a max of one time: + while (realIndex < 0) { + realIndex += getSize(); + } + + return buffer[realIndex]; +} + + + +////////////////////////////// +// +// CircularBuffer::read -- an alias for the extract function. +// + +template +type CircularBuffer::read(void) { + return extract(); +} + + + +////////////////////////////// +// +// CircularBuffer::reset -- throws out all previous data and +// sets the read/write/count to initial values. The size +// data variable must be valid before this function is +// called. +// + +template +void CircularBuffer::reset(void) { + readIndex = writeIndex = getSize() - 1; + itemCount = 0; +} + + + +////////////////////////////// +// +// CircularBuffer::setSize -- warning: will throw out all previous data +// stored in buffer. +// + +template +void CircularBuffer::setSize(int aSize) { + if (aSize < 0) { + std::cerr << "Error: cannot have a negative buffer size: " << aSize << std::endl; + exit(1); + } + if (buffer != NULL) { + delete [] buffer; + } + + if (aSize == 0) { + size = aSize; + buffer = NULL; + reset(); + } else { + size = aSize; + buffer = new type[aSize]; + reset(); + } +} + + + +////////////////////////////// +// +// CircularBuffer::write -- an alias for the insert function. +// + +template +void CircularBuffer::write(const type& anElement) { + write(anElement); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// private functions +// + +////////////////////////////// +// +// CircularBuffer::increment -- adds one to specified index and +// will automatically wrap the index when it gets too large. +// + +template +void CircularBuffer::increment(int& index) { + index++; + if (index >= getSize()) { + index = 0; + } +} + + +#endif /* _CIRCULARBUFFER_CPP_INCLUDED */ + + + +// md5sum: 31b2e8d6efe7398a12ddb0a1b5680ca2 - CircularBuffer.cpp =css= 20030102 diff --git a/src/midiio/include/CircularBuffer.h b/src/midiio/include/CircularBuffer.h new file mode 100644 index 0000000..6bb3071 --- /dev/null +++ b/src/midiio/include/CircularBuffer.h @@ -0,0 +1,66 @@ +// +// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: 19 December 1997 +// Last Modified: Wed Jan 21 23:08:13 GMT-0800 1998 +// Filename: ...sig/maint/code/base/CircularBuffer/CircularBuffer.h +// Web Address: http://sig.sapp.org/include/sigBase/CircularBuffer.cpp +// Documentation: http://sig.sapp.org/doc/classes/CircularBuffer +// Syntax: C++ +// +// Description: A Circular buffer designed to handle MIDI input, +// but able to store any type of object. Elements +// can be read out of the buffer in two ways. +// (1) from a read pointer which extracts the +// elements in order by following the write pointer, +// and (2) from an index operator related to the +// write pointer's location, for example, +// object[0] is the last value written into the +// buffer and object[-1] (or object[1]) is the +// item written just before that. +// + +#ifndef _CIRCULARBUFFER_H_INCLUDED +#define _CIRCULARBUFFER_H_INCLUDED + + +template +class CircularBuffer { + public: + CircularBuffer (void); + CircularBuffer (int maxElements); + CircularBuffer (const CircularBuffer& + anotherBuffer); + ~CircularBuffer (); + + int capacity (void) const; + type extract (void); + int getCount (void) const; + int getSize (void) const; + void insert (const type& aMessage); + type& operator[] (int index); + type read (void); + void reset (void); + void setSize (int aSize); + void write (const type& aMessage); + + protected: + type* buffer; + int size; + int writeIndex; + int readIndex; + int itemCount; + + void increment (int& index); +}; + + +#include "CircularBuffer.cpp" + + + +#endif /* _CIRCULARBUFFER_H_INCLUDED */ + + + +// md5sum: 2857693ec37fdcb6df09db479faf110b - CircularBuffer.h =css= 20030102 diff --git a/src/midiio/include/Collection.cpp b/src/midiio/include/Collection.cpp new file mode 100644 index 0000000..74eef16 --- /dev/null +++ b/src/midiio/include/Collection.cpp @@ -0,0 +1,355 @@ +// +// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Feb 5 19:42:53 PST 1997 +// Last Modified: Wed Apr 23 22:08:34 GMT-0800 1997 +// Last Modified: Fri Sep 14 15:50:52 PDT 2001 (added last() function) +// Filename: ...sig/maint/code/base/Collection/Collection.cpp +// Web Address: http://sig.sapp.org/src/sigBase/Collection.cpp +// Syntax: C++ +// +// Description: A dynamic array which can grow as necessary. +// This class can hold any type of item, but the +// derived Array class is specifically for collections +// of numbers. +// + +#ifndef _COLLECTION_CPP_INCLUDED +#define _COLLECTION_CPP_INCLUDED + +#include "Collection.h" +#include +#include + + +////////////////////////////// +// +// Collection::Collection +// + +template +Collection::Collection(void) { + allocSize = 0; + size = 0; + array = NULL; + allowGrowthQ = 0; + growthAmount = 8; + maxSize = 0; +} + +template +Collection::Collection(int arraySize) { + array = new type[arraySize]; + size = arraySize; + allocSize = arraySize; + allowGrowthQ = 0; + growthAmount = arraySize; + maxSize = 0; +} + + +template +Collection::Collection(int arraySize, type *aCollection) { + size = arraySize; + allocSize = arraySize; + array = new type[size]; + for (int i=0; i +Collection::Collection(Collection& aCollection) { + size = aCollection.size; + allocSize = size; + array = new type[size]; + for (int i=0; i +Collection::~Collection() { + if (getAllocSize() != 0) { + delete [] array; + } +} + + + +////////////////////////////// +// +// Collection::allowGrowth +// default value: status = 1 +// + +template +void Collection::allowGrowth(int status) { + if (status == 0) { + allowGrowthQ = 0; + } else { + allowGrowthQ = 1; + } +} + + + +////////////////////////////// +// +// Collection::append +// + +template +void Collection::append(type& element) { + if (size == getAllocSize()) { + grow(); + } + array[size] = element; + size++; +} + +template +void Collection::appendcopy(type element) { + if (size == getAllocSize()) { + grow(); + } + array[size] = element; + size++; +} + +template +void Collection::append(type *element) { + if (size == getAllocSize()) { + grow(); + } + array[size] = *element; + size++; +} + + + +////////////////////////////// +// +// Collection::grow +// default parameter: growamt = -1 +// + +template +void Collection::grow(long growamt) { + allocSize += growamt > 0 ? growamt : growthAmount; + if (maxSize != 0 && getAllocSize() > maxSize) { + std::cerr << "Error: Maximum size allowed for array exceeded." << std::endl; + exit(1); + } + + type *temp = new type[getAllocSize()]; + for (int i=0; i +type* Collection::pointer(void) { + return array; +} + + + +////////////////////////////// +// +// Collection::getBase +// + +template +type* Collection::getBase(void) { + return array; +} + + + +////////////////////////////// +// +// Collection::getAllocSize +// + +template +long Collection::getAllocSize(void) const { + return allocSize; +} + + + +////////////////////////////// +// +// Collection::getSize -- +// + +template +long Collection::getSize(void) const { + return size; +} + + + +////////////////////////////// +// +// Collection::last -- +// + +template +type& Collection::last(void) { + return array[getSize()-1]; +} + + + +////////////////////////////// +// +// Collection::setAllocSize +// + +template +void Collection::setAllocSize(long aSize) { + if (aSize < getSize()) { + std::cerr << "Error: cannot set allocated size smaller than actual size." + << std::endl; + exit(1); + } + + if (aSize <= getAllocSize()) { + shrinkTo(aSize); + } else { + grow(aSize-getAllocSize()); + size = aSize; + } +} + + + +////////////////////////////// +// +// Collection::setGrowth +// default parameter: growth = -1 +// + +template +void Collection::setGrowth(long growth) { + if (growth > 0) { + growthAmount = growth; + } +} + + + +////////////////////////////// +// +// Collection::setSize +// + +template +void Collection::setSize(long newSize) { + if (newSize <= getAllocSize()) { + size = newSize; + } else { + grow(newSize-getAllocSize()); + size = newSize; + } +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Collection operators +// + +////////////////////////////// +// +// Collection::operator[] +// + +template +type& Collection::operator[](int elementIndex) { + if (allowGrowthQ && elementIndex == size) { + if (size == getAllocSize()) { + grow(); + } + size++; + } else if (elementIndex >= size) { + std::cerr << "Error: accessing invalid array location " + << elementIndex + << " Maximum is " << size-1 << std::endl; + exit(1); + } + return array[elementIndex]; +} + + +////////////////////////////// +// +// Collection::operator[] const +// + +template +type Collection::operator[](int elementIndex) const { + if (elementIndex >= size) { + std::cerr << "Error: accessing invalid array location " + << elementIndex + << " Maximum is " << size-1 << std::endl; + exit(1); + } + return array[elementIndex]; +} + +////////////////////////////// +// +// shrinkTo +// + +template +void Collection::shrinkTo(long aSize) { + if (aSize < getSize()) { + exit(1); + } + + type *temp = new type[aSize]; + for (int i=0; i allocSize) { + size = allocSize; + } +} + + +#endif /* _COLLECTION_CPP_INCLUDED */ + + + +// md5sum: 9929fee30b1bede4305e1fb46303ddc1 - Collection.cpp =css= 20030102 diff --git a/src/midiio/include/Collection.h b/src/midiio/include/Collection.h new file mode 100644 index 0000000..6775366 --- /dev/null +++ b/src/midiio/include/Collection.h @@ -0,0 +1,70 @@ +// +// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Feb 5 19:42:53 PST 1997 +// Last Modified: Tue Apr 22 20:28:16 GMT-0800 1997 +// Last Modified: Fri Sep 14 15:50:52 PDT 2001 (added last() function) +// Filename: ...sig/maint/code/base/Collection/Collection.h +// Web Address: http://sig.sapp.org/include/sigBase/Collection.h +// Documentation: http://sig.sapp.org/doc/classes/Collection +// Syntax: C++ +// +// Description: A dynamic array which can grow as necessary. +// This class can hold any type of item, but the +// derived Array class is specifically for collections +// of numbers. +// + +#ifndef _COLLECTION_H_INCLUDED +#define _COLLECTION_H_INCLUDED + + +template +class Collection { + public: + Collection (void); + Collection (int arraySize); + Collection (int arraySize, type *aCollection); + Collection (Collection& aCollection); + ~Collection (); + + void allowGrowth (int status = 1); + void append (type& element); + void appendcopy (type element); + void append (type* element); + type *getBase (void); + long getAllocSize (void) const; + long getSize (void) const; + type *pointer (void); + void setAllocSize (long aSize); + void setGrowth (long growth); + void setSize (long newSize); + type& operator[] (int arrayIndex); + type operator[] (int arrayIndex) const; + void grow (long growamt = -1); + type& last (void); + + + protected: + long size; // actual array size + long allocSize; // maximum allowable array size + type *array; // where the array data is stored + char allowGrowthQ; // allow/disallow growth + long growthAmount; // number of elements to grow by if index + // element one beyond max size is accessed + long maxSize; // the largest size the array is allowed + // to grow to, if 0, then ignore max + + void shrinkTo (long aSize); +}; + + +#include "Collection.cpp" + + + +#endif /* _COLLECTION_H_INCLUDED */ + + + +// md5sum: 01bec04835c0bd117f40c2bfe51c4abd - Collection.h =css= 20030102 diff --git a/src/midiio/include/FileIO.h b/src/midiio/include/FileIO.h new file mode 100644 index 0000000..fdec5de --- /dev/null +++ b/src/midiio/include/FileIO.h @@ -0,0 +1,148 @@ +// +// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Fri May 9 22:30:32 PDT 1997 +// Last Modified: Sun Dec 14 05:26:16 GMT-0800 1997 +// Filename: ...sig/maint/code/base/FileIO/FileIO.h +// Web Address: http://sig.sapp.org/include/sigBase/FileIO.h +// Documentation: http://sig.sapp.org/doc/classes/FileIO +// Syntax: C++ +// +// Description: Derived from the fstream class, this class has +// functions which allow writing binary files in +// both little and big endian formats. Useful for +// writing files such as soundfiles and MIDI files +// which require numbers to be stored in a particular +// endian format. +// + +#ifndef _FILEIO_H_INCLUDED +#define _FILEIO_H_INCLUDED + + +#include + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned int uint; + +// templates would be nice to use here, but they don't seem +// to work intuitively... + +class FileIO : public std::fstream { + public: + FileIO (void); + FileIO (const char* filename, std::ios::openmode state); + ~FileIO (); + + void readBigEndian (char& aNumber); + void readBigEndian (uchar& aNumber); + void readBigEndian (short& aNumber); + void readBigEndian (ushort& aNumber); + void readBigEndian (long& aNumber); + void readBigEndian (ulong& aNumber); + void readBigEndian (int& aNumber); + void readBigEndian (uint& aNumber); + void readBigEndian (float& aNumber); + void readBigEndian (double& aNumber); + + void readLittleEndian (char& aNumber); + void readLittleEndian (uchar& aNumber); + void readLittleEndian (short& aNumber); + void readLittleEndian (ushort& aNumber); + void readLittleEndian (long& aNumber); + void readLittleEndian (ulong& aNumber); + void readLittleEndian (int& aNumber); + void readLittleEndian (uint& aNumber); + void readLittleEndian (float& aNumber); + void readLittleEndian (double& aNumber); + + void readMachineEndian (char& aNumber); + void readMachineEndian (uchar& aNumber); + void readMachineEndian (short& aNumber); + void readMachineEndian (ushort& aNumber); + void readMachineEndian (long& aNumber); + void readMachineEndian (ulong& aNumber); + void readMachineEndian (int& aNumber); + void readMachineEndian (uint& aNumber); + void readMachineEndian (float& aNumber); + void readMachineEndian (double& aNumber); + + void readNotMachineEndian (char& aNumber); + void readNotMachineEndian (uchar& aNumber); + void readNotMachineEndian (short& aNumber); + void readNotMachineEndian (ushort& aNumber); + void readNotMachineEndian (long& aNumber); + void readNotMachineEndian (ulong& aNumber); + void readNotMachineEndian (int& aNumber); + void readNotMachineEndian (uint& aNumber); + void readNotMachineEndian (float& aNumber); + void readNotMachineEndian (double& aNumber); + + void writeBigEndian (char aNumber); + void writeBigEndian (uchar aNumber); + void writeBigEndian (short aNumber); + void writeBigEndian (ushort aNumber); + void writeBigEndian (long aNumber); + void writeBigEndian (ulong aNumber); + void writeBigEndian (int aNumber); + void writeBigEndian (uint aNumber); + void writeBigEndian (float aNumber); + void writeBigEndian (double aNumber); + + void writeLittleEndian (char aNumber); + void writeLittleEndian (uchar aNumber); + void writeLittleEndian (short aNumber); + void writeLittleEndian (ushort aNumber); + void writeLittleEndian (long aNumber); + void writeLittleEndian (ulong aNumber); + void writeLittleEndian (int aNumber); + void writeLittleEndian (uint aNumber); + void writeLittleEndian (float aNumber); + void writeLittleEndian (double aNumber); + + void writeMachineEndian (char aNumber); + void writeMachineEndian (uchar aNumber); + void writeMachineEndian (short aNumber); + void writeMachineEndian (ushort aNumber); + void writeMachineEndian (long aNumber); + void writeMachineEndian (ulong aNumber); + void writeMachineEndian (int aNumber); + void writeMachineEndian (uint aNumber); + void writeMachineEndian (float aNumber); + void writeMachineEndian (double aNumber); + + void writeNotMachineEndian (char aNumber); + void writeNotMachineEndian (uchar aNumber); + void writeNotMachineEndian (short aNumber); + void writeNotMachineEndian (ushort aNumber); + void writeNotMachineEndian (long aNumber); + void writeNotMachineEndian (ulong aNumber); + void writeNotMachineEndian (int aNumber); + void writeNotMachineEndian (uint aNumber); + void writeNotMachineEndian (float aNumber); + void writeNotMachineEndian (double aNumber); + + protected: + + char flipBytes (char aNumber); + uchar flipBytes (uchar aNumber); + short flipBytes (short aNumber); + ushort flipBytes (ushort aNumber); + long flipBytes (long aNumber); + ulong flipBytes (ulong aNumber); + int flipBytes (int aNumber); + uint flipBytes (uint aNumber); + float flipBytes (float aNumber); + double flipBytes (double aNumber); + +}; + + + +#endif /* _FILEIO_H_INCLUDED */ + + + +// md5sum: 0a146ebe5c6bd0850be973f612827d20 - FileIO.h =css= 20030102 diff --git a/src/midiio/include/MidiFile.h b/src/midiio/include/MidiFile.h new file mode 100644 index 0000000..10794d5 --- /dev/null +++ b/src/midiio/include/MidiFile.h @@ -0,0 +1,108 @@ +// +// Copyright 1999-2000 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Fri Nov 26 14:12:01 PST 1999 +// Last Modified: Fri Dec 2 13:26:44 PST 1999 +// Last Modified: Fri Nov 10 12:13:15 PST 2000 (added some more editing cap.) +// Last Modified: Thu Jan 10 10:03:39 PST 2002 (added allocateEvents()) +// Last Modified: Mon Jun 10 22:43:10 PDT 2002 (added clear()) +// Filename: ...sig/include/sigInfo/MidiFile.h +// Web Address: http://sig.sapp.org/include/sigInfo/MidiFile.h +// Syntax: C++ +// +// Description: A class which can read/write Standard MIDI files. +// MIDI data is stored by track in an array. This +// class is used for example in the MidiPerform class. +// + +#ifndef _MIDIfILE_H_INCLUDED +#define _MIDIfILE_H_INCLUDED + +#include "FileIO.h" +#include "Array.h" +#include "Collection.h" + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned long ulong; + +#define TIME_STATE_DELTA 0 +#define TIME_STATE_ABSOLUTE 1 + +#define TRACK_STATE_SPLIT 0 +#define TRACK_STATE_JOINED 1 + + +class _MFEvent { + public: + _MFEvent (void); + _MFEvent (int command); + _MFEvent (int command, int param1); + _MFEvent (int command, int param1, int param2); + _MFEvent (int track, int command, int param1, int param2); + _MFEvent (int aTime, int aTrack, int command, int param1, int param2); + ~_MFEvent (); + int time; + int track; + Array data; +}; + + + +class MidiFile { + public: + MidiFile (void); + MidiFile (char* aFile); + ~MidiFile (); + + void absoluteTime (void); + int addEvent (int aTrack, int aTime, + Array& midiData); + int addTrack (void); + int addTrack (int count); + void allocateEvents (int track, int aSize); + void deltaTime (void); + void deleteTrack (int aTrack); + void erase (void); + void clear (void); + _MFEvent& getEvent (int aTrack, int anIndex); + int getTimeState (void); + int getTrackState (void); + int getTicksPerQuarterNote (void); + int getTrackCount (void); + int getNumTracks (void); + int getNumEvents (int aTrack); + void joinTracks (void); + void mergeTracks (int aTrack1, int aTrack2); + int read (char* aFile); + void setTicksPerQuarterNote (int ticks); + void sortTrack (Collection<_MFEvent>& trackData); + void sortTracks (void); + void splitTracks (void); + int write (const char* aFile); + + protected: + Collection*> events; // midi file events + int ticksPerQuarterNote; // time base of file + int trackCount; // # of tracks in file + int theTrackState; // joined or split + int theTimeState; // absolute or delta + char* readFileName; // read file name + + private: + void extractMidiData (FileIO& inputfile, Array& array, + uchar& runningCommand); + ulong extractVlvTime (FileIO& inputfile); + ulong unpackVLV (uchar a, uchar b, uchar c, uchar d, uchar e); + void writeVLValue (long aValue, Array& data); +}; + + +int eventcompare(const void* a, const void* b); +std::ostream& operator<<(std::ostream& out, MidiFile& aMidiFile); + +#endif /* _MIDIfILE_H_INCLUDED */ + + + +// md5sum: ff46e64698e2d9e88ebeef3efa9927d0 - MidiFile.h =css= 20030102 diff --git a/src/midiio/include/MidiFileWrite.h b/src/midiio/include/MidiFileWrite.h new file mode 100644 index 0000000..a213fdf --- /dev/null +++ b/src/midiio/include/MidiFileWrite.h @@ -0,0 +1,61 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Mar 15 10:55:56 GMT-0800 1998 +// Last Modified: Sun Mar 15 10:55:56 GMT-0800 1998 +// Filename: ...sig/code/control/MidiFileWrite/MidiFileWrite.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiFileWrite.h +// Syntax: C++ +// +// Description: The MidiFileWrite class will write out a Type 0 MidiFile. +// Used for recording MIDI data streams into Standard +// MIDI files. +// + +#ifndef _MIDIFILEWRITE_INCLUDED +#define _MIDIFILEWRITE_INCLUDED + + +#include "FileIO.h" + + +class MidiFileWrite { + public: + MidiFileWrite (void); + MidiFileWrite (const char* aFilename, int startTime = -1); + ~MidiFileWrite (); + + void close (void); + void setup (const char* aFilename, int startTime = -1); + void start (int startTime = -1); + void writeAbsolute (int aTime, int command, int p1, int p2); + void writeAbsolute (int aTime, int command, int p1); + void writeAbsolute (int aTime, int command); + void writeRaw (uchar aByte); + void writeRaw (uchar aByte, uchar Byte); + void writeRaw (uchar aByte, uchar Byte, uchar cByte); + void writeRaw (uchar aByte, uchar Byte, uchar cByte, + uchar dByte); + void writeRaw (uchar aByte, uchar Byte, uchar cByte, + uchar dByte, uchar eByte); + void writeRaw (uchar* anArray, int arraySize); + void writeRelative (int aTime, int command, int p1, int p2); + void writeRelative (int aTime, int command, int p1); + void writeRelative (int aTime, int command); + void writeVLValue (long aValue); + + + protected: + FileIO *midifile; // file stream for MIDI file + long trackSize; // size count for MIDI track + int lastPlayTime; // for calculating delta times + int openQ; // for checking file status + +}; + + + +#endif /* _MIDIFILEWRITE_INCLUDED */ + + + +// md5sum: 44ac572078bff648d096c7e7867d1b3c - MidiFileWrite.h =css= 20030102 diff --git a/src/midiio/include/MidiIO.h b/src/midiio/include/MidiIO.h new file mode 100644 index 0000000..80c9168 --- /dev/null +++ b/src/midiio/include/MidiIO.h @@ -0,0 +1,58 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 21 December 1997 +// Last Modified: Sun Jan 25 15:44:35 GMT-0800 1998 +// Filename: ...sig/code/control/MidiIO/MidiIO.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiIO.h +// Syntax: C++ +// +// Description: A unified class for MidiInput and MidiOutput that handles +// MIDI input and output connections. The Synthesizer +// and RadioBaton classes are derived from this class. +// + +#ifndef _MIDIIO_H_INCLUDED +#define _MIDIIO_H_INCLUDED + + +#include "MidiInput.h" +#include "MidiOutput.h" + + +class MidiIO : public MidiOutput, public MidiInput { + public: + MidiIO (void); + MidiIO (int outPort, int inPort); + ~MidiIO (); + + void close (void); + void closeInput (void); + void closeOutput (void); + int getChannelInOffset (void) const; + int getChannelOutOffset (void) const; + int getInputPort (void); + int getInputTrace (void); + int getNumInputPorts (void); + int getNumOutputPorts (void); + int getOutputPort (void); + int getOutputTrace (void); + int open (void); + int openInput (void); + int openOutput (void); + void setChannelOffset (int anOffset); + void setInputPort (int aPort); + void setInputTrace (int aState); + void setOutputPort (int aPort); + void setOutputTrace (int aState); + void toggleInputTrace (void); + void toggleOutputTrace (void); + +}; + + + +#endif /* _MIDIIO_H_INCLUDED */ + + + +// md5sum: 9f6122405c4d9e83994457210217ff22 - MidiIO.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort.h b/src/midiio/include/MidiInPort.h new file mode 100644 index 0000000..ac225c4 --- /dev/null +++ b/src/midiio/include/MidiInPort.h @@ -0,0 +1,98 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Jan 21 22:35:31 GMT-0800 1998 +// Last Modified: Thu Jan 22 23:13:54 GMT-0800 1998 +// Last Modified: Sat Nov 7 16:09:18 PST 1998 +// Last Modified: Tue Jun 29 16:14:50 PDT 1999 (added Sysex input) +// Last Modified: Tue May 23 23:08:44 PDT 2000 (oss/alsa selection added) +// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort.h +// Web Address: http://sig.sapp.org/include/sig/MidiInPort.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of an +// operating-system specific MIDI input method. +// Provides control of all low-level MIDI input +// functionality such that it will work on all +// computers in the same manner. +// + +#ifndef _MIDIINPORT_H_INCLUDED +#define _MIDIINPORT_H_INCLUDED + + +#include "MidiMessage.h" + +#ifdef VISUAL + #define MIDIINPORT MidiInPort_visual + #include "MidiInPort_visual.h" +#elif defined(LINUX) && defined(ALSA) && defined(OSS) + #define MIDIINPORT MidiInPort_linux + #include "MidiInPort_linux.h" +#elif defined(LINUX) && defined(ALSA) && !defined(OSS) + #define MIDIINPORT MidiInPort_alsa + #include "MidiInPort_alsa.h" +#elif defined (LINUX) && defined(OSS) && !defined(ALSA) + #define MIDIINPORT MidiInPort_oss + #include "MidiInPort_oss.h" +#elif defined(LINUX) + #define MIDIINPORT MidiInPort_oss + #include "MidiInPort_oss.h" +#else + #define MIDIINPORT MidiInPort_unsupported + #include "MidiInPort_unsupported.h" +#endif + + +class MidiInPort : protected MIDIINPORT { + public: + MidiInPort (void) : MIDIINPORT() {} + MidiInPort (int aPort, int autoOpen = 1) : + MIDIINPORT(aPort, autoOpen) {} + ~MidiInPort() { } + + void clearSysex(void) { MIDIINPORT::clearSysex(); } + void clearSysex(int buffer) { MIDIINPORT::clearSysex(buffer); } + void close(void) { MIDIINPORT::close(); } + void closeAll(void) { MIDIINPORT::closeAll(); } + MidiMessage extract(void) { return MIDIINPORT::extract(); } + int getBufferSize(void) { return MIDIINPORT::getBufferSize(); } + int getChannelOffset(void) const { + return MIDIINPORT::getChannelOffset(); } + int getCount(void) { return MIDIINPORT::getCount(); } + const char* getName(void) { return MIDIINPORT::getName(); } + static const char* getName(int i) { return MIDIINPORT::getName(i); } + static int getNumPorts(void) { + return MIDIINPORT::getNumPorts(); } + int getPort(void) { return MIDIINPORT::getPort(); } + int getPortStatus(void){ + return MIDIINPORT::getPortStatus(); } + uchar* getSysex(int buffer) { return MIDIINPORT::getSysex(buffer); } + int getSysexSize(int buffer) { return MIDIINPORT::getSysexSize(buffer); } + int getTrace(void) { return MIDIINPORT::getTrace(); } + void insert(const MidiMessage& aMessage) { + MIDIINPORT::insert(aMessage); } + int installSysex(uchar* anArray, int aSize) { + return MIDIINPORT::installSysex(anArray, aSize); } + int open(void) { return MIDIINPORT::open(); } + MidiMessage& operator[](int index) { + return MIDIINPORT::message(index); } + void pause(void) { MIDIINPORT::pause(); } + void setBufferSize(int aSize) { + MIDIINPORT::setBufferSize(aSize); } + void setChannelOffset(int anOffset) { + MIDIINPORT::setChannelOffset(anOffset); } + void setAndOpenPort(int aPort) { setPort(aPort); open(); } + void setPort(int aPort) { MIDIINPORT::setPort(aPort); } + int setTrace(int aState) { + return MIDIINPORT::setTrace(aState); } + void toggleTrace(void) { MIDIINPORT::toggleTrace(); } + void unpause(void) { MIDIINPORT::unpause(); } +}; + + + +#endif /* _MIDIINPORT_H_INCLUDED */ + + + +// md5sum: 96f8a2b4411a356d1b73cd96421b8931 - MidiInPort.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort_alsa.h b/src/midiio/include/MidiInPort_alsa.h new file mode 100644 index 0000000..b321600 --- /dev/null +++ b/src/midiio/include/MidiInPort_alsa.h @@ -0,0 +1,107 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun May 14 22:05:27 PDT 2000 +// Last Modified: Sat Oct 13 16:11:24 PDT 2001 (updated for ALSA 0.9) +// Last Modified: Sat Nov 2 20:35:50 PST 2002 (added #ifdef ALSA) +// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_alsa.h +// Web Address: http://sig.sapp.org/include/sig/MidiInPort_alsa.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// linux ALSA sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// + +#ifndef _MIDIINPORT_ALSA_H_INCLUDED +#define _MIDIINPORT_ALSA_H_INCLUDED + +#ifdef LINUX +#ifdef ALSA + +#include "MidiMessage.h" +#include "CircularBuffer.h" +#include "Array.h" +#include "Sequencer_alsa.h" +#include "SigTimer.h" +#include + +typedef unsigned char uchar; +typedef void (*MIDI_Callback_function)(int arrivalPort); + + +class MidiInPort_alsa : public Sequencer_alsa { + public: + MidiInPort_alsa (void); + MidiInPort_alsa (int aPort, int autoOpen = 1); + ~MidiInPort_alsa (); + + void clearSysex (int buffer); + void clearSysex (void); + void close (void); + void closeAll (void); + MidiMessage extract (void); + int getBufferSize (void); + int getChannelOffset (void) const; + int getCount (void); + const char* getName (void); + static const char* getName (int i); + static int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + uchar* getSysex (int buffer); + int getSysexSize (int buffer); + int getTrace (void); + void insert (const MidiMessage& aMessage); + int installSysex (uchar* anArray, int aSize); + MidiMessage& message (int index); + int open (void); + void pause (void); + void setBufferSize (int aSize); + void setChannelOffset (int anOffset); + void setPort (int aPort); + int setTrace (int aState); + void toggleTrace (void); + void unpause (void); + + static Array threadinitport; + + protected: + int port; // the port to which this object belongs + + static MIDI_Callback_function callbackFunction; + + static int installSysexPrivate (int port, + uchar* anArray, int aSize); + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* trace; // for verifying input + static std::ostream* tracedisplay; // stream for displaying trace + static int numDevices; // number of input ports + static CircularBuffer** midiBuffer; // MIDI storage frm ports + static int channelOffset; // channel offset, either 0 or 1 + // not being used right now. + static int* pauseQ; // for adding items to Buffer or not + static SigTimer midiTimer; // for timing MIDI input + static Array midiInThread; // for MIDI input thread function + static int* sysexWriteBuffer; // for MIDI sysex write location + static Array** sysexBuffers; // for MIDI sysex storage + + private: + void deinitialize (void); + void initialize (void); + + + friend void *interpretMidiInputStreamPrivateALSA(void * x); + +}; + + +#endif /* ALSA */ +#endif /* LINUX */ + +#endif /* _MIDIINPORT_ALSA_H_INCLUDED */ + + + +// md5sum: 260a0accd6b08b638a00904c382293bc - MidiInPort_alsa.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort_alsa05.h b/src/midiio/include/MidiInPort_alsa05.h new file mode 100644 index 0000000..27af569 --- /dev/null +++ b/src/midiio/include/MidiInPort_alsa05.h @@ -0,0 +1,107 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun May 14 22:05:27 PDT 2000 +// Last Modified: Wed Oct 3 22:28:20 PDT 2001 (frozen for ALSA 0.5) +// Last Modified: Thu Jan 2 18:55:12 PST 2003 (added #ifdef ALSA05) +// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_alsa05.h +// Web Address: http://sig.sapp.org/include/sig/MidiInPort_alsa05.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// linux ALSA sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// + +#ifndef _MIDIINPORT_ALSA05_H_INCLUDED +#define _MIDIINPORT_ALSA05_H_INCLUDED + +#ifdef LINUX +#ifdef ALSA05 + +#include "MidiMessage.h" +#include "CircularBuffer.h" +#include "Array.h" +#include "Sequencer_alsa05.h" +#include "SigTimer.h" +#include + +typedef unsigned char uchar; +typedef void (*MIDI_Callback_function)(int arrivalPort); + + +class MidiInPort_alsa05 : public Sequencer_alsa05 { + public: + MidiInPort_alsa05 (void); + MidiInPort_alsa05 (int aPort, int autoOpen = 1); + ~MidiInPort_alsa05 (); + + void clearSysex (int buffer); + void clearSysex (void); + void close (void); + void closeAll (void); + MidiMessage extract (void); + int getBufferSize (void); + int getChannelOffset (void) const; + int getCount (void); + const char* getName (void); + static const char* getName (int i); + static int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + uchar* getSysex (int buffer); + int getSysexSize (int buffer); + int getTrace (void); + void insert (const MidiMessage& aMessage); + int installSysex (uchar* anArray, int aSize); + MidiMessage& message (int index); + int open (void); + void pause (void); + void setBufferSize (int aSize); + void setChannelOffset (int anOffset); + void setPort (int aPort); + int setTrace (int aState); + void toggleTrace (void); + void unpause (void); + + static Array threadinitport; + + protected: + int port; // the port to which this object belongs + + static MIDI_Callback_function callbackFunction; + + static int installSysexPrivate (int port, + uchar* anArray, int aSize); + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* trace; // for verifying input + static ostream* tracedisplay; // stream for displaying trace + static int numDevices; // number of input ports + static CircularBuffer** midiBuffer; // MIDI storage frm ports + static int channelOffset; // channel offset, either 0 or 1 + // not being used right now. + static int* pauseQ; // for adding items to Buffer or not + static SigTimer midiTimer; // for timing MIDI input + static Array midiInThread; // for MIDI input thread function + static int* sysexWriteBuffer; // for MIDI sysex write location + static Array** sysexBuffers; // for MIDI sysex storage + + private: + void deinitialize (void); + void initialize (void); + + + friend void *interpretMidiInputStreamPrivateALSA05(void * x); + +}; + + +#endif /* ALSA05 */ +#endif /* LINUX */ + +#endif /* _MIDIINPORT_ALSA05_H_INCLUDED */ + + + +// md5sum: 7b85b4a658c6f1d45dc1da7752f25cae - MidiInPort_alsa05.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort_linux.h b/src/midiio/include/MidiInPort_linux.h new file mode 100644 index 0000000..589d27a --- /dev/null +++ b/src/midiio/include/MidiInPort_linux.h @@ -0,0 +1,94 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun May 14 22:30:04 PDT 2000 +// Last Modified: Thu May 18 23:36:07 PDT 2000 (added ifdef LINUX lines) +// Last Modified: Sat Nov 2 20:37:49 PST 2002 (added ifdef ALSA OSS) +// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort_linux.h +// Web Address: http://sig.sapp.org/include/sig/MidiInPort_linux.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of an +// operating-system specific MIDI input method. +// Provides control of all low-level MIDI input +// functionality such that it will work on all +// computers in the same manner. +// + +#ifndef _MIDIINPORT_LINUX_H_INCLUDED +#define _MIDIINPORT_LINUX_H_INCLUDED + +#ifdef LINUX +#if defined(ALSA) && defined(OSS) + +#define MIDI_IN_UNKNOWN_SELECT 0 +#define MIDI_IN_OSS_SELECT 1 +#define MIDI_IN_ALSA_SELECT 2 + +#include "MidiInPort_oss.h" +#include "MidiInPort_alsa.h" +#include "MidiInPort_unsupported.h" +#include "MidiMessage.h" + + +class MidiInPort_linux { + public: + MidiInPort_linux(void); + MidiInPort_linux(int aPort, int autoOpen = 1); + ~MidiInPort_linux(); + + void clearSysex (void); + void clearSysex (int buffer); + void close (void); + void closeAll (void); + MidiMessage extract (void); + int getBufferSize (void); + int getChannelOffset (void) const; + int getCount (void); + const char* getName (void); + static const char* getName (int i); + static int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + uchar* getSysex (int buffer); + int getSysexSize (int buffer); + int getTrace (void); + void insert (const MidiMessage& aMessage); + int installSysex (uchar* anArray, int aSize); + MidiMessage& message (int index); + int open (void); + MidiMessage& operator[] (int index); + void pause (void); + void setBufferSize (int aSize); + void setChannelOffset (int anOffset); + void setAndOpenPort (int aPort); + void setPort (int aPort); + int setTrace (int aState); + void toggleTrace (void); + void unpause (void); + + static int getSelect (void); + static int selectOSS (void); + static int selectALSA (void); + static int selectUnknown (void); + + private: + + static int current; // the type of MIDI out selected + static int alsaQ; // boolean for if ALSA is present + static int ossQ; // boolean for if OSS is present + static int objectCount; // keeps track of static variables + + static MidiInPort_oss *oss_input; + static MidiInPort_alsa *alsa_input; + static MidiInPort_unsupported *unknown_input; + + void determineDrivers (void); +}; + +#endif /* ALSA and OSS def */ +#endif /* LINUX def */ + +#endif /* _MIDIINPORT_LINUX_H_INCLUDED */ + + +// md5sum: cc3608fb63ccf222f018efc89a4275f0 - MidiInPort_linux.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort_oss.h b/src/midiio/include/MidiInPort_oss.h new file mode 100644 index 0000000..ffa5666 --- /dev/null +++ b/src/midiio/include/MidiInPort_oss.h @@ -0,0 +1,105 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Fri Jan 8 08:33:57 PST 1999 +// Last Modified: Fri Jan 8 08:34:01 PST 1999 +// Last Modified: Tue Jun 29 16:18:02 PDT 1999 (added sysex capability) +// Last Modified: Wed May 10 17:10:05 PDT 2000 (name change from _linux to _oss) +// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_oss.h +// Web Address: http://sig.sapp.org/include/sig/MidiInPort_oss.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// linux OSS sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// + +#ifndef _MIDIINPORT_OSS_H_INCLUDED +#define _MIDIINPORT_OSS_H_INCLUDED + +#ifdef LINUX + +#include "MidiMessage.h" +#include "CircularBuffer.h" +#include "Array.h" +#include "Sequencer_oss.h" +#include "SigTimer.h" +#include + +typedef unsigned char uchar; +typedef void (*MIDI_Callback_function)(int arrivalPort); + + +class MidiInPort_oss : public Sequencer_oss { + public: + MidiInPort_oss (void); + MidiInPort_oss (int aPort, int autoOpen = 1); + ~MidiInPort_oss (); + + void clearSysex (int buffer); + void clearSysex (void); + void close (void); + void close (int i) { close(); } + void closeAll (void); + MidiMessage extract (void); + int getBufferSize (void); + int getChannelOffset (void) const; + int getCount (void); + const char* getName (void); + static const char* getName (int i); + static int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + uchar* getSysex (int buffer); + int getSysexSize (int buffer); + int getTrace (void); + void insert (const MidiMessage& aMessage); + int installSysex (uchar* anArray, int aSize); + MidiMessage& message (int index); + int open (void); + void pause (void); + void setBufferSize (int aSize); + void setChannelOffset (int anOffset); + void setPort (int aPort); + int setTrace (int aState); + void toggleTrace (void); + void unpause (void); + + protected: + int port; // the port to which this object belongs + + static MIDI_Callback_function callbackFunction; + + static int installSysexPrivate (int port, + uchar* anArray, int aSize); + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* trace; // for verifying input + static std::ostream* tracedisplay; // stream for displaying trace + static int numDevices; // number of input ports + static CircularBuffer** midiBuffer; // MIDI storage frm ports + static int channelOffset; // channel offset, either 0 or 1 + // not being used right now. + static int* pauseQ; // for adding items to Buffer or not + static SigTimer midiTimer; // for timing MIDI input + static pthread_t midiInThread; // for MIDI input thread function + static int* sysexWriteBuffer; // for MIDI sysex write location + static Array** sysexBuffers; // for MIDI sysex storage + + private: + void deinitialize (void); + void initialize (void); + + + friend void *interpretMidiInputStreamPrivate(void * x); + +}; + + +#endif /* LINUX */ + +#endif /* _MIDIINPORT_OSS_H_INCLUDED */ + + + +// md5sum: 05331ff5c3806fc753ebebaeffa3c377 - MidiInPort_oss.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort_unsupported.h b/src/midiio/include/MidiInPort_unsupported.h new file mode 100644 index 0000000..1f3bcf0 --- /dev/null +++ b/src/midiio/include/MidiInPort_unsupported.h @@ -0,0 +1,89 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Fri Jan 23 00:04:51 GMT-0800 1998 +// Last Modified: Fri Jan 23 00:04:58 GMT-0800 1998 +// Last Modified: Wed Jun 30 11:42:59 PDT 1999 (added sysex capability) +// Filename: ...sig/code/control/MidiInPort/unsupported/MidiInPort_unsupported.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiInPort_unsupported.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// an unknown sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// This class is used when there is no MIDI input, so +// that MIDI programs can otherwise be compiled and run. +// This file can also serve as a template for creating +// an OS specific class for MIDI input. +// + +#ifndef _MIDIINPUT_UNSUPPORTED_H_INCLUDED +#define _MIDIINPUT_UNSUPPORTED_H_INCLUDED + +#include "MidiMessage.h" +#include "CircularBuffer.h" +#include "Array.h" + +class MidiInPort_unsupported { + public: + MidiInPort_unsupported (void); + MidiInPort_unsupported (int aPort, int autoOpen = 1); + ~MidiInPort_unsupported (); + + void clearSysex (int index) { } + void clearSysex (void) { } + int getSysexSize (int index) { return 0; } + uchar* getSysex (int buffer) { return NULL; } + int installSysex (unsigned char *&, int &) { return 0; } + int getBufferSize (void) { return 0; } + void close (void); + void close (int i) { close(); } + void closeAll (void); + MidiMessage extract (void); + int getChannelOffset (void) const; + int getCount (void); + const char* getName (void); + static const char* getName (int i); + int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + int getTrace (void); + void insert (const MidiMessage& aMessage); + MidiMessage& message (int index); + int open (void); + void pause (void); + void setBufferSize (int aSize); + void setChannelOffset (int anOffset); + void setPort (int aPort); + int setTrace (int aState); + void toggleTrace (void); + void unpause (void); + + protected: + int port; // the port to which this object belongs + int trace; + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* openQ; // for open/close status of port + static int numDevices; // number of input ports + static CircularBuffer* midiBuffer; // MIDI storage from ports + static int channelOffset; // channel offset, either 0 or 1 + // not being used right now. + static int* sysexWriteBuffer; // for MIDI sysex write location + static Array** sysexBuffers; // for MIDI sysex storage + + private: + void deinitialize (void); + void initialize (void); + void setPortStatus (int aStatus); + + +}; + + + +#endif /* _MIDIINPUT_UNSUPPORTED_H_INCLUDED */ + + + +// md5sum: ff5492fbd59a47e48e2c0ce06705add1 - MidiInPort_unsupported.h =css= 20030102 diff --git a/src/midiio/include/MidiInPort_visual.h b/src/midiio/include/MidiInPort_visual.h new file mode 100644 index 0000000..398a187 --- /dev/null +++ b/src/midiio/include/MidiInPort_visual.h @@ -0,0 +1,114 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997 +// Last Modified: Mon Jan 12 20:05:27 GMT-0800 1998 +// Last Modified: Wed Jun 30 11:29:51 PDT 1999 (added sysex capability) +// Filename: ...sig/code/control/MidiInPort/visual/MidiInPort_visual.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiInPort_visual.h +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// Windows 95/NT/98 specific MIDI input methods. +// as defined in winmm.lib. This class is inherited +// privately by the MidiInPort class. +// + +#ifndef _MIDIINPUT_VISUAL_H_INCLUDED +#define _MIDIINPUT_VISUAL_H_INCLUDED + + +#ifdef VISUAL + +#define DEFAULT_INPUT_BUFFER_SIZE (1024) + +#include +#include + +#include "MidiMessage.h" +#include "CircularBuffer.h" +#include "Array.h" + +class MidiInPort_visual { + public: + MidiInPort_visual (void); + MidiInPort_visual (int aPort, int autoOpen = 1); + ~MidiInPort_visual (); + + void clearSysex (void); + void clearSysex (int buffer); + void close (void); + void closeAll (void); + MidiMessage extract (void); + int getBufferSize (void); + int getChannelOffset (void) const; + int getCount (void); + const char* getName (void); + static const char* getName (int i); + static int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + uchar* getSysex (int buffer); + int getSysexSize (int buffer); + int getTrace (void); + void insert (const MidiMessage& aMessage); + int installSysex (uchar* anArray, int aSize); + MidiMessage& message (int index); + int open (void); + void pause (void); + void setBufferSize (int aSize); + void setChannelOffset (int anOffset); + void setPort (int aPort); + int setTrace (int aState); + void toggleTrace (void); + void unpause (void); + + protected: + int port; // the port to which this object belongs + int trace; + + int installSysexPrivate (int port, uchar* anArray, int aSize); + void installSysexStuff (HMIDIIN dev, int port); + void uninstallSysexStuff (HMIDIIN dev, int port); + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* openQ; // for open/close status of port + static int* inrunningQ; // for running open input port + static int numDevices; // number of input ports + static HMIDIIN* device; // Windoze MIDI-in device structure + static MIDIHDR** sysexDriverBuffer1; // for Windoze driver sysex buffers + static MIDIHDR** sysexDriverBuffer2; // for Windoze driver sysex buffers + static int* sysexDBnumber; // for Windoze driver sysex buffers + static HANDLE* hMutex; // mutual exclusive + static CircularBuffer* midiBuffer; // MIDI storage from ports + static int channelOffset; // channel offset from either 0 or 1. + // not being used right now. + static int* sysexWriteBuffer; // for MIDI sysex write location + static Array** sysexBuffers;// for MIDI sysex storage + static int* sysexStatus; // tracing multiple MIM_LONGDATA messgs + + private: + void deinitialize (void); + void initialize (void); + void releaseMutex (void); + void setPortStatus (int aStatus); + void waitForMutex (void); + + + friend void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus, + DWORD instancePtr, DWORD midiMessage, DWORD timestamp); +}; + + +// This is the command which is called by the driver when there is +// MIDI data being received from the MIDI input port: + void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus, + DWORD instancePtr, DWORD midiMessage, DWORD timestamp); + + +#endif /* VISUAL */ +#endif /* _MIDIINPUT_VISUAL_H_INCLUDED */ + + + +// md5sum: d5aee7a88c4a054b3e2d4d40622fdc42 - MidiInPort_visual.h =css= 20030102 diff --git a/src/midiio/include/MidiInput.h b/src/midiio/include/MidiInput.h new file mode 100644 index 0000000..4425f75 --- /dev/null +++ b/src/midiio/include/MidiInput.h @@ -0,0 +1,53 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 18 December 1997 +// Last Modified: Sun Jan 25 15:27:02 GMT-0800 1998 +// Last Modified: Thu Apr 20 16:23:24 PDT 2000 (added scale function) +// Filename: ...sig/code/control/MidiInput/MidiInput.h +// Web Address: http://sig.sapp.org/include/sig/MidiInput.h +// Syntax: C++ +// +// Description: A higher-level MIDI input interface than the +// MidiInPort class. Can be used to allow multiple +// objects to share a single MIDI input stream, or +// to fake a MIDI input connection. +// + +#ifndef _MIDIINPUT_H_INCLUDED +#define _MIDIINPUT_H_INCLUDED + + +#include "MidiInPort.h" + + +class MidiInput : public MidiInPort { + public: + MidiInput (void); + MidiInput (int aPort, int autoOpen = 1); + ~MidiInput (); + + int getBufferSize (void); + int getCount (void); + MidiMessage extract (void); + void insert (const MidiMessage& aMessage); + int isOrphan (void) const; + void makeOrphanBuffer (int aSize = 1024); + void removeOrphanBuffer(void); + void setBufferSize (int aSize); + + int scale (int value, int min, int max); + double fscale (int value, double min, double max); + int scale14 (int value, int min, int max); + double fscale14 (int value, double min, double max); + + protected: + CircularBuffer* orphanBuffer; + +}; + + +#endif /* _MIDIINPUT_H_INCLUDED */ + + + +// md5sum: 73972cc29d7bcf0fba136b098c0419a0 - MidiInput.h =css= 20030102 diff --git a/src/midiio/include/MidiMessage.h b/src/midiio/include/MidiMessage.h new file mode 100644 index 0000000..e4b59ba --- /dev/null +++ b/src/midiio/include/MidiMessage.h @@ -0,0 +1,78 @@ +// +// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: 19 December 1997 +// Last Modified: Fri Jan 23 00:21:24 GMT-0800 1998 +// Last Modified: Sun Sep 20 20:30:53 PDT 1998 +// Last Modified: Mon Oct 15 14:29:12 PDT 2001 (added is_note functions) +// Filename: ...sig/include/sigInfo/MidiMessage.h +// Web Address: http://sig.sapp.org/include/sigInfo/MidiMessage.h +// Syntax: C++ +// +// Description: A structure for handling MIDI input messages. +// This class stores a time stamp plus up to +// four MIDI message bytes. System Exclusive messages +// are stored in a separate array in the MidiInPort +// class, and their storage index is passed to the +// user through a MIDI message for later extraction +// of the full sysex message. +// + +#ifndef _MIDIMESSAGE_H_INCLUDED +#define _MIDIMESSAGE_H_INCLUDED + +#include + +typedef unsigned char uchar; +typedef unsigned long ulong; + +class MidiMessage { + public: + ulong time; // timestamp + ulong data; // MIDI command and parameters + + MidiMessage (void); + MidiMessage (int aCommand, int aP1, int aP2, + int aTime = 0); + MidiMessage (const MidiMessage& aMessage); + ~MidiMessage (); + + uchar& command (void); + MidiMessage& operator= (const MidiMessage& aMessage); + uchar& operator[] (int index); + uchar& p0 (void); + uchar& p1 (void); + uchar& p2 (void); + uchar& p3 (void); + int getArgCount (void) const; + int getParameterCount (void) const; + + uchar getCommand (void) const; + uchar getP0 (void) const; + uchar getP1 (void) const; + uchar getP2 (void) const; + uchar getP3 (void) const; + + void setCommand (uchar aCommand); + void setData (uchar aCommand, uchar aP1 = 0, + uchar aP2 = 0, uchar aP3 = 0); + void setP0 (uchar aP0); + void setP1 (uchar aP1); + void setP2 (uchar aP2); + void setP3 (uchar aP3); + + int is_note (void); + int is_note_on (void); + int is_note_off (void); + +}; + + +std::ostream& operator<<(std::ostream& out, MidiMessage& aMessage); + + +#endif /* _MIDIMESSAGE_H_INCLUDED */ + + + +// md5sum: 4738e957fb8a233f6dbaeebda490e6a4 - MidiMessage.h =css= 20030102 diff --git a/src/midiio/include/MidiOutPort.h b/src/midiio/include/MidiOutPort.h new file mode 100644 index 0000000..0287dfd --- /dev/null +++ b/src/midiio/include/MidiOutPort.h @@ -0,0 +1,92 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Dec 28 15:04:24 GMT-0800 1997 +// Last Modified: Fri Jan 23 10:56:18 GMT-0800 1998 +// Last Modified: Sat Nov 7 16:15:54 PST 1998 +// Last Modified: Tue May 23 23:08:44 PDT 2000 (oss/alsa selection added) +// Last Modified: Mon Jun 19 10:32:11 PDT 2000 (oss/alsa define fix) +// Filename: ...sig/code/control/MidiOutPort/MidiOutPort.h +// Web Address: http://sig.sapp.org/include/sig/MidiOutPort.h +// Syntax: C++ +// +// Description: Operating-System independent interface for +// basic MIDI output capabilities. Privately +// inherits the operating-system specific class +// for MIDI output. +// + +#ifndef _MIDIOUTPORT_H_INCLUDED +#define _MIDIOUTPORT_H_INCLUDED + + +#ifdef VISUAL + #define MIDIOUTPORT MidiOutPort_visual + #include "MidiOutPort_visual.h" +#elif defined(LINUX) && defined(ALSA) && defined(OSS) + #define MIDIOUTPORT MidiOutPort_linux + #include "MidiOutPort_linux.h" +#elif defined(LINUX) && defined(ALSA) && !defined(OSS) + #define MIDIOUTPORT MidiOutPort_alsa + #include "MidiOutPort_alsa.h" +#elif defined (LINUX) && defined(OSS) && !defined(ALSA) + #define MIDIOUTPORT MidiOutPort_oss + #include "MidiOutPort_oss.h" +#elif defined(LINUX) + #define MIDIOUTPORT MidiOutPort_oss + #include "MidiOutPort_oss.h" +#else + #define MIDIOUTPORT MidiOutPort_unsupported + #include "MidiOutPort_unsupported.h" +#endif + + +class MidiOutPort : protected MIDIOUTPORT { + public: + MidiOutPort (void) : MIDIOUTPORT() {} + MidiOutPort (int aPort, int autoOpen = 1) : + MIDIOUTPORT(aPort, autoOpen) {} + ~MidiOutPort() { } + + void close(void) { MIDIOUTPORT::close(); } + void closeAll(void) { MIDIOUTPORT::closeAll(); } + int getChannelOffset(void) const { + return MIDIOUTPORT::getChannelOffset(); } + const char* getName(void) { return MIDIOUTPORT::getName(); } + static const char* getName(int i) { return MIDIOUTPORT::getName(i); } + static int getNumPorts(void) { return MIDIOUTPORT::getNumPorts(); } + int getPort(void) { return MIDIOUTPORT::getPort(); } + int getPortStatus(void) { + return MIDIOUTPORT::getPortStatus(); } + int getTrace(void) { + return MIDIOUTPORT::getTrace(); } + int open(void) { return MIDIOUTPORT::open(); } + int rawsend(int command, int p1, int p2) { + return MIDIOUTPORT::rawsend(command, p1, p2); } + int rawsend(int command, int p1) { + return MIDIOUTPORT::rawsend(command, p1); } + int rawsend(int command) { + return MIDIOUTPORT::rawsend(command); } + int rawsend(uchar* array, int size) { + return MIDIOUTPORT::rawsend(array, size); } + void setAndOpenPort(int aPort) { setPort(aPort); open(); } +// void setChannelOffset(int aChannel) { +// MIDIOUTPORT::setChannelOffset(aChannel); } + void setPort(int aPort) { MIDIOUTPORT::setPort(aPort); } + int setTrace(int aState) { + return MIDIOUTPORT::setTrace(aState); } + int sysex(uchar* array, int size) { + return MIDIOUTPORT::sysex(array, size); } + void toggleTrace(void) { MIDIOUTPORT::toggleTrace(); } + MidiOutPort& operator=(MidiOutPort& other) { + setPort(other.getPort()); + if (other.getPortStatus()) { open(); } + return *this; } +}; + + + + +#endif /* _MIDIOUTPORT_H_INCLUDED */ + + +// md5sum: 2f7b8aa8ef705eab57179b626ce1d62d - MidiOutPort.h =css= 20030102 diff --git a/src/midiio/include/MidiOutPort_alsa.h b/src/midiio/include/MidiOutPort_alsa.h new file mode 100644 index 0000000..34139a3 --- /dev/null +++ b/src/midiio/include/MidiOutPort_alsa.h @@ -0,0 +1,79 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed May 10 16:22:00 PDT 2000 +// Last Modified: Sun May 14 20:43:44 PDT 2000 +// Last Modified: Sat Nov 2 20:39:01 PST 2002 (added ALSA def) +// Filename: ...sig/maint/code/control/MidiOutPort/linux/MidiOutPort_alsa.h +// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_alsa.h +// Syntax: C++ +// +// Description: Operating-System specific interface for +// basic MIDI output capabilities in Linux using +// OSS sound drivers. Privately inherited by the +// MidiOutPort class. +// + +#ifndef _MIDIOUTPORT_ALSA_H_INCLUDED +#define _MIDIOUTPORT_ALSA_H_INCLUDED + +#ifdef LINUX +#ifdef ALSA + +#include "Sequencer_alsa.h" +#include + +typedef unsigned char uchar; + + +class MidiOutPort_alsa : public Sequencer_alsa { + public: + MidiOutPort_alsa (void); + MidiOutPort_alsa (int aPort, int autoOpen = 1); + ~MidiOutPort_alsa (); + + void close (void); + void closeAll (void); + int getChannelOffset (void) const; + const char* getName (void); + static const char* getName (int i); + int getPort (void); + static int getNumPorts (void); + int getPortStatus (void); + int getTrace (void); + int rawsend (int command, int p1, int p2); + int rawsend (int command, int p1); + int rawsend (int command); + int rawsend (uchar* array, int size); + int open (void); + void setChannelOffset (int aChannel); + void setPort (int aPort); + int setTrace (int aState); + int sysex (uchar* array, int size); + void toggleTrace (void); + + protected: + int port; // the port to which this object belongs + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int numDevices; // number of output ports + static int* trace; // for printing messages to output + static std::ostream* tracedisplay; // for printing trace messages + + private: + void deinitialize (void); + void initialize (void); + void setPortStatus (int aStatus); + + static int channelOffset; // channel offset, either 0 or 1. + // not being used right now. +}; + + + +#endif /* ALSA */ +#endif /* LINUX */ +#endif /* _MIDIOUTPUT_ALSA_H_INCLUDED */ + + +// md5sum: 5b7648c7b493df7cb0d1fae3bbb8be24 - MidiOutPort_alsa.h =css= 20030102 diff --git a/src/midiio/include/MidiOutPort_linux.h b/src/midiio/include/MidiOutPort_linux.h new file mode 100644 index 0000000..a02dc22 --- /dev/null +++ b/src/midiio/include/MidiOutPort_linux.h @@ -0,0 +1,80 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed May 10 16:03:52 PDT 2000 +// Last Modified: Thu May 18 23:37:17 PDT 2000 +// Last Modified: Sat Nov 2 20:40:01 PST 2002 (added ALSA OSS def) +// Filename: ...sig/code/control/MidiOutPort_linux/MidiOutPort_linux.h +// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_linux.h +// Syntax: C++ +// +// Description: Linux MIDI output class which detects which +// type of MIDI drivers are available: either +// ALSA or OSS. +// + +#ifndef _MIDIOUTPORT_LINUX_H_INCLUDED +#define _MIDIOUTPORT_LINUX_H_INCLUDED + +#ifdef LINUX +#if defined(ALSA) && defined(OSS) + +#include "MidiOutPort_oss.h" +#include "MidiOutPort_alsa.h" +#include "MidiOutPort_unsupported.h" + +#define UNKNOWN_MIDI_SELECT 0 /* use dummy MIDI output */ +#define OSS_MIDI_SELECT 1 /* use OSS MIDI output */ +#define ALSA_MIDI_SELECT 2 /* use ALSA MIDI output */ + +class MidiOutPort_linux { + public: + MidiOutPort_linux (void); + MidiOutPort_linux (int aPort, int autoOpen = 1); + ~MidiOutPort_linux (); + + void close (void); + void closeAll (void); + int getChannelOffset (void) const; + const char* getName (void); + static const char* getName (int i); + static int getNumPorts (void); + int getPort (void); + int getPortStatus (void); + int getTrace (void); + int open (void); + int rawsend (int command, int p1, int p2); + int rawsend (int command, int p1); + int rawsend (int command); + int rawsend (uchar* array, int size); + void setAndOpenPort (int aPort); + void setChannelOffset (int aChannel); + void setPort (int aPort); + int setTrace (int aState); + int sysex (uchar* array, int size); + void toggleTrace (void); + + static int getSelect (void); + static int selectOSS (void); + static int selectALSA (void); + static int selectUnknown (void); + + private: + static int current; // the type of MIDI out selected + static int alsaQ; // boolean for if ALSA is present + static int ossQ; // boolean for if OSS is present + + static int objectCount; + static MidiOutPort_oss *oss_output; + static MidiOutPort_alsa *alsa_output; + static MidiOutPort_unsupported *unknown_output; + + void determineDrivers (void); +}; + +#endif /* ALSA and OSS */ +#endif /* LINUX */ + +#endif /* _MIDIOUTPORT_LINUX_H_INCLUDED */ + + +// md5sum: c80f9f47c45a6d4a20b6549743cae9fb - MidiOutPort_linux.h =css= 20030102 diff --git a/src/midiio/include/MidiOutPort_oss.h b/src/midiio/include/MidiOutPort_oss.h new file mode 100644 index 0000000..22cf32d --- /dev/null +++ b/src/midiio/include/MidiOutPort_oss.h @@ -0,0 +1,75 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Fri Dec 18 19:15:00 PST 1998 +// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss) +// Filename: ...sig/maint/code/control/MidiOutPort/linux/MidiOutPort_oss.h +// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_oss.h +// Syntax: C++ +// +// Description: Operating-System specific interface for +// basic MIDI output capabilities in Linux using +// OSS sound drivers. Privately inherited by the +// MidiOutPort class. +// + +#ifndef _MIDIOUTPORT_OSS_H_INCLUDED +#define _MIDIOUTPORT_OSS_H_INCLUDED + +#ifdef LINUX + +#include "Sequencer_oss.h" + +typedef unsigned char uchar; + + +class MidiOutPort_oss : public Sequencer_oss { + public: + MidiOutPort_oss (void); + MidiOutPort_oss (int aPort, int autoOpen = 1); + ~MidiOutPort_oss (); + + void close (void); + void closeAll (void); + int getChannelOffset (void) const; + const char* getName (void); + static const char* getName (int i); + int getPort (void); + static int getNumPorts (void); + int getPortStatus (void); + int getTrace (void); + int rawsend (int command, int p1, int p2); + int rawsend (int command, int p1); + int rawsend (int command); + int rawsend (uchar* array, int size); + int open (void); + void setChannelOffset (int aChannel); + void setPort (int aPort); + int setTrace (int aState); + int sysex (uchar* array, int size); + void toggleTrace (void); + + protected: + int port; // the port to which this object belongs + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int numDevices; // number of output ports + static int* trace; // for printing messages to output + static std::ostream* tracedisplay; // for printing trace messages + + private: + void deinitialize (void); + void initialize (void); + void setPortStatus (int aStatus); + + static int channelOffset; // channel offset, either 0 or 1. + // not being used right now. +}; + + + +#endif /* LINUX */ +#endif /* _MIDIOUTPUT_OSS_H_INCLUDED */ + + +// md5sum: f60183e23c49741e93d9b965bbe9a6d8 - MidiOutPort_oss.h =css= 20030102 diff --git a/src/midiio/include/MidiOutPort_unsupported.h b/src/midiio/include/MidiOutPort_unsupported.h new file mode 100644 index 0000000..a5e8c35 --- /dev/null +++ b/src/midiio/include/MidiOutPort_unsupported.h @@ -0,0 +1,71 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Mon Jan 12 21:36:26 GMT-0800 1998 +// Last Modified: Mon Jan 12 21:36:31 GMT-0800 1998 +// Filename: ...sig/code/control/MidiOutPort/unsupported/MidiOutPort_unsupported.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutPort_unsupported.h +// Syntax: C++ +// +// Description: Operating-System specific interface for basic MIDI output +// capabilities in an unknown operating system. Privately +// inherited by the MidiOutPort class. Used for compiling +// and running MIDI programs on a computer with no +// MIDI output. +// + +#ifndef _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED +#define _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED + +typedef unsigned char uchar; + +class MidiOutPort_unsupported { + public: + MidiOutPort_unsupported (void); + MidiOutPort_unsupported (int aPort, int autoOpen = 1); + ~MidiOutPort_unsupported (); + + void close (void); + void closeAll (void); + int getChannelOffset (void) const; + const char* getName (void) const; + const char* getName (int i) const; + int getPort (void) const; + int getNumPorts (void) const; + int getPortStatus (void) const; + int getTrace (void) const; + int rawsend (int command, int p1, int p2); + int rawsend (int command, int p1); + int rawsend (int command); + int rawsend (uchar* array, int size); + int open (void); + void setChannelOffset (int aChannel); + void setPort (int aPort); + int setTrace (int aState); + int sysex (uchar* array, int size); + void toggleTrace (void); + + protected: + int port; // the port to which this object belongs + int trace; // for printing out midi messages to standard output + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* openQ; // for open/close status of port + static int numDevices; // number of output ports + + private: + void deinitialize (void); + void initialize (void); + void setPortStatus (int aStatus); + + static int channelOffset; // channel offset, either 0 or 1 + // not being used right now. +}; + + + +#endif /* _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED */ + + + +// md5sum: e244688a99d220addc7b1c6f6f6a8022 - MidiOutPort_unsupported.h =css= 20030102 diff --git a/src/midiio/include/MidiOutPort_visual.h b/src/midiio/include/MidiOutPort_visual.h new file mode 100644 index 0000000..d6a3984 --- /dev/null +++ b/src/midiio/include/MidiOutPort_visual.h @@ -0,0 +1,75 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997 +// Last Modified: Mon Jan 12 20:05:27 GMT-0800 1998 +// Filename: ...sig/code/control/MidiOutPort/visual/MidiOutPort_visual.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutPort_visual.h +// Syntax: C++ +// +// Description: Operating-System specific interface for +// basic MIDI output capabilities in Windows 95/NT/98 +// using winmm.lib. Privately inherited by the +// MidiOutPort class. +// + +#ifndef _MIDIOUTPUT_VISUAL_H_INCLUDED +#define _MIDIOUTPUT_VISUAL_H_INCLUDED + +#ifdef VISUAL + +typedef unsigned char uchar; + +#include +#include + +class MidiOutPort_visual { + public: + MidiOutPort_visual (void); + MidiOutPort_visual (int aPort, int autoOpen = 1); + ~MidiOutPort_visual (); + + void close (void); + void closeAll (void); + int getChannelOffset (void) const; + const char* getName (void); + static const char* getName (int i); + int getPort (void); + static int getNumPorts (void); + int getPortStatus (void); + int getTrace (void); + int rawsend (int command, int p1, int p2); + int rawsend (int command, int p1); + int rawsend (int command); + int rawsend (uchar* array, int size); + int open (void); + void setChannelOffset (int aChannel); + void setPort (int aPort); + int setTrace (int aState); + int sysex (uchar* array, int size); + void toggleTrace (void); + + protected: + int port; // the port to which this object belongs + int trace; // for printing out Midi messages to standard output + + static int objectCount; // num of similar objects in existence + static int* portObjectCount; // objects connected to particular port + static int* openQ; // for open/close status of port + static int numDevices; // number of output ports + static HMIDIOUT* device; // Windoze midi out device structure + + private: + void deinitialize (void); + void initialize (void); + void setPortStatus (int aStatus); + + static int channelOffset; // channel offset, either 0 or 1. + // not being used right now. +}; + + +#endif /* VISUAL */ +#endif /* _MIDIOUTPUT_VISUAL_H_INCLUDED */ + + +// md5sum: 47799e340effa57676be8a3943cabb70 - MidiOutPort_visual.h =css= 20030102 diff --git a/src/midiio/include/MidiOutput.h b/src/midiio/include/MidiOutput.h new file mode 100644 index 0000000..d424816 --- /dev/null +++ b/src/midiio/include/MidiOutput.h @@ -0,0 +1,140 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 18 December 1997 +// Last Modified: Mon Jan 26 23:53:05 GMT-0800 1998 +// Last Modified: Sat Jan 30 14:00:29 PST 1999 +// Last Modified: Sun Jul 18 18:52:42 PDT 1999 (added RPN functions) +// Filename: ...sig/maint/code/control/MidiOutput/MidiOutput.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutput.h +// Syntax: C++ +// +// Description: The MIDI output interface for MIDI synthesizers/equipment +// which has many convienience functions defined for +// various types of MIDI output. +// + +#ifndef _MIDIOUTPUT_H_INCLUDED +#define _MIDIOUTPUT_H_INCLUDED + +#include "MidiOutPort.h" +#include "FileIO.h" +#include "SigTimer.h" +#include "Array.h" + + +class MidiOutput : public MidiOutPort { + public: + MidiOutput (void); + MidiOutput (int aPort, int autoOpen = 1); + ~MidiOutput (); + + // Basic user MIDI output commands: + int cont (int channel, int controller, int data); + int off (int channel, int keynum, int releaseVelocity); + int pc (int channel, int timbre); + int play (int channel, int keynum, int velocity); + int pw (int channel, int mostByte, int leastByte); + int pw (int channel, int tuningData); + int pw (int channel, double tuningData); + void recordStart (char *filename, int format); + void recordStop (void); + void reset (void); + int send (int command, int p1, int p2); + int send (int command, int p1); + int send (int command); + void silence (int aChannel = -1); + void sustain (int channel, int status); + int sysex (char* data, int length); + int sysex (uchar* data, int length); + + protected: + int outputRecordQ; // boolean for recording + int outputRecordType; // what form to record MIDI data in + int lastFlushTime; // for recording midi data + FileIO outputRecordFile; // file for recording midi data + static SigTimer timer; // for recording midi data + static Array* rpn_lsb_status; // for RPN messages + static Array* rpn_msb_status; // for RPN messages + static int objectCount; // for RPN messages + + void deinitializeRPN (void); + void initializeRPN (void); + void writeOutputAscii (int channel, int p1, int p2); + void writeOutputBinary (int channel, int p1, int p2); + void writeOutputMidifile(int channel, int p1, int p2); + + public: // RPN controller functions + int NRPN (int channel, int nrpn_msb, int nrpn_lsb, + int data_msb, int data_lsb); + int NRPN (int channel, int nrpn_msb, int nrpn_lsb, + int data_msb); + int NRPN (int channel, int nrpn_msb, int nrpn_lsb, + double data); + int NRPN_null (int channel); + int NRPN_attack (int channel, double value); + int NRPN_attack (int channel, int value); + int NRPN_decay (int channel, double value); + int NRPN_decay (int channel, int value); + int NRPN_drumAttack (int drum, double value); + int NRPN_drumAttack (int drum, int value); + int NRPN_drumChorus (int drum, double value); + int NRPN_drumChorus (int drum, int value); + int NRPN_drumDecay (int drum, double value); + int NRPN_drumDecay (int drum, int value); + int NRPN_drumLevel (int drum, double value); + int NRPN_drumLevel (int drum, int value); + int NRPN_drumPan (int drum, double value); + int NRPN_drumPan (int drum, int value); + int NRPN_drumPitch (int drum, double value); + int NRPN_drumPitch (int drum, int value); + int NRPN_drumFilterCutoff (int drum, double value); + int NRPN_drumFilterCutoff (int drum, int value); + int NRPN_drumFilterResonance(int drum, double value); + int NRPN_drumFilterResonance(int drum, int value); + int NRPN_drumReverb (int drum, double value); + int NRPN_drumReverb (int drum, int value); + int NRPN_drumVariation (int drum, double value); + int NRPN_drumVariation (int drum, int value); + int NRPN_filterCutoff (int channel, double value); + int NRPN_filterCutoff (int channel, int value); + int NRPN_release (int channel, double value); + int NRPN_release (int channel, int value); + int NRPN_vibratoDelay (int channel, double value); + int NRPN_vibratoDelay (int channel, int value); + int NRPN_vibratoDepth (int channel, double value); + int NRPN_vibratoDepth (int channel, int value); + int NRPN_vibratoRate (int channel, double value); + int NRPN_vibratoRate (int channel, int value); + + int RPN (int channel, int rpn_msb, int rpn_lsb, + int data_msb, int data_lsb); + int RPN (int channel, int rpn_msb, int rpn_lsb, + int data_msb); + int RPN (int channel, int rpn_msb, int rpn_lsb, + double data); + int RPN_null (void); + int RPN_null (int channel); + int pbRange (int channel, int steps); + int tuneFine (int channel, int cents); + int fineTune (int channel, int cents); + int tuneCoarse (int channel, int steps); + int coarseTune (int channel, int steps); + int tuningProgram (int channel, int program); + int tuningBank (int channel, int bank); + +}; + + +#endif /* _MIDIOUTPUT_H_INCLUDED */ + +// Brief description of MidiOutput public member functions: +// +// send: sends a MIDI command to the MIDI output with up to two parameters +// play: sends a playnote command to the MIDI output +// pc: Patch Change. changes the timbre (instrument) on the given channel +// cont: sends a CONTinuous CONTroller MIDI command +// sysex: sends a system exclusive command to the MIDI output +// + + +// md5sum: 12ee02c32563ae219aaa8c7599de55db - MidiOutput.h =css= 20030102 diff --git a/src/midiio/include/MidiPort.h b/src/midiio/include/MidiPort.h new file mode 100644 index 0000000..834877e --- /dev/null +++ b/src/midiio/include/MidiPort.h @@ -0,0 +1,49 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 21 December 1997 +// Last Modified: Fri Jan 23 10:21:25 GMT-0800 1998 +// Filename: .../sig/code/control/MidiPort/MidiPort.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiPort.h +// Syntax: C++ +// +// Description: A unified object that handles basic MIDI input and output. +// Derived from the MidiInPort and MidiOutPort classes. +// + +#ifndef _MIDIPORT_H_INCLUDED +#define _MIDIPORT_H_INCLUDED + + +#include "MidiInPort.h" +#include "MidiOutPort.h" + + +class MidiPort : public MidiOutPort, public MidiInPort { + public: + MidiPort (void); + MidiPort (int outputPort, int inputPort); + ~MidiPort (); + + int getChannelInOffset (void) const; + int getChannelOutOffset (void) const; + int getInputPort (void); + int getInputTrace (void); + int getOutputPort (void); + int getOutputTrace (void); + void setChannelOffset (int anOffset); + void setInputPort (int aPort); + int setInputTrace (int aState); + void setOutputPort (int aPort); + int setOutputTrace (int aState); + void toggleInputTrace (void); + void toggleOutputTrace (void); + +}; + + + +#endif /* _MIDIPORT_H_INCLUDED */ + + + +// md5sum: 84d8155528b06c9aa902e8f06649385f - MidiPort.h =css= 20030102 diff --git a/src/midiio/include/Options.h b/src/midiio/include/Options.h new file mode 100644 index 0000000..71754fb --- /dev/null +++ b/src/midiio/include/Options.h @@ -0,0 +1,106 @@ +// +// Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Apr 5 13:07:18 PDT 1998 +// Last Modified: Fri Jan 15 07:24:00 PST 1999 +// Last Modified: Sat Mar 27 18:17:59 PST 1999 +// Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function) +// Last Modified: Fri May 5 17:57:50 PDT 2000 (added --options suppression) +// Filename: ...sig/maint/code/base/Options/Options.h +// Web Address: http://sig.sapp.org/include/sigBase/Options.h +// Documentation: http://sig.sapp.org/doc/classes/Options +// Syntax: C++ +// +// Description: Handles command-line options in a graceful manner. +// + +#ifndef _OPTIONS_H_INCLUDED +#define _OPTIONS_H_INCLUDED + +#include "Array.h" + +class option_list; +class option_register; + + +class Options { + public: + Options (void); + Options (int argc, char** argv); + ~Options (); + + int argc (void) const; + char** argv (void) const; + void define (const char* aDefinition); + void define (const char* aDefinition, + const char* description); + char* getArg (int index); + char* getArgument (int index); + int getArgCount (void); + int getArgumentCount (void); + int getBoolean (const char* optionName); + const char* getCommand (void); + const char* getCommandLine (void); + const char* getString (void); + const char* getDefinition (const char* optionName); + double getDouble (const char* optionName); + char getFlag (void); + float getFloat (const char* optionName); + int getInt (const char* optionName); + int getInteger (const char* optionName); + const char* getString (const char* optionName); + char getType (const char* optionName); + int optionsArg (void); + void print (void); + void process (int error_check = 1, int suppress = 0); + void process (int argc, char** argv, + int error_check = 1, + int suppress = 0); + void reset (void); + void verify (int argc, char** argv, + int error_check = 1, + int suppress = 0); + void verify (int error_check = 1, + int suppress = 0); + void setFlag (char aFlag); + void setModified (const char* optionName, + const char* optionValue); + void setOptions (int argc, char** argv); + + protected: + int options_error_check; // for verify command + int gargc; + char** gargv; + char* commandString; + char optionFlag; + Array argument; + Array optionRegister; + Array optionList; + int processedQ; + int sortedQ; + int suppressQ; // prevent the --options option + int optionsArgument; // indicates --options present + + int getRegIndex (const char* optionName); + int optionQ (const char* aString, int& argp); + void sortOptionNames (void); + int storeOption (int gargp, int& position, + int& running); + +}; + +#define OPTION_BOOLEAN_TYPE 'b' +#define OPTION_CHAR_TYPE 'c' +#define OPTION_DOUBLE_TYPE 'd' +#define OPTION_FLOAT_TYPE 'f' +#define OPTION_INT_TYPE 'i' +#define OPTION_STRING_TYPE 's' +#define OPTION_UNKNOWN_TYPE 'x' + + + +#endif /* _OPTIONS_H_INCLUDED */ + + + +// md5sum: c59d297a8081cb48f61b534484819f48 - Options.h =css= 20030102 diff --git a/src/midiio/include/Options_private.h b/src/midiio/include/Options_private.h new file mode 100644 index 0000000..8349d55 --- /dev/null +++ b/src/midiio/include/Options_private.h @@ -0,0 +1,73 @@ +// +// Copyright 1998-1999 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Apr 5 13:07:18 PDT 1998 +// Last Modified: Sun Jan 10 05:44:48 PST 1999 +// Filename: ...sig/maint/code/base/Options/Options_private.h +// Web Address: http://sig.sapp.org/include/sigBase/Options_private.h +// Syntax: C++ +// +// Description: A private function for use in the Options class. +// + +#ifndef _OPTIONS_PRIVATE_H_INCLUDED +#define _OPTIONS_PRIVATE_H_INCLUDED + + +class option_register { + public: + option_register (void); + option_register (const char* aDefinition, char aType, + const char* aDefaultOption, + const char* aModifiedOption); + ~option_register (); + void clearModified (void); + const char* getDefinition (void); + const char* getDefault (void); + const char* getOption (void); + const char* getModified (void); + int getModifiedQ (void); + char getType (void); + void reset (void); + void setDefault (const char* aString); + void setDefinition (const char* aString); + void setModified (const char* aString); + void setType (char aType); + + protected: + char* definition; + char* defaultOption; + char* modifiedOption; + char type; + +}; + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +class option_list { + public: + option_list (void); + option_list (const char* optionName, int anIndex); + ~option_list (); + + int getIndex (void); + const char* getName (void); + void setName (const char* aString); + void setIndex (int anIndex); + + protected: + char* name; + int index; + +}; + + + +#endif /* _OPTIONS_PRIVATE_H_INCLUDED */ + + + +// md5sum: b440ad2158e9921d0e31463a8c3e1ae0 - Options_private.h =css= 20030102 diff --git a/src/midiio/include/Sequencer_alsa.h b/src/midiio/include/Sequencer_alsa.h new file mode 100644 index 0000000..3227f5e --- /dev/null +++ b/src/midiio/include/Sequencer_alsa.h @@ -0,0 +1,139 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Thu May 11 21:06:21 PDT 2000 +// Last Modified: Sat Oct 13 14:50:04 PDT 2001 (updated for ALSA 0.9 interface) +// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_alsa.h +// Web Address: http://sig.sapp.org/include/sig/Sequencer_alsa.h +// Syntax: C++ +// +// Description: Basic MIDI input/output functionality for the +// Linux ALSA midi device /dev/snd/midiXX. This class +// is inherited by the classes MidiInPort_alsa and +// MidiOutPort_alsa. +// +// to get information of status a alsa hardware & software +// cat /proc/asound/version +// cat /proc/asound/devices +// cat /proc/asound/card0/midi0 +// + +#ifndef _SEQUENCER_ALSA_H_INCLUDED +#define _SEQUENCER_ALSA_H_INCLUDED + +#include + +#ifdef ALSA + +#include +#include "Collection.h" + +#define MIDI_EXTERNAL (1) +#define MIDI_INTERNAL (2) + +typedef unsigned char uchar; + + +class Sequencer_alsa { + public: + Sequencer_alsa (int autoOpen = 1); + ~Sequencer_alsa (); + + void close (void); + void closeInput (int index); + void closeOutput (int index); + void displayInputs (std::ostream& out = std::cout, + char* initial = "\t"); + void displayOutputs (std::ostream& out = std::cout, + char* initial = "\t"); + static const char* getInputName (int aDevice); + static const char* getOutputName (int aDevice); + static int getNumInputs (void); + static int getNumOutputs (void); + int is_open (int mode, int index); + int is_open_in (int index); + int is_open_out (int index); + int open (int direction, int index); + int openInput (int index); + int openOutput (int index); + void read (int dev, uchar* buf, int count); + void rebuildInfoDatabase (void); + int write (int aDevice, int aByte); + int write (int aDevice, uchar* bytes, int count); + int write (int aDevice, char* bytes, int count); + int write (int aDevice, int* bytes, int count); + + int getInCardValue (int aDevice) const; + int getOutCardValue (int aDevice) const; + protected: + static int class_count; // number of existing classes using + static int indevcount; // number of MIDI input devices + static int outdevcount; // number of MIDI output devices + static int initialized; // for starting buileinfodatabase + + static Collection Sequencer_alsa::rawmidi_in; + static Collection Sequencer_alsa::rawmidi_out; + static Collection Sequencer_alsa::midiincard; + static Collection Sequencer_alsa::midioutcard; + static Collection Sequencer_alsa::midiindevice; + static Collection Sequencer_alsa::midioutdevice; + static Collection Sequencer_alsa::midiinname; + static Collection Sequencer_alsa::midioutname; + + private: + static void buildInfoDatabase (void); + static void getPossibleMidiStreams(Collection& cards, + Collection& devices); + int getInDeviceValue (int aDevice) const; + int getInputType (int aDevice) const; + int getOutDeviceValue (int aDevice) const; + int getOutputType (int aDevice) const; + void removeInfoDatabase (void); + + + friend void *interpretMidiInputStreamPrivateALSA(void * x); + +}; + +#else /* ALSA is not defined */ + +typedef unsigned char uchar; + +class Sequencer_alsa { + public: + Sequencer_alsa (int autoOpen = 1) { } + ~Sequencer_alsa () { } + + void close (void) { }; + void displayInputs (std::ostream& out = std::cout, + char* initial = "\t") + { out << initial << "NONE\n"; } + void displayOutputs (std::ostream& out = std::cout, + char* initial = "\t") + { out << initial << "NONE\n"; } + static const char* getInputName (int aDevice) { return ""; } + static const char* getOutputName (int aDevice) { return ""; } + static int getNumInputs (void) { return 0; } + static int getNumOutputs (void) { return 0; } + int is_open (int mode, int index) { return 0; } + int is_open_in (int index) { return 0; } + int is_open_out (int index) { return 0; } + int open (void) { return 0; } + void read (int dev, uchar* buf, int count) { } + void rebuildInfoDatabase (void) { } + int write (int aDevice, int aByte) { return 0; } + int write (int aDevice, uchar* bytes, int count) { return 0; } + int write (int aDevice, char* bytes, int count) { return 0; } + int write (int aDevice, int* bytes, int count) { return 0; } + int getInCardValue (int aDevice) const { return 0; } + int getOutCardValue (int aDevice) const { return 0; } + +}; + + +#endif /* ALSA */ + + +#endif /* _SEQUENCER_ALSA_H_INCLUDED */ + + +// md5sum: 6147020b0646fca8245f653505308949 - Sequencer_alsa.h =css= 20030102 diff --git a/src/midiio/include/Sequencer_oss.h b/src/midiio/include/Sequencer_oss.h new file mode 100644 index 0000000..5f269a7 --- /dev/null +++ b/src/midiio/include/Sequencer_oss.h @@ -0,0 +1,92 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Jan 3 21:02:02 PST 1999 +// Last Modified: Sat Jan 30 14:11:18 PST 1999 +// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _oss to _oss) +// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_oss.h +// Web Address: http://sig.sapp.org/include/sig/Sequencer_oss.h +// Syntax: C++ +// +// Description: Basic MIDI input/output functionality for the +// Linux OSS midi device /dev/sequencer. This class +// is inherited by the classes MidiInPort_oss and +// MidiOutPort_oss. +// + +#ifndef _SEQUENCER_OSS_H_INCLUDED +#define _SEQUENCER_OSS_H_INCLUDED + +#include + +#define MIDI_EXTERNAL (1) +#define MIDI_INTERNAL (2) + +typedef unsigned char uchar; + + +class Sequencer_oss { + public: + Sequencer_oss (int autoOpen = 1); + ~Sequencer_oss (); + + void close (void); + void displayInputs (std::ostream& out = std::cout, + char* initial = "\t"); + void displayOutputs (std::ostream& out = std::cout, + char* initial = "\t"); + static int getNumInputs (void); + static int getNumOutputs (void); + static const char* getInputName (int aDevice); + static const char* getOutputName (int aDevice); + int is_open (void); + int open (void); + void read (uchar* buf, uchar* dev, int count); + void rawread (uchar* buf, int packetCount); + void rebuildInfoDatabase (void); + int write (int aDevice, int aByte); + int write (int aDevice, uchar* bytes, int count); + int write (int aDevice, char* bytes, int count); + int write (int aDevice, int* bytes, int count); + + protected: + static const char* sequencer; // name of sequencer device + static int sequencer_fd; // sequencer file descriptor + static int class_count; // number of existing classes using + static uchar midi_write_packet[4]; // for writing MIDI bytes out + static uchar midi_read_packet[4]; // for reading MIDI bytes out + static uchar synth_write_message[8]; // for writing to internal seq + static int indevcount; // number of MIDI input devices + static int outdevcount; // number of MIDI output devices + static char** indevnames; // MIDI input device names + static char** outdevnames; // MIDI output device names + static int* indevnum; // total number of MIDI inputs + static int* outdevnum; // total number of MIDI outputs + static int* indevtype; // 1 = External, 2 = Internal + static int* outdevtype; // 1 = External, 2 = Internal + static uchar synth_message_buffer[1024]; // hold bytes for synth dev + static int synth_message_buffer_count; // count of synth buffer + static int synth_message_bytes_expected; // expected count of synth + static int synth_message_curr_device; // for keeping track of dev + static int initialized; // for starting buileinfodatabase + + private: + static void buildInfoDatabase (void); + static int getFd (void); + int getInDeviceValue (int aDevice) const; + int getInputType (int aDevice) const; + int getOutDeviceValue (int aDevice) const; + int getOutputType (int aDevice) const; + void removeInfoDatabase (void); + void setFd (int anFd); + + int writeInternal(int aDevice, int aByte); + int transmitMessageToInternalSynth(void); + int transmitVoiceMessage(void); + int transmitCommonMessage(void); +}; + + +#endif /* _SEQUENCER_OSS_H_INCLUDED */ + + +// md5sum: 1df08cd946c609b9b42aadbc96b7a296 - Sequencer_oss.h =css= 20030102 diff --git a/src/midiio/include/SigTimer.h b/src/midiio/include/SigTimer.h new file mode 100644 index 0000000..e93345c --- /dev/null +++ b/src/midiio/include/SigTimer.h @@ -0,0 +1,104 @@ +// +// Programmer: Craig Stuart Sapp +// Thanks to: Erik Neuenschwander +// for Windows 95 assembly code for Pentium clock cycles. +// Ozgur Izmirli +// for concept of periodic timer. +// Creation Date: Mon Oct 13 11:34:57 GMT-0800 1997 +// Last Modified: Tue Feb 10 21:05:19 GMT-0800 1998 +// Last Modified: Sat Sep 19 15:56:48 PDT 1998 +// Last Modified: Mon Feb 22 04:44:25 PST 1999 +// Last Modified: Sun Nov 28 12:39:39 PST 1999 (added adjustPeriod()) +// Filename: .../sig/code/control/SigTimer/SigTimer.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/SigTimer.h +// Syntax: C++ +// +// Description: This class can only be used on Motorola Pentinum 75 Mhz +// chips or better because the timing information is +// extracted from the clock cycle count from a register +// on the CPU itself. This class will estimate the +// speed of the computer, but it would be better if there +// was a way of finding out the speed from some function. +// This class is used primarily for timing of MIDI input +// and output at a millisecond resolution. +// +// Interesting: http://www.datasilicon.nl/I786/timer_1.htm +// + +#ifndef _SIGTIMER_H_INCLUDED +#define _SIGTIMER_H_INCLUDED + + +#ifdef VISUAL + #include + typedef LONGLONG int64bits; +#else + typedef long long int int64bits; + #include /* for millisleep function */ +#endif + + +class SigTimer { + public: + SigTimer (void); + SigTimer (int aSpeed); + SigTimer (SigTimer& aTimer); + ~SigTimer (); + + void adjustPeriod (double periodDelta); + int expired (void) const; + double getPeriod (void) const; + double getPeriodCount (void) const; + double getTempo (void) const; + int getTicksPerSecond (void) const; + int getTime (void) const; + double getTimeInSeconds (void) const; + int getTimeInTicks (void) const; + void reset (void); + void setPeriod (double aPeriod); + void setTempo (double beatsPerMinute); + void setPeriodCount (double aCount); + void setTicksPerSecond (int aTickRate); + void start (void); + void sync (SigTimer& aTimer); + void update (void); + void update (int periodCount); + + // The following functions are semi-private. They do not have + // anything to do with timing themselves, but are a by-product + // of the timer implementation. They are useful, so they have + // been left public; however, they should be used judiciously. + static int getCpuSpeed (void); + static int measureCpuSpeed (int quantize = 0); + static void setCpuSpeed (int aSpeed); + + // the following function is hardware specific to Intel Pentium + // computers with a processor speed of at least 75 MHz. + // This function is the only non-portable function in this + // class, but everything else is based on it. + static int64bits clockCycles (void); + + protected: + static int64bits globalOffset; + static int cpuSpeed; + + int64bits offset; + int ticksPerSecond; + double period; + + // protected functions + double getFactor (void) const; + +}; + + +// The following function is mostly for Linux: +void millisleep(int milliseconds); +void millisleep(float milliseconds); + + +#endif /* _SIGTIMER_H_INCLUDED */ + + + +// md5sum: 601fa3caae4e3bacc4e6fb87f545c86b - SigTimer.h =css= 20030102 diff --git a/src/midiio/include/Voice.h b/src/midiio/include/Voice.h new file mode 100644 index 0000000..3cddf9f --- /dev/null +++ b/src/midiio/include/Voice.h @@ -0,0 +1,70 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Oct 11 18:21:46 PDT 1998 +// Last Modified: Sun Oct 11 18:33:04 PDT 1998 +// Filename: ...sig/maint/code/control/Voice/Voice.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/Voice.h +// Syntax: C++ +// +// Description: The Voice class is a MIDI output class which keeps +// track of the last note played in to it. If the last +// note was not turned off when a new note is played, +// then the old note will be turned off before the +// new note is played. +// + +#ifndef _VOICE_H_INCLUDED +#define _VOICE_H_INCLUDED + +#include "MidiOutput.h" + +class Voice : public MidiOutput { + public: + Voice (int aChannel); + Voice (const Voice& aVoice); + Voice (void); + ~Voice (); + + void cont (int controler, int data); + int getChan (void) const; + int getChannel (void) const; + int getKey (void) const; + int getKeynum (void) const; + int getOffTime (void) const; + int getOnTime (void) const; + int getVel (void) const; + int getVelocity (void) const; + void off (void); + void pc (int aTimbre); + void play (int aChannel, int aKeyno, int aVelocity); + void play (int aKeyno, int aVelocity); + void play (void); + void setChan (int aChannel); + void setChannel (int aChannel); + void setKey (int aKeyno); + void setKeynum (int aKeyno); + void setVel (int aVelocity); + void setVelocity (int aVelocity); + int status (void) const; + void sustain (int aStatus); + + protected: + int chan; // the current channel number + int key; // the current key number + int vel; // the current velocity value + + int onTime; // last note on message sent + int offTime; // last note off message sent + + int oldChan; // last channel played on + int oldKey; // last key to be played + int oldVel; // last velocity of last key + + static SigTimer timer; // for recording on/off times +}; + + +#endif /* _VOICE_H_INCLUDED */ + + +// md5sum: 8a5495ecc10d42be6b1832492e107723 - Voice.h =css= 20030102 diff --git a/src/midiio/include/gminstruments.h b/src/midiio/include/gminstruments.h new file mode 100644 index 0000000..0e567da --- /dev/null +++ b/src/midiio/include/gminstruments.h @@ -0,0 +1,251 @@ +// +// Copyright 1997-2000 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp (from 18Dec1997) +// Creation Date: 26 December 1997 +// Last Modified: Tue Apr 18 11:38:28 PDT 2000 (put CH_X defines here) +// Filename: ...sig/include/sigInfo/gminstruments.h +// Web Address: http://sig.sapp.org/include/sigInfo/gminstruments.h +// Syntax: C +// +// Description: Defines names for instruments as arranged in General MIDI. +// + +#ifndef _GMINSTRUMENTS_H_INCLUDED +#define _GMINSTRUMENTS_H_INCLUDED + +#define CH_1 0 +#define CH_2 1 +#define CH_3 2 +#define CH_4 3 +#define CH_5 4 +#define CH_6 5 +#define CH_7 6 +#define CH_8 7 +#define CH_9 8 +#define CH_10 9 +#define CH_11 10 +#define CH_12 11 +#define CH_13 12 +#define CH_14 13 +#define CH_15 14 +#define CH_16 15 + +#define GM_PIANO(X) (0+(X)) +#define GM_ACOUSTIC_GRAND_PIANO (0) +#define GM_BRIGHT_ACOUSTIC_PIANO (1) +#define GM_ELECTRIC_GRAND_PIANO (1) +#define GM_HONKYTONK_PIANO (2) +#define GM_HONKY_TONK_PIANO (3) +#define GM_ELECTRIC_PIANO_1 (4) +#define GM_ELECTRIC_PIANO_2 (5) +#define GM_HARPSICHORD (6) +#define GM_CLAVI (7) + +#define GM_CHROMATIC(X) (8+(X)) +#define GM_CELESTA (8) +#define GM_GLOCKENSPIEL (9) +#define GM_MUSIC_BOX (10) +#define GM_VIBRAPHONE (11) +#define GM_MARIMBA (12) +#define GM_XYLOPHONE (13) +#define GM_TUBULAR_BELLS (14) +#define GM_DULCIMER (15) + +#define GM_ORGAN(X) (16+(X)) +#define GM_DRAWBAR_ORGAN (16) +#define GM_PERCUSSIVE_ORGAN (17) +#define GM_ROCK_ORGAN (18) +#define GM_CHURCH_ORGAN (19) +#define GM_REED_ORGAN (20) +#define GM_ACCORDION (21) +#define GM_HARMONICA (22) +#define GM_TANGO_ACCORDION (23) + +#define GM_GUITAR(X) (24+(X)) +#define GM_ACOUSTIC_GUITAR_NYLON (24) +#define GM_ACOUSTIC_GUITAR_STEEL (25) +#define GM_ELECTRIC_GUITAR_JAZZ (26) +#define GM_ELECTRIC_GUITAR_CLEAN (27) +#define GM_ELECTRIC_GUITAR_MUTED (28) +#define GM_OVERDRIVEN_GUITAR (29) +#define GM_DISTORTION_GUITAR (30) +#define GM_GUITAR_HARMONICS (31) + +#define GM_BASS(X) (32+(X)) +#define GM_ACOUSTIC_BASS (32) +#define GM_ELECTRIC_BASS_FINGER (33) +#define GM_ELECTRIC_BASS_PICK (34) +#define GM_FRETLESS_BASS (35) +#define GM_SLAP_BASS_1 (36) +#define GM_SLAP_BASS_2 (37) +#define GM_SYNTH_BASS_1 (38) +#define GM_SYNTH_BASS_2 (39) + +#define GM_STRINGS(X) (40+(X)) +#define GM_VIOLIN (40) +#define GM_VIOLA (41) +#define GM_CELLO (42) +#define GM_CONTRABASS (43) +#define GM_TREMOLO_STRINGS (44) +#define GM_PIZZACATO_STRINGS (45) +#define GM_ORCHESTRAL_HARP (46) +#define GM_TIMPANI (47) + +#define GM_ENSEMBLE(X) (48+(X)) +#define GM_STRING_ENSEMBLE_1 (48) +#define GM_STRING_ENSEMBLE_2 (49) +#define GM_SYNTHSTRINGS_1 (50) +#define GM_SYNTHSTRINGS_2 (51) +#define GM_CHOIR_AAHS (52) +#define GM_VOICE_OOHS (53) +#define GM_SYNTH_VOICE (54) +#define GM_ORCHESTRA_HIT (55) + +#define GM_BRASS(X) (56+(X)) +#define GM_TRUMPET (56) +#define GM_TROMBONE (57) +#define GM_TUBA (58) +#define GM_MUTED_TRUMPED (59) +#define GM_FRENCH_HORN (60) +#define GM_BRASS_SECTION (61) +#define GM_SYNTHBRASS_1 (62) +#define GM_SYNTHBRASS_2 (63) + +#define GM_REED(X) (64+(X)) +#define GM_SOPRANO_SAX (64) +#define GM_ALTO_SAX (65) +#define GM_TENOR_SAX (66) +#define GM_BARITONE_SAX (67) +#define GM_OBOE (68) +#define GM_ENGLISH_HORN (69) +#define GM_BASSOON (70) +#define GM_CLARINET (71) + +#define GM_PIPE(X) (72+(X)) +#define GM_PICCOLO (72) +#define GM_FLUTE (73) +#define GM_RECORDER (74) +#define GM_PAN_FLUTE (75) +#define GM_BLOWN_BOTTLE (76) +#define GM_SHAKUHACHI (77) +#define GM_WHISTLE (78) +#define GM_OCARINA (79) + +#define GM_LEAD(X) (80+(X)) +#define GM_LEAD_SQUARE (80) +#define GM_LEAD_SAWTOOTH (81) +#define GM_LEAD_CALLIOPE (82) +#define GM_LEAD_CHIFF (83) +#define GM_LEAD_CHARANG (84) +#define GM_LEAD_VOICE (85) +#define GM_LEAD_FIFTHS (86) +#define GM_LEAD_BASS (87) + +#define GM_PAD(X) (88+(X)) +#define GM_PAD_NEW_AGE (88) +#define GM_PAD_WARM (89) +#define GM_PAD_POLYSYNTH (90) +#define GM_PAD_CHOIR (91) +#define GM_PAD_BOWED (92) +#define GM_PAD_METALLIC (93) +#define GM_PAD_HALO (94) +#define GM_PAD_SWEEP (95) + +#define GM_FX(X) (96+(X)) +#define GM_FX_TRAIN (96) +#define GM_FX_SOUNDTRACK (97) +#define GM_FX_CRYSTAL (98) +#define GM_FX_ATMOSPHERE (99) +#define GM_FX_BRIGHTNESS (100) +#define GM_FX_GOBLINS (101) +#define GM_FX_ECHOES (102) +#define GM_FX_SCI_FI (103) + +#define GM_ETHNIC(X) (104+(X)) +#define GM_SITAR (104) +#define GM_BANJO (105) +#define GM_SHAMISEN (106) +#define GM_KOTO (107) +#define GM_KALIMBA (108) +#define GM_BAGPIPE (109) +#define GM_FIDDLE (110) +#define GM_SHANAI (111) + +#define GM_PERCUSSION(X) (112+(X)) +#define GM_TINKLE_BELL (112) +#define GM_AGOGO (113) +#define GM_STEEL_DRUMS (114) +#define GM_WOODBLOCKS (115) +#define GM_TAIKO_DRUM (116) +#define GM_MELODIC_DRUM (117) +#define GM_SYNTH_DRUM (118) +#define GM_REVERSE_CYMBAL (119) + +#define GM_SOUNDEFFECT(X) (120+(X)) +#define GM_GUITAR_FRET_NOISE (120) +#define GM_BREATH_NOISE (121) +#define GM_SEASHORE (122) +#define GM_BIRD_TWEET (123) +#define GM_TELEPHONE_RING (124) +#define GM_HELICOPTER (125) +#define GM_APPLAUSE (126) +#define GM_GUNSHOT (127) + +// +// Percussion instruments on channel 10 +// + +#define GM_ACOUSTIC_BASS_DRUM (35) +#define GM_BASS_DRUM_1 (36) +#define GM_SIDE_STICK (37) +#define GM_ACOUSTIC_SNARE (38) +#define GM_HAND_CLAP (39) +#define GM_ELECTRIC_SNARE (40) +#define GM_LOW_FLOOR_TOM (41) +#define GM_CLOSED_HI_HAT (42) +#define GM_HIGH_FLOOR_TOM (43) +#define GM_PEDAL_HI_HAT (44) +#define GM_LOW_TOM (45) +#define GM_OPEN_HI_HAT (46) +#define GM_LOW_MID_TOM (47) +#define GM_HIGH_MID_TOM (48) +#define GM_CRASH_CYMBAL_1 (49) +#define GM_HIGH_TOM (50) +#define GM_RIDE_CYMBAL_1 (51) +#define GM_CHINESE_CYMBAL (52) +#define GM_RIDE_BELL (53) +#define GM_TAMBOURINE (54) +#define GM_SPLASH_CYMBAL (55) +#define GM_COWBELL (56) +#define GM_CRASH_CYMBAL_2 (57) +#define GM_VIBRASLAP (58) +#define GM_RIDE_CYMBAL_2 (59) +#define GM_HI_BONGO (60) +#define GM_LOW_BONGO (61) +#define GM_MUTE_HI_CONGA (62) +#define GM_OPEN_HI_CONGA (63) +#define GM_LOW_CONGA (64) +#define GM_HIGH_TIMBALE (65) +#define GM_LOW_TIMBALE (66) +#define GM_HIGH_AGOGO (67) +#define GM_LOW_AGOGO (68) +#define GM_CABASA (69) +#define GM_MARACAS (70) +#define GM_SHORT_WHISTLE (71) +#define GM_LONG_WHISTLE (72) +#define GM_SHORT_GUIRO (73) +#define GM_LONG_GUIRO (74) +#define GM_CLAVES (75) +#define GM_HI_WOOD_BLOCK (76) +#define GM_LOW_WOOD_BLOCK (77) +#define GM_MUTE_CUICA (78) +#define GM_OPEN_CUICA (79) +#define GM_MUTE_TRIANGLE (80) +#define GM_OPEN_TRIANGLE (81) + + +#endif /* _GMINSTRUMENTS_H_INCLUDED */ + + + +// md5sum: 6299d04892a6899533b9164aa9e1a874 - gminstruments.h =css= 20030102 diff --git a/src/midiio/include/midichannels.h b/src/midiio/include/midichannels.h new file mode 100644 index 0000000..4526813 --- /dev/null +++ b/src/midiio/include/midichannels.h @@ -0,0 +1,42 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 21 December 1997 +// Last Modified: Wed Feb 11 22:49:59 GMT-0800 1998 +// Filename: ...sig/code/control/misc/midichannels.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/midichannels.h +// Syntax: C++ +// +// Description: Offset by 1 MIDI channel names. +// + +#ifndef _MIDICHANNELS_H_INCLUDED +#define _MIDICHANNELS_H_INCLUDED + +/* temporarily changed : + +// channel defines: offset from 0 +#define CH_1 (0x00) +#define CH_2 (0x01) +#define CH_3 (0x02) +#define CH_4 (0x03) +#define CH_5 (0x04) +#define CH_6 (0x05) +#define CH_7 (0x06) +#define CH_8 (0x07) +#define CH_9 (0x08) +#define CH_10 (0x09) +#define CH_11 (0x0a) +#define CH_12 (0x0b) +#define CH_13 (0x0c) +#define CH_14 (0x0d) +#define CH_15 (0x0e) +#define CH_16 (0x0f) + +*/ + +#endif /* _MIDICHANNELS_H_INCLUDED */ + + + + +// md5sum: 5267399f7ff90a6ea3ad2dc132afae3e - midichannels.h =css= 20030102 diff --git a/src/midiio/include/mididefines.h b/src/midiio/include/mididefines.h new file mode 100644 index 0000000..4161c2f --- /dev/null +++ b/src/midiio/include/mididefines.h @@ -0,0 +1,34 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 21 December 1997 +// Last Modified: Wed Feb 11 22:49:59 GMT-0800 1998 +// Filename: ...sig/code/control/misc/mididefines.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/mididefines.h +// Syntax: C++ +// +// Description: Collection of all of the MIDI convienience defines. +// + +#ifndef _MIDIDEFINES_H_INCLUDED +#define _MIDIDEFINES_H_INCLUDED + + +// include channel defines +#include "midichannels.h" + + +// include note name defines +#include "notenames.h" + + +// include General MIDI instrument names +#include "gminstruments.h" + + + +#endif /* _MIDIDEFINES_H_INCLUDED */ + + + + +// md5sum: 0f081c8e0b386a11e448b6088bfcd489 - mididefines.h =css= 20030102 diff --git a/src/midiio/include/midiiolib.h b/src/midiio/include/midiiolib.h new file mode 100644 index 0000000..17d0430 --- /dev/null +++ b/src/midiio/include/midiiolib.h @@ -0,0 +1,57 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sat Nov 2 20:20:24 PST 2002 +// Last Modified: Thu Jan 2 18:51:20 PST 2003 (changed name from midio.h) +// Filename: ...sig/code/misc/midiiolib.h +// Web Address: http://sig.sapp.org/include/sig/midiiolib.h +// Syntax: C++ +// +// Description: Includes all of the header files for using the midiio +// Library. +// + +#ifndef _MIDIIOLIB_H_INCLUDED +#define _MIDIIOLIB_H_INCLUDED + +#include "Array.h" +#include "CircularBuffer.h" +#include "Collection.h" +#include "FileIO.h" +#include "gminstruments.h" +#include "midichannels.h" +#include "mididefines.h" +#include "MidiFile.h" +#include "MidiFileWrite.h" +#include "MidiInPort_alsa05.h" +#include "MidiInPort_alsa.h" +#include "MidiInPort.h" +#include "MidiInPort_linux.h" +#include "MidiInPort_oss.h" +#include "MidiInPort_unsupported.h" +#include "MidiInPort_visual.h" +#include "MidiInput.h" +#include "MidiIO.h" +#include "MidiMessage.h" +#include "MidiOutPort_alsa.h" +#include "MidiOutPort.h" +#include "MidiOutPort_linux.h" +#include "MidiOutPort_oss.h" +#include "MidiOutPort_unsupported.h" +#include "MidiOutPort_visual.h" +#include "MidiOutput.h" +#include "MidiPort.h" +#include "notenames.h" +#include "Options.h" +#include "Options_private.h" +#include "Sequencer_alsa.h" +#include "Sequencer_oss.h" +#include "sigConfiguration.h" +#include "SigTimer.h" +#include "Voice.h" + + +#endif /* _MIDIIO_H_INCLUDED */ + + + +// md5sum: b389c20c620865344d827a88a0fb048d - midiiolib.h =css= 20030102 diff --git a/src/midiio/include/notenames.h b/src/midiio/include/notenames.h new file mode 100644 index 0000000..ce9d505 --- /dev/null +++ b/src/midiio/include/notenames.h @@ -0,0 +1,219 @@ +// +// Programmer: Craig Stuart Sapp (from 18Dec1997) +// Creation Date: 26 December 1997 +// Last Modified: 26 December 1997 +// Filename: ...sig/code/control/misc/notenames.h +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/notenames.h +// Syntax: C +// +// Description: Defines for pitch names of midi key numbers +// + +#ifndef _NOTENAMES_H_INCLUDED +#define _NOTENAMES_H_INCLUDED + +#define C00 (0) +#define Cs00 (1) +#define Db00 (1) +#define D00 (2) +#define Ds00 (3) +#define Eb00 (3) +#define E00 (4) +#define F00 (5) +#define Fs00 (6) +#define Gb00 (6) +#define G00 (7) +#define Gs00 (8) +#define Ab00 (8) +#define A00 (9) +#define As00 (10) +#define Bb00 (10) +#define B00 (11) + +#define C0 (12) +#define Cs0 (13) +#define Db0 (13) +#define D0 (14) +#define Ds0 (15) +#define Eb0 (15) +#define E0 (16) +#define F0 (17) +#define Fs0 (18) +#define Gb0 (18) +#define G0 (19) +#define Gs0 (20) +#define Ab0 (20) +#define A0 (21) +#define As0 (22) +#define Bb0 (22) + +/* + * Note that the following symbol B0 is used in + * unix in the file /usr/include/termios.h also as + * a symbol, so It is disabled for now in this file. + * termios.h is need in Unix for the KeyboardInput.h file + */ + +// #define B0 (23) + +#define C1 (24) +#define Cs1 (25) +#define Db1 (25) +#define D1 (26) +#define Ds1 (27) +#define Eb1 (27) +#define E1 (28) +#define F1 (29) +#define Fs1 (30) +#define Gb1 (30) +#define G1 (31) +#define Gs1 (32) +#define Ab1 (32) +#define A1 (33) +#define As1 (34) +#define Bb1 (34) +#define B1 (35) + +#define C2 (36) +#define Cs2 (37) +#define Db2 (37) +#define D2 (38) +#define Ds2 (39) +#define Eb2 (39) +#define E2 (40) +#define F2 (41) +#define Fs2 (42) +#define Gb2 (42) +#define G2 (43) +#define Gs2 (44) +#define Ab2 (44) +#define A2 (45) +#define As2 (46) +#define Bb2 (46) +#define B2 (47) + +#define C3 (48) +#define Cs3 (49) +#define Db3 (49) +#define D3 (50) +#define Ds3 (51) +#define Eb3 (51) +#define E3 (52) +#define F3 (53) +#define Fs3 (54) +#define Gb3 (54) +#define G3 (55) +#define Gs3 (56) +#define Ab3 (56) +#define A3 (57) +#define As3 (58) +#define Bb3 (58) +#define B3 (59) + +#define C4 (60) +#define Cs4 (61) +#define Db4 (61) +#define D4 (62) +#define Ds4 (63) +#define Eb4 (63) +#define E4 (64) +#define F4 (65) +#define Fs4 (66) +#define Gb4 (66) +#define G4 (67) +#define Gs4 (68) +#define Ab4 (68) +#define A4 (69) +#define As4 (70) +#define Bb4 (70) +#define B4 (71) + +#define C5 (72) +#define Cs5 (73) +#define Db5 (73) +#define D5 (74) +#define Ds5 (75) +#define Eb5 (75) +#define E5 (76) +#define F5 (77) +#define Fs5 (78) +#define Gb5 (78) +#define G5 (79) +#define Gs5 (80) +#define Ab5 (81) +#define A5 (81) +#define As5 (82) +#define Bb5 (82) +#define B5 (83) + +#define C6 (84) +#define Cs6 (85) +#define Db6 (85) +#define D6 (86) +#define Ds6 (87) +#define Eb6 (87) +#define E6 (88) +#define F6 (89) +#define Fs6 (90) +#define Gb6 (90) +#define G6 (91) +#define Gs6 (92) +#define Ab6 (92) +#define A6 (93) +#define As6 (94) +#define Bb6 (94) +#define B6 (95) + +#define C7 (96) +#define Cs7 (97) +#define Db7 (97) +#define D7 (98) +#define Ds7 (99) +#define Eb7 (99) +#define E7 (100) +#define F7 (101) +#define Fs7 (102) +#define Gb7 (102) +#define G7 (103) +#define Gs7 (104) +#define Ab7 (104) +#define A7 (105) +#define As7 (106) +#define Bb7 (106) +#define B7 (107) + +#define C8 (108) +#define Cs8 (109) +#define Db8 (109) +#define D8 (110) +#define Ds8 (111) +#define Eb8 (111) +#define E8 (112) +#define F8 (113) +#define Fs8 (114) +#define Gb8 (114) +#define G8 (115) +#define Gs8 (116) +#define Ab8 (116) +#define A8 (117) +#define As8 (118) +#define Bb8 (118) +#define B8 (119) + +#define C9 (120) +#define Cs9 (121) +#define Db9 (121) +#define D9 (122) +#define Ds9 (123) +#define Eb9 (123) +#define E9 (124) +#define F9 (125) +#define Fs9 (126) +#define Gb9 (126) +#define G9 (127) + + +#endif /* _NOTENAMES_H_INCLUDED */ + + +// md5sum: c0f727163d32e04212a0ce5c8b6c4a6f - notenames.h =css= 20030102 diff --git a/src/midiio/include/sigConfiguration.h b/src/midiio/include/sigConfiguration.h new file mode 100644 index 0000000..b1e5f17 --- /dev/null +++ b/src/midiio/include/sigConfiguration.h @@ -0,0 +1,100 @@ +// +// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Mon Dec 1 18:16:57 GMT-0800 1997 +// Last Modified: Mon Dec 1 18:16:57 GMT-0800 1997 +// Filename: ...sig/maint/code/misc/sigConfiguration.h +// Web Address: http://sig.sapp.org/include/sig/sigConfiguration.h +// Syntax: C +// +// Description: This file defines flags for different code setups: +// You specify the OS in a compiler flag and this file takes care +// of the rest of the defines for that OS. This file should +// automatically be included in any file which uses any of the +// define flags below. +// +// OS setup defines to use in compiling files: +// +// -DLINUX: Linux running on intel computers +// -DNEXTI: NeXT OS on Intel Hardware +// -DNEXTM: NeXT OS on Motorola Hardware +// -DSUN: Sun SPARCstations +// -DVISUAL: Windows 95/NT using Microsoft Visual C++ 5.0 +// -DHPUX: Hewlett-Packard Unix Workstations. +// -DIRIX: SGI computers with IRIX OS. +// +// +// Various options that can be defined for each OS. These +// defines may be mixed and matched in different OSes: +// +// -DOTHEREND: If the computer is little-endian, then this +// define switches the byte ordering behavior for writing/reading +// soundfiles. Intel computers need this define, most others +// will not.need this define. +// +// -DSHORTRAND: Indicates that the rand() function generates +// numbers between 0 and 0x7fff. The default without this +// option is a range between 0 and 0x7fffffff. +// +// -DINTEL: Indicates that the computer hardware uses an +// intel x86 CPU. Not used for anything right now except to +// define the endian flag (OTHEREND). +// +// -DMOTOROLA: Indicates that the computer hardware uses a +// Motorola 68k CPU. Not used for anything right now. +// +// + +#ifndef _SIGCONFIGURATION_H_INCLUDED +#define _SIGCONFIGURATION_H_INCLUDED + + +#ifdef LINUX + #define INTEL +#endif + + +#ifdef NEXTI + #define INTEL +#endif + + +#ifdef NEXT + #define MOTOROLA +#endif + + +#ifdef VISUAL + #define INTEL +#endif + + +#ifdef SUN + #define SHORTRAND +#endif + + +#ifdef HPUX + #define SHORTRAND +#endif + + +#ifdef IRIX + #define SHORTRAND +#endif + + +// These defines must come after the previous defines: + + +#ifdef INTEL + #define OTHEREND +#endif + + + +#endif /* _SIGCONFIGURATION_H_INCLUDED */ + + + +// md5sum: 32f74a7c264b158b83ff38db1ea885f8 - sigConfiguration.h =css= 20030102 diff --git a/src/midiio/src/FileIO.cpp b/src/midiio/src/FileIO.cpp new file mode 100644 index 0000000..93ef153 --- /dev/null +++ b/src/midiio/src/FileIO.cpp @@ -0,0 +1,761 @@ +// +// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Fri May 9 22:30:32 PDT 1997 +// Last Modified: Sun Dec 14 03:29:39 GMT-0800 1997 +// Filename: ...sig/maint/code/sigBase/FileIO.cpp +// Web Address: http://sig.sapp.org/src/sigBase/FileIO.cpp +// Documentation: http://sig.sapp.org/doc/classes/FileIO +// Syntax: C++ +// +// Description: Derived from the fstream class, this class has +// functions which allow writing binary files in +// both little and big endian formats. Useful for +// writing files such as soundfiles and MIDI files +// which require numbers to be stored in a particular +// endian format. +// + +#include "FileIO.h" +#include "sigConfiguration.h" + +////////////////////////////// +// +// FileIO::FileIO -- +// + +FileIO::FileIO(void) { + // do nothing +}; + +FileIO::FileIO(const char* filename, std::ios::openmode state) : +#ifdef VISUAL /* for stupid LF-CR prevention in DOS */ + std::fstream(filename, state | ios::binary) { +#else + std::fstream(filename, state) { +#endif + // do nothing +}; + + + +////////////////////////////// +// +// FileIO::~FileIO -- +// + +FileIO::~FileIO() { + // do nothing +} + + + +////////////////////////////// +// +// FileIO::readBigEndian -- +// Read numbers from a file as big endian +// + +void FileIO::readBigEndian(char& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(uchar& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(short& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(ushort& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(long& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(ulong& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(int& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(uint& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(float& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + +void FileIO::readBigEndian(double& aNumber) { + #ifdef OTHEREND + readNotMachineEndian(aNumber); + #else + readMachineEndian(aNumber); + #endif +} + + + +////////////////////////////// +// +// FileIO::readLittleEndian -- +// Read numbers from a file as little endian +// + +void FileIO::readLittleEndian(char& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(uchar& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(short& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(ushort& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(long& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(ulong& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(int& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(uint& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(float& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + +void FileIO::readLittleEndian(double& aNumber) { + #ifdef OTHEREND + readMachineEndian(aNumber); + #else + readNotMachineEndian(aNumber); + #endif +} + + + +////////////////////////////// +// +// FileIO::readMachineEndian -- +// Read numbers from a file in the same endian as the computer. +// + +void FileIO::readMachineEndian(char& aNumber) { + this->read(&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(uchar& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(short& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(ushort& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(long& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(ulong& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(int& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(uint& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(float& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::readMachineEndian(double& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); +} + + + +////////////////////////////// +// +// FileIO::readNotMachineEndian -- +// Read numbers from a file with different endian from the computer. +// + +void FileIO::readNotMachineEndian(char& aNumber) { + this->read(&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(uchar& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(short& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(ushort& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(long& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(ulong& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(int& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(uint& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(float& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + +void FileIO::readNotMachineEndian(double& aNumber) { + this->read((char*)&aNumber, sizeof(aNumber)); + aNumber = flipBytes(aNumber); +} + + + +////////////////////////////// +// +// FileIO::writeBigEndian -- +// + +void FileIO::writeBigEndian(char aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(uchar aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(short aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(ushort aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(long aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(ulong aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(int aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(uint aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(float aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + +void FileIO::writeBigEndian(double aNumber) { + #ifdef OTHEREND + writeNotMachineEndian(aNumber); + #else + writeMachineEndian(aNumber); + #endif +} + + + +////////////////////////////// +// +// FileIO::writeLittleEndian -- +// + +void FileIO::writeLittleEndian(char aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(uchar aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(short aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(ushort aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(long aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(ulong aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(int aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(uint aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(float aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + +void FileIO::writeLittleEndian(double aNumber) { + #ifdef OTHEREND + writeMachineEndian(aNumber); + #else + writeNotMachineEndian(aNumber); + #endif +} + + + +////////////////////////////// +// +// FileIO::writeMachineEndian -- +// + +void FileIO::writeMachineEndian(char aNumber) { + this->write(&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(uchar aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(short aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(ushort aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(long aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(ulong aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(int aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(uint aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(float aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeMachineEndian(double aNumber) { + this->write((char*)&aNumber, sizeof(aNumber)); +} + + + +////////////////////////////// +// +// FileIO::writeNotMachineEndian -- +// + +void FileIO::writeNotMachineEndian(char aNumber) { + // aNumber = flipBytes(aNumber); + this->write(&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(uchar aNumber) { + // aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(short aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(ushort aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(long aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(ulong aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(int aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(uint aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(float aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + +void FileIO::writeNotMachineEndian(double aNumber) { + aNumber = flipBytes(aNumber); + this->write((char*)&aNumber, sizeof(aNumber)); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// private functions +// + + +////////////////////////////// +// +// flipBytes -- flip the bytes in a number +// + +char FileIO::flipBytes(char aNumber) { + return aNumber; +} + + +uchar FileIO::flipBytes(uchar aNumber) { + return aNumber; +} + + +short FileIO::flipBytes(short aNumber) { + static uchar output[2]; + static uchar* input; + input = (uchar*)(&aNumber); + + output[0] = input[1]; + output[1] = input[0]; + + return *((short*)(&output)); +} + + +ushort FileIO::flipBytes(ushort aNumber) { + static uchar output[2]; + static uchar* input; + input = (uchar*)(&aNumber); + + output[0] = input[1]; + output[1] = input[0]; + + return *((ushort*)(&output)); +} + + +long FileIO::flipBytes(long aNumber) { + static uchar output[4]; + static uchar* input; + input = (uchar*)(&aNumber); + + output[0] = input[3]; + output[1] = input[2]; + output[2] = input[1]; + output[3] = input[0]; + + return *((long*)(&output)); +} + + +ulong FileIO::flipBytes(ulong aNumber) { + static uchar output[4]; + static uchar* input; + input = (uchar*)(&aNumber); + + output[0] = input[3]; + output[1] = input[2]; + output[2] = input[1]; + output[3] = input[0]; + + return *((ulong*)(&output)); +} + + +int FileIO::flipBytes(int aNumber) { + static uchar output[sizeof(uint)]; + static uchar* input; + input = (uchar*)(&aNumber); + + for(uint i=0; i +type FileIO::flipBytes(type aThing) { + uchar* input = (uchar*)(&aNumber); + uchar output[sizeof(aThing)]; + + for(int i=0; i +// Creation Date: Fri Nov 26 14:12:01 PST 1999 +// Last Modified: Fri Dec 2 13:26:29 PST 1999 +// Last Modified: Wed Dec 13 10:33:30 PST 2000 (modified sorting routine) +// Last Modified: Tue Jan 22 23:23:37 PST 2002 (allowed reading of meta events) +// Filename: ...sig/src/sigInfo/MidiFile.cpp +// Web Address: http://sig.sapp.org/src/sigInfo/MidiFile.cpp +// Syntax: C++ +// +// Description: A class which can read/write Standard MIDI files. +// MIDI data is stored by track in an array. This +// class is used for example in the MidiPerform class. +// + +#include "MidiFile.h" +#include + +////////////////////////////// +// +// _MFEvent::_MFEvent -- +// + +_MFEvent::_MFEvent(void) { + time = 0; + track = 0; + data.allowGrowth(); + data.setSize(0); +} + +_MFEvent::_MFEvent(int command) { + time = 0; + track = 0; + data.allowGrowth(); + data.setSize(1); + data[0] = (uchar)command; +} + +_MFEvent::_MFEvent(int command, int param1) { + time = 0; + track = 0; + data.allowGrowth(); + data.setSize(2); + data[0] = (uchar)command; + data[1] = (uchar)param1; +} + +_MFEvent::_MFEvent(int command, int param1, int param2) { + time = 0; + track = 0; + data.allowGrowth(); + data.setSize(3); + data[0] = (uchar)command; + data[1] = (uchar)param1; + data[2] = (uchar)param2; +} + +_MFEvent::_MFEvent(int aTrack, int command, int param1, int param2) { + time = 0; + track = aTrack; + data.allowGrowth(); + data.setSize(3); + data[0] = (uchar)command; + data[1] = (uchar)param1; + data[2] = (uchar)param2; +} + +_MFEvent::_MFEvent(int aTime, int aTrack, int command, int param1, int param2) { + time = aTime; + track = aTrack; + data.allowGrowth(); + data.setSize(3); + data[0] = (uchar)command; + data[1] = (uchar)param1; + data[2] = (uchar)param2; +} + + + +////////////////////////////// +// +// _MFEvent::~MFEvent +// + +_MFEvent::~_MFEvent() { + time = -1; + track = -1; + data.setSize(0); +} + + + +////////////////////////////// +// +// MidiFile::MidiFile -- +// + +MidiFile::MidiFile(void) { + ticksPerQuarterNote = 48; // time base of file + trackCount = 1; // # of tracks in file + theTrackState = TRACK_STATE_SPLIT; // joined or split + theTimeState = TIME_STATE_DELTA; // absolute or delta + events.setSize(1); + events[0] = new Collection<_MFEvent>; + events[0]->setSize(0); + events[0]->allowGrowth(1); + readFileName = new char[1]; + readFileName[0] = '\0'; +} + + +MidiFile::MidiFile(char* aFile) { + ticksPerQuarterNote = 48; // time base of file + trackCount = 1; // # of tracks in file + theTrackState = TRACK_STATE_SPLIT; // joined or split + theTimeState = TIME_STATE_DELTA; // absolute or delta + events.setSize(1); + events[0] = new Collection<_MFEvent>; + events[0]->setSize(0); + events[0]->allowGrowth(1); + readFileName = new char[1]; + readFileName[0] = '\0'; + read(aFile); +} + + + +////////////////////////////// +// +// MidiFile::~MidiFile -- +// + +MidiFile::~MidiFile() { + if (readFileName != NULL) { + delete [] readFileName; + readFileName = NULL; + } + + erase(); + + if (events[0] != NULL) { + delete events[0]; + events[0] = NULL; + } + +} + + + +////////////////////////////// +// +// MidiFile::absoluteTime -- convert the time data to +// absolute time, which means that the time field +// in the _MFEvent struct represents the exact tick +// time to play the event rather than the time since +// the last event to wait untill playing the current +// event. +// + +void MidiFile::absoluteTime(void) { + if (getTimeState() == TIME_STATE_ABSOLUTE) { + return; + } + int i, j; + int length = getNumTracks(); + int* timedata = new int[length]; + for (i=0; igetSize() > 0) { + timedata[i] = (*events[i])[0].time; + } else { + continue; + } + for (j=1; jgetSize(); j++) { + timedata[i] += (*events[i])[j].time; + (*events[i])[j].time = timedata[i]; + } + } + theTimeState = TIME_STATE_ABSOLUTE; + delete [] timedata; +} + +////////////////////////////// +// +// MidiFile::addEvent -- +// + +int MidiFile::addEvent(int aTrack, int aTime, Array& midiData) { + _MFEvent anEvent; + anEvent.time = aTime; + anEvent.track = aTrack; + anEvent.data = midiData; + + events[aTrack]->append(anEvent); + return events[aTrack]->getSize() - 1; +} + + + +////////////////////////////// +// +// MidiFile::addTrack -- adds a blank track at end of the +// track list. Returns the track number of the added +// track. +// + +int MidiFile::addTrack(void) { + int length = getNumTracks(); + events.setSize(length+1); + events[length] = new Collection<_MFEvent>; + events[length]->setSize(10000); + events[length]->setSize(0); + events[length]->allowGrowth(1); + return length; +} + +int MidiFile::addTrack(int count) { + int length = getNumTracks(); + events.setSize(length+count); + int i; + for (i=0; i; + events[length + i]->setSize(10000); + events[length + i]->setSize(0); + events[length + i]->allowGrowth(1); + } + return length + count - 1; +} + + +////////////////////////////// +// +// MidiFile::allocateEvents -- +// + +void MidiFile::allocateEvents(int track, int aSize) { + int oldsize = events[track]->getSize(); + if (oldsize < aSize) { + events[track]->setSize(aSize); + events[track]->setSize(oldsize); + } +} + + + +////////////////////////////// +// +// MidiFile::deleteTrack -- remove a track from the MidiFile. +// Tracks are numbered starting at track 0. +// + +void MidiFile::deleteTrack(int aTrack) { + int length = getNumTracks(); + if (aTrack < 0 || aTrack >= length) { + return; + } + if (length == 1) { + return; + } + delete events[aTrack]; + for (int i=aTrack; igetSize() > 0) { + timedata[i] = (*events[i])[0].time; + } else { + continue; + } + for (j=1; jgetSize(); j++) { + temp = (*events[i])[j].time; + (*events[i])[j].time = temp - timedata[i]; + timedata[i] = temp; + } + } + theTimeState = TIME_STATE_DELTA; + delete [] timedata; +} + + + +////////////////////////////// +// +// MidiFile::erase -- make the MIDI file empty with one +// track with no data in it. +// + +void MidiFile::erase(void) { + int length = getNumTracks(); + for (int i=0; i; + events[0]->setSize(0); + events[0]->allowGrowth(1); +} + + +void MidiFile::clear(void) { + MidiFile::erase(); +} + + + +////////////////////////////// +// +// MidiFile::getEvent -- return the event at the given index in the +// specified track. +// + +_MFEvent& MidiFile::getEvent(int aTrack, int anIndex) { + return (*events[aTrack])[anIndex]; +} + + + +////////////////////////////// +// +// MidiFile::getTicksPerQuarterNote -- returns the number of +// time units that are supposed to occur during a quarternote. +// + +int MidiFile::getTicksPerQuarterNote(void) { + return ticksPerQuarterNote; +} + + + +////////////////////////////// +// +// MidiFile::getTrackCount -- return the number of tracks in +// the Midi File. +// + +int MidiFile::getTrackCount(void) { + return events.getSize(); +} + +int MidiFile::getNumTracks(void) { + return events.getSize(); +} + + + +////////////////////////////// +// +// MidiFile::getNumEvents -- returns the number of events +// in a given track. +// + +int MidiFile::getNumEvents(int aTrack) { + return events[aTrack]->getSize(); +} + + + +////////////////////////////// +// +// MidiFile::joinTracks -- merge the data from all tracks, +// but keeping the identity of the tracks unique so that +// the function splitTracks can be called to split the +// tracks into separate units again. The style of the +// MidiFile when read from a file is with tracks split. +// + +void MidiFile::joinTracks(void) { + if (getTrackState() == TRACK_STATE_JOINED) { + return; + } + if (getNumTracks() == 1) { + return; + } + + Collection <_MFEvent>* joinedTrack; + joinedTrack = new Collection<_MFEvent>; + joinedTrack->setSize(200000); + joinedTrack->setSize(0); + int oldTimeState = getTimeState(); + if (oldTimeState == TIME_STATE_DELTA) { + absoluteTime(); + } + int i, j; + int length = getNumTracks(); + for (i=0; igetSize(); j++) { + joinedTrack->append((*events[i])[j]); + } + } + + erase(); + + delete events[0]; + events[0] = joinedTrack; + sortTracks(); + if (oldTimeState == TIME_STATE_DELTA) { + deltaTime(); + } +} + + + +////////////////////////////// +// +// MidiFile::mergeTracks -- combine the data from two +// tracks into one. Placing the data in the first +// track location listed, and Moving the other tracks +// in the file around to fill in the spot where Track2 +// used to be. The results of this function call cannot +// be reversed. +// + +void MidiFile::mergeTracks(int aTrack1, int aTrack2) { + Collection <_MFEvent>* mergedTrack; + mergedTrack = new Collection<_MFEvent>; + mergedTrack->setSize(0); + int oldTimeState = getTimeState(); + if (oldTimeState == TIME_STATE_DELTA) { + absoluteTime(); + } + int i, j; + int length = getNumTracks(); + for (i=0; igetSize(); i++) { + mergedTrack->append((*events[aTrack1])[i]); + } + for (j=0; jgetSize(); i++) { + (*events[aTrack2])[i].track = aTrack1; + mergedTrack->append((*events[aTrack2])[i]); + } + + sortTrack(*mergedTrack); + + delete events[aTrack1]; + + events[aTrack1] = mergedTrack; + + for (i=aTrack2; i; + events[z]->setAllocSize(10000); + events[z]->setSize(0); + events[z]->allowGrowth(1); + } + + // read ticks per quarter note + short signeddata; + inputfile.readBigEndian(signeddata); + if (signeddata <= 0) { + std::cout << "Error: cannot handle SMTP tick values for quarter notes" + " yet" << std::endl; + return 0; + } + ticksPerQuarterNote = signeddata; + + ////////////////////////////////////////////////// + // + // now read individual tracks: + // + + uchar runningCommand = 0; + _MFEvent event; + int absticks; + int barline; + + for (int i=0; isetSize(longdata/2); + events[i]->setSize(0); + + // process the track + absticks = 0; + barline = 1; + while (!inputfile.eof()) { + longdata = extractVlvTime(inputfile); +//std::cout << "ticks = " << longdata << std::endl; + absticks += longdata; + extractMidiData(inputfile, event.data, runningCommand); +//std::cout << "command = " << std::hex << (int)event.data[0] << std::dec << std::endl; + if (event.data[0] == 0xff && (event.data[1] == 1 || + event.data[1] == 2 || event.data[1] == 3 || event.data[1] == 4)) { + // mididata.append('\0'); + // std::cout << '\t'; + // for (int m=0; mappend(event); + } else { + event.time = absticks; + event.track = i; + events[i]->append(event); + } + + } + + } + // std::cout << std::endl; + + theTimeState = TIME_STATE_ABSOLUTE; + return 1; +} + + + +////////////////////////////// +// +// MidiFile::setTicksPerQuarterNote -- +// + +void MidiFile::setTicksPerQuarterNote(int ticks) { + ticksPerQuarterNote = ticks; +} + + + +////////////////////////////// +// +// MidiFile::sortTrack -- +// + +void MidiFile::sortTrack(Collection<_MFEvent>& trackData) { + qsort(trackData.getBase(), trackData.getSize(), + sizeof(_MFEvent), eventcompare); +} + + + +////////////////////////////// +// +// MidiFile::sortTracks -- sort all tracks in the MidiFile. +// + +void MidiFile::sortTracks(void) { + for (int i=0; igetSize(); + for (i=0; i maxTrack) { + maxTrack = (*events[0])[i].track; + } + } + + Collection<_MFEvent>* olddata = events[0]; + events[0] = NULL; + events.setSize(maxTrack); + for (i=0; i; + events[i]->setSize(0); + events[i]->allowGrowth(); + } + + int trackValue = 0; + for (i=0; length; i++) { + trackValue = (*olddata)[i].track; + events[trackValue]->append((*olddata)[i]); + } + + delete olddata; + + if (oldTimeState == TIME_STATE_DELTA) { + deltaTime(); + } +} + + + +////////////////////////////// +// +// MidiFile::timeState -- returns what type of time method is +// being used: either TIME_STATE_ABSOLUTE or TIME_STATE_DELTA. +// + +int MidiFile::getTimeState(void) { + return theTimeState; +} + + + +////////////////////////////// +// +// MidiFile::getTrackState -- returns what type of track method +// is being used: either TRACK_STATE_JOINED or TRACK_STATE_SPLIT. +// + +int MidiFile::getTrackState(void) { + return theTrackState; +} + + + +////////////////////////////// +// +// MidiFile::write -- write a standard MIDI file from data. +// + +int MidiFile::write(const char* aFile) { + int oldTimeState = getTimeState(); + if (oldTimeState == TIME_STATE_ABSOLUTE) { + deltaTime(); + } + + #ifdef VISUAL + FileIO outputfile(aFile, ios::out | ios::noreplace | ios::binary); + #else + // ios::noreplace does not exists anymore in GCC 3.x + FileIO outputfile(aFile, std::ios::out /* | std::ios::noreplace */); + #endif + + if (!outputfile.is_open()) { + std::cout << "Error: could not write: " << aFile << std::endl; + exit(1); + } + + // write the header of the Standard MIDI File + + char ch; + // 1. The characters "MThd" + ch = 'M'; + outputfile.writeBigEndian(ch); + ch = 'T'; + outputfile.writeBigEndian(ch); + ch = 'h'; + outputfile.writeBigEndian(ch); + ch = 'd'; + outputfile.writeBigEndian(ch); + + // 2. write the size of the header (alwas a "6" stored in unsigned long + ulong longdata = 6; + outputfile.writeBigEndian(longdata); + + // 3. MIDI file format, type 0, 1, or 2 + ushort shortdata; + if (getNumTracks() == 1) { + shortdata = 0; + } else { + shortdata = 1; + } + outputfile.writeBigEndian(shortdata); + + // 4. write out the number of tracks. + shortdata = getNumTracks(); + outputfile.writeBigEndian(shortdata); + + // 5. write out the number of ticks per quarternote. (avoiding SMTPE for now) + shortdata = getTicksPerQuarterNote(); + outputfile.writeBigEndian(shortdata); + + // now write each track. + Array trackdata; + uchar endoftrack[4] = {0, 0xff, 0x2f, 0x00}; + int i, j, k; + int size; + for (i=0; igetSize(); j++) { + writeVLValue((*events[i])[j].time, trackdata); + for (k=0; k<(*events[i])[j].data.getSize(); k++) { + trackdata.append((*events[i])[j].data[k]); + } + } + size = trackdata.getSize(); + if ((trackdata[size-3] != 0xff) && (trackdata[size-2] != 0x2f)) { + trackdata.append(endoftrack[0]); + trackdata.append(endoftrack[1]); + trackdata.append(endoftrack[2]); + trackdata.append(endoftrack[3]); + } + + // now ready to write to MIDI file. + + // first write the track ID marker "MTrk": + ch = 'M'; + outputfile.writeBigEndian(ch); + ch = 'T'; + outputfile.writeBigEndian(ch); + ch = 'r'; + outputfile.writeBigEndian(ch); + ch = 'k'; + outputfile.writeBigEndian(ch); + + // A. write the size of the MIDI data to follow: + longdata = trackdata.getSize(); + outputfile.writeBigEndian(longdata); + + // B. write the actual data + outputfile.write((char*)trackdata.getBase(), trackdata.getSize()); + } + + if (oldTimeState == TIME_STATE_ABSOLUTE) { + absoluteTime(); + } + + outputfile.close(); + + return 1; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// private functions +// + + +////////////////////////////// +// +// MidiF::extractMidiData -- +// + +void MidiFile::extractMidiData(FileIO& inputfile, Array& array, + uchar& runningCommand) { + + uchar byte; + array.setSize(0); + array.allowGrowth(); + int runningQ; + + inputfile.readBigEndian(byte); + + if (byte < 0x80) { + runningQ = 1; + if (runningCommand == 0) { + std::cout << "Error: running command with no previous command" << std::endl; + exit(1); + } + } else { + runningCommand = byte; + runningQ = 0; + } + + array.append(runningCommand); + if (runningQ) { + array.append(byte); + } + + uchar metai; + switch (runningCommand & 0xf0) { + case 0x80: // note off (2 more bytes) + case 0x90: // note on (2 more bytes) + case 0xA0: // aftertouch (2 more bytes) + case 0xB0: // cont. controller (2 more bytes) + case 0xE0: // pitch wheel (2 more bytes) + inputfile.readBigEndian(byte); + array.append(byte); + if (!runningQ) { + inputfile.readBigEndian(byte); + array.append(byte); + } + break; + case 0xC0: // patch change (1 more byte) + case 0xD0: // channel pressure (1 more byte) + if (!runningQ) { + inputfile.readBigEndian(byte); + array.append(byte); + } + break; + case 0xF0: + switch (runningCommand) { + case 0xff: // meta event + { + if (!runningQ) { + inputfile.readBigEndian(byte); // meta type + array.append(byte); + } + inputfile.readBigEndian(metai); // meta size + array.append(metai); + for (uchar j=0; j 0x7f) { + std::cout << "Error: VLV value was too long" << std::endl; + exit(1); + } + + uchar bytes[5] = {a, b, c, d, e}; + int count = 0; + while (bytes[count] > 0x7f && count < 5) { + count++; + } + count++; + + ulong output = 0; + for (int i=0; i& outdata) { + uchar bytes[5] = {0}; + bytes[0] = (uchar)(((ulong)aValue >> 28) & 0x7f); // most significant 5 bits + bytes[1] = (uchar)(((ulong)aValue >> 21) & 0x7f); // next largest 7 bits + bytes[2] = (uchar)(((ulong)aValue >> 14) & 0x7f); + bytes[3] = (uchar)(((ulong)aValue >> 7) & 0x7f); + bytes[4] = (uchar)(((ulong)aValue) & 0x7f); // least significant 7 bits + + int start = 0; + while (start<5 && bytes[start] == 0) start++; + + for (int i=start; i<4; i++) { + bytes[i] = bytes[i] | 0x80; + outdata.append(bytes[i]); + } + outdata.append(bytes[4]); +} + + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// external functions +// + + +////////////////////////////// +// +// eventcompare -- for sorting the tracks +// + +int eventcompare(const void* a, const void* b) { + _MFEvent& aevent = *((_MFEvent*)a); + _MFEvent& bevent = *((_MFEvent*)b); + + if (aevent.time > bevent.time) { + return 1; + } else if (aevent.time < bevent.time) { + return -1; + } else if (aevent.data[0] == 0xff && bevent.data[0] != 0xff) { + return 1; + } else if (bevent.data[0] == 0xff && aevent.data[0] != 0xff) { + return -1; + } else if (bevent.data[0] == 0xff && bevent.data[1] == 0x2f) { + return -1; + } else if (aevent.data[0] == 0xff && aevent.data[1] == 0x2f) { + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// operator<< -- for printing an ASCII version of the MIDI file +// + +std::ostream& operator<<(std::ostream& out, MidiFile& aMidiFile) { + int i, j, k; + out << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; + out << "Number of Tracks: " << aMidiFile.getTrackCount() << "\n"; + out << "Time method: " << aMidiFile.getTimeState(); + if (aMidiFile.getTimeState() == TIME_STATE_DELTA) { + out << " (Delta timing)"; + } else if (aMidiFile.getTimeState() == TIME_STATE_ABSOLUTE) { + out << " (Absolute timing)"; + } else { + out << " (unknown method)"; + } + out << "\n"; + + out << "Divisions per Quarter Note: " << std::dec << aMidiFile.getTicksPerQuarterNote() << "\n"; + for (i=0; i +// Creation Date: Sun Mar 15 10:55:56 GMT-0800 1998 +// Last Modified: Sun Mar 15 10:55:56 GMT-0800 1998 +// Filename: ...sig/code/control/MidiFileWrite/MidiFileWrite.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiFileWrite.cpp +// Syntax: C++ +// +// Description: The MidiFileWrite class will write out a Type 0 MidiFile. +// Used for recording MIDI data streams into Standard +// MIDI files. +// + +#include "MidiFileWrite.h" +#include "SigTimer.h" +#include + + +////////////////////////////// +// +// MidiFileWrite::MidiFileWrite +// default value: startTime = -1 +// + +MidiFileWrite::MidiFileWrite(void) { + trackSize = 0; + lastPlayTime = 0; + midifile = NULL; + openQ = 0; +} + + +MidiFileWrite::MidiFileWrite(const char* aFilename, int startTime) { + trackSize = 0; + lastPlayTime = 0; + midifile = NULL; + openQ = 0; + setup(aFilename, startTime); +} + + + +////////////////////////////// +// +// MidiFileWrite::~MidiFileWrite +// + +MidiFileWrite::~MidiFileWrite() { + close(); +} + + + +////////////////////////////// +// +// MidiFileWrite::close +// + +void MidiFileWrite::close(void) { + writeRaw(0, 0xff, 0x2f, 0); // end of track meta event + + midifile->seekg(18); + midifile->writeBigEndian(trackSize); + + midifile->close(); + + midifile = NULL; + openQ = 0; +} + + + +////////////////////////////// +// +// MidiFileWrite::setup -- writes the Midi file header and +// prepares the midifile for writing of data +// default value: startTime = -1 +// + +void MidiFileWrite::setup(const char* aFilename, int startTime) { + if (openQ) { + close(); + } + + if (midifile != NULL) delete midifile; + midifile = new FileIO; + midifile->open(aFilename, std::ios::out); + + // write the header chunk + *midifile << "MThd"; // file identification: MIDI file + midifile->writeBigEndian(6L); // size of header (always 6) + midifile->writeBigEndian((short)0); // format: type 0; + midifile->writeBigEndian((short)0); // num of tracks (always 0 for type 0) + midifile->writeBigEndian((short)1000); // divisions per quarter note + + + // write the track header + *midifile << "MTrk"; + midifile->writeBigEndian(0xffffL); // the track size which will + // be corrected with close() + + + // the midifile stream is now setup for writing + // track events + + openQ = 1; + + start(); // start can be called later and will behave well + // as long as no track events have been written +} + + + +////////////////////////////// +// +// MidiFileWrite::start +// default value: startTime = -1; +// + +void MidiFileWrite::start(int startTime) { + if (startTime < 0) { + SigTimer localTime; + lastPlayTime = localTime.getTime(); + } else { + lastPlayTime = startTime; + } +} + + + +////////////////////////////// +// +// MidiFileWrite::writeAbsolute -- considers the time data +// to be the current time. It will generate a difference +// time with the previously stored last playing time. +// + +void MidiFileWrite::writeAbsolute(int aTime, int command, int p1, int p2) { + writeVLValue(aTime - lastPlayTime); + writeRaw((uchar)command, (uchar)p1, (uchar)p2); + lastPlayTime = aTime; +} + +void MidiFileWrite::writeAbsolute(int aTime, int command, int p1) { + writeVLValue(aTime - lastPlayTime); + writeRaw((uchar)command, (uchar)p1); + lastPlayTime = aTime; +} + +void MidiFileWrite::writeAbsolute(int aTime, int command) { + writeVLValue(aTime - lastPlayTime); + writeRaw((uchar)command); + lastPlayTime = aTime; +} + + + +////////////////////////////// +// +// MidiFileWrite::writeRaw -- write an event byte to the midifile +// + +void MidiFileWrite::writeRaw(uchar aByte) { + assert(midifile != NULL); + *midifile << aByte; + trackSize++; +} + + +void MidiFileWrite::writeRaw(uchar aByte, uchar bByte) { + writeRaw(aByte); + writeRaw(bByte); +} + + +void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte) { + writeRaw(aByte); + writeRaw(bByte); + writeRaw(cByte); +} + + +void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte, + uchar dByte) { + writeRaw(aByte); + writeRaw(bByte); + writeRaw(cByte); + writeRaw(dByte); +} + + +void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte, + uchar dByte, uchar eByte) { + writeRaw(aByte); + writeRaw(bByte); + writeRaw(cByte); + writeRaw(dByte); + writeRaw(eByte); +} + + +void MidiFileWrite::writeRaw(uchar* anArray, int arraySize) { + for (int i=0; i> 28) & 0x7f); // most significant 5 bits + bytes[1] = (uchar)((aValue >> 21) & 0x7f); // next largest 7 bits + bytes[2] = (uchar)((aValue >> 14) & 0x7f); + bytes[3] = (uchar)((aValue >> 7) & 0x7f); + bytes[4] = (uchar)((aValue) & 0x7f); // least significant 7 bits + + int start = 0; + while (start<5 && bytes[start] == 0) start++; + + for (int i=start; i<4; i++) { + writeRaw((uchar)(bytes[i] | 0x80)); + } + writeRaw(bytes[4]); +} + +// md5sum: 251468fa23862745f0cf36f359bccc17 - MidiFileWrite.cpp =css= 20030102 diff --git a/src/midiio/src/MidiIO.cpp b/src/midiio/src/MidiIO.cpp new file mode 100644 index 0000000..26363f2 --- /dev/null +++ b/src/midiio/src/MidiIO.cpp @@ -0,0 +1,283 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 21 December 1997 +// Last Modified: Sun Jan 25 15:45:18 GMT-0800 1998 +// Filename: ...sig/code/control/MidiIO/MidiIO.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiIO.cpp +// Syntax: C++ +// +// Description: A unified class for MidiInput and MidiOutput that handles +// MIDI input and output connections. The Synthesizer +// and RadioBaton classes are derived from this class. +// + +#include "MidiIO.h" + + +////////////////////////////// +// +// MidiIO::MidiIO +// + +MidiIO::MidiIO(void) : MidiOutput(), MidiInput() { + // does nothing +} + + +MidiIO::MidiIO(int outPort, int inPort) : + MidiOutput(outPort), MidiInput(inPort) { + // does nothing +} + + + +////////////////////////////// +// +// MidiIO::~MidiIO +// + +MidiIO::~MidiIO() { + // does nothing +} + + + +////////////////////////////// +// +// MidiIO::close +// + +void MidiIO::close(void) { + MidiInput::close(); + MidiOutput::close(); +} + + + +////////////////////////////// +// +// MidiIO::closeInput +// + +void MidiIO::closeInput(void) { + MidiInput::close(); +} + + + +////////////////////////////// +// +// MidiIO::closeOutput +// + +void MidiIO::closeOutput(void) { + MidiOutput::close(); +} + + + +////////////////////////////// +// +// MidiIO::getChannelInOffset -- return the MIDI channel offset of +// the MIDI input. +// + +int MidiIO::getChannelInOffset(void) const { + return MidiInPort::getChannelOffset(); +} + + + +////////////////////////////// +// +// MidiIO::getChannelOutOffset -- return the MIDI channel offset of +// the MIDI output. +// + +int MidiIO::getChannelOutOffset (void) const { + return MidiOutPort::getChannelOffset(); +} + + + +////////////////////////////// +// +// MidiIO::getInputPort +// + +int MidiIO::getInputPort(void) { + return MidiInput::getPort(); +} + + + +////////////////////////////// +// +// MidiIO::getInputTrace +// + +int MidiIO::getInputTrace(void) { + return MidiInput::getTrace(); +} + + + +////////////////////////////// +// +// MidiIO::getNumInputPorts +// + +int MidiIO::getNumInputPorts(void) { + return MidiInput::getNumPorts(); +} + + + +////////////////////////////// +// +// MidiIO::getNumOutputPorts +// + +int MidiIO::getNumOutputPorts(void) { + return MidiOutput::getNumPorts(); +} + + + +////////////////////////////// +// +// MidiIO::getOutputPort +// + +int MidiIO::getOutputPort(void) { + return MidiOutput::getPort(); +} + + + +////////////////////////////// +// +// MidiIO::getOutputTrace +// + +int MidiIO::getOutputTrace(void) { + return MidiOutput::getTrace(); +} + + + +////////////////////////////// +// +// MidiIO::open +// + +int MidiIO::open(void) { + if (MidiInput::open()) { + return MidiOutput::open(); + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiIO::openInput +// + +int MidiIO::openInput(void) { + return MidiInput::open(); +} + + + +////////////////////////////// +// +// MidiIO::openOutput +// + +int MidiIO::openOutput(void) { + return MidiOutput::open(); +} + + + +////////////////////////////// +// +// MidiIO::setChannelOffset -- sets the MIDI channel offset +// + +void MidiIO::setChannelOffset(int anOffset) { + MidiInPort::setChannelOffset(anOffset); + MidiOutPort::setChannelOffset(anOffset); +} + + + +////////////////////////////// +// +// MidiIO::setInputPort +// + +void MidiIO::setInputPort(int aPort) { + MidiInput::setPort(aPort); +} + + + +////////////////////////////// +// +// MidiIO::setInputTrace +// + +void MidiIO::setInputTrace(int aState) { + MidiInput::setTrace(aState); +} + + + +////////////////////////////// +// +// MidiIO::setOutputPort +// + +void MidiIO::setOutputPort(int aPort) { + MidiOutput::setPort(aPort); +} + + + +////////////////////////////// +// +// MidiIO::setOutputTrace +// + +void MidiIO::setOutputTrace(int aState) { + MidiOutput::setTrace(aState); +} + + + +////////////////////////////// +// +// MidiIO::toggleInputTrace +// + +void MidiIO::toggleInputTrace(void) { + MidiInput::toggleTrace(); +} + + +////////////////////////////// +// +// MidiIO::toggleOutputTrace +// + +void MidiIO::toggleOutputTrace(void) { + MidiOutput::toggleTrace(); +} + + + +// md5sum: 860227c67236eb6f8897ae67f1338cb0 - MidiIO.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInPort_alsa.cpp b/src/midiio/src/MidiInPort_alsa.cpp new file mode 100644 index 0000000..55d22b0 --- /dev/null +++ b/src/midiio/src/MidiInPort_alsa.cpp @@ -0,0 +1,1038 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun May 14 22:03:16 PDT 2000 +// Last Modified: Sat Oct 13 16:11:10 PDT 2001 (updated for ALSA 0.9) +// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0 +// fixed by Daniel Gardner) +// Last Modified: Mon Nov 19 17:52:15 PST 2001 (thread on exit improved) +// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_alsa.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiInPort_alsa.cpp +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// linux ALSA sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// + +#if defined(LINUX) && defined(ALSA) + +#include "MidiInPort_alsa.h" +#include +#include +#include +#include +#include + +#define DEFAULT_INPUT_BUFFER_SIZE (1024) + +// initialized static variables + +int MidiInPort_alsa::numDevices = 0; +int MidiInPort_alsa::objectCount = 0; +int* MidiInPort_alsa::portObjectCount = NULL; +CircularBuffer** MidiInPort_alsa::midiBuffer = NULL; +int MidiInPort_alsa::channelOffset = 0; +SigTimer MidiInPort_alsa::midiTimer; +int* MidiInPort_alsa::pauseQ = NULL; +int* MidiInPort_alsa::trace = NULL; +std::ostream* MidiInPort_alsa::tracedisplay = &std::cout; +Array MidiInPort_alsa::midiInThread; +int* MidiInPort_alsa::sysexWriteBuffer = NULL; +Array** MidiInPort_alsa::sysexBuffers = NULL; + +Array MidiInPort_alsa::threadinitport; + + + +////////////////////////////// +// +// MidiInPort_alsa::MidiInPort_alsa +// default values: autoOpen = 1 +// + +MidiInPort_alsa::MidiInPort_alsa(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiInPort_alsa::MidiInPort_alsa(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::~MidiInPort_alsa +// + +MidiInPort_alsa::~MidiInPort_alsa() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + std::cerr << "Error: bad MidiInPort_alsa object count!: " + << objectCount << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::clearSysex -- clears the data from a sysex +// message and sets the allocation size to the default size (of 32 +// bytes). +// + +void MidiInPort_alsa::clearSysex(int buffer) { + buffer = 0x7f | buffer; // limit buffer range from 0 to 127 + + if (getPort() == -1) { + return; + } + + sysexBuffers[getPort()][buffer].setSize(0); + if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) { + // shrink the storage buffer's size if necessary + sysexBuffers[getPort()][buffer].setAllocSize(32); + } +} + + +void MidiInPort_alsa::clearSysex(void) { + // clear all sysex buffers + for (int i=0; i<128; i++) { + clearSysex(i); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::close +// + +void MidiInPort_alsa::close(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 1; + Sequencer_alsa::closeInput(getPort()); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::closeAll -- +// + +void MidiInPort_alsa::closeAll(void) { + for (int i=0; iextract(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getBufferSize -- returns the maximum possible number +// of MIDI messages that can be stored in the buffer +// + +int MidiInPort_alsa::getBufferSize(void) { + if (getPort() == -1) return 0; + + return midiBuffer[getPort()]->getSize(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getChannelOffset -- returns zero if MIDI channel +// offset is 0, or 1 if offset is 1. +// + +int MidiInPort_alsa::getChannelOffset(void) const { + return channelOffset; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getCount -- returns the number of unexamined +// MIDI messages waiting in the input buffer. +// + +int MidiInPort_alsa::getCount(void) { + if (getPort() == -1) return 0; + return midiBuffer[getPort()]->getCount(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getName -- returns the name of the port. +// returns "" if no name. Name is valid until all instances +// of MIDI classes are. +// + +const char* MidiInPort_alsa::getName(void) { + if (getPort() == -1) { + return "Null ALSA MIDI Input"; + } + return getInputName(getPort()); +} + + +const char* MidiInPort_alsa::getName(int i) { + return getInputName(i); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getNumPorts -- returns the number of available +// ports for MIDI input +// + +int MidiInPort_alsa::getNumPorts(void) { + return getNumInputs(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getPort -- returns the port to which this +// object belongs (as set with the setPort function). +// + +int MidiInPort_alsa::getPort(void) { + return port; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getPortStatus -- 0 if closed, 1 if open +// + +int MidiInPort_alsa::getPortStatus(void) { + return is_open_in(getPort()); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getSysex -- returns the sysex message contents +// of a given buffer. You should check to see that the size is +// non-zero before looking at the data. The data pointer will +// be NULL if there is no data in the buffer. +// + +uchar* MidiInPort_alsa::getSysex(int buffer) { + buffer &= 0x7f; // limit the buffer access to indices 0 to 127. + if (getPort() == -1) { + return NULL; + } + + if (sysexBuffers[getPort()][buffer].getSize() < 2) { + return NULL; + } else { + return sysexBuffers[getPort()][buffer].getBase(); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getSysexSize -- returns the sysex message byte +// count of a given buffer. Buffers are in the range from +// 0 to 127. +// + +int MidiInPort_alsa::getSysexSize(int buffer) { + if (getPort() == -1) { + return 0; + } else { + return sysexBuffers[getPort()][buffer & 0x7f].getSize(); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::getTrace -- returns true if trace is on or false +// if trace is off. if trace is on, then prints to standard +// output the Midi message received. +// + +int MidiInPort_alsa::getTrace(void) { + if (getPort() == -1) return -1; + + return trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::insert +// + +void MidiInPort_alsa::insert(const MidiMessage& aMessage) { + if (getPort() == -1) return; + + midiBuffer[getPort()]->insert(aMessage); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::installSysex -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_alsa::installSysex(uchar* anArray, int aSize) { + if (getPort() == -1) { + return -1; + } else { + return installSysexPrivate(getPort(), anArray, aSize); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::installSysexPrivate -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_alsa::installSysexPrivate(int port, uchar* anArray, int aSize) { + // choose a buffer to install sysex data into: + int bufferNumber = sysexWriteBuffer[port]; + sysexWriteBuffer[port]++; + if (sysexWriteBuffer[port] >= 128) { + sysexWriteBuffer[port] = 0; + } + + // copy contents of sysex message into the chosen buffer + sysexBuffers[port][bufferNumber].setSize(aSize); + uchar* dataptr = sysexBuffers[port][bufferNumber].getBase(); + uchar* indataptr = anArray; + for (int i=0; i& temp = *midiBuffer[getPort()]; + return temp[index]; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::open -- returns true if MIDI input port was +// opened. +// + +int MidiInPort_alsa::open(void) { + if (getPort() == -1) return 0; + + int status = Sequencer_alsa::openInput(getPort()); + if (status) { + pauseQ[getPort()] = 0; + return 1; + } else { + pauseQ[getPort()] = 1; + return 0; + } + + return 0; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::pause -- stop the Midi input port from +// inserting MIDI messages into the buffer, but keeps the +// port open. Use unpause() to reverse the effect of pause(). +// + +void MidiInPort_alsa::pause(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 1; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::setBufferSize -- sets the allocation +// size of the MIDI input buffer. +// + +void MidiInPort_alsa::setBufferSize(int aSize) { + if (getPort() == -1) return; + + midiBuffer[getPort()]->setSize(aSize); +} + + + +////////////////////////////// +// +// MidiInPort_alsa::setChannelOffset -- sets the MIDI chan offset, +// either 0 or 1. +// + +void MidiInPort_alsa::setChannelOffset(int anOffset) { + switch (anOffset) { + case 0: channelOffset = 0; break; + case 1: channelOffset = 1; break; + default: + std::cout << "Error: Channel offset can be only 0 or 1." << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::setPort -- +// + +void MidiInPort_alsa::setPort(int aPort) { +// if (aPort == -1) return; + if (aPort < -1 || aPort >= getNumPorts()) { +// std::cerr << "Error: maximum port number is: " << getNumPorts()-1 +// << ", but you tried to access port: " << aPort << std::endl; +// exit(1); + } + else { + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + if (port != -1) { + portObjectCount[port]++; + } + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa::setTrace -- if false, then don't print MIDI messages +// to the screen. +// + +int MidiInPort_alsa::setTrace(int aState) { + if (getPort() == -1) return -1; + + + int oldtrace = trace[getPort()]; + if (aState == 0) { + trace[getPort()] = 0; + } else { + trace[getPort()] = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::toggleTrace -- switches the state of trace +// Returns the previous value of the trace variable. +// + +void MidiInPort_alsa::toggleTrace(void) { + if (getPort() == -1) return; + + trace[getPort()] = !trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiInPort_alsa::unpause -- enables the Midi input port +// to inserting MIDI messages into the buffer after the +// port is already open. +// + +void MidiInPort_alsa::unpause(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 0; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiInPort_alsa::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiInPort_alsa::deinitialize(void) { + closeAll(); + + for (int i=0; i*[numDevices]; + + // allocate space for Midi input sysex buffer write indices + if (sysexWriteBuffer != NULL) { + delete [] sysexWriteBuffer; + } + sysexWriteBuffer = new int[numDevices]; + + // allocate space for Midi input sysex buffers + if (sysexBuffers != NULL) { + std::cout << "Error: memory leak on sysex buffers initialization" << std::endl; + exit(1); + } + sysexBuffers = new Array*[numDevices]; + + int flag; + midiInThread.setSize(getNumPorts()); + threadinitport.setSize(getNumPorts()); + // initialize the static arrays + for (int i=0; i; + midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE); + + sysexWriteBuffer[i] = 0; + sysexBuffers[i] = new Array[128]; + for (int n=0; n<128; n++) { + sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow + sysexBuffers[i][n].setAllocSize(32); + sysexBuffers[i][n].setSize(0); + sysexBuffers[i][n].setGrowth(32); // in case it will ever grow + } + + threadinitport[i] = i; + flag = pthread_create(&midiInThread[i], NULL, + interpretMidiInputStreamPrivateALSA, &threadinitport[i]); + if (flag == -1) { + std::cout << "Unable to create MIDI input thread." << std::endl; + exit(1); + } + } + + } +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// friendly functions +// + + +////////////////////////////// +// +// interpretMidiInputStreamPrivateALSA -- handles the MIDI input stream +// for the various input devices from the ALSA MIDI driver. +// +// Note about system exclusive messages: +// System Exclusive messages are stored in a separate buffer from +// Other Midi messages since they can be variable in length. If +// The Midi Input returns a message with command byte 0xf0, then +// the p1() byte indicates the system exclusive buffer number that is +// holding the system exclusive data for that Midi message. There +// are 128 system exclusive buffers that are numbered between +// 0 and 127. These buffers are filled in a cycle. +// To extract a System exclusive message from MidiInPort_alsa, +// you first will receive a Message with a command byte of 0xf0. +// you can then access the data for that sysex by the command: +// MidiInPort_alsa::getSysex(buffer_number), this will return +// a pointer to the beginning of the sysex data. The first byte +// of the sysex data should be 0xf0, and the last byte of the data +// is 0xf7. All other bytes of data should be in the range from +// 0 to 127. You can also get the size of the sysex buffer by the +// following command: MidiInPort_alsa::getSysexSize(buffer_number). +// This command will tell you the number of bytes in the system +// exclusive message including the starting 0xf0 and the ending 0xf7. +// +// If you want to minimize memory useage of the system exclusive +// buffers you can run the command: +// MidiInPort_alsa::clearSysex(buffer_number); Otherwise the sysex +// buffer will be erased automatically the next time that the +// buffer number is cycled through when receiving more system exclusives. +// Allocated the allocated size of the system exclusive storage will +// not be adjusted when the computer replaces the system exclusive +// message unless more storage size is needed, clearSysex however, +// will resize the sysex buffer to its default size (currently 32 bytes). +// clearSysex() without arguments will resize all buffers so that +// they are allocated to the default size and will erase data from +// all buffers. You can spoof a system exclusive message coming in +// by installing a system exclusive message and then inserting +// the system message command into the input buffer of the MidiInPort +// class, int sysex_buffer = MidiInPort_alsa::installSysex( +// uchar *data, int size); will put the data into a sysex buffer and +// return the buffer number that it was placed into. +// +// This function assumes that System Exclusive messages cannot be sent +// as a running status messages. +// +// Note about MidiMessage time stamps: +// The MidiMessage::time field is a recording of the time that the +// first byte of the MidiMessage arrived. If the message is from +// running status mode, then the time that the first parameter byte +// arrived is stored. System exclusive message arrival times are +// recoreded at the time of the last byte (0xf7) arriving. This is +// because other system messages can be coming in while the sysex +// message is coming in. Anyway, sysex messages are not really to +// be used for real time MIDI messaging, so the exact moment that the +// first byte of the sysex came in is not important to me. +// +// + +void *interpretMidiInputStreamPrivateALSA(void * arg) { + int portToWatch = *(int*)arg; + if (portToWatch < 0 || portToWatch > 1000) { + // the port to watch is invalid -- because the program has died + // before the thread function could start. Cause of invalid port + // data should be examined more carefully. + return NULL; + } + + int* argsExpected = NULL; // MIDI parameter bytes expected to follow + int* argsLeft = NULL; // MIDI parameter bytes left to wait for + uchar packet[1]; // bytes for sequencer driver + MidiMessage* message = NULL; // holder for current MIDI message + int newSigTime = 0; // for millisecond timer + int lastSigTime = -1; // for millisecond timer + int zeroSigTime = -1; // for timing incoming events + int device = -1; // for sorting out the bytes by input device + Array* sysexIn; // MIDI Input sysex temporary storage + + // Note on the use of argsExpected and argsLeft for sysexs: + // If argsExpected is -1, then a sysex message is coming in. + // If argsLeft < 0, then the sysex message has not finished comming + // in. If argsLeft == 0 and argsExpected == -1, then the sysex + // has finished coming in and is to be sent to the correct + // location. + + // allocate space for MIDI messages, each device has a different message + // holding spot in case the messages overlap in the input stream + message = new MidiMessage[MidiInPort_alsa::numDevices]; + argsExpected = new int[MidiInPort_alsa::numDevices]; + argsLeft = new int[MidiInPort_alsa::numDevices]; + + sysexIn = new Array[MidiInPort_alsa::numDevices]; + for (int j=0; j 0 && + Sequencer_alsa::rawmidi_in[portToWatch] != NULL) { + packetReadCount = snd_rawmidi_read( + Sequencer_alsa::rawmidi_in[portToWatch], packet, 1); + } else { + usleep(100000); // sleep for 1/10th of a second if the Input + // port is not open. + continue; + } + + + if (packetReadCount != 1) { + // this if statement is used to prevent cases where the + // read function above will time out and return 0 bytes + // read. This if statment will also take care of -1 + // error return values by ignoring them. + continue; + } + + if (Sequencer_alsa::initialized == 0) { + continue; + } + + // determination of a full MIDI message from the input MIDI + // stream is based here on the observation that MIDI status + // bytes and subsequent data bytes are NOT returned in the same + // read() call. Rather, they are spread out over multiple read() + // returns, with only a single value per return. So if we + // find a status byte, we then determine the number of expected + // operands and process that number of subsequent read()s to + // to determine the complete midi message. + + // store the MIDI input device to which the incoming MIDI + // byte belongs. + device = portToWatch; + + // ignore the active sensing 0xfe and MIDI clock 0xf8 commands: + if (packet[0] == 0xfe || packet[0] == 0xf8) { + continue; + } + + if (packet[0] & 0x80) { // a command byte has arrived + switch (packet[0] & 0xf0) { + case 0xf0: + if (packet[0] == 0xf0) { + argsExpected[device] = -1; + argsLeft[device] = -1; + if (sysexIn[device].getSize() != 0) { + // ignore the command for now. It is most + // likely an active sensing message. + goto top_of_loop; + } else { + uchar datum = 0xf0; + sysexIn[device].append(datum); + } + } if (packet[0] == 0xf7) { + argsLeft[device] = 0; // indicates sysex is done + uchar datum = 0xf7; + sysexIn[device].append(datum); + } else if (argsExpected[device] != -1) { + // this is a system message that may or may + // not be coming while a sysex is coming in + argsExpected[device] = 0; + } else { + // this is a system message that is not coming + // while a system exclusive is coming in + //argsExpected[device] = 0; + } + break; + case 0xc0: + if (argsExpected[device] < 0) { + std::cout << "Error: received program change during sysex" + << std::endl; + exit(1); + } else { + argsExpected[device] = 1; + } + break; + case 0xd0: + if (argsExpected[device] < 0) { + std::cout << "Error: received aftertouch message during" + " sysex" << std::endl; + exit(1); + } else { + argsExpected[device] = 1; + } + break; + default: + if (argsExpected[device] < 0) { + std::cout << "Error: received another message during sysex" + << std::endl; + exit(1); + } else { + argsExpected[device] = 2; + } + break; + } + if (argsExpected[device] >= 0) { + argsLeft[device] = argsExpected[device]; + } + + newSigTime = MidiInPort_alsa::midiTimer.getTime(); + message[device].time = newSigTime - zeroSigTime; + + if (packet[0] != 0xf7) { + message[device].p0() = packet[0]; + } + message[device].p1() = 0; + message[device].p2() = 0; + message[device].p3() = 0; + + if (packet[0] == 0xf7) { + goto sysex_done; + } + } else if (argsLeft[device]) { // not a command byte coming in + if (message[device].time == 0) { + // store the receipt time of the first message byte + newSigTime = MidiInPort_alsa::midiTimer.getTime(); + message[device].time = newSigTime - zeroSigTime; + } + + if (argsExpected[device] < 0) { + // continue processing a sysex message + sysexIn[device].append(packet[0]); + } else { + // handle a message other than a sysex message + if (argsLeft[device] == argsExpected[device]) { + message[device].p1() = packet[0]; + } else { + message[device].p2() = packet[0]; + } + argsLeft[device]--; + } + + // if MIDI message is complete, setup for running status, and + // insert note into proper buffer. + + if (argsExpected[device] >= 0 && !argsLeft[device]) { + + // store parameter data for running status + switch (message[device].p0() & 0xf0) { + case 0xc0: argsLeft[device] = 1; break; + case 0xd0: argsLeft[device] = 1; break; // fix by dan + default: argsLeft[device] = 2; break; + // 0x80 expects two arguments + // 0x90 expects two arguments + // 0xa0 expects two arguments + // 0xb0 expects two arguments + // 0xe0 expects two arguments + } + + lastSigTime = newSigTime; + + sysex_done: // come here when a sysex is completely done + + // insert the MIDI message into the appropriate buffer + // do not insert into buffer if the MIDI input device + // is paused (which can mean closed). Or if the + // pauseQ array is pointing to NULL (which probably means that + // things are about to shut down). + if (MidiInPort_alsa::pauseQ != NULL && + MidiInPort_alsa::pauseQ[device] == 0) { + if (argsExpected[device] < 0) { + // store the sysex in the MidiInPort_alsa + // buffer for sysexs and return the storage + // location: + int sysexlocation = + MidiInPort_alsa::installSysexPrivate(device, + sysexIn[device].getBase(), + sysexIn[device].getSize()); + + message[device].p0() = 0xf0; + message[device].p1() = sysexlocation; + + sysexIn[device].setSize(0); // empty the sysex storage + argsExpected[device] = 0; // no run status for sysex + argsLeft[device] = 0; // turn off sysex input flag + } + MidiInPort_alsa::midiBuffer[device]->insert( + message[device]); +// if (MidiInPort_alsa::callbackFunction != NULL) { +// MidiInPort_alsa::callbackFunction(device); +// } + if (MidiInPort_alsa::trace[device]) { + std::cout << '[' << std::hex << (int)message[device].p0() + << ':' << std::dec << (int)message[device].p1() + << ',' << (int)message[device].p2() << ']' + << std::flush; + } + message[device].time = 0; + } else { + if (MidiInPort_alsa::trace[device]) { + std::cout << '[' << std::hex << (int)message[device].p0() + << 'P' << std::dec << (int)message[device].p1() + << ',' << (int)message[device].p2() << ']' + << std::flush; + } + } + } + } + + } // end while (1) + + // This code is not yet reached, but should be made to do so eventually + + if (message != NULL) { + delete message; + message = NULL; + } + + if (argsExpected != NULL) { + delete argsExpected; + argsExpected = NULL; + } + + if (argsLeft != NULL) { + delete argsLeft; + argsLeft = NULL; + } + + if (sysexIn != NULL) { + delete sysexIn; + sysexIn = NULL; + } + + + return NULL; +} + + + +#endif // LINUX && ALSA + + + +// md5sum: 14663a91d1f5283e05ca36399d5ab767 - MidiInPort_alsa.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInPort_alsa05.cpp b/src/midiio/src/MidiInPort_alsa05.cpp new file mode 100644 index 0000000..1aad849 --- /dev/null +++ b/src/midiio/src/MidiInPort_alsa05.cpp @@ -0,0 +1,995 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun May 14 22:03:16 PDT 2000 +// Last Modified: Wed Oct 3 22:28:20 PDT 2001 (frozen for ALSA 0.5) +// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0 +// fixed by Daniel Gardner) +// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_alsa05.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiInPort_alsa05.cpp +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// linux ALSA sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// + +#if defined(LINUX) && defined(ALSA05) + +#include "MidiInPort_alsa05.h" +#include +#include +#include +#include + +#define DEFAULT_INPUT_BUFFER_SIZE (1024) + +// initialized static variables + +int MidiInPort_alsa05::numDevices = 0; +int MidiInPort_alsa05::objectCount = 0; +int* MidiInPort_alsa05::portObjectCount = NULL; +CircularBuffer** MidiInPort_alsa05::midiBuffer = NULL; +int MidiInPort_alsa05::channelOffset = 0; +SigTimer MidiInPort_alsa05::midiTimer; +int* MidiInPort_alsa05::pauseQ = NULL; +int* MidiInPort_alsa05::trace = NULL; +ostream* MidiInPort_alsa05::tracedisplay = &cout; +Array MidiInPort_alsa05::midiInThread; +int* MidiInPort_alsa05::sysexWriteBuffer = NULL; +Array** MidiInPort_alsa05::sysexBuffers = NULL; + +Array MidiInPort_alsa05::threadinitport; + + + +////////////////////////////// +// +// MidiInPort_alsa05::MidiInPort_alsa05 +// default values: autoOpen = 1 +// + +MidiInPort_alsa05::MidiInPort_alsa05(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiInPort_alsa05::MidiInPort_alsa05(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::~MidiInPort_alsa05 +// + +MidiInPort_alsa05::~MidiInPort_alsa05() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + cerr << "Error: bad MidiInPort_alsa05 object count!: " + << objectCount << endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::clearSysex -- clears the data from a sysex +// message and sets the allocation size to the default size (of 32 +// bytes). +// + +void MidiInPort_alsa05::clearSysex(int buffer) { + buffer = 0x7f | buffer; // limit buffer range from 0 to 127 + + if (getPort() == -1) { + return; + } + + sysexBuffers[getPort()][buffer].setSize(0); + if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) { + // shrink the storage buffer's size if necessary + sysexBuffers[getPort()][buffer].setAllocSize(32); + } +} + + +void MidiInPort_alsa05::clearSysex(void) { + // clear all sysex buffers + for (int i=0; i<128; i++) { + clearSysex(i); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::close +// + +void MidiInPort_alsa05::close(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 1; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::closeAll -- +// + +void MidiInPort_alsa05::closeAll(void) { + Sequencer_alsa05::close(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::extract -- returns the next MIDI message +// received since that last extracted message. +// + +MidiMessage MidiInPort_alsa05::extract(void) { + if (getPort() == -1) { + MidiMessage temp; + return temp; + } + + return midiBuffer[getPort()]->extract(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getBufferSize -- returns the maximum possible number +// of MIDI messages that can be stored in the buffer +// + +int MidiInPort_alsa05::getBufferSize(void) { + if (getPort() == -1) return 0; + + return midiBuffer[getPort()]->getSize(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getChannelOffset -- returns zero if MIDI channel +// offset is 0, or 1 if offset is 1. +// + +int MidiInPort_alsa05::getChannelOffset(void) const { + return channelOffset; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getCount -- returns the number of unexamined +// MIDI messages waiting in the input buffer. +// + +int MidiInPort_alsa05::getCount(void) { + if (getPort() == -1) return 0; + return midiBuffer[getPort()]->getCount(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getName -- returns the name of the port. +// returns "" if no name. Name is valid until all instances +// of MIDI classes are. +// + +const char* MidiInPort_alsa05::getName(void) { + if (getPort() == -1) { + return "Null ALSA MIDI Input"; + } + return getInputName(getPort()); +} + + +const char* MidiInPort_alsa05::getName(int i) { + return getInputName(i); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getNumPorts -- returns the number of available +// ports for MIDI input +// + +int MidiInPort_alsa05::getNumPorts(void) { + return getNumInputs(); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getPort -- returns the port to which this +// object belongs (as set with the setPort function). +// + +int MidiInPort_alsa05::getPort(void) { + return port; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getPortStatus -- 0 if closed, 1 if open +// + +int MidiInPort_alsa05::getPortStatus(void) { + return is_open_in(0); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getSysex -- returns the sysex message contents +// of a given buffer. You should check to see that the size is +// non-zero before looking at the data. The data pointer will +// be NULL if there is no data in the buffer. +// + +uchar* MidiInPort_alsa05::getSysex(int buffer) { + buffer &= 0x7f; // limit the buffer access to indices 0 to 127. + if (getPort() == -1) { + return NULL; + } + + if (sysexBuffers[getPort()][buffer].getSize() < 2) { + return NULL; + } else { + return sysexBuffers[getPort()][buffer].getBase(); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getSysexSize -- returns the sysex message byte +// count of a given buffer. Buffers are in the range from +// 0 to 127. +// + +int MidiInPort_alsa05::getSysexSize(int buffer) { + if (getPort() == -1) { + return 0; + } else { + return sysexBuffers[getPort()][buffer & 0x7f].getSize(); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::getTrace -- returns true if trace is on or false +// if trace is off. if trace is on, then prints to standard +// output the Midi message received. +// + +int MidiInPort_alsa05::getTrace(void) { + if (getPort() == -1) return -1; + + return trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::insert +// + +void MidiInPort_alsa05::insert(const MidiMessage& aMessage) { + if (getPort() == -1) return; + + midiBuffer[getPort()]->insert(aMessage); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::installSysex -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_alsa05::installSysex(uchar* anArray, int aSize) { + if (getPort() == -1) { + return -1; + } else { + return installSysexPrivate(getPort(), anArray, aSize); + } +} + +////////////////////////////// +// +// MidiInPort_alsa05::installSysexPrivate -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_alsa05::installSysexPrivate(int port, uchar* anArray, int aSize) { + // choose a buffer to install sysex data into: + int bufferNumber = sysexWriteBuffer[port]; + sysexWriteBuffer[port]++; + if (sysexWriteBuffer[port] >= 128) { + sysexWriteBuffer[port] = 0; + } + + // copy contents of sysex message into the chosen buffer + sysexBuffers[port][bufferNumber].setSize(aSize); + uchar* dataptr = sysexBuffers[port][bufferNumber].getBase(); + uchar* indataptr = anArray; + for (int i=0; i& temp = *midiBuffer[getPort()]; + return temp[index]; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::open -- returns true if MIDI input port was +// opened. +// + +int MidiInPort_alsa05::open(void) { + if (getPort() == -1) return 0; + + return Sequencer_alsa05::open(); + pauseQ[getPort()] = 0; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::pause -- stop the Midi input port from +// inserting MIDI messages into the buffer, but keeps the +// port open. Use unpause() to reverse the effect of pause(). +// + +void MidiInPort_alsa05::pause(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 1; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::setBufferSize -- sets the allocation +// size of the MIDI input buffer. +// + +void MidiInPort_alsa05::setBufferSize(int aSize) { + if (getPort() == -1) return; + + midiBuffer[getPort()]->setSize(aSize); +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::setChannelOffset -- sets the MIDI chan offset, +// either 0 or 1. +// + +void MidiInPort_alsa05::setChannelOffset(int anOffset) { + switch (anOffset) { + case 0: channelOffset = 0; break; + case 1: channelOffset = 1; break; + default: + cout << "Error: Channel offset can be only 0 or 1." << endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::setPort -- +// + +void MidiInPort_alsa05::setPort(int aPort) { +// if (aPort == -1) return; + if (aPort < -1 || aPort >= getNumPorts()) { + cerr << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + if (port != -1) { + portObjectCount[port]++; + } +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::setTrace -- if false, then don't print MIDI messages +// to the screen. +// + +int MidiInPort_alsa05::setTrace(int aState) { + if (getPort() == -1) return -1; + + + int oldtrace = trace[getPort()]; + if (aState == 0) { + trace[getPort()] = 0; + } else { + trace[getPort()] = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::toggleTrace -- switches the state of trace +// Returns the previous value of the trace variable. +// + +void MidiInPort_alsa05::toggleTrace(void) { + if (getPort() == -1) return; + + trace[getPort()] = !trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiInPort_alsa05::unpause -- enables the Midi input port +// to inserting MIDI messages into the buffer after the +// port is already open. +// + +void MidiInPort_alsa05::unpause(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 0; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiInPort_alsa05::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiInPort_alsa05::deinitialize(void) { + closeAll(); + + for (int i=0; i*[numDevices]; + + // allocate space for Midi input sysex buffer write indices + if (sysexWriteBuffer != NULL) { + delete [] sysexWriteBuffer; + } + sysexWriteBuffer = new int[numDevices]; + + // allocate space for Midi input sysex buffers + if (sysexBuffers != NULL) { + cout << "Error: memory leak on sysex buffers initialization" << endl; + exit(1); + } + sysexBuffers = new Array*[numDevices]; + + int flag; + midiInThread.setSize(getNumPorts()); + threadinitport.setSize(getNumPorts()); + // initialize the static arrays + for (int i=0; i; + midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE); + + sysexWriteBuffer[i] = 0; + sysexBuffers[i] = new Array[128]; + for (int n=0; n<128; n++) { + sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow + sysexBuffers[i][n].setAllocSize(32); + sysexBuffers[i][n].setSize(0); + sysexBuffers[i][n].setGrowth(32); // in case it will ever grow + } + + threadinitport[i] = i; + flag = pthread_create(&midiInThread[i], NULL, + interpretMidiInputStreamPrivateALSA05, &threadinitport[i]); + if (flag == -1) { + cout << "Unable to create MIDI input thread." << endl; + exit(1); + } + } + + } +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// friendly functions +// + + +////////////////////////////// +// +// interpretMidiInputStreamPrivateALSA05 -- handles the MIDI input stream +// for the various input devices from the ALSA MIDI driver. +// +// Note about system exclusive messages: +// System Exclusive messages are stored in a separate buffer from +// Other Midi messages since they can be variable in length. If +// The Midi Input returns a message with command byte 0xf0, then +// the p1() byte indicates the system exclusive buffer number that is +// holding the system exclusive data for that Midi message. There +// are 128 system exclusive buffers that are numbered between +// 0 and 127. These buffers are filled in a cycle. +// To extract a System exclusive message from MidiInPort_alsa05, +// you first will receive a Message with a command byte of 0xf0. +// you can then access the data for that sysex by the command: +// MidiInPort_alsa05::getSysex(buffer_number), this will return +// a pointer to the beginning of the sysex data. The first byte +// of the sysex data should be 0xf0, and the last byte of the data +// is 0xf7. All other bytes of data should be in the range from +// 0 to 127. You can also get the size of the sysex buffer by the +// following command: MidiInPort_alsa05::getSysexSize(buffer_number). +// This command will tell you the number of bytes in the system +// exclusive message including the starting 0xf0 and the ending 0xf7. +// +// If you want to minimize memory useage of the system exclusive +// buffers you can run the command: +// MidiInPort_alsa05::clearSysex(buffer_number); Otherwise the sysex +// buffer will be erased automatically the next time that the that +// buffer number is cycled through when receiving more system exclusives. +// Allocated the allocated size of the system exclusive storage will +// not be adjusted when the computer replaces the system exclusive +// message unless more storage size is needed, clearSysex however, +// will resize the sysex buffer to its default size (currently 32 bytes). +// clearSysex() without arguments will resize all buffers so that +// they are allocated to the default size and will erase data from +// all buffers. You can spoof a system exclusive message coming in +// by installing a system exclusive message and then inserting +// the system message command into the input buffer of the MidiInPort +// class, int sysex_buffer = MidiInPort_alsa05::installSysex( +// uchar *data, int size); will put the data into a sysex buffer and +// return the buffer number that it was placed into. +// +// This function assumes that System Exclusive messages cannot be sent +// as a running status messages. +// +// Note about MidiMessage time stamps: +// The MidiMessage::time field is a recording of the time that the +// first byte of the MidiMessage arrived. If the message is from +// running status mode, then the time that the first parameter byte +// arrived is stored. System exclusive message arrival times are +// recoreded at the time of the last byte (0xf7) arriving. This is +// because other system messages can be coming in while the sysex +// message is coming in. Anyway, sysex messages are not really to +// be used for real time MIDI messaging, so the exact moment that the +// first byte of the sysex came in is not important to me. +// +// + +void *interpretMidiInputStreamPrivateALSA05(void * arg) { + int portToWatch = *(int*)arg; + + int* argsExpected = NULL; // MIDI parameter bytes expected to follow + int* argsLeft = NULL; // MIDI parameter bytes left to wait for + uchar packet[1]; // bytes for sequencer driver + MidiMessage* message = NULL; // holder for current MIDI message + int newSigTime = 0; // for millisecond timer + int lastSigTime = -1; // for millisecond timer + int zeroSigTime = -1; // for timing incoming events + int device = -1; // for sorting out the bytes by input device + Array* sysexIn; // MIDI Input sysex temporary storage + + // Note on the use of argsExpected and argsLeft for sysexs: + // If argsExpected is -1, then a sysex message is coming in. + // If argsLeft < 0, then the sysex message has not finished comming + // in. If argsLeft == 0 and argsExpected == -1, then the sysex + // has finished coming in and is to be sent to the correct + // location. + + // allocate space for MIDI messages, each device has a different message + // holding spot in case the messages overlap in the input stream + message = new MidiMessage[MidiInPort_alsa05::numDevices]; + argsExpected = new int[MidiInPort_alsa05::numDevices]; + argsLeft = new int[MidiInPort_alsa05::numDevices]; + + sysexIn = new Array[MidiInPort_alsa05::numDevices]; + for (int j=0; j= 0) { + argsLeft[device] = argsExpected[device]; + } + + newSigTime = MidiInPort_alsa05::midiTimer.getTime(); + message[device].time = newSigTime - zeroSigTime; + + if (packet[0] != 0xf7) { + message[device].p0() = packet[0]; + } + message[device].p1() = 0; + message[device].p2() = 0; + message[device].p3() = 0; + + if (packet[0] == 0xf7) { + goto sysex_done; + } + } else if (argsLeft[device]) { // not a command byte coming in + if (message[device].time == 0) { + // store the receipt time of the first message byte + newSigTime = MidiInPort_alsa05::midiTimer.getTime(); + message[device].time = newSigTime - zeroSigTime; + } + + if (argsExpected[device] < 0) { + // continue processing a sysex message + sysexIn[device].append(packet[0]); + } else { + // handle a message other than a sysex message + if (argsLeft[device] == argsExpected[device]) { + message[device].p1() = packet[0]; + } else { + message[device].p2() = packet[0]; + } + argsLeft[device]--; + } + + // if MIDI message is complete, setup for running status, and + // insert note into proper buffer. + + if (argsExpected[device] >= 0 && !argsLeft[device]) { + + // store parameter data for running status + switch (message[device].p0() & 0xf0) { + case 0xc0: argsLeft[device] = 1; break; + case 0xd0: argsLeft[device] = 1; break; // fix by dan + default: argsLeft[device] = 2; break; + // 0x80 expects two arguments + // 0x90 expects two arguments + // 0xa0 expects two arguments + // 0xb0 expects two arguments + // 0xe0 expects two arguments + } + + lastSigTime = newSigTime; + + sysex_done: // come here when a sysex is completely done + + // insert the MIDI message into the appropriate buffer + // do not insert into buffer if the MIDI input device + // is paused (which can mean closed). Or if the + // pauseQ array is pointing to NULL (which probably means that + // things are about to shut down). + if (MidiInPort_alsa05::pauseQ != NULL && + MidiInPort_alsa05::pauseQ[device] == 0) { + if (argsExpected[device] < 0) { + // store the sysex in the MidiInPort_alsa05 + // buffer for sysexs and return the storage + // location: + int sysexlocation = + MidiInPort_alsa05::installSysexPrivate(device, + sysexIn[device].getBase(), + sysexIn[device].getSize()); + + message[device].p0() = 0xf0; + message[device].p1() = sysexlocation; + + sysexIn[device].setSize(0); // empty the sysex storage + argsExpected[device] = 0; // no run status for sysex + argsLeft[device] = 0; // turn off sysex input flag + } + MidiInPort_alsa05::midiBuffer[device]->insert( + message[device]); +// if (MidiInPort_alsa05::callbackFunction != NULL) { +// MidiInPort_alsa05::callbackFunction(device); +// } + if (MidiInPort_alsa05::trace[device]) { + cout << '[' << hex << (int)message[device].p0() + << ':' << dec << (int)message[device].p1() + << ',' << (int)message[device].p2() << ']' + << flush; + } + message[device].time = 0; + } else { + if (MidiInPort_alsa05::trace[device]) { + cout << '[' << hex << (int)message[device].p0() + << 'P' << dec << (int)message[device].p1() + << ',' << (int)message[device].p2() << ']' + << flush; + } + } + } + } + + } // end while (1) + + // This code is not yet reached, but should be made to do so eventually + + if (message != NULL) { + delete message; + message = NULL; + } + + if (argsExpected != NULL) { + delete argsExpected; + argsExpected = NULL; + } + + if (argsLeft != NULL) { + delete argsLeft; + argsLeft = NULL; + } + + if (sysexIn != NULL) { + delete sysexIn; + sysexIn = NULL; + } + + + return NULL; +} + + + +#endif /* LINUX and ALSA05 */ + + + +// md5sum: cc5ea6a6078cb534fc6c39543aa57a83 - MidiInPort_alsa05.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInPort_linux.cpp b/src/midiio/src/MidiInPort_linux.cpp new file mode 100644 index 0000000..01274e2 --- /dev/null +++ b/src/midiio/src/MidiInPort_linux.cpp @@ -0,0 +1,491 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun May 14 22:35:27 PDT 2000 +// Last Modified: Thu May 18 23:36:00 PDT 2000 +// Last Modified: Sat Nov 2 20:37:49 PST 2002 (added ifdef ALSA OSS) +// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort_linux.cpp +// Web Address: http://sig.sapp.org/include/sig/MidiInPort_linux.cpp +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of an +// operating-system specific MIDI input method. +// Provides control of all low-level MIDI input +// functionality such that it will work on all +// computers in the same manner. +// + +#ifdef LINUX +#if defined(ALSA) && defined(OSS) + +#include +#include +#include "MidiInPort_linux.h" + + +// initialize static variables oss_input->close(); break; +int MidiInPort_linux::objectCount = 0; +int MidiInPort_linux::current = MIDI_IN_OSS_SELECT; +int MidiInPort_linux::alsaQ = 0; +int MidiInPort_linux::ossQ = 0; +MidiInPort_oss *MidiInPort_linux::oss_input = NULL; +MidiInPort_alsa *MidiInPort_linux::alsa_input = NULL; +MidiInPort_unsupported *MidiInPort_linux::unknown_input = NULL; + + +MidiInPort_linux::MidiInPort_linux(void) { + if (objectCount == 0) { + determineDrivers(); + } else if (objectCount < 0) { + cout << "Error: unusual MidiInPort_linux object count" << endl; + exit(1); + } + + objectCount++; +} + + +MidiInPort_linux::MidiInPort_linux(int aPort, int autoOpen = 1) { + if (objectCount == 0) { + determineDrivers(); + setAndOpenPort(aPort); + } else if (objectCount < 0) { + cout << "Error: unusual MidiInPort_linux object count" << endl; + exit(1); + } + + objectCount++; +} + + +MidiInPort_linux::~MidiInPort_linux() { + objectCount--; + if (objectCount == 0) { + if (oss_input != NULL) { + delete oss_input; + oss_input = NULL; + } + if (alsa_input != NULL) { + delete alsa_input; + alsa_input = NULL; + } + if (unknown_input != NULL) { + delete unknown_input; + unknown_input = NULL; + } + } + + if (objectCount < 0) { + cout << "Error: unusual MidiOutPort_linux count when destructing" << endl; + exit(1); + } +} + + +void MidiInPort_linux::clearSysex(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->clearSysex(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->clearSysex(); break; + default: unknown_input->clearSysex(); break; + } +} + + +void MidiInPort_linux::clearSysex(int buffer) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->clearSysex(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->clearSysex(); break; + default: unknown_input->clearSysex(); break; + } +} + + +void MidiInPort_linux::close(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->close(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->close(); break; + default: unknown_input->close(); break; + } +} + + +void MidiInPort_linux::closeAll(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->closeAll(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->closeAll(); break; + default: unknown_input->closeAll(); break; + } +} + + +MidiMessage MidiInPort_linux::extract(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->extract(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->extract(); break; + default: return unknown_input->extract(); break; + } +} + + +int MidiInPort_linux::getBufferSize(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getBufferSize(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getBufferSize(); break; + default: return unknown_input->getBufferSize(); break; + } +} + + +int MidiInPort_linux::getChannelOffset(void) const { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getChannelOffset(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getChannelOffset(); break; + default: return unknown_input->getChannelOffset(); break; + } +} + + +int MidiInPort_linux::getCount(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getCount(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getCount(); break; + default: return unknown_input->getCount(); break; + } +} + + +const char* MidiInPort_linux::getName(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getName(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getName(); break; + default: return unknown_input->getName(); break; + } +} + + +const char* MidiInPort_linux::getName(int i) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getName(i); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getName(i); break; + default: return unknown_input->getName(i); break; + } +} + + +int MidiInPort_linux::getNumPorts(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getNumPorts(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getNumPorts(); break; + default: return unknown_input->getNumPorts(); break; + } +} + + +int MidiInPort_linux::getPort(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getPort(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getPort(); break; + default: return unknown_input->getPort(); break; + } +} + + +int MidiInPort_linux::getPortStatus(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getPortStatus(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getPortStatus(); break; + default: return unknown_input->getPortStatus(); break; + } +} + + +uchar* MidiInPort_linux::getSysex(int buffer) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getSysex(buffer); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getSysex(buffer); break; + default: return unknown_input->getSysex(buffer); break; + } +} + + +int MidiInPort_linux::getSysexSize(int buffer) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getSysexSize(buffer); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getSysexSize(buffer); break; + default: return unknown_input->getSysexSize(buffer); break; + } +} + + +int MidiInPort_linux::getTrace(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->getTrace(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->getTrace(); break; + default: return unknown_input->getTrace(); break; + } +} + + +void MidiInPort_linux::insert(const MidiMessage& aMessage) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->insert(aMessage); break; + case MIDI_IN_ALSA_SELECT: alsa_input->insert(aMessage); break; + default: unknown_input->insert(aMessage); break; + } +} + + +int MidiInPort_linux::installSysex(uchar* anArray, int aSize) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: + return oss_input->installSysex(anArray, aSize); + break; + case MIDI_IN_ALSA_SELECT: + return alsa_input->installSysex(anArray, aSize); + break; + default: + return unknown_input->installSysex(anArray, aSize); + break; + } +} + + +MidiMessage& MidiInPort_linux::message(int index) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->message(index); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->message(index); break; + default: return unknown_input->message(index); break; + } +} + +int MidiInPort_linux::open(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->open(); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->open(); break; + default: return unknown_input->open(); break; + } +} + + +MidiMessage& MidiInPort_linux::operator[](int index) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->message(index); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->message(index); break; + default: return unknown_input->message(index); break; + } +} + + +void MidiInPort_linux::pause(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->pause(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->pause(); break; + default: unknown_input->pause(); break; + } +} + + +void MidiInPort_linux::setBufferSize(int aSize) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->setBufferSize(aSize); break; + case MIDI_IN_ALSA_SELECT: alsa_input->setBufferSize(aSize); break; + default: unknown_input->setBufferSize(aSize); break; + } +} + + +void MidiInPort_linux::setChannelOffset(int anOffset) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->setChannelOffset(anOffset); break; + case MIDI_IN_ALSA_SELECT: alsa_input->setChannelOffset(anOffset); break; + default: unknown_input->setChannelOffset(anOffset); break; + } +} + + +void MidiInPort_linux::setAndOpenPort(int aPort) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: + oss_input->setPort(aPort); + oss_input->open(); + break; + case MIDI_IN_ALSA_SELECT: + alsa_input->setPort(aPort); + alsa_input->open(); + break; + default: + unknown_input->setPort(aPort); + unknown_input->open(); + break; + } +} + + +void MidiInPort_linux::setPort(int aPort) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->setPort(aPort); break; + case MIDI_IN_ALSA_SELECT: alsa_input->setPort(aPort); break; + default: unknown_input->setPort(aPort); break; + } +} + + +int MidiInPort_linux::setTrace(int aState) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: return oss_input->setTrace(aState); break; + case MIDI_IN_ALSA_SELECT: return alsa_input->setTrace(aState); break; + default: return unknown_input->setTrace(aState); break; + } +} + + +void MidiInPort_linux::toggleTrace(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->toggleTrace(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->toggleTrace(); break; + default: unknown_input->toggleTrace(); break; + } +} + + +void MidiInPort_linux::unpause(void) { + switch (getSelect()) { + case MIDI_IN_OSS_SELECT: oss_input->unpause(); break; + case MIDI_IN_ALSA_SELECT: alsa_input->unpause(); break; + default: unknown_input->unpause(); break; + } +} + + + +////////////////////////////// +// +// MidiInPort_linux::getSelect -- return the type of MIDI which +// is being used to send MIDI output. +// + +int MidiInPort_linux::getSelect(void) { + return current; +} + + +////////////////////////////// +// +// MidiInPort_linux::selectOSS -- select the OSS MIDI output +// returns 1 if OSS is available, otherwise returns 0. +// + +int MidiInPort_linux::selectOSS(void) { + if (ossQ) { + current = MIDI_IN_OSS_SELECT; + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiInPort_linux::selectALSA -- select the ALSA MIDI output +// returns 1 if ALSA is available, otherwise returns 0. +// + +int MidiInPort_linux::selectALSA(void) { + if (alsaQ) { + current = MIDI_IN_ALSA_SELECT; + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiInPort_linux::selectUnknown -- select the Unknown MIDI output +// returns 1 always. +// + +int MidiInPort_linux::selectUnknown(void) { + current = MIDI_IN_UNKNOWN_SELECT; + return 1; +} + + +////////////////////////////////////////////////////////////////////////// +// +// Private Functions +// + +////////////////////////////// +// +// MidiInPort_linux::determineDrivers -- see if OSS/ALSA are +// available. If /dev/sequencer is present, assume that OSS is +// available. If /dev/snd/sdq is present, assume that ALSA is +// available. +// + +void MidiInPort_linux::determineDrivers(void) { + struct stat filestats; + int status; + status = stat("/dev/sequencer", &filestats); + + if (status != 0) { + ossQ = 0; + } else { + ossQ = 1; + } + + status = stat("/dev/snd/seq", &filestats); + + if (status != 0) { + alsaQ = 0; + } else { + alsaQ = 1; + } + + + current = MIDI_IN_UNKNOWN_SELECT; + + if (ossQ) { + current = MIDI_IN_OSS_SELECT; + } + + if (alsaQ) { + current = MIDI_IN_ALSA_SELECT; + } + + // create MIDI output types which are available: + + if (oss_input != NULL) { + delete oss_input; + oss_input = NULL; + } + if (alsa_input != NULL) { + delete alsa_input; + alsa_input = NULL; + } + if (unknown_input != NULL) { + delete unknown_input; + unknown_input = NULL; + } + + if (ossQ) { + oss_input = new MidiInPort_oss; + } + if (alsaQ) { + alsa_input = new MidiInPort_alsa; + } + + unknown_input = new MidiInPort_unsupported; + +} + + +#endif /* ALSA and OSS */ +#endif /* LINUX */ + + +// md5sum: d634dd5c3b7e8c4d75b99d7459c3f073 - MidiInPort_linux.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInPort_oss.cpp b/src/midiio/src/MidiInPort_oss.cpp new file mode 100644 index 0000000..d16c865 --- /dev/null +++ b/src/midiio/src/MidiInPort_oss.cpp @@ -0,0 +1,1036 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998 +// Last Modified: Sat Jan 9 06:05:24 PST 1999 +// Last Modified: Tue Jun 29 16:18:45 PDT 1999 (added sysex capability) +// Last Modified: Mon Dec 6 16:28:45 PST 1999 +// Last Modified: Wed Jan 12 10:59:33 PST 2000 (orphan 0xf0 behavior change) +// Last Modified: Wed May 10 17:10:05 PDT 2000 (name change from _linux to _oss) +// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0 +// fixed by Daniel Gardner) +// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_oss.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiInPort_oss.cpp +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// linux OSS sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// + +#ifdef LINUX + +#include "MidiInPort_oss.h" +#include +#include +#include +#include + + +#define DEFAULT_INPUT_BUFFER_SIZE (1024) + +// initialized static variables + +int MidiInPort_oss::numDevices = 0; +int MidiInPort_oss::objectCount = 0; +int* MidiInPort_oss::portObjectCount = NULL; +CircularBuffer** MidiInPort_oss::midiBuffer = NULL; +int MidiInPort_oss::channelOffset = 0; +SigTimer MidiInPort_oss::midiTimer; +int* MidiInPort_oss::pauseQ = NULL; +int* MidiInPort_oss::trace = NULL; +std::ostream* MidiInPort_oss::tracedisplay = &std::cout; +pthread_t MidiInPort_oss::midiInThread; +int* MidiInPort_oss::sysexWriteBuffer = NULL; +Array** MidiInPort_oss::sysexBuffers = NULL; + + + +////////////////////////////// +// +// MidiInPort_oss::MidiInPort_oss +// default values: autoOpen = 1 +// + +MidiInPort_oss::MidiInPort_oss(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiInPort_oss::MidiInPort_oss(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::~MidiInPort_oss +// + +MidiInPort_oss::~MidiInPort_oss() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + std::cerr << "Error: bad MidiInPort_oss object count!: " + << objectCount << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::clearSysex -- clears the data from a sysex +// message and sets the allocation size to the default size (of 32 +// bytes). +// + +void MidiInPort_oss::clearSysex(int buffer) { + buffer = 0x7f | buffer; // limit buffer range from 0 to 127 + if (getPort() == -1) { + return; + } + + sysexBuffers[getPort()][buffer].setSize(0); + if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) { + // shrink the storage buffer's size if necessary + sysexBuffers[getPort()][buffer].setAllocSize(32); + } +} + + +void MidiInPort_oss::clearSysex(void) { + // clear all sysex buffers + for (int i=0; i<128; i++) { + clearSysex(i); + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::close +// + +void MidiInPort_oss::close(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 1; +} + + + +////////////////////////////// +// +// MidiInPort_oss::closeAll -- +// + +void MidiInPort_oss::closeAll(void) { + Sequencer_oss::close(); +} + + + +////////////////////////////// +// +// MidiInPort_oss::extract -- returns the next MIDI message +// received since that last extracted message. +// + +MidiMessage MidiInPort_oss::extract(void) { + if (getPort() == -1) { + MidiMessage temp; + return temp; + } + + return midiBuffer[getPort()]->extract(); +} + + + +////////////////////////////// +// +// MidiInPort_oss::getBufferSize -- returns the maximum possible number +// of MIDI messages that can be stored in the buffer +// + +int MidiInPort_oss::getBufferSize(void) { + if (getPort() == -1) return 0; + + return midiBuffer[getPort()]->getSize(); +} + + + +////////////////////////////// +// +// MidiInPort_oss::getChannelOffset -- returns zero if MIDI channel +// offset is 0, or 1 if offset is 1. +// + +int MidiInPort_oss::getChannelOffset(void) const { + return channelOffset; +} + + + +////////////////////////////// +// +// MidiInPort_oss::getCount -- returns the number of unexamined +// MIDI messages waiting in the input buffer. +// + +int MidiInPort_oss::getCount(void) { + if (getPort() == -1) return 0; + + return midiBuffer[getPort()]->getCount(); +} + + + +////////////////////////////// +// +// MidiInPort_oss::getName -- returns the name of the port. +// returns "" if no name. Name is valid until all instances +// of MIDI classes are. +// + +const char* MidiInPort_oss::getName(void) { + if (getPort() == -1) { + return "Null OSS MIDI Input"; + } + return getInputName(getPort()); +} + + +const char* MidiInPort_oss::getName(int i) { + return getInputName(i); +} + + + +////////////////////////////// +// +// MidiInPort_oss::getNumPorts -- returns the number of available +// ports for MIDI input +// + +int MidiInPort_oss::getNumPorts(void) { + return getNumInputs(); +} + + + +////////////////////////////// +// +// MidiInPort_oss::getPort -- returns the port to which this +// object belongs (as set with the setPort function). +// + +int MidiInPort_oss::getPort(void) { + return port; +} + + + +////////////////////////////// +// +// MidiInPort_oss::getPortStatus -- 0 if closed, 1 if open +// + +int MidiInPort_oss::getPortStatus(void) { + return is_open(); +} + + + +////////////////////////////// +// +// MidiInPort_oss::getSysex -- returns the sysex message contents +// of a given buffer. You should check to see that the size is +// non-zero before looking at the data. The data pointer will +// be NULL if there is no data in the buffer. +// + +uchar* MidiInPort_oss::getSysex(int buffer) { + buffer &= 0x7f; // limit the buffer access to indices 0 to 127. + + if (getPort() == -1) { + return NULL; + } + + if (sysexBuffers[getPort()][buffer].getSize() < 2) { + return NULL; + } else { + return sysexBuffers[getPort()][buffer].getBase(); + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::getSysexSize -- returns the sysex message byte +// count of a given buffer. Buffers are in the range from +// 0 to 127. +// + +int MidiInPort_oss::getSysexSize(int buffer) { + if (getPort() == -1) { + return 0; + } else { + return sysexBuffers[getPort()][buffer & 0x7f].getSize(); + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::getTrace -- returns true if trace is on or false +// if trace is off. if trace is on, then prints to standard +// output the Midi message received. +// + +int MidiInPort_oss::getTrace(void) { + if (getPort() == -1) return -1; + + return trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiInPort_oss::insert +// + +void MidiInPort_oss::insert(const MidiMessage& aMessage) { + if (getPort() == -1) return; + + midiBuffer[getPort()]->insert(aMessage); +} + + + +////////////////////////////// +// +// MidiInPort_oss::installSysex -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_oss::installSysex(uchar* anArray, int aSize) { + if (getPort() == -1) { + return -1; + } else { + return installSysexPrivate(getPort(), anArray, aSize); + } +} + +////////////////////////////// +// +// MidiInPort_oss::installSysexPrivate -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_oss::installSysexPrivate(int port, uchar* anArray, int aSize) { + // choose a buffer to install sysex data into: + int bufferNumber = sysexWriteBuffer[port]; + sysexWriteBuffer[port]++; + if (sysexWriteBuffer[port] >= 128) { + sysexWriteBuffer[port] = 0; + } + + // copy contents of sysex message into the chosen buffer + sysexBuffers[port][bufferNumber].setSize(aSize); + uchar* dataptr = sysexBuffers[port][bufferNumber].getBase(); + uchar* indataptr = anArray; + for (int i=0; i& temp = *midiBuffer[getPort()]; + return temp[index]; +} + + + +////////////////////////////// +// +// MidiInPort_oss::open -- returns true if MIDI input port was +// opened. +// + +int MidiInPort_oss::open(void) { + if (getPort() == -1) return 0; + + return Sequencer_oss::open(); + pauseQ[getPort()] = 0; +} + + + +////////////////////////////// +// +// MidiInPort_oss::pause -- stop the Midi input port from +// inserting MIDI messages into the buffer, but keeps the +// port open. Use unpause() to reverse the effect of pause(). +// + +void MidiInPort_oss::pause(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 1; +} + + + +////////////////////////////// +// +// MidiInPort_oss::setBufferSize -- sets the allocation +// size of the MIDI input buffer. +// + +void MidiInPort_oss::setBufferSize(int aSize) { + if (getPort() == -1) return; + + midiBuffer[getPort()]->setSize(aSize); +} + + + +////////////////////////////// +// +// MidiInPort_oss::setChannelOffset -- sets the MIDI chan offset, +// either 0 or 1. +// + +void MidiInPort_oss::setChannelOffset(int anOffset) { + switch (anOffset) { + case 0: channelOffset = 0; break; + case 1: channelOffset = 1; break; + default: + std::cout << "Error: Channel offset can be only 0 or 1." << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::setPort +// + +void MidiInPort_oss::setPort(int aPort) { +// if (aPort == -1) return; + if (aPort < -1 || aPort >= getNumPorts()) { +// std::cerr << "Error: maximum port number is: " << getNumPorts()-1 +// << ", but you tried to access port: " << aPort << std::endl; +// exit(1); + } + else { + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + if (port != -1) { + portObjectCount[port]++; + } + } +} + + + +////////////////////////////// +// +// MidiInPort_oss::setTrace -- if false, then don't print MIDI messages +// to the screen. +// + +int MidiInPort_oss::setTrace(int aState) { + if (getPort() == -1) return -1; + + + int oldtrace = trace[getPort()]; + if (aState == 0) { + trace[getPort()] = 0; + } else { + trace[getPort()] = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiInPort_oss::toggleTrace -- switches the state of trace +// Returns the previous value of the trace variable. +// + +void MidiInPort_oss::toggleTrace(void) { + if (getPort() == -1) return; + + trace[getPort()] = !trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiInPort_oss::unpause -- enables the Midi input port +// to inserting MIDI messages into the buffer after the +// port is already open. +// + +void MidiInPort_oss::unpause(void) { + if (getPort() == -1) return; + + pauseQ[getPort()] = 0; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiInPort_oss::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiInPort_oss::deinitialize(void) { + closeAll(); + + for (int i=0; i*[numDevices]; + + // allocate space for Midi input sysex buffer write indices + if (sysexWriteBuffer != NULL) { + delete [] sysexWriteBuffer; + } + sysexWriteBuffer = new int[numDevices]; + + // allocate space for Midi input sysex buffers + if (sysexBuffers != NULL) { + std::cout << "Error: memory leak on sysex buffers initialization" << std::endl; + exit(1); + } + sysexBuffers = new Array*[numDevices]; + + // initialize the static arrays + for (int i=0; i; + midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE); + + sysexWriteBuffer[i] = 0; + sysexBuffers[i] = new Array[128]; + for (int n=0; n<128; n++) { + sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow + sysexBuffers[i][n].setAllocSize(32); + sysexBuffers[i][n].setSize(0); + sysexBuffers[i][n].setGrowth(32); // in case it will ever grow + } + } + + int flag = pthread_create(&midiInThread, NULL, + interpretMidiInputStreamPrivate, NULL); + if (flag == -1) { + std::cout << "Unable to create MIDI input thread." << std::endl; + exit(1); + } + + } +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// friendly functions +// + + +////////////////////////////// +// +// interpretMidiInputStreamPrivate -- handles the MIDI input stream +// for the various input devices. +// +// Note about system exclusive messages: +// System Exclusive messages are stored in a separate buffer from +// Other Midi messages since they can be variable in length. If +// The Midi Input returns a message with command byte 0xf0, then +// the p1() byte indicates the system exclusive buffer number that is +// holding the system exclusive data for that Midi message. There +// are 128 system exclusive buffers that are numbered between +// 0 and 127. These buffers are filled in a cycle. +// To extract a System exclusive message from MidiInPort_oss, +// you first will receive a Message with a command byte of 0xf0. +// you can then access the data for that sysex by the command: +// MidiInPort_oss::getSysex(buffer_number), this will return +// a pointer to the beginning of the sysex data. The first byte +// of the sysex data should be 0xf0, and the last byte of the data +// is 0xf7. All other bytes of data should be in the range from +// 0 to 127. You can also get the size of the sysex buffer by the +// following command: MidiInPort_oss::getSysexSize(buffer_number). +// This command will tell you the number of bytes in the system +// exclusive message including the starting 0xf0 and the ending 0xf7. +// +// If you want to minimize memory useage of the system exclusive +// buffers you can run the command: +// MidiInPort_oss::clearSysex(buffer_number); Otherwise the sysex +// buffer will be erased automatically the next time that the that +// buffer number is cycled through when receiving more system exclusives. +// Allocated the allocated size of the system exclusive storage will +// not be adjusted when the computer replaces the system exclusive +// message unless more storage size is needed, clearSysex however, +// will resize the sysex buffer to its default size (currently 32 bytes). +// clearSysex() without arguments will resize all buffers so that +// they are allocated to the default size and will erase data from +// all buffers. You can spoof a system exclusive message coming in +// by installing a system exclusive message and then inserting +// the system message command into the input buffer of the MidiInPort +// class, int sysex_buffer = MidiInPort_oss::installSysex( +// uchar *data, int size); will put the data into a sysex buffer and +// return the buffer number that it was placed into. +// +// This function assumes that System Exclusive messages cannot be sent +// as a running status messages. +// +// Note about MidiMessage time stamps: +// The MidiMessage::time field is a recording of the time that the +// first byte of the MidiMessage arrived. If the message is from +// running status mode, then the time that the first parameter byte +// arrived is stored. System exclusive message arrival times are +// recoreded at the time of the last byte (0xf7) arriving. This is +// because other system messages can be coming in while the sysex +// message is coming in. Anyway, sysex messages are not really to +// be used for real time MIDI messaging, so the exact moment that the +// first byte of the sysex came in is not important to me. +// +// + +void *interpretMidiInputStreamPrivate(void *) { + + int* argsExpected = NULL; // MIDI parameter bytes expected to follow + int* argsLeft = NULL; // MIDI parameter bytes left to wait for + uchar packet[4]; // bytes for sequencer driver + MidiMessage* message = NULL; // holder for current MIDI message + int newSigTime = 0; // for millisecond timer + int lastSigTime = -1; // for millisecond timer + int zeroSigTime = -1; // for timing incoming events + int device = -1; // for sorting out the bytes by input device + Array* sysexIn; // MIDI Input sysex temporary storage + + // Note on the use of argsExpected and argsLeft for sysexs: + // If argsExpected is -1, then a sysex message is coming in. + // If argsLeft < 0, then the sysex message has not finished comming + // in. If argsLeft == 0 and argsExpected == -1, then the sysex + // has finished coming in and is to be sent to the correct + // location. + + static int count = 0; + if (count != 0) { + std::cerr << "Cannot run this function more than once" << std::endl; + exit(1); + } else { + // allocate space for MIDI messages, each device has a different message + // holding spot in case the messages overlap in the input stream + message = new MidiMessage[MidiInPort_oss::numDevices]; + argsExpected = new int[MidiInPort_oss::numDevices]; + argsLeft = new int[MidiInPort_oss::numDevices]; + + sysexIn = new Array[MidiInPort_oss::numDevices]; + for (int j=0; j= 0) { + argsLeft[device] = argsExpected[device]; + } + + newSigTime = MidiInPort_oss::midiTimer.getTime(); + message[device].time = newSigTime - zeroSigTime; + + if (packet[1] != 0xf7) { + message[device].p0() = packet[1]; + } + message[device].p1() = 0; + message[device].p2() = 0; + message[device].p3() = 0; + + if (packet[1] == 0xf7) { + goto sysex_done; + } + } else if (argsLeft[device]) { // not a command byte coming in + if (message[device].time == 0) { + // store the receipt time of the first message byte + newSigTime = MidiInPort_oss::midiTimer.getTime(); + message[device].time = newSigTime - zeroSigTime; + } + + if (argsExpected[device] < 0) { + // continue processing a sysex message + sysexIn[device].append(packet[1]); + } else { + // handle a message other than a sysex message + if (argsLeft[device] == argsExpected[device]) { + message[device].p1() = packet[1]; + } else { + message[device].p2() = packet[1]; + } + argsLeft[device]--; + } + + // if MIDI message is complete, setup for running status, and + // insert note into proper buffer. + + if (argsExpected[device] >= 0 && !argsLeft[device]) { + + // store parameter data for running status + switch (message[device].p0() & 0xf0) { + case 0xc0: argsLeft[device] = 1; break; + case 0xd0: argsLeft[device] = 1; break; // fix by dan + default: argsLeft[device] = 2; break; + // 0x80 expects two arguments + // 0x90 expects two arguments + // 0xa0 expects two arguments + // 0xb0 expects two arguments + // 0xe0 expects two arguments + } + + lastSigTime = newSigTime; + + sysex_done: // come here when a sysex is completely done + + // insert the MIDI message into the appropriate buffer + // do not insert into buffer if the MIDI input device + // is paused (which can mean closed). Or if the + // pauseQ array is pointing to NULL (which probably means that + // things are about to shut down). + if (MidiInPort_oss::pauseQ != NULL && + MidiInPort_oss::pauseQ[device] == 0) { + if (argsExpected[device] < 0) { + // store the sysex in the MidiInPort_oss + // buffer for sysexs and return the storage + // location: + int sysexlocation = + MidiInPort_oss::installSysexPrivate(device, + sysexIn[device].getBase(), + sysexIn[device].getSize()); + + message[device].p0() = 0xf0; + message[device].p1() = sysexlocation; + + sysexIn[device].setSize(0); // empty the sysex storage + argsExpected[device] = 0; // no run status for sysex + argsLeft[device] = 0; // turn off sysex input flag + } + MidiInPort_oss::midiBuffer[device]->insert( + message[device]); +// if (MidiInPort_oss::callbackFunction != NULL) { +// MidiInPort_oss::callbackFunction(device); +// } + if (MidiInPort_oss::trace[device]) { + std::cout << '[' << std::hex << (int)message[device].p0() + << ':' << std::dec << (int)message[device].p1() + << ',' << (int)message[device].p2() << ']' + << std::flush; + } + message[device].time = 0; + } else { + if (MidiInPort_oss::trace[device]) { + std::cout << '[' << std::hex << (int)message[device].p0() + << 'P' << std::dec << (int)message[device].p1() + << ',' << (int)message[device].p2() << ']' + << std::flush; + } + } + } + } + break; + + default: + break; + } // end switch + } // end while (1) + + // This code is not yet reached, but should be made to do so eventually + + if (message != NULL) { + delete message; + message = NULL; + } + + if (argsExpected != NULL) { + delete argsExpected; + argsExpected = NULL; + } + + if (argsLeft != NULL) { + delete argsLeft; + argsLeft = NULL; + } + + if (sysexIn != NULL) { + delete sysexIn; + sysexIn = NULL; + } + +} + + + +#endif // LINUX + + + +// md5sum: 2008f4a298bef0cd85620a5507815866 - MidiInPort_oss.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInPort_unsupported.cpp b/src/midiio/src/MidiInPort_unsupported.cpp new file mode 100644 index 0000000..584a468 --- /dev/null +++ b/src/midiio/src/MidiInPort_unsupported.cpp @@ -0,0 +1,487 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998 +// Last Modified: Thu Jan 22 22:53:53 GMT-0800 1998 +// Last Modified: Wed Jun 30 11:42:59 PDT 1999 (added sysex capability) +// Filename: ...sig/code/control/MidiInPort/unsupported/MidiInPort_unsupported.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiInPort_unsupported.cpp +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// an unknown sound driver's specific MIDI input methods. +// This class is inherited privately by the MidiInPort class. +// This class is used when there is no MIDI input, so +// that MIDI programs can otherwise be compiled and run. +// This file can also serve as a template for creating +// an OS specific class for MIDI input. +// + +#include "MidiInPort_unsupported.h" +#include +#include + + +#define DEFAULT_INPUT_BUFFER_SIZE (1024) + +// initialized static variables +int MidiInPort_unsupported::numDevices = 0; +int MidiInPort_unsupported::objectCount = 0; +int* MidiInPort_unsupported::openQ = NULL; +int* MidiInPort_unsupported::portObjectCount = NULL; +CircularBuffer* MidiInPort_unsupported::midiBuffer = NULL; +int MidiInPort_unsupported::channelOffset = 0; +int* MidiInPort_unsupported::sysexWriteBuffer = NULL; +Array** MidiInPort_unsupported::sysexBuffers = NULL; + + +////////////////////////////// +// +// MidiInPort_unsupported::MidiInPort_unsupported +// default values: autoOpen = 1 +// + +MidiInPort_unsupported::MidiInPort_unsupported(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiInPort_unsupported::MidiInPort_unsupported(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::~MidiInPort_unsupported +// + +MidiInPort_unsupported::~MidiInPort_unsupported() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + std::cerr << "Error: bad MidiInPort_unsupported object count!: " + << objectCount << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::close +// + +void MidiInPort_unsupported::close(void) { + if (getPortStatus() == 1) { + openQ[getPort()] = 0; + } +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::closeAll +// + +void MidiInPort_unsupported::closeAll(void) { + for (int i=0; i= getNumPorts()) { + std::cerr << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << std::endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + portObjectCount[port]++; +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::setTrace -- if false, then don't print MIDI messages +// to the screen. +// + +int MidiInPort_unsupported::setTrace(int aState) { + int oldtrace = trace; + if (aState == 0) { + trace = 0; + } else { + trace = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::toggleTrace -- switches the state of trace +// Returns the previous value of the trace variable. +// + +void MidiInPort_unsupported::toggleTrace(void) { + trace = !trace; +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::unpause -- enables the Midi input port +// to inserting MIDI messages into the buffer after the +// port is already open. +// + +void MidiInPort_unsupported::unpause(void) { + // nothing +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiInPort_unsupported::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiInPort_unsupported::deinitialize(void) { + int deviceCount = numDevices; + closeAll(); + + if (sysexBuffers != NULL) { + for (int i=0; i*[numDevices]; + + // allocate space for sysexWriteBuffer, the port open/close status + if (sysexWriteBuffer != NULL) delete [] sysexWriteBuffer; + sysexWriteBuffer = new int[numDevices]; + + // allocate space for openQ, the port open/close status + if (openQ != NULL) delete [] openQ; + openQ = new int[numDevices]; + + // allocate space for object count on each port: + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = new int[numDevices]; + + // allocate space for the Midi input buffers + if (midiBuffer != NULL) delete [] midiBuffer; + midiBuffer = new CircularBuffer[numDevices]; + + // initialize the static arrays + for (int i=0; i[128]; + for (int n=0; n<128; n++) { + sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow + sysexBuffers[i][n].setAllocSize(32); + sysexBuffers[i][n].setSize(0); + sysexBuffers[i][n].setGrowth(32); // in case it will ever grow + } + + } +} + + + +////////////////////////////// +// +// MidiInPort_unsupported::setPortStatus +// + +void MidiInPort_unsupported::setPortStatus(int aStatus) { + if (aStatus) { + openQ[getPort()] = 1; + } else { + openQ[getPort()] = 0; + } +} + + +// md5sum: d8b8f65af70a9b3c33e62794c2a4a91e - MidiInPort_unsupported.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInPort_visual.cpp b/src/midiio/src/MidiInPort_visual.cpp new file mode 100644 index 0000000..b4659bf --- /dev/null +++ b/src/midiio/src/MidiInPort_visual.cpp @@ -0,0 +1,1267 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998 +// Last Modified: Wed Jun 30 11:29:51 PDT 1999 (added sysex capability) +// Last Modified: Wed Oct 13 10:18:22 PDT 1999 (midiInUnprepareHeader change) +// Last Modified: Tue Nov 23 15:01:17 PST 1999 (fixed sysex NULL init) +// Filename: ...sig/code/control/MidiInPort/visual/MidiInPort_visual.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiInPort_visual.cpp +// Syntax: C++ +// +// Description: An interface for MIDI input capabilities of +// Windows 95/NT/98 specific MIDI input methods. +// as defined in winmm.lib. This class is inherited +// privately by the MidiInPort class. +// + +#ifdef VISUAL + + +#include "MidiInPort_visual.h" + +#include +#include + +#include + + +// initialized static variables +int MidiInPort_visual::numDevices = 0; +int MidiInPort_visual::objectCount = 0; +int* MidiInPort_visual::openQ = NULL; +int* MidiInPort_visual::inrunningQ = NULL; +int* MidiInPort_visual::portObjectCount = NULL; +HMIDIIN* MidiInPort_visual::device = NULL; +MIDIHDR** MidiInPort_visual::sysexDriverBuffer1 = NULL; +MIDIHDR** MidiInPort_visual::sysexDriverBuffer2 = NULL; +int* MidiInPort_visual::sysexDBnumber = NULL; +HANDLE* MidiInPort_visual::hMutex = NULL; +CircularBuffer* MidiInPort_visual::midiBuffer = NULL; +int MidiInPort_visual::channelOffset = 0; +int* MidiInPort_visual::sysexWriteBuffer = NULL; +Array** MidiInPort_visual::sysexBuffers = NULL; +int* MidiInPort_visual::sysexStatus = NULL; + + +////////////////////////////// +// +// MidiInPort_visual::MidiInPort_visual +// default values: autoOpen = 1 +// + +MidiInPort_visual::MidiInPort_visual(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + trace = 0; + port = -1; + setPort(0); +} + + +MidiInPort_visual::MidiInPort_visual(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + trace = 0; + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::~MidiInPort_visual +// + +MidiInPort_visual::~MidiInPort_visual() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + cerr << "Error: bad MidiInPort_visual object count!: " + << objectCount << endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::clearSysex -- clears the data from a sysex +// message and sets the allocation size to the default size (of 32 +// bytes). +// + +void MidiInPort_visual::clearSysex(int buffer) { + buffer = 0x7f | buffer; // limit buffer range from 0 to 127 + + if (getPort() == -1) { + return; + } + + sysexBuffers[getPort()][buffer].setSize(0); + if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) { + // shrink the storage buffer's size if necessary + sysexBuffers[getPort()][buffer].setAllocSize(32); + } +} + + +void MidiInPort_visual::clearSysex(void) { + // clear all sysex buffers + for (int i=0; i<128; i++) { + clearSysex(i); + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::close +// + +void MidiInPort_visual::close(void) { + if (getPort() == -1) { + return; + } + if (getPortStatus() == 1 && device[getPort()] != NULL) { + midiInReset(device[getPort()]); + midiInClose(device[getPort()]); + uninstallSysexStuff(device[getPort()], port); + openQ[getPort()] = 0; + inrunningQ[getPort()] = 0; + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::closeAll +// + +void MidiInPort_visual::closeAll(void) { + for (int i=0; i getNumPorts()) { + cerr << "Error invalid index for getName: " << i << endl; + exit(1); + } + + midiInGetDevCaps(i, &inputCapabilities, sizeof(MIDIINCAPS)); + + return inputCapabilities.szPname; +} + + + +////////////////////////////// +// +// MidiInPort_visual::getNumPorts -- returns the number of available +// ports for MIDI input +// + +int MidiInPort_visual::getNumPorts(void) { + return midiInGetNumDevs(); +} + + + +////////////////////////////// +// +// MidiInPort_visual::getPort -- returns the port to which this +// object belongs (as set with the setPort function). +// + +int MidiInPort_visual::getPort(void) { + return port; +} + + + +////////////////////////////// +// +// MidiInPort_visual::getPortStatus -- 0 if closed, 1 if open, 2 if +// specifically not connected to any MIDI port. +// + +int MidiInPort_visual::getPortStatus(void) { + if (getPort() == -1) { + return 2; + } + + if (openQ[getPort()] == 1) { + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::getSysex -- returns the sysex message contents +// of a given buffer. You should check to see that the size is +// non-zero before looking at the data. The data pointer will +// be NULL if there is no data in the buffer. +// + +uchar* MidiInPort_visual::getSysex(int buffer) { + buffer &= 0x7f; // limit the buffer access to indices 0 to 127. + + if (getPort() == -1) { + return NULL; + } + + if (sysexBuffers[getPort()][buffer].getSize() < 2) { + return NULL; + } else { + return sysexBuffers[getPort()][buffer].getBase(); + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::getSysexSize -- returns the sysex message byte +// count of a given buffer. Buffers are in the range from +// 0 to 127. +// + +int MidiInPort_visual::getSysexSize(int buffer) { + if (getPort() == -1) { + return 0; + } else { + return sysexBuffers[getPort()][buffer & 0x7f].getSize(); + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::getTrace -- returns true if trace is on or false +// if trace is off. if trace is on, then prints to standard +// output the Midi message received. +// + +int MidiInPort_visual::getTrace(void) { + return trace; +} + + + +////////////////////////////// +// +// MidiInPort_visual::insert +// + +void MidiInPort_visual::insert(const MidiMessage& aMessage) { + waitForMutex(); + if (getPort() == -1) { + // do nothing + } else { + midiBuffer[getPort()].insert(aMessage); + } + releaseMutex(); +} + + + +////////////////////////////// +// +// MidiInPort_visual::installSysex -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_visual::installSysex(uchar* anArray, int aSize) { + return installSysexPrivate(getPort(), anArray, aSize); +} + + + +////////////////////////////// +// +// MidiInPort_visual::installSysexPrivate -- put a sysex message into a +// buffer. The buffer number that it is put into is returned. +// + +int MidiInPort_visual::installSysexPrivate(int port, uchar* anArray, int aSize){ + if (port == -1) { + return -1; + } + + // choose a buffer to install sysex data into: + int bufferNumber = sysexWriteBuffer[port]; + sysexWriteBuffer[port]++; + if (sysexWriteBuffer[port] >= 128) { + sysexWriteBuffer[port] = 0; + } + + // copy contents of sysex message into the chosen buffer + sysexBuffers[port][bufferNumber].setSize(aSize); + uchar* dataptr = sysexBuffers[port][bufferNumber].getBase(); + uchar* indataptr = anArray; + for (int i=0; i= getNumPorts()) { + cerr << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + if (port != -1) { + portObjectCount[port]++; + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::setTrace -- if false, then don't print MIDI messages +// to the screen. +// + +int MidiInPort_visual::setTrace(int aState) { + int oldtrace = trace; + if (aState == 0) { + trace = 0; + } else { + trace = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiInPort_visual::toggleTrace -- switches the state of trace +// Returns the previous value of the trace variable. +// + +void MidiInPort_visual::toggleTrace(void) { + trace = !trace; +} + + + +////////////////////////////// +// +// MidiInPort_visual::unpause -- enables the Midi input port +// to inserting MIDI messages into the buffer after the +// port is already open. +// + +void MidiInPort_visual::unpause(void) { + if (getPort() == -1) { + return; + } + + if (openQ[getPort()]) { + if (inrunningQ[getPort()] == 0) { + midiInStart(device[getPort()]); + inrunningQ[getPort()] = 1; + } + } +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiInPort_visual::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiInPort_visual::deinitialize(void) { + int num = numDevices; + + closeAll(); + + if (sysexBuffers != NULL) { + for (int i=0; i[numDevices]; + + // allocate space for the MIDI sysex buffer indices + if (sysexWriteBuffer != NULL) delete [] sysexWriteBuffer; + sysexWriteBuffer = new int[numDevices]; + + // allocate space for the sysex MIM_LONGDATA message tracking + if (sysexStatus != NULL) delete [] sysexStatus; + sysexStatus = new int[numDevices]; + + // allocate space for sysex buffers + if (sysexBuffers != NULL) { + cout << "Error: memory leak on sysex buffers initialization" << endl; + exit(1); + } + sysexBuffers = new Array*[numDevices]; + + // allocate system exclusive buffers for MIDI driver + if (sysexDriverBuffer1 != NULL) { + cout << "Error: memory leak on sysex buffer for drivers creation" << endl; + exit(1); + } + sysexDriverBuffer1 = new MIDIHDR*[numDevices]; + for (i=0; i[128]; + for (int n=0; n<128; n++) { + sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow + sysexBuffers[i][n].setAllocSize(32); + sysexBuffers[i][n].setSize(0); + sysexBuffers[i][n].setGrowth(32); // in case it will ever grow + } + + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::installSysexStuff -- install all the mess that +// a MIDIIN structure needs in order to receive system exclusives. +// + +void MidiInPort_visual::installSysexStuff(HMIDIIN dev, int port) { + if (sysexDriverBuffer1 != NULL) { + if (sysexDriverBuffer1[port] != NULL) { + // some memory leaks here + delete sysexDriverBuffer1[port]; + sysexDriverBuffer1[port] = NULL; + } + } + if (sysexDriverBuffer2 != NULL) { + if (sysexDriverBuffer2[port] != NULL) { + // some memory leaks here + delete sysexDriverBuffer2[port]; + sysexDriverBuffer2[port] = NULL; + } + } + + // allocate space for Drivers sysex byte buffer + sysexDriverBuffer1[port] = (LPMIDIHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE | + GMEM_SHARE, sizeof(MIDIHDR))); + sysexDriverBuffer2[port] = (LPMIDIHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE | + GMEM_SHARE, sizeof(MIDIHDR))); + + if (sysexDriverBuffer1[port] == NULL) { + cout << "Error: could not allocate sysex driver's buffer" << endl; + exit(1); + } + + if (sysexDriverBuffer2[port] == NULL) { + cout << "Error: could not allocate sysex driver's buffer" << endl; + exit(1); + } + + // allocate buffer inside of sysexDriverBuffer + sysexDriverBuffer1[port]->lpData = (LPSTR)GlobalLock(GlobalAlloc( + GMEM_MOVEABLE | GMEM_SHARE, (DWORD)1024)); + sysexDriverBuffer2[port]->lpData = (LPSTR)GlobalLock(GlobalAlloc( + GMEM_MOVEABLE | GMEM_SHARE, (DWORD)1024)); + + if (sysexDriverBuffer1[port]->lpData == NULL) { + cout << "Error: there was not enought space to allocate sysex buffer" + << endl; + // leaking memory here + exit(1); + } + + if (sysexDriverBuffer2[port]->lpData == NULL) { + cout << "Error: there was not enought space to allocate sysex buffer" + << endl; + // leaking memory here + exit(1); + } + + + // setup other sysexDriverBuffer data fields + sysexDriverBuffer1[port]->dwBufferLength = 1024; // total size of buffer + sysexDriverBuffer1[port]->dwBytesRecorded = 0L; // number of byte in buffer + sysexDriverBuffer1[port]->dwFlags = 0L; // initialize flags + sysexDriverBuffer1[port]->dwUser = 0L; // userdata: used for sysex time + + // setup other sysexDriverBuffer data fields + sysexDriverBuffer2[port]->dwBufferLength = 1024; // total size of buffer + sysexDriverBuffer2[port]->dwBytesRecorded = 0L; // number of byte in buffer + sysexDriverBuffer2[port]->dwFlags = 0L; // initialize flags + sysexDriverBuffer2[port]->dwUser = 0L; // userdata: used for sysex time + + // prepare the header + int status = midiInPrepareHeader(device[port], sysexDriverBuffer1[port], + sizeof(MIDIHDR)); + + if (status != 0) { + cout << "Error preparing sysex buffer number: " << port << endl; + // leaking some memory here? + exit(1); + } + + // prepare the header + status = midiInPrepareHeader(device[port], sysexDriverBuffer2[port], + sizeof(MIDIHDR)); + + if (status != 0) { + cout << "Error preparing sysex buffer number: " << port << endl; + // leaking some memory here? + exit(1); + } + + // add the sysex buffer to the driver + status = midiInAddBuffer(device[port], sysexDriverBuffer1[port], + sizeof(MIDIHDR)); + + if (status != 0) { + cout << "Error adding sysex buffer to driver: " << port << endl; + // leaking some memory here? + exit(1); + } + + status = midiInAddBuffer(device[port], sysexDriverBuffer2[port], + sizeof(MIDIHDR)); + + if (status != 0) { + cout << "Error adding sysex buffer to driver: " << port << endl; + // leaking some memory here? + exit(1); + } + +} + + + +////////////////////////////// +// +// MidiInPort_visual::uninstallSysexStuff -- uninstalls all the mess that +// a MIDIIN structure needs in order to receive system exclusives. +// + +void MidiInPort_visual::uninstallSysexStuff(HMIDIIN dev, int port) { + if (port == -1) { + return; + } + // unprepare the headers + midiInUnprepareHeader(device[port], sysexDriverBuffer1[port], + sizeof(MIDIHDR)); + midiInUnprepareHeader(device[port], sysexDriverBuffer2[port], + sizeof(MIDIHDR)); + + // deallocate buffer inside of sysexDriverBuffer + /* Following code caused problems: perhaps lpData was deleted by driver + delete [] sysexDriverBuffer1[port]->lpData; + sysexDriverBuffer1[port]->lpData = NULL; + delete [] sysexDriverBuffer2[port]->lpData; + sysexDriverBuffer2[port]->lpData = NULL; + */ + + // deallocate space for Drivers sysex byte buffer + delete sysexDriverBuffer1[port]; + delete sysexDriverBuffer2[port]; + sysexDriverBuffer1[port] = NULL; + sysexDriverBuffer2[port] = NULL; +} + + + +////////////////////////////// +// +// MidiInPort_visual::releaseMutex +// + +void MidiInPort_visual::releaseMutex(void) { +/* int flag = */ ReleaseMutex(hMutex[getPort()]); +/* + if (flag != 0) { + cerr << "Error relasing mutex in MIDI input; flag was: " << flag << endl; + } +*/ +} + + + +////////////////////////////// +// +// MidiInPort_visual::setPortStatus +// + +void MidiInPort_visual::setPortStatus(int aStatus) { + if (getPort() == -1) { + return; + } + + if (aStatus) { + openQ[getPort()] = 1; + } else { + openQ[getPort()] = 0; + } +} + + + +////////////////////////////// +// +// MidiInPort_visual::waitForMutex +// + +void MidiInPort_visual::waitForMutex(void) { +/* + DWORD mutexResult = WaitForSingleObject(hMutex[getPort()], 5000L); + if (mutexResult != WAIT_OBJECT_0) { + cerr << "Error waiting for mutex in MIDI input" << endl; + } +*/ +} + + + +/////////////////////////////////////////////////////////////////////////// + + +////////////////////////////// +// +// midiInputCallback -- the function the MIDI input driver calls when +// it has a message from the Midi in cable ready +// + +void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus, + DWORD instancePtr, DWORD midiMessage, DWORD timestamp) { + static MidiMessage newMessage; + + switch (inputStatus) { + case MIM_MOREDATA: + // There is more data waiting at the device. + // If this case is exists, then that means that the MIDI + // device is too slow and some data was lost. + // Windows sends a MIM_MOREDATA event only if you specify + // the MIDI_IO_STATUS flag to midiInOpen(). + + // no break; + case MIM_DATA: + + // One regular (non sysex) message has been completely + // received. + + // ignore the Yamaha Active Sensing command and MIDI time clock + // at least for now. + if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) { + break; + } + + newMessage.time = timestamp; + newMessage.data = midiMessage; + ((MidiInPort_visual*)instancePtr)->insert(newMessage); + if (((MidiInPort_visual*)instancePtr)->getTrace()) { + cout << "[" << hex << (int)newMessage.command() << dec + << ":" << (int)newMessage.p1() << "," + << (int)newMessage.p2() << "]"; + cout.flush(); + } + break; + + case MIM_LONGDATA: + { + // A sysex or part of a sysex message is coming in. + // The timestamp variable contains a pointer to a + // MIDIHDR pointer + + MIDIHDR* midiheader = (MIDIHDR*)midiMessage; + int dataCount = midiheader->dwBytesRecorded; + char* data = midiheader->lpData; + int port = ((MidiInPort_visual*)instancePtr)->getPort(); + if (port == -1) { + break; + } + int* sysexStatus = ((MidiInPort_visual*)instancePtr)->sysexStatus; +// MIDIHDR** sysexDriverBuffer = ((MidiInPort_visual*)instancePtr)-> +// sysexDriverBuffer; + HMIDIIN devicex = ((MidiInPort_visual*)instancePtr)->device[port]; + + if (dataCount == 0) { + // can't handle a zero-length sysex + break; + } + + // step 1: determine if this is the first part of the sysex + // message or a continuation + int continuation = 0; + if (data[0] == (char)0xf0) { + continuation = 0; + if (sysexStatus[port] != -1) { + cout << "Error: there is another sysex command being " + "received on port " << port << endl; + exit(1); + } + } else { + if (sysexStatus[port] == -1) { + cout << "Error: no sysex command is being " + "received on port " << port << endl; + if (data[0] < 128) { + cout << "First byte is: " << dec << (int)data[0] << endl; + } else { + cout << "First byte is: " << hex << (int)data[0] << endl; + } + if (data[1] < 128) { + cout << "Second byte is: " << dec << (int)data[1] << endl; + } else { + cout << "Second byte is: " << hex << (int)data[1] << endl; + } + + exit(1); + } + continuation = 1; + } + + // step 2: if continuing, add the data to the preallocated + // sysex buffer, otherwise, get a new buffer location + int buffer = -1; + if (continuation) { + buffer = sysexStatus[port]; + if (buffer < 0 || buffer > 127) { + cout << "Sysex buffer was out of range: " << buffer << endl; + } + for (int i=0; i + sysexBuffers[port][buffer].append(datum); + if (datum == 0xf7) { + for (int k=i; kdwBytesRecorded = dataCount - i - 1; + + goto insert_sysex_message; + } + } + } else { // if not a continuation of a sysex event + buffer = ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port]; + ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port]++; + if (buffer == 127) { + ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port] = 0; + } + + ((MidiInPort_visual*)instancePtr)-> + sysexBuffers[port][buffer].setSize(0); + for (int j=0; j + sysexBuffers[port][buffer].append(datum); + if (datum == 0xf7) { + for (int k=j; kinsert(newMessage); + if (((MidiInPort_visual*)instancePtr)->getTrace()) { + cout << "[" << hex << (int)newMessage.command() << dec + << ":" << (int)newMessage.p1() << "," + << (int)newMessage.p2() << "]"; + cout.flush(); + } + + } // end of local variable range + break; + + case MIM_ERROR: + // An invalid regular MIDI message was received. + + break; + + case MIM_LONGERROR: + { + // An invalid sysex MIDI message was received. + + // if a sysex message was continuing from a previous part, + // then kill that message. + + int port = ((MidiInPort_visual*)instancePtr)->getPort(); + if (port == -1) { + break; + } + int buffer = ((MidiInPort_visual*)instancePtr)->sysexStatus[port]; + if (buffer != -1) { + ((MidiInPort_visual*)instancePtr)-> + sysexBuffers[port][buffer].setSize(0); + ((MidiInPort_visual*)instancePtr)->sysexStatus[port] = -1; + } + + HMIDIIN devicex = ((MidiInPort_visual*)instancePtr)->device[port]; + MIDIHDR* midiheader = (MIDIHDR*)midiMessage; + + // recycle the MIDI input buffer for the driver + midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR)); + int status = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR)); + if (status != MMSYSERR_NOERROR) { + cout << "Error when calling midiInAddBuffer" << endl; + exit(1); + } + + + break; + } + default: ; + // case MIM_OPEN: // MIDI device is opening + // case MIM_CLOSE: // MIDI device is closing + } +} + + + +#endif // VISUAL + + +// md5sum: db55d9f375b86f54c0c8340547c5701f - MidiInPort_visual.cpp =css= 20030102 diff --git a/src/midiio/src/MidiInput.cpp b/src/midiio/src/MidiInput.cpp new file mode 100644 index 0000000..93fce87 --- /dev/null +++ b/src/midiio/src/MidiInput.cpp @@ -0,0 +1,224 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: 18 December 1997 +// Last Modified: Sun Jan 25 15:31:49 GMT-0800 1998 +// Last Modified: Thu Apr 27 17:56:03 PDT 2000 (added scale function) +// Filename: ...sig/code/control/MidiInput/MidiInput.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiInput.cpp +// Syntax: C++ +// +// Description: A higher-level MIDI input interface than the +// MidiInPort class. Can be used to allow multiple +// objects to share a single MIDI input stream, or +// to fake a MIDI input connection. +// + +#include "MidiInput.h" +#include +#include + + +////////////////////////////// +// +// MidiInput::MidiInput -- opens the specified MIDI input device and +// sets the size of the input buffer. +// + +MidiInput::MidiInput(void) : MidiInPort() { + orphanBuffer = NULL; +} + + +MidiInput::MidiInput(int aPort, int autoOpen) : MidiInPort(aPort, autoOpen) { + orphanBuffer = NULL; +} + + + +////////////////////////////// +// +// MidiInput::~MidiInput +// + +MidiInput::~MidiInput() { + if (orphanBuffer != NULL) { + delete orphanBuffer; + orphanBuffer = NULL; + } +} + + + +////////////////////////////// +// +// MidiInput::getBufferSize +// + +int MidiInput::getBufferSize(void) { + if (isOrphan()) { + return orphanBuffer->getSize(); + } else { + return MidiInPort::getBufferSize(); + } +} + + + +////////////////////////////// +// +// MidiInput::getCount +// + +int MidiInput::getCount(void) { + if (isOrphan()) { + return orphanBuffer->getCount(); + } else { + return MidiInPort::getCount(); + } +} + + + +////////////////////////////// +// +// MidiInput::extract +// + +MidiMessage MidiInput::extract(void) { + if (isOrphan()) { + return orphanBuffer->extract(); + } else { + return MidiInPort::extract(); + } +} + + + +////////////////////////////// +// +// fscale -- converts a value in the range from 0 to 127 +// into a number in a new range. For example the value +// 64 scaled to the range from 0 to 2 would be 1. +// + +double MidiInput::fscale(int value, double min, double max) { + return value >= 127 ? max : (value/127.0*(max-min)+min); +} + + + +////////////////////////////// +// +// fscale14 -- converts a value in the range from 0 to 2^15-1 +// into a number in a new range. +// + +double MidiInput::fscale14(int value, double min, double max) { + return value >= 16383 ? max : (value/16383.0*(max-min)+min); +} + + + +////////////////////////////// +// +// MidiInput::insert +// + +void MidiInput::insert(const MidiMessage& aMessage) { + if (isOrphan()) { + orphanBuffer->insert(aMessage); + } else { + MidiInPort::insert(aMessage); + } +} + + + +////////////////////////////// +// +// MidiInput::isOrphan +// + +int MidiInput::isOrphan(void) const { + if (orphanBuffer == NULL) { + return 0; + } else { + return 1; + } +} + + + +////////////////////////////// +// +// MidiInput::makeOrphanBuffer +// default value: aSize = 1024 +// + +void MidiInput::makeOrphanBuffer(int aSize) { + if (!isOrphan()) { + if (orphanBuffer == NULL) { + delete orphanBuffer; + orphanBuffer = NULL; + } + orphanBuffer = new CircularBuffer(aSize); + } +} + + + +////////////////////////////// +// +// MidiInput::removeOrphanBuffer +// + +void MidiInput::removeOrphanBuffer(void) { + if (isOrphan()) { + delete orphanBuffer; + orphanBuffer = NULL; + } +} + + + +////////////////////////////// +// +// scale -- converts a value in the range from 0 to 127 +// into a number in a new range. For example the value +// 64 scaled to the range from 0 to 2 would be 1. +// + +int MidiInput::scale(int value, int min, int max) { + return value >= 127 ? max : (int)(value/127.0*(max-min+1)+min); +} + + + +////////////////////////////// +// +// scale14 -- converts a value in the range from 0 to 2^15-1 +// into a number in a new range. +// + +int MidiInput::scale14(int value, int min, int max) { + return value >= 16383 ? max : (int)(value/16383.0*(max-min+1)+min); +} + + + +////////////////////////////// +// +// MidiInput::setBufferSize +// + +void MidiInput::setBufferSize(int aSize) { + if (isOrphan()) { + orphanBuffer->setSize(aSize); + } else { + MidiInPort::setBufferSize(aSize); + } +} + + + +// md5sum: 826d403708263eaf0089b4742179c58c - MidiInput.cpp =css= 20030102 diff --git a/src/midiio/src/MidiMessage.cpp b/src/midiio/src/MidiMessage.cpp new file mode 100644 index 0000000..5f3df19 --- /dev/null +++ b/src/midiio/src/MidiMessage.cpp @@ -0,0 +1,406 @@ +// +// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: 19 December 1997 +// Last Modified: Fri Jan 23 00:26:12 GMT-0800 1998 +// Last Modified: Sun Sep 20 12:17:26 PDT 1998 +// Last Modified: Mon Oct 15 14:29:12 PDT 2001 (added is_note functions) +// Filename: ...sig/src/sigControl/MidiMessage.cpp +// Web Address: http://sig.sapp.org/src/sigControl/MidiMessage.cpp +// Syntax: C++ +// +// Description: A structure for handling MIDI input messages. +// This class stores a time stamp plus up to +// four MIDI message bytes. System Exclusive messages +// are stored in a separate array in the MidiInPort +// class, and their storage index is passed to the +// user through a MIDI message for later extraction +// of the full sysex message. +// + +#include "MidiMessage.h" + + +////////////////////////////// +// +// MidiMessage::MidiMessage +// + +MidiMessage::MidiMessage(void) { + // no initialization. Note that the default contents are undefined. +} + + +// default value aTime = 0 +MidiMessage::MidiMessage(int aCommand, int aP1, int aP2, int aTime) { + time = aTime; + command() = (uchar)aCommand; + p1() = (uchar)aP1; + p2() = (uchar)aP2; +} + + +MidiMessage::MidiMessage(const MidiMessage& aMessage) { + time = aMessage.time; + data = aMessage.data; +} + + + +////////////////////////////// +// +// MidiMessage::~MidiMessage -- Destructor. +// + +MidiMessage::~MidiMessage() { + // do nothing +} + + + +////////////////////////////// +// +// MidiMessage::command -- returns the MIDI command byte +// + +uchar& MidiMessage::command(void) { + return p0(); +} + + + +////////////////////////////// +// +// MidiMessage::operator= -- defines how objects are to be copied +// + +MidiMessage& MidiMessage::operator=(const MidiMessage& aMessage) { + time = aMessage.time; + data = aMessage.data; + return *this; +} + + + +////////////////////////////// +// +// MidiMessage::operator[] -- access to byte data +// can only access index 0 to 3, other number will be +// chopped. +// + +uchar& MidiMessage::operator[](int index) { + return *(((uchar*)&data)+(index & 0x3)); +} + + + +////////////////////////////// +// +// MidiMessage::p0 -- returns the command byte of the +// midi message. Same as the command() function. +// + +uchar& MidiMessage::p0(void) { + return *(((uchar*)&data)+0); +} + + + +////////////////////////////// +// +// MidiMessage::p1 -- returns the first parameter of the +// midi message. Valid if the command requires a parameter. +// + +uchar& MidiMessage::p1(void) { + return *(((uchar*)&data)+1); +} + + + +////////////////////////////// +// +// MidiMessage::p2 -- returns the second parameter of the +// midi message. Valid if the command requires two parameters. +// + +uchar& MidiMessage::p2(void) { + return *(((uchar*)&data)+2); +} + + +////////////////////////////// +// +// MidiMessage::p3 -- returns the third parameter of the +// midi message. Valid if the command requires three parameters +// (but none of the MIDI command do). +// + +uchar& MidiMessage::p3(void) { + return *(((uchar*)&data)+3); +} + + + +////////////////////////////// +// +// MidiMessage:getArgCount -- +// + +int MidiMessage::getArgCount(void) const { + return getParameterCount(); +} + + + +////////////////////////////// +// +// MidiMessage::getParameterCount -- returns the number +// of valid parameters for the assiciated MIDI command +// stored in p0. Returns -1 if MIDI command is invalid, +// or the number of valid parameters is unknown. +// + +int MidiMessage::getParameterCount(void) const { + int output = -1; + switch (*(((uchar*)&data)+0) & 0xf0) { + case 0x80: // note-off + case 0x90: // note-on + case 0xa0: // aftertouch + case 0xb0: // continuous controller + case 0xe0: // pitch wheel + output = 2; + break; + case 0xc0: // patch change + case 0xd0: // channel pressure + output = 1; + break; + case 0xf0: + switch (*(((uchar*)&data)+0)) { + // System Common Messages + case 0xf0: return -1; // variable for sysex + case 0xf1: return 1; // MIDI Time Code Quarter Frame + case 0xf2: return 2; // Song Position Pointer + case 0xf3: return 1; // Song Select + case 0xf4: return 0; // Undefined + case 0xf5: return 0; // Undefined + case 0xf6: return 0; // Tune Request + case 0xf7: return 0; // End of System exclusive + // System Real-Time Messages + case 0xf8: return 0; // Timing Clock + case 0xf9: return 0; // Undefined + case 0xfa: return 0; // Start + case 0xfb: return 0; // Continue + case 0xfc: return 0; // Stop + case 0xfd: return 0; // Undefined + case 0xfe: return 0; // Active Sensing + case 0xff: return 0; // System Reset + } + return -1; + break; + default: // don't know or invalid command + output = -1; + break; + } + + return output; +} + + + +////////////////////////////// +// +// MidiMessage::getCommand -- same as command(). +// + +uchar MidiMessage::getCommand(void) const { + return getP0(); +} + + + +////////////////////////////// +// +// MidiMessage::getP0 -- same as p0(). +// + +uchar MidiMessage::getP0(void) const { + return *(((uchar*)&data)+0); +} + + + +////////////////////////////// +// +// MidiMessage::getP1 -- same as p1(). +// + +uchar MidiMessage::getP1(void) const { + return *(((uchar*)&data)+1); +} + + + +////////////////////////////// +// +// MidiMessage::getP2 -- same as p2(). +// + +uchar MidiMessage::getP2(void) const { + return *(((uchar*)&data)+2); +} + + + +////////////////////////////// +// +// MidiMessage::getP3 -- same as p3(). +// + +uchar MidiMessage::getP3(void) const { + return *(((uchar*)&data)+3); +} + + + +////////////////////////////// +// +// MidiMessage::setCommand -- same as command(). +// + +void MidiMessage::setCommand(uchar aCommand) { + command() = aCommand; +} + + + +////////////////////////////// +// +// MidiMessage::setData -- sets the message bytes +// default values: aP1 = 0, aP2 = 0, aP3 = 0. +// + +void MidiMessage::setData(uchar aCommand, uchar aP1, uchar aP2, uchar aP3) { + setCommand(aCommand); + setP1(aP1); + setP2(aP2); + setP3(aP3); +} + + + +////////////////////////////// +// +// MidiMessage::setP0 -- same as p0(). +// + +void MidiMessage::setP0(uchar aP0) { + p0() = aP0; +} + + + +////////////////////////////// +// +// MidiMessage::setP1 -- same as p1(). +// + +void MidiMessage::setP1(uchar aP1) { + p1() = aP1; +} + + + +////////////////////////////// +// +// MidiMessage::setP2 -- same as p2(). +// + +void MidiMessage::setP2(uchar aP2) { + p2() = aP2; +} + + + +////////////////////////////// +// +// MidiMessage::setP3 -- same as p3(). +// + +void MidiMessage::setP3(uchar aP3) { + p3() = aP3; +} + + + +////////////////////////////// +// +// MidiMessage::is_note -- Returns true if the MIDI command is 0x80 or 0x90. +// + +int MidiMessage::is_note(void) { + if ((p0() & 0xf0) == 0x90) { // note-on or note-off + return 1; + } else if ((p0() & 0xf0) == 0x80) { // note-off + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiMessage::is_note_on -- Returns true if the MIDI command is a note +// on message (0x90 series with p2() > 0). +// + +int MidiMessage::is_note_on(void) { + if (((p0() & 0xf0) == 0x90) && p2() > 0) { + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiMessage::is_note_off -- Returns true if the MIDI command is a note +// off message (0x80 series or 0x90 series with p2() == 0). +// + +int MidiMessage::is_note_off(void) { + if ((p0() & 0xf0) == 0x80) { + return 1; + } else if (((p0() & 0xf0) == 0x90) && (p2() == 0)) { + return 1; + } else { + return 0; + } +} + + +/////////////////////////////////////////////////////////////////////////// + +////////////////////////////// +// +// operator<< MidiMessage +// + +std::ostream& operator<<(std::ostream& out, MidiMessage& aMessage) { + out << "(" << aMessage.time << ") " + << std::hex << (int)aMessage.getP0() << ": "; + for (int i=1; i<=aMessage.getArgCount(); i++) { + out << std::dec << (int)aMessage[i] << ' '; + } + + return out; +} + + + +// md5sum: 487f0fddeb8db20d81f9c039e2a460c9 - MidiMessage.cpp =css= 20030102 diff --git a/src/midiio/src/MidiOutPort_alsa.cpp b/src/midiio/src/MidiOutPort_alsa.cpp new file mode 100644 index 0000000..07f4e5d --- /dev/null +++ b/src/midiio/src/MidiOutPort_alsa.cpp @@ -0,0 +1,469 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Wed May 10 16:16:21 PDT 2000 +// Last Modified: Sun May 14 20:44:12 PDT 2000 +// Filename: ...sig/code/control/MidiOutPort/alsa/MidiOutPort_alsa.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiOutPort_alsa.cpp +// Syntax: C++ +// +// Description: Operating-System specific interface for +// basic MIDI output capabilities in Linux using +// ALSA sound drivers. Privately inherited by the +// MidiOutPort class via the MidiOutPort_alsa class. +// + +#if defined(LINUX) && defined(ALSA) + +#include "MidiOutPort_alsa.h" +#include +#include + +// initialized static variables +int MidiOutPort_alsa::numDevices = 0; +int MidiOutPort_alsa::objectCount = 0; +int* MidiOutPort_alsa::portObjectCount = NULL; +int MidiOutPort_alsa::channelOffset = 0; +int* MidiOutPort_alsa::trace = NULL; +std::ostream* MidiOutPort_alsa::tracedisplay = &std::cout; + + + +////////////////////////////// +// +// MidiOutPort_alsa::MidiOutPort_alsa +// default values: autoOpen = 1 +// + +#include + +MidiOutPort_alsa::MidiOutPort_alsa(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiOutPort_alsa::MidiOutPort_alsa(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::~MidiOutPort_alsa -- +// + +MidiOutPort_alsa::~MidiOutPort_alsa() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + std::cout << "Error: bad MidiOutPort object count!: " << objectCount << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::close -- +// + +void MidiOutPort_alsa::close(void) { + Sequencer_alsa::closeOutput(getPort()); +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::closeAll -- +// + +void MidiOutPort_alsa::closeAll(void) { + int i; + for (i=0; i= getNumPorts()) { + std::cout << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << std::endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + if (port != -1) { + portObjectCount[port]++; + } +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::setTrace -- if false, then won't print +// Midi messages to standard output. +// + +int MidiOutPort_alsa::setTrace(int aState) { + if (getPort() == -1) return -1; + + int oldtrace = trace[getPort()]; + if (aState == 0) { + trace[getPort()] = 0; + } else { + trace[getPort()] = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::sysex -- send a system exclusive message. +// The message must start with a 0xf0 byte and end with +// a 0xf7 byte. +// + +int MidiOutPort_alsa::sysex(uchar* array, int size) { + if (getPort() == -1) { + return 2; + } + + if (size == 0 || array[0] != 0xf0 || array[size-1] != 0xf7) { + std::cout << "Error: invalid sysex message" << std::endl; + exit(1); + } + + return rawsend(array,size); +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::toggleTrace -- +// + +void MidiOutPort_alsa::toggleTrace(void) { + if (getPort() == -1) return; + + trace[getPort()] = !trace[getPort()]; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiOutPort_alsa::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_alsa::deinitialize(void) { + closeAll(); + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = NULL; + if (trace != NULL) delete [] trace; + trace = NULL; +} + + + +////////////////////////////// +// +// MidiOutPort_alsa::initialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_alsa::initialize(void) { + // get the number of ports + numDevices = getNumOutputs(); + if (getNumPorts() <= 0) { + std::cout << "Warning: no MIDI output devices" << std::endl; + portObjectCount = NULL; + trace = NULL; + } else { + // allocate space for object count on each port: + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = new int[numDevices]; + + // allocate space for trace variable for each port: + if (trace != NULL) delete [] trace; + trace = new int[numDevices]; + + // initialize the static arrays + for (int i=0; i +// Creation Date: Sun May 14 20:58:32 PDT 2000 +// Last Modified: Thu May 18 23:37:11 PDT 2000 +// Last Modified: Sat Nov 2 20:40:01 PST 2002 (added ALSA OSS def) +// Filename: ...sig/code/control/MidiOutPort_linux/MidiOutPort_linux.cpp +// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_linux.cpp +// Syntax: C++ +// +// Description: Linux MIDI output class which detects which +// type of MIDI drivers are available: either +// ALSA or OSS. +// + +#ifdef LINUX +#if defined(ALSA) && defined(OSS) + +#include "MidiOutPort_linux.h" +#include +#include +#include + + +// initialize static members +int MidiOutPort_linux::objectCount = 0; +int MidiOutPort_linux::current = UNKNOWN_MIDI_SELECT; // MIDI out selected +int MidiOutPort_linux::alsaQ = 0; // boolean for if ALSA is present +int MidiOutPort_linux::ossQ = 0; // boolean for if OSS is present + +MidiOutPort_oss *MidiOutPort_linux::oss_output = NULL; +MidiOutPort_alsa *MidiOutPort_linux::alsa_output = NULL; +MidiOutPort_unsupported *MidiOutPort_linux::unknown_output = NULL; + + +MidiOutPort_linux::MidiOutPort_linux(void) { + if (objectCount == 0) { + determineDrivers(); + } else if (objectCount < 0) { + cout << "Error: unusual MidiOutPort_linux object count" << endl; + exit(1); + } + + objectCount++; +} + +MidiOutPort_linux::MidiOutPort_linux(int aPort, int autoOpen = 1) { + determineDrivers(); + setAndOpenPort(aPort); +} + +MidiOutPort_linux::~MidiOutPort_linux() { + objectCount--; + if (objectCount == 0) { + if (oss_output != NULL) { + delete oss_output; + oss_output = NULL; + } + + if (alsa_output != NULL) { + delete alsa_output; + alsa_output = NULL; + } + + if (unknown_output != NULL) { + delete unknown_output; + unknown_output = NULL; + } + } + + if (objectCount < 0) { + cout << "Error: unusual MidiOutPort_linux count when destructing" << endl; + exit(1); + } +} + + +void MidiOutPort_linux::close(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: oss_output->close(); break; + case ALSA_MIDI_SELECT: alsa_output->close(); break; + default: unknown_output->close(); break; + } +} + +void MidiOutPort_linux::closeAll(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: oss_output->closeAll(); break; + case ALSA_MIDI_SELECT: alsa_output->closeAll(); break; + default: unknown_output->closeAll(); break; + } +} + +int MidiOutPort_linux::getChannelOffset(void) const { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getChannelOffset(); break; + case ALSA_MIDI_SELECT: return alsa_output->getChannelOffset(); break; + default: return unknown_output->getChannelOffset(); break; + } +} + +const char* MidiOutPort_linux::getName(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getName(); break; + case ALSA_MIDI_SELECT: return alsa_output->getName(); break; + default: return unknown_output->getName(); break; + } +} + +const char* MidiOutPort_linux::getName(int i) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getName(i); break; + case ALSA_MIDI_SELECT: return alsa_output->getName(i); break; + default: return unknown_output->getName(i); break; + } +} + +int MidiOutPort_linux::getNumPorts(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getNumPorts(); break; + case ALSA_MIDI_SELECT: return alsa_output->getNumPorts(); break; + default: return unknown_output->getNumPorts(); break; + } +} + +int MidiOutPort_linux::getPort(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getPort(); break; + case ALSA_MIDI_SELECT: return alsa_output->getPort(); break; + default: return unknown_output->getPort(); break; + } +} + +int MidiOutPort_linux::getPortStatus(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getPortStatus(); break; + case ALSA_MIDI_SELECT: return alsa_output->getPortStatus(); break; + default: return unknown_output->getPortStatus(); break; + } +} + +int MidiOutPort_linux::getTrace(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->getTrace(); break; + case ALSA_MIDI_SELECT: return alsa_output->getTrace(); break; + default: return unknown_output->getTrace(); break; + } +} + +int MidiOutPort_linux::open(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->open(); break; + case ALSA_MIDI_SELECT: return alsa_output->open(); break; + default: return unknown_output->open(); break; + } +} + +int MidiOutPort_linux::rawsend(int command, int p1, int p2) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->rawsend(command, p1, p2); break; + case ALSA_MIDI_SELECT: return alsa_output->rawsend(command, p1, p2); break; + default: return unknown_output->rawsend(command, p1, p2); break; + } +} + +int MidiOutPort_linux::rawsend(int command, int p1) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->rawsend(command, p1); break; + case ALSA_MIDI_SELECT: return alsa_output->rawsend(command, p1); break; + default: return unknown_output->rawsend(command, p1); break; + } +} + +int MidiOutPort_linux::rawsend(int command) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->rawsend(command); break; + case ALSA_MIDI_SELECT: return alsa_output->rawsend(command); break; + default: return unknown_output->rawsend(command); break; + } +} + +int MidiOutPort_linux::rawsend(uchar* array, int size) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->rawsend(array, size); break; + case ALSA_MIDI_SELECT: return alsa_output->rawsend(array, size); break; + default: return unknown_output->rawsend(array, size); break; + } +} + +void MidiOutPort_linux::setAndOpenPort(int aPort) { + switch (getSelect()) { + case OSS_MIDI_SELECT: + oss_output->setPort(aPort); + oss_output->open(); + break; + case ALSA_MIDI_SELECT: + alsa_output->setPort(aPort); + alsa_output->open(); + break; + default: + unknown_output->setPort(aPort); + unknown_output->open(); + break; + } +} + +void MidiOutPort_linux::setChannelOffset(int aChannel) { + switch (getSelect()) { + case OSS_MIDI_SELECT: oss_output->setChannelOffset(aChannel); break; + case ALSA_MIDI_SELECT: alsa_output->setChannelOffset(aChannel); break; + default: unknown_output->setChannelOffset(aChannel); break; + } +} + +void MidiOutPort_linux::setPort(int aPort) { + switch (getSelect()) { + case OSS_MIDI_SELECT: oss_output->setPort(aPort); break; + case ALSA_MIDI_SELECT: + alsa_output->setPort(aPort); break; + default: unknown_output->setPort(aPort); break; + } +} + +int MidiOutPort_linux::setTrace(int aState) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->setTrace(aState); break; + case ALSA_MIDI_SELECT: return alsa_output->setTrace(aState); break; + default: return unknown_output->setTrace(aState); break; + } +} + +int MidiOutPort_linux::sysex(uchar* array, int size) { + switch (getSelect()) { + case OSS_MIDI_SELECT: return oss_output->sysex(array, size); break; + case ALSA_MIDI_SELECT: return alsa_output->sysex(array, size); break; + default: return unknown_output->sysex(array, size); break; + } +} + +void MidiOutPort_linux::toggleTrace(void) { + switch (getSelect()) { + case OSS_MIDI_SELECT: oss_output->toggleTrace(); break; + case ALSA_MIDI_SELECT: alsa_output->toggleTrace(); break; + default: unknown_output->toggleTrace(); break; + } +} + + + +////////////////////////////// +// +// MidiOutPort_linux::getSelect -- return the type of MIDI which +// is being used to send MIDI output. +// + +int MidiOutPort_linux::getSelect(void) { + return current; +} + + + +////////////////////////////// +// +// MidiOutPort_linux::selectOSS -- select the OSS MIDI output +// returns 1 if OSS is available, otherwise returns 0. +// + +int MidiOutPort_linux::selectOSS(void) { + if (ossQ) { + current = OSS_MIDI_SELECT; + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiOutPort_linux::selectALSA -- select the ALSA MIDI output +// returns 1 if ALSA is available, otherwise returns 0. +// + +int MidiOutPort_linux::selectALSA(void) { + if (alsaQ) { + current = ALSA_MIDI_SELECT; + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// MidiOutPort_linux::selectUnknown -- select the Unknown MIDI output +// returns 1 always. +// + +int MidiOutPort_linux::selectUnknown(void) { + current = UNKNOWN_MIDI_SELECT; + return 1; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private Functions +// + +#include + +////////////////////////////// +// +// MidiOutPort_linux::determineDrivers -- see if OSS/ALSA are +// available. If /dev/sequencer is present, assume that OSS is +// available. If /dev/snd/sdq is present, assume that ALSA is +// available. +// + +void MidiOutPort_linux::determineDrivers(void) { + struct stat filestats; + int status; + status = stat("/dev/sequencer", &filestats); + + if (status != 0) { + ossQ = 0; + } else { + ossQ = 1; + } + + status = stat("/dev/snd/seq", &filestats); + + if (status != 0) { + alsaQ = 0; + } else { + alsaQ = 1; + } + + + current = UNKNOWN_MIDI_SELECT; + + if (ossQ) { + current = OSS_MIDI_SELECT; + } + + if (alsaQ) { + current = ALSA_MIDI_SELECT; + } + + // create MIDI output types which are available: + + if (oss_output != NULL) { + delete oss_output; + oss_output = NULL; + } + if (alsa_output != NULL) { + delete alsa_output; + alsa_output = NULL; + } + if (unknown_output != NULL) { + delete unknown_output; + unknown_output = NULL; + } + + if (ossQ) { + oss_output = new MidiOutPort_oss; + } + if (alsaQ) { + alsa_output = new MidiOutPort_alsa; + } + unknown_output = new MidiOutPort_unsupported; +} + + +#endif /* ALSA and OSS */ +#endif /* LINUX */ + +// md5sum: be1ccf667122f1c9cf56a95b2ffb8e79 - MidiOutPort_linux.cpp =css= 20030102 diff --git a/src/midiio/src/MidiOutPort_oss.cpp b/src/midiio/src/MidiOutPort_oss.cpp new file mode 100644 index 0000000..74f17c4 --- /dev/null +++ b/src/midiio/src/MidiOutPort_oss.cpp @@ -0,0 +1,462 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Fri Dec 18 19:22:20 PST 1998 +// Last Modified: Fri Jan 8 04:26:16 PST 1999 +// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss) +// Filename: ...sig/code/control/MidiOutPort/linux/MidiOutPort_oss.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiOutPort_oss.cpp +// Syntax: C++ +// +// Description: Operating-System specific interface for +// basic MIDI output capabilities in Linux using +// OSS sound drivers. Privately inherited by the +// MidiOutPort class. +// + +#ifdef LINUX + +#include "MidiOutPort_oss.h" +#include +#include + +// initialized static variables +int MidiOutPort_oss::numDevices = 0; +int MidiOutPort_oss::objectCount = 0; +int* MidiOutPort_oss::portObjectCount = NULL; +int MidiOutPort_oss::channelOffset = 0; +int* MidiOutPort_oss::trace = NULL; +std::ostream* MidiOutPort_oss::tracedisplay = &std::cout; + + + +////////////////////////////// +// +// MidiOutPort_oss::MidiOutPort_oss +// default values: autoOpen = 1 +// + + +MidiOutPort_oss::MidiOutPort_oss(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiOutPort_oss::MidiOutPort_oss(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiOutPort_oss::~MidiOutPort_oss +// + +MidiOutPort_oss::~MidiOutPort_oss() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + std::cerr << "Error: bad MidiOutPort object count!: " << objectCount << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiOutPort_oss::close +// + +void MidiOutPort_oss::close(void) { + // don't close anything, because the + // Linux driver keeps all of the ports open while the + // midi driver (/dev/sequencer) is running. +} + + + +////////////////////////////// +// +// MidiOutPort_oss::closeAll +// + +void MidiOutPort_oss::closeAll(void) { + // the Linux MIDI driver will close the /dev/sequencer device + // which will close all MIDI output ports at the same time. + Sequencer_oss::close(); +} + + + +////////////////////////////// +// +// MidiOutPort_oss::getChannelOffset -- returns zero if MIDI channel +// offset is 0, or 1 if offset is 1. +// + +int MidiOutPort_oss::getChannelOffset(void) const { + return channelOffset; +} + + + +////////////////////////////// +// +// MidiOutPort_oss::getName -- returns the name of the port. +// returns "" if no name. Name is valid until getName is called again. +// + +const char* MidiOutPort_oss::getName(void) { + if (getPort() == -1) { + return "Null OSS MIDI Output"; + } + return getOutputName(getPort()); +} + + +const char* MidiOutPort_oss::getName(int i) { + return Sequencer_oss::getOutputName(i); +} + + + +////////////////////////////// +// +// MidiOutPort_oss::getNumPorts -- returns the number of available +// ports for MIDI output +// + +int MidiOutPort_oss::getNumPorts(void) { + return Sequencer_oss::getNumOutputs(); +} + + + +////////////////////////////// +// +// MidiOutPort_oss::getPort -- returns the port to which this +// object belongs (as set with the setPort function). +// + +int MidiOutPort_oss::getPort(void) { + return port; +} + + + +////////////////////////////// +// +// MidiOutPort_oss::getPortStatus -- 0 if closed, 1 if open +// + +int MidiOutPort_oss::getPortStatus(void) { + // Linux MIDI devices are all open at the same time, + // so if one is open, then they all are. + return is_open(); +} + + + +////////////////////////////// +// +// MidiOutPort_oss::getTrace -- returns true if trace is on or +// false if off. If trace is on, then prints to standard output +// the Midi message being sent. +// + +int MidiOutPort_oss::getTrace(void) { + if (getPort() == -1) return -1; + + return trace[getPort()]; +} + + + +////////////////////////////// +// +// MidiOutPort_oss::rawsend -- send the Midi command and its parameters +// + +int MidiOutPort_oss::rawsend(int command, int p1, int p2) { + if (getPort() == -1) return 0; + + int status; + uchar mdata[3] = {(uchar)command, (uchar)p1, (uchar)p2}; + status = write(getPort(), mdata, 3); + + if (getTrace()) { + if (status == 1) { + std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":" + << (int)mdata[1] << "," << (int)mdata[2] << ")"; + std::cout.flush(); + } else { + std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X" + << (int)mdata[1] << "," << (int)mdata[2] << ")"; + std::cout.flush(); + } + } + + return status; +} + + +int MidiOutPort_oss::rawsend(int command, int p1) { + if (getPort() == -1) return 0; + + int status; + uchar mdata[2] = {(uchar)command, (uchar)p1}; + + status = write(getPort(), mdata, 2); + + if (getTrace()) { + if (status == 1) { + std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":" + << (int)mdata[1] << ")"; + std::cout.flush(); + } else { + std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X" + << (int)mdata[1] << "," << (int)mdata[2] << ")"; + std::cout.flush(); + } + } + + return status; +} + + +int MidiOutPort_oss::rawsend(int command) { + if (getPort() == -1) return 0; + + int status; + uchar mdata[1] = {(uchar)command}; + + status = write(getPort(), mdata, 1); + + if (getTrace()) { + if (status == 1) { + std::cout << "(" << std::hex << (int)mdata[0] << ")"; + std::cout.flush(); + } else { + std::cout << "(" << std::hex << (int)mdata[0] << ")"; + std::cout.flush(); + } + } + + return status; +} + + +int MidiOutPort_oss::rawsend(uchar* array, int size) { + if (getPort() == -1) return 0; + + int status; + status = write(getPort(), array, size); + + if (getTrace()) { + if (status == 1) { + std::cout << "(array)"; + std::cout.flush(); + } else { + std::cout << "(XarrayX)"; + std::cout.flush(); + } + } + + return status; +} + + + +////////////////////////////// +// +// MidiOutPort_oss::open -- returns true if MIDI output port was +// opened. +// + +int MidiOutPort_oss::open(void) { + return Sequencer_oss::open(); +} + + + +////////////////////////////// +// +// MidiOutPort_oss::setChannelOffset -- sets the MIDI channel offset, +// either 0 or 1. +// + +void MidiOutPort_oss::setChannelOffset(int anOffset) { + switch (anOffset) { + case 0: channelOffset = 0; break; + case 1: channelOffset = 1; break; + default: + std::cout << "Error: Channel offset can be only 0 or 1." << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiOutPort_oss::setPort -- +// + +void MidiOutPort_oss::setPort(int aPort) { + if (aPort < -1 || aPort >= getNumPorts()) { + std::cerr << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << std::endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + if (port != -1) { + portObjectCount[port]++; + } +} + + + +////////////////////////////// +// +// MidiOutPort_oss::setTrace -- if false, then won't print +// Midi messages to standard output. +// + +int MidiOutPort_oss::setTrace(int aState) { + if (getPort() == -1) return -1; + + int oldtrace = trace[getPort()]; + if (aState == 0) { + trace[getPort()] = 0; + } else { + trace[getPort()] = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiOutPort_oss::sysex -- send a system exclusive message. +// The message must start with a 0xf0 byte and end with +// a 0xf7 byte. +// + +int MidiOutPort_oss::sysex(uchar* array, int size) { + if (size == 0 || array[0] != 0xf0) { + std::cout << "Error: invalid sysex message" << std::endl; + exit(1); + } + + return rawsend(array,size); +} + + + +////////////////////////////// +// +// MidiOutPort_oss::toggleTrace +// + +void MidiOutPort_oss::toggleTrace(void) { + if (getPort() == -1) return; + + trace[getPort()] = !trace[getPort()]; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiOutPort_oss::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_oss::deinitialize(void) { + closeAll(); + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = NULL; + if (trace != NULL) delete [] trace; + trace = NULL; +} + + + +////////////////////////////// +// +// MidiOutPort_oss::initialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_oss::initialize(void) { + // get the number of ports + numDevices = getNumOutputs(); + if (getNumPorts() <= 0) { + std::cerr << "Warning: no MIDI output devices" << std::endl; + portObjectCount = NULL; + trace = NULL; + } else { + // allocate space for object count on each port: + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = new int[numDevices]; + + // allocate space for trace variable for each port: + if (trace != NULL) delete [] trace; + trace = new int[numDevices]; + + // initialize the static arrays + for (int i=0; i +// Creation Date: Mon Jan 12 21:40:35 GMT-0800 1998 +// Last Modified: Mon Jan 12 21:40:39 GMT-0800 1998 +// Filename: ...sig/code/control/MidiOutPort/unsupported/MidiOutPort_unsupported.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiOutPort_unsupported.cpp +// Syntax: C++ +// +// Description: Operating-System specific interface for basic MIDI output +// capabilities in an unknown operating system. Privately +// inherited by the MidiOutPort class. Used for compiling +// and running MIDI programs on a computer with no +// MIDI output. +// + +#include "MidiOutPort_unsupported.h" + +#include +#include +#include +#include + +// initialized static variables +int MidiOutPort_unsupported::numDevices = 0; +int MidiOutPort_unsupported::objectCount = 0; +int* MidiOutPort_unsupported::openQ = NULL; +int* MidiOutPort_unsupported::portObjectCount = NULL; +int MidiOutPort_unsupported::channelOffset = 0; + + +////////////////////////////// +// +// MidiOutPort_unsupported::MidiOutPort_unsupported +// default values: autoOpen = 1 +// + + +MidiOutPort_unsupported::MidiOutPort_unsupported(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiOutPort_unsupported::MidiOutPort_unsupported(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::~MidiOutPort_unsupported +// + +MidiOutPort_unsupported::~MidiOutPort_unsupported() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + std::cerr << "Error: bad MidiOutPort object count!: " << objectCount << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::close +// + +void MidiOutPort_unsupported::close(void) { + if (getPortStatus() == 1) { + setPortStatus(0); + } +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::closeAll +// + +void MidiOutPort_unsupported::closeAll(void) { + for (int i=0; i= getNumPorts()) { + std::cerr << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << std::endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + portObjectCount[port]++; +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::setTrace -- if false, then won't print +// Midi messages to standard output. +// + +int MidiOutPort_unsupported::setTrace(int aState) { + int oldtrace = trace; + if (aState == 0) { + trace = 0; + } else { + trace = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::sysex -- +// + +int MidiOutPort_unsupported::sysex(uchar* array, int size) { + return 1; +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::toggleTrace -- +// + +void MidiOutPort_unsupported::toggleTrace(void) { + trace = !trace; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiOutPort_unsupported::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_unsupported::deinitialize(void) { + closeAll(); + if (openQ != NULL) delete [] openQ; + openQ = NULL; + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = NULL; +} + + + +////////////////////////////// +// +// MidiOutPort_unsupported::initialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_unsupported::initialize(void) { + // get the number of ports + numDevices = 16; + if (getNumPorts() <= 0) { + std::cerr << "Error: no MIDI output devices" << std::endl; + exit(1); + } + + + // allocate space for openQ, the port open/close status + if (openQ != NULL) delete [] openQ; + openQ = new int[numDevices]; + + // allocate space for object count on each port: + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = new int[numDevices]; + + + // initialize the static arrays + for (int i=0; i +// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997 +// Last Modified: Mon Jan 12 15:42:44 GMT-0800 1998 +// Last Modified: Tue Jun 29 13:10:30 PDT 1999 (verified sysex sending) +// Last Modified: Tue Jun 4 22:10:16 PDT 2002 (getNumPorts fix for static use) +// Filename: ...sig/code/control/MidiOutPort/visual/MidiOutPort_visual.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiOutPort_visual.cpp +// Syntax: C++ +// +// Description: Operating-System specific interface for +// basic MIDI output capabilities in Windows 95/NT/98 +// using winmm.lib. Privately inherited by the +// MidiOutPort class. +// + + +#ifdef VISUAL + +#include +#include "MidiOutPort_visual.h" + +typedef unsigned long ulong; +typedef unsigned char uchar; + + +// initialized static variables +int MidiOutPort_visual::numDevices = 0; +int MidiOutPort_visual::objectCount = 0; +int* MidiOutPort_visual::openQ = NULL; +int* MidiOutPort_visual::portObjectCount = NULL; +HMIDIOUT* MidiOutPort_visual::device = NULL; +int MidiOutPort_visual::channelOffset = 0; + + + +////////////////////////////// +// +// MidiOutPort_visual::MidiOutPort_visual +// default values: autoOpen = 1 +// + + +MidiOutPort_visual::MidiOutPort_visual(void) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(0); +} + + +MidiOutPort_visual::MidiOutPort_visual(int aPort, int autoOpen) { + if (objectCount == 0) { + initialize(); + } + objectCount++; + + port = -1; + setPort(aPort); + if (autoOpen) { + open(); + } +} + + + +////////////////////////////// +// +// MidiOutPort_visual::~MidiOutPort_visual +// + +MidiOutPort_visual::~MidiOutPort_visual() { + objectCount--; + if (objectCount == 0) { + deinitialize(); + } else if (objectCount < 0) { + cerr << "Error: bad MidiOutPort object count!: " << objectCount << endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiOutPort_visual::close +// + +void MidiOutPort_visual::close(void) { + if (getPort() == -1) { + return; + } + + if (getPortStatus() == 1 && device[getPort()] != NULL) { + + // The following function, midiOutClose, is not what I like. + // It will send note offs to any note which it thinks is + // on when the port is closed. Uncomment the line if + // you want this feature. + // midiOutReset(device[getPort()]); + + midiOutClose(device[getPort()]); + setPortStatus(0); + } +} + + + +////////////////////////////// +// +// MidiOutPort_visual::closeAll +// + +void MidiOutPort_visual::closeAll(void) { + for (int i=0; i 64000 || size < 1) { + cerr << "Warning: cannot write a MIDI stream larger than 64kB" << endl; + return 0; + } + + MIDIHDR midiheader; // structure for sending an array of MIDI bytes + + midiheader.lpData = (char *)array; + midiheader.dwBufferLength = size; + // midiheader.dwBytesRecorded = size; // example program doesn't set + midiheader.dwFlags = 0; // flags must be set to 0 + + if (getPort() == -1) { + return -1; + } + + int status = midiOutPrepareHeader(device[getPort()], &midiheader, + sizeof(MIDIHDR)); + + if (status != MMSYSERR_NOERROR) { + return 0; + } + + status = midiOutLongMsg(device[getPort()], &midiheader, sizeof(MIDIHDR)); + + if (status != MMSYSERR_NOERROR) { + return 0; + } + + while (MIDIERR_STILLPLAYING == midiOutUnprepareHeader(device[getPort()], + &midiheader, sizeof(MIDIHDR))) { + Sleep(1); // sleep for 1 millisecond + } + + return 1; +} + + + +////////////////////////////// +// +// MidiOutPort_visual::open -- returns true if MIDI output port was +// opened. +// + +int MidiOutPort_visual::open(void) { + if (getPort() == -1) { + return 2; + } + + if (getPortStatus() == 0) { + int flag; + flag = midiOutOpen(&device[getPort()], getPort(), 0, 0, CALLBACK_NULL); + if (flag == MMSYSERR_NOERROR) { + openQ[getPort()] = 1; + return 1; + } else { // faied to open + openQ[getPort()] = 0; + device[getPort()] = NULL; + return 0; + } + } else { // already open + return 1; + } +} + + + +////////////////////////////// +// +// MidiOutPort_visual::setChannelOffset -- sets the MIDI channel offset, +// either 0 or 1. +// + +void MidiOutPort_visual::setChannelOffset(int anOffset) { + switch (anOffset) { + case 0: channelOffset = 0; break; + case 1: channelOffset = 1; break; + default: + cout << "Error: Channel offset can be only 0 or 1." << endl; + exit(1); + } +} + + + +////////////////////////////// +// +// MidiOutPort_visual::setPort +// + +void MidiOutPort_visual::setPort(int aPort) { + if (aPort < 0 || aPort >= getNumPorts()) { + cerr << "Error: maximum port number is: " << getNumPorts()-1 + << ", but you tried to access port: " << aPort << endl; + exit(1); + } + + if (port != -1) { + portObjectCount[port]--; + } + port = aPort; + portObjectCount[port]++; +} + + + +////////////////////////////// +// +// MidiOutPort_visual::setTrace -- if false, then won't print +// Midi messages to standard output. +// + +int MidiOutPort_visual::setTrace(int aState) { + int oldtrace = trace; + if (aState == 0) { + trace = 0; + } else { + trace = 1; + } + return oldtrace; +} + + + +////////////////////////////// +// +// MidiOutPort_visual::sysex -- send a system exclusive message. +// The first byte of the message must be a 0xf0 byte. +// + +int MidiOutPort_visual::sysex(uchar* array, int size) { + if (size == 0 || array[0] != 0xf0) { + cout << "Error: invalid system exclusive message," + " first byte must be 0xf0" << endl; + exit(1); + } + + return rawsend(array, size); +} + + + +////////////////////////////// +// +// MidiOutPort_visual::toggleTrace +// + +void MidiOutPort_visual::toggleTrace(void) { + trace = !trace; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Private functions +// + + + +////////////////////////////// +// +// MidiOutPort_visual::deinitialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_visual::deinitialize(void) { + closeAll(); + if (device != NULL) delete [] device; + device = NULL; + if (openQ != NULL) delete [] openQ; + openQ = NULL; + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = NULL; +} + + + +////////////////////////////// +// +// MidiOutPort_visual::initialize -- sets up storage if necessary +// This function should be called if the current object is +// the first object to be created. +// + +void MidiOutPort_visual::initialize(void) { + // get the number of ports + numDevices = midiOutGetNumDevs(); + if (getNumPorts() <= 0) { + cerr << "Error: no MIDI output devices" << endl; + exit(1); + } + + // allocate space for Windoze MIDI output structures + if (device != NULL) { + cerr << "Error: device array should be NULL when calling " + << "initialize() in MidiOutPort." << endl; + exit(1); + } + device = new HMIDIOUT[numDevices]; + + // allocate space for openQ, the port open/close status + if (openQ != NULL) delete [] openQ; + openQ = new int[numDevices]; + + // allocate space for object count on each port: + if (portObjectCount != NULL) delete [] portObjectCount; + portObjectCount = new int[numDevices]; + + + // initialize the static arrays + for (int i=0; i +// Creation Date: 18 December 1997 +// Last Modified: Mon Jan 26 23:54:36 GMT-0800 1998 +// Last Modified: Tue Feb 2 08:30:28 PST 1999 +// Last Modified: Sun Jul 18 18:52:29 PDT 1999 (added RPN functions) +// Last Modified: Sun Dec 9 15:01:33 PST 2001 (switched con/des code) +// Filename: ...sig/code/control/MidiOutput/MidiOutput.cpp +// Web Address: http://sig.sapp.org/src/sig/MidiOutput.cpp +// Syntax: C++ +// +// Description: The MIDI output interface for MIDI synthesizers/equipment +// which has many convienience functions defined for +// various types of MIDI output. +// + +#include "MidiOutput.h" +#include +#include + +#define RECORD_ASCII (0) +#define RECORD_BINARY (1) +#define RECORD_MIDI_FILE (2) + + +// declaration of static variables +SigTimer MidiOutput::timer; +Array* MidiOutput::rpn_lsb_status = NULL; +Array* MidiOutput::rpn_msb_status = NULL; +int MidiOutput::objectCount = 0; + + +////////////////////////////// +// +// MidiOutput::MidiOutput -- +// + + +MidiOutput::MidiOutput(void) : MidiOutPort() { + outputRecordQ = 0; + + if (objectCount == 0) { + initializeRPN(); + } + objectCount++; +} + + + +MidiOutput::MidiOutput(int aPort, int autoOpen) : MidiOutPort(aPort, autoOpen) { + outputRecordQ = 0; + + if (objectCount == 0) { + initializeRPN(); + } + objectCount++; +} + + + +////////////////////////////// +// +// MidiOutput::~MidiOutput +// + +MidiOutput::~MidiOutput() { + objectCount--; + if (objectCount == 0) { + deinitializeRPN(); + } else if (objectCount < 0) { + std::cout << "Error in MidiOutput decontruction" << std::endl; + } + +} + + + +////////////////////////////// +// +// MidiOutput::cont -- send a controller command MIDI message. +// +// channel = the Midi channel ofset from 0 [0..15] +// controller = the continuous controller number [0..127] +// data = the value of the specified controller [0..127] +// + +int MidiOutput::cont(int channel, int controller, int data) { + return send(0xb0 | (channel & 0x0f), controller, data); +} + + + +////////////////////////////// +// +// MidiOutput::off -- sends a Note Off MIDI message (0x80). +// +// channel = MIDI channel to send note on. range is [0..15] +// keynum = MIDI key number to play (middle C = 60, C# = 61, etc.) [0..127] +// velocity = release velocity of the note, 127 = quickest possible +// +// Note: The more common method of turning off a note is to use the +// play() function (midi command 0x90) but send an attack velocity of 0. +// + +int MidiOutput::off(int channel, int keynum, int releaseVelocity) { + return send(0x80 | (channel & 0x0f), keynum, releaseVelocity); +} + + + +////////////////////////////// +// +// MidiOutput::pc -- send a patch change MIDI message. changes the timbre +// on the specified channel. +// +// channel = MIDI channel to which to send the patch change [0..15] +// timbre = the voice to select on the specified channel [0..127] +// + +int MidiOutput::pc(int channel, int timbre) { + return send(0xc0 | (channel & 0x0f), timbre); +} + + + +////////////////////////////// +// +// MidiOutput::play -- sends a Note On/Off MIDI message. +// +// channel = MIDI channel to send note on. range is [0..15] +// keynum = MIDI key number to play (middle C = 60, C# = 61, etc.) [0..127] +// velocity = attack velocity of the note, 0 = 0ff, 127 = loudest possible +// + +int MidiOutput::play(int channel, int keynum, int velocity) { + return send(0x90 | (channel & 0x0f), keynum, velocity); +} + + + +////////////////////////////// +// +// MidiOutput::pw -- Pitch Wheel: send a MIDI pitch bend. +// Parameters are: +// 1. channel -- MIDI channel offset from 0. +// 2. mostByte -- most significant 7 bits (coarse tuning) +// 3. leastByte -- least significant 7 bits (fine tuning) +// + +int MidiOutput::pw(int channel, int mostByte, int leastByte) { + return send(0xe0 | (channel & 0x0f), leastByte, mostByte); +} + + + +////////////////////////////// +// +// MidiOutput::pw -- Pitch Wheel: 14 bit number given as input +// range for 14 bit number is 0 to 16383. +// + +int MidiOutput::pw(int channel, int tuningData) { + uchar greaterBits = (uchar)((tuningData >> 7) & 0x7f); + uchar lesserBits = (uchar)(tuningData & 0x7f); + return pw(channel, greaterBits, lesserBits); +} + + + +////////////////////////////// +// +// MidiOutput::pw -- Pitch Wheel: range between -1 to 1 given as input. +// Range is then converted to a 14 bit number. +// +1 = highest value of pitch wheel +// 0 = rest position of pitch wheel +// -1 = lowest value of pitch wheel +// + +int MidiOutput::pw(int channel, double tuningData) { + if (tuningData < -1.0 || tuningData > 1.0) { + std::cerr << "Error: pitch wheel data is out of range: " << tuningData << std::endl; + exit(1); + } + + int output = (int)((tuningData+1.0)/2.0*16383 + 0.5); + return pw(channel, output); +} + + + +////////////////////////////// +// +// MidiOutput::recordStart +// + +void MidiOutput::recordStart(char *filename, int format) { + if (outputRecordQ) { // already recording, so close old file + recordStop(); + } + + outputRecordFile.open(filename, std::ios::out); + if (!outputRecordFile) { // open file failed + std::cerr << "Error: cannot open file " << filename << std::endl; + outputRecordQ = 0; + } else { + outputRecordQ = 1; + } + + if (outputRecordQ) { + switch (format) { + case RECORD_ASCII: // ascii + outputRecordType = RECORD_ASCII; + outputRecordFile <<"; delta time/MIDI output at delta time" << std::endl; + break; + case RECORD_BINARY: // binary + outputRecordType = RECORD_BINARY; + // record the magic number for binary format + outputRecordFile << (uchar)0xf8 << (uchar)0xf8 + << (uchar)0xf8 << (uchar)0xf8; + break; + case RECORD_MIDI_FILE: // standard MIDI file, type 0 + default: + outputRecordType = RECORD_MIDI_FILE; + // header stuff to be written here + break; + } + } + + lastFlushTime = timer.getTime(); +} + + + +////////////////////////////// +// +// MidiOutput::recordStop +// + +void MidiOutput::recordStop(void) { + if (outputRecordQ) { + outputRecordQ = 0; + outputRecordFile.close(); + } +} + + + +////////////////////////////// +// +// MidiOutput::reset -- sends the MIDI command 0xFF which +// should force the MIDI devices on the other side of the +// MIDI cable into their power-on reset condition, clear running +// status, turn off any sounding notes, set Local Control on, and +// otherwise clean up the state of things. +// + +void MidiOutput::reset(void) { + send(0xff, 0, 0); +} + + + +////////////////////////////// +// +// MidiOutput::send -- send a byte to the MIDI port but record it +// first. +// + +int MidiOutput::send(int command, int p1, int p2) { + if (outputRecordQ) { + switch (outputRecordType) { + case 0: // ascii + writeOutputAscii(command, p1, p2); + break; + case 1: // binary + writeOutputBinary(command, p1, p2); + break; + case 2: // standard MIDI file type 0 + writeOutputMidifile(command, p1, p2); + break; + } + lastFlushTime = timer.getTime(); // only keep track if recording + } + return rawsend(command, p1, p2); +} + + +int MidiOutput::send(int command, int p1) { + if (outputRecordQ) { + switch (outputRecordType) { + case 0: // ascii + writeOutputAscii(command, p1, -1); + break; + case 1: // binary + writeOutputBinary(command, p1, -1); + break; + case 2: // standard MIDI file type 0 + writeOutputMidifile(command, p1, -1); + break; + } + lastFlushTime = timer.getTime(); // only keep track if recording + } + return rawsend(command, p1); +} + + +int MidiOutput::send(int command) { + if (outputRecordQ) { + switch (outputRecordType) { + case 0: // ascii + writeOutputAscii(command, -1, -1); + break; + case 1: // binary + writeOutputBinary(command, -1, -1); + break; + case 2: // standard MIDI file type 0 + writeOutputMidifile(command, -1, -1); + break; + } + lastFlushTime = timer.getTime(); // only keep track if recording + } + return rawsend(command); +} + + + +////////////////////////////// +// +// MidiOutput::silence -- send a note off to all notes on all channels. +// default value: aChannel = -1 +// + +void MidiOutput::silence(int aChannel) { + int keyno; + if (aChannel == -1) { + for (int channel=0; channel<16; channel++) { + for (keyno=0; keyno<128; keyno++) { + play(channel, keyno, 0); + } + } + } else { + for (keyno=0; keyno<128; keyno++) { + play(aChannel, keyno, 0); + } + } +} + + + +////////////////////////////// +// +// MidiOutput::sustain -- set the MIDI sustain continuous controller on or off. +// Equivalent to the command cont(channel, 0x40, status). +// + +void MidiOutput::sustain(int channel, int status) { + if (status) { // turn on sustain + cont(channel, 0x40, 127); + } else { // turn off sustain + cont(channel, 0x40, 0); + } +} + + + +/////////////////////////////// +// +// MidiOutput::sysex -- sends a system exclusive MIDI message. +// you must supply the 0xf0 at the start of the array +// and the 0xf7 at the end of the array. +// + +int MidiOutput::sysex(char* data, int length) { + return rawsend((uchar*)data, length); +} + + +int MidiOutput::sysex(uchar* data, int length) { + return rawsend(data, length); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// RPN functions +// + + +////////////////////////////// +// +// NRPN -- sends a Non-registered parameter number where: +// parameter #1: channel (0-15) +// parameter #2: NRPN MSB indicator (controller #99 data) +// parameter #3: NRPN LSB indicator (controller #98 data) +// parameter #4: NRPN MSB data (controller #6 data) +// [parameter #5: NRPN LSB data (controller #38 data)] +// or: +// parameter #1: channel (0-15) +// parameter #2: NRPN MSB indicator (controller #99 data) +// parameter #3: NRPN LSB indicator (controller #98 data) +// parameter #4: NRPN Floating point in range (-1..1) (ccont#6 and #38 data) +// +// +// NRPN (Non-registered parameter number) -- General MIDI and +// Extended MIDI mess. It becomes the receiving synthesizer's +// responsibility to determine the meaning of continuous +// controller (ccont) #6 from data sent with cconts #98,99 (for +// NRPNS) and cconts #100,101 (for RPNS). NRPN parameters +// are not reset when the ccont#121 is sent to reset controllers. +// +// NRPN's are "non-standard" meaning that any synthesizer could +// do whatever they want with a given NRPN; However, the +// GS and XG specifications are given in the table further below. +// +// The data for NRPNs are transfered to synthesizer with +// data slider ccont #6(MSB) and ccont #38(LSB). Also data increment +// ccont#96 (data increment) and ccont#97 (data decrement) are in +// relation to the RPN or NRPN in effect. Increment and Decrement +// are not recommend to use with RPN's because of confusion in the +// MIDI industry over which 7-bit data (#6 or #38) to increment. +// +// Once you have selected an NRPN on a given channel, the +// channel will apply subsequent Data Entry to the +// selected parameter. After making the necessary settings +// you should set NRPN to NULL to reduce the risk of +// operational errors. a NUL RPN will disable the previous +// values of either RPN or NRPN data. +// +// The following NRPN values are supported in Yamaha's XG specification: +// CCont #98 = LSB of NRPN parameter ID +// CCont #99 = MSB of NRPN parameter ID +// +// NRPN +// MSB LSB Data Range +// #99 #98 Parameter (ccont#6=MSB, ccont#38=LSB) +// === ===== ====================== ====================== +// 1 8 Vibrato Rate -64.. 0..+63 logical range or (-50..+50) +// 0..64..127 MIDI data range ( 14..114) +// 1 9 Vibrato Depth same ranges as above +// 1 10 Vibrato Delay same ranges as above +// 1 32 Filter Cutoff Freq. same ranges as above +// 1 33 Filter Resonance same ranges as above +// 1 99 EG Attack Time same ranges as above +// 1 100 EG Decay Time same ranges as above +// 1 102 EG Release Time same ranges as above +// 20 xx Drum Filter Cutoff Freq same ranges as above +// xx = drum MIDI key number +// 21 xx Drum Filter Resonance same ranges as above +// xx = drum MIDI key number +// 22 xx Drum EG Attack Rage same ranges as above +// xx = drum MIDI key number +// 23 xx Drum EG Decay Rate same ranges as above +// xx = drum MIDI key number +// 24 xx Drum Pitch Coarse same ranges as above +// xx = drum MIDI key number +// 25 xx Drum Pitch Fine same ranges as above +// xx = drum MIDI key number +// 26 xx Drum Level 0..64..127 MIDI data range +// xx = drum MIDI key number +// 28 xx Drum Pan Random, Left..Center..Right +// 0.......1.....64......127 MIDI data range +// xx = drum MIDI key number +// 29 xx Drum Reverb Send Level 0..64..127 MIDI data range +// xx = drum MIDI key number +// 30 xx Drum Chorus Send Level 0..64..127 MIDI data range +// xx = drum MIDI key number +// 31 xx Drum Variation Send Level 0..64..127 MIDI data range +// xx = drum MIDI key number +// 127 127 Null RPN (disables RPN/NRPN parameters from being altered). +// +// + +int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, + int data_msb, int data_lsb) { + channel = channel & 0x0f; + nrpn_msb = nrpn_msb & 0x7f; + nrpn_lsb = nrpn_msb & 0x7f; + data_msb = nrpn_msb & 0x7f; + data_lsb = nrpn_msb & 0x7f; + + int status = 1; + + // check to see if the nrpn_msb and nrpn_lsb are the same + // as the last call to this function, if not, then send + // the appropriate MIDI controller values. + if (rpn_msb_status[getPort()][channel] != nrpn_msb) { + status &= cont(channel, 99, nrpn_msb); + rpn_msb_status[getPort()][channel] = nrpn_msb; + } + if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) { + status &= cont(channel, 98, nrpn_lsb); + rpn_lsb_status[getPort()][channel] = nrpn_lsb; + } + + // now that the NRPN state is set, send the NRPN data values + // but do not bother sending any data if the Null RPN is in effect. + if (nrpn_msb != 127 && nrpn_lsb != 127) { + status &= cont(channel, 6, data_msb); + status &= cont(channel, 38, data_msb); + } + + return status; +} + + +int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, int data_msb) { + channel = channel & 0x0f; + nrpn_msb = nrpn_msb & 0x7f; + nrpn_lsb = nrpn_msb & 0x7f; + data_msb = nrpn_msb & 0x7f; + + int status = 1; + + // check to see if the nrpn_msb and nrpn_lsb are the same + // as the last call to this function, if not, then send + // the appropriate MIDI controller values. + if (rpn_msb_status[getPort()][channel] != nrpn_msb) { + status &= cont(channel, 99, nrpn_msb); + rpn_msb_status[getPort()][channel] = nrpn_msb; + } + if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) { + status &= cont(channel, 98, nrpn_lsb); + rpn_lsb_status[getPort()][channel] = nrpn_lsb; + } + + // now that the NRPN state is set, send the NRPN data value, + // but do not bother sending any data if the Null RPN is in effect. + if (nrpn_msb != 127 && nrpn_lsb != 127) { + status &= cont(channel, 6, data_msb); + } + + return status; +} + + +int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, double data) { + channel = channel & 0x0f; + nrpn_msb = nrpn_msb & 0x7f; + nrpn_lsb = nrpn_msb & 0x7f; + if (data < -1.0) { + data = -1.0; + } else if (data > 1.0) { + data = 1.0; + } + + int status = 1; + + // check to see if the nrpn_msb and nrpn_lsb are the same + // as the last call to this function, if not, then send + // the appropriate MIDI controller values. + if (rpn_msb_status[getPort()][channel] != nrpn_msb) { + status &= cont(channel, 99, nrpn_msb); + rpn_msb_status[getPort()][channel] = nrpn_msb; + } + if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) { + status &= cont(channel, 98, nrpn_lsb); + rpn_lsb_status[getPort()][channel] = nrpn_lsb; + } + + // convert data into 14 bit number + int data14 = (int)((data+1.0)/2.0*16383 + 0.5); + + // send the NRPN data values, two message of 7 bits each + // but do not bother sending any data if the Null RPN is in effect. + if (nrpn_msb != 127 && nrpn_lsb != 127) { + status &= cont(channel, 6, data14 >> 7); + status &= cont(channel, 38, data14 & 0x7f); + } + + return status; +} + + +////////// +// +// Convenience functions for use of NRPN function. Note that these +// are "Non-Registered" Parameter Numbers which means that each +// synthesizer manufacture can do whatever they want, so these +// functions might not behave the way you expect them to do so. +// Yamaha XG and Roland GS NRPN specifications are given below. +// + +int MidiOutput::NRPN_null(int channel) { + return NRPN(channel, 127, 127, 0); +} + +int MidiOutput::NRPN_vibratoRate(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 8, value+64); +} + +int MidiOutput::NRPN_vibratoRate(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 8, value); +} + +int MidiOutput::NRPN_vibratoDepth(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 9, value+64); +} + +int MidiOutput::NRPN_vibratoDepth(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 9, value); +} + +int MidiOutput::NRPN_vibratoDelay(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 32, value+64); +} + +int MidiOutput::NRPN_vibratoDelay(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 32, value); +} + +int MidiOutput::NRPN_filterCutoff(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 33, value+64); +} + +int MidiOutput::NRPN_filterCutoff(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 33, value); +} + +int MidiOutput::NRPN_attack(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 99, value+64); +} + +int MidiOutput::NRPN_attack(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 99, value); +} + +int MidiOutput::NRPN_decay(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 100, value+64); +} + +int MidiOutput::NRPN_decay(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 100, value); +} + +int MidiOutput::NRPN_release(int channel, int value) { + // value in range -64..+63 + return NRPN(channel, 1, 102, value+64); +} + +int MidiOutput::NRPN_release(int channel, double value) { + // value in range -1.0..+1.0 + return NRPN(channel, 1, 102, value); +} + +int MidiOutput::NRPN_drumFilterCutoff(int drum, int value) { + // value in range -64..+63 + return NRPN(9, 20, drum, value+64); +} + +int MidiOutput::NRPN_drumFilterCutoff(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 20, drum, value); +} + +int MidiOutput::NRPN_drumFilterResonance(int drum, int value) { + // value in range -64..+63 + return NRPN(9, 21, drum, value+64); +} + +int MidiOutput::NRPN_drumFilterResonance(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 21, drum, value); +} + +int MidiOutput::NRPN_drumAttack(int drum, int value) { + // value in range -64..+63 + return NRPN(9, 22, drum, value+64); +} + +int MidiOutput::NRPN_drumAttack(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 22, drum, value); +} + +int MidiOutput::NRPN_drumDecay(int drum, int value) { + // value in range -64..+63 + return NRPN(9, 23, drum, value+64); +} + +int MidiOutput::NRPN_drumDecay(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 23, drum, value); +} + +int MidiOutput::NRPN_drumPitch(int drum, int value) { + // value in range -64..+63 + return NRPN(9, 24, drum, value+64); +} + +int MidiOutput::NRPN_drumPitch(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 24, drum, value); +} + +int MidiOutput::NRPN_drumLevel(int drum, int value) { + // value in range -64..+63 + return NRPN(9, 26, drum, value+64); +} + +int MidiOutput::NRPN_drumLevel(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 26, drum, value); +} + +int MidiOutput::NRPN_drumPan(int drum, int value) { + return NRPN(9, 28, drum, value+64); +} + +int MidiOutput::NRPN_drumPan(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 28, drum, value); +} + +int MidiOutput::NRPN_drumReverb(int drum, int value) { + // note offset from 0 not -64 + return NRPN(9, 29, drum, value); +} + +int MidiOutput::NRPN_drumReverb(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 29, drum, value); +} + +int MidiOutput::NRPN_drumChorus(int drum, int value) { + // note offset from 0 not -64 + return NRPN(9, 30, drum, value); +} + +int MidiOutput::NRPN_drumChorus(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 30, drum, value); +} + +int MidiOutput::NRPN_drumVariation(int drum, int value) { + // note offset from 0 not -64 + return NRPN(9, 31, drum, value); +} + +int MidiOutput::NRPN_drumVariation(int drum, double value) { + // value in range -1.0..+1.0 + return NRPN(9, 31, drum, value); +} + +// +// Convenience functions for use of NRPN function. +// +////////// + + + +////////////////////////////// +// +// RPN -- sends a registered parameter number where: +// parameter #1: channel (0-15) +// parameter #2: RPN MSB indicator (controller #101 data) +// parameter #3: RPN LSB indicator (controller #100 data) +// parameter #4: RPN MSB data (controller #6 data) +// [parameter #5: RPN LSB data (controller #38 data)] +// or: +// parameter #1: channel (0-15) +// parameter #2: NRPN MSB indicator (controller #99 data) +// parameter #3: NRPN LSB indicator (controller #98 data) +// parameter #4: NRPN Floating point in range (-1..1) (ccont#6 and #38 data) +// +// +// RPN (registered parameter number) -- General MIDI and +// Extended MIDI mess. It becomes the receiving synthesizer's +// responsibility to determine the meaning of continuous +// controller (ccont) #6 from data sent with cconts #100,101 (for +// RPNS) and cconts #98,99 (for NRPNS). +// +// The data for RPNs are transfered to synthesizer with +// data slider ccont #6(MSB) and ccont #38(LSB). Also data increment +// ccont#96 (data increment) and ccont#97 (data decrement) are in +// relation to the RPN or NRPN in effect. Increment and Decrement +// are not recommend to use with RPN's because of confusion in the +// MIDI industry over which 7-bit data (#6 or #38) to increment. +// +// Once you have selected an RPN on a given channel, the +// channel will apply subsequent Data Entry to the +// selected parameter. After making the necessary settings +// you should set RPN's to NULL to reduce the risk of +// operational errors. a NULL RPN will disable the previous +// values of either RPN or NRPN data. +// +// The following RPN values are registered: +// CCont #100 = LSB of RPN parameter ID +// CCont #101 = MSB of RPN parameter ID +// +// RPN Data Range +// MSB LSB Parameter (ccont#6=MSB, ccont#38=LSB) +// === ===== ====================== ====================== + +// 0 0 Pitchbend Sensitivity 0-127 (default 2) (LSB ignored) +// (The number of +/- half steps in +// pitch wheel range). +// 0 1 Fine Tune -64.. 0..+63 logical range +// 0..64..127 MIDI data range +// 0 2 Coarse Tune same range as above. +// 0 3 Change Tuning Program 0..127 +// 0 4 Change Tuning Bank 0..127 +// + +int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, + int data_msb, int data_lsb) { + channel = channel & 0x0f; + rpn_msb = rpn_msb & 0x7f; + rpn_lsb = rpn_msb & 0x7f; + data_msb = rpn_msb & 0x7f; + data_lsb = rpn_msb & 0x7f; + + int status = 1; + + // check to see if the rpn_msb and rpn_lsb are the same + // as the last call to this function, if not, then send + // the appropriate MIDI controller values. + if (rpn_msb_status[getPort()][channel] != rpn_msb) { + status &= cont(channel, 101, rpn_msb); + rpn_msb_status[getPort()][channel] = rpn_msb; + } + if (rpn_lsb_status[getPort()][channel] != rpn_lsb) { + status &= cont(channel, 100, rpn_lsb); + rpn_lsb_status[getPort()][channel] = rpn_lsb; + } + + // now that the RPN state is set, send the RPN data values + // but do not bother sending any data if the Null RPN is in effect. + if (rpn_msb != 127 && rpn_lsb != 127) { + status &= cont(channel, 6, data_msb); + status &= cont(channel, 38, data_msb); + } + + return status; +} + + +int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, int data_msb) { + channel = channel & 0x0f; + rpn_msb = rpn_msb & 0x7f; + rpn_lsb = rpn_msb & 0x7f; + data_msb = rpn_msb & 0x7f; + + int status = 1; + + // check to see if the rpn_msb and rpn_lsb are the same + // as the last call to this function, if not, then send + // the appropriate MIDI controller values. + if (rpn_msb_status[getPort()][channel] != rpn_msb) { + status &= cont(channel, 101, rpn_msb); + rpn_msb_status[getPort()][channel] = rpn_msb; + } + if (rpn_lsb_status[getPort()][channel] != rpn_lsb) { + status &= cont(channel, 100, rpn_lsb); + rpn_lsb_status[getPort()][channel] = rpn_lsb; + } + + // now that the RPN state is set, send the RPN data value, + // but do not bother sending any data if the Null RPN is in effect. + if (rpn_msb != 127 && rpn_lsb != 127) { + status &= cont(channel, 6, data_msb); + } + + return status; +} + + +int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, double data) { + channel = channel & 0x0f; + rpn_msb = rpn_msb & 0x7f; + rpn_lsb = rpn_msb & 0x7f; + if (data < -1.0) { + data = -1.0; + } else if (data > 1.0) { + data = 1.0; + } + + int status = 1; + + // check to see if the rpn_msb and rpn_lsb are the same + // as the last call to this function, if not, then send + // the appropriate MIDI controller values. + if (rpn_msb_status[getPort()][channel] != rpn_msb) { + status &= cont(channel, 101, rpn_msb); + rpn_msb_status[getPort()][channel] = rpn_msb; + } + if (rpn_lsb_status[getPort()][channel] != rpn_lsb) { + status &= cont(channel, 100, rpn_lsb); + rpn_lsb_status[getPort()][channel] = rpn_lsb; + } + + // convert data into 14 bit number + int data14 = (int)((data+1.0)/2.0*16383 + 0.5); + + // send the RPN data values, two message of 7 bits each + // but do not bother sending any data if the Null RPN is in effect. + if (rpn_msb != 127 && rpn_lsb != 127) { + status &= cont(channel, 6, data14 >> 7); + status &= cont(channel, 38, data14 & 0x7f); + } + + return status; +} + + +////////// +// +// Convenience functions for use of RPN function. +// + +int MidiOutput::RPN_null(void) { + int status = 1; + for (int i=0; i<16; i++) { + status &= RPN_null(i); + } + return status; +} + +int MidiOutput::RPN_null(int channel) { + return RPN(channel, 127, 127, 0); +} + +int MidiOutput::pbRange(int channel, int steps) { + // default value for pitch bend sensitivity is 2 semitones. + return RPN(channel, 0, 0, steps); +} + +int MidiOutput::tuneFine(int channel, int cents) { + // data from -64 to + 63 + return RPN(channel, 0, 1, cents+64); +} + +int MidiOutput::fineTune(int channel, int cents) { + return tuneFine(channel, cents); +} + +int MidiOutput::tuneCoarse(int channel, int steps) { + // data from -64 to + 63 + return RPN(channel, 0, 1, steps+64); +} + +int MidiOutput::coarseTune(int channel, int steps) { + return tuneCoarse(channel, steps); +} + +int MidiOutput::tuningProgram(int channel, int program) { + return RPN(channel, 0, 3, program); +} + +int MidiOutput::tuningBank(int channel, int bank) { + return RPN(channel, 0, 4, bank); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// private functions +// + + +////////////////////////////// +// +// MidiOutput::initializeRPN -- set up the RPN status arrays +// ignores initiaization request if already initialized. +// + +void MidiOutput::initializeRPN(void) { + int i, channel; + + if (rpn_lsb_status == NULL) { + rpn_lsb_status = new Array[getNumPorts()]; + for (i=0; i[getNumPorts()]; + for (i=0; i +// Creation Date: 21 December 1997 +// Last Modified: Fri Jan 23 10:24:35 GMT-0800 1998 +// Filename: .../sig/code/control/MidiPort/MidiPort.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiPort.cpp +// Syntax: C++ +// +// Description: A unified object that handles basic MIDI input and output. +// Derived from the MidiInPort and MidiOutPort classes. +// + +#include "MidiPort.h" + + +////////////////////////////// +// +// MidiPort::MidiPort +// + +MidiPort::MidiPort(void) : MidiOutPort(), MidiInPort() { + // nothing +} + + +MidiPort::MidiPort(int outputPort, int inputPort) : + MidiOutPort(outputPort), MidiInPort(inputPort) { + // nothing +} + + + +////////////////////////////// +// +// MidiPort::~MidiPort +// + +MidiPort::~MidiPort() { + // nothing +} + + + +////////////////////////////// +// +// MidiPort::getChannelInOffset -- return the MIDI channel offset of +// the MIDI input. +// + +int MidiPort::getChannelInOffset(void) const { + return MidiInPort::getChannelOffset(); +} + + + +////////////////////////////// +// +// MidiPort::getChannelOutOffset -- return the MIDI channel offset of +// the MIDI output. +// + +int MidiPort::getChannelOutOffset (void) const { + return MidiOutPort::getChannelOffset(); +} + + + +////////////////////////////// +// +// MidiPort::getInputPort +// + +int MidiPort::getInputPort(void) { + return MidiInPort::getPort(); +} + + + +////////////////////////////// +// +// MidiPort::getInputTrace +// + +int MidiPort::getInputTrace(void) { + return MidiInPort::getTrace(); +} + + + +////////////////////////////// +// +// MidiPort::getOutputPort +// + +int MidiPort::getOutputPort(void) { + return MidiOutPort::getPort(); +} + + + +////////////////////////////// +// +// MidiPort::getOutputTrace +// + +int MidiPort::getOutputTrace(void) { + return MidiOutPort::getTrace(); +} + + + +////////////////////////////// +// +// MidiPort::setChannelOffset -- sets the MIDI channel offset +// + +void MidiPort::setChannelOffset(int anOffset) { + MidiInPort::setChannelOffset(anOffset); + MidiOutPort::setChannelOffset(anOffset); +} + + + +////////////////////////////// +// +// MidiPort::setInputPort +// + +void MidiPort::setInputPort(int aPort) { + MidiInPort::setPort(aPort); +} + + + +////////////////////////////// +// +// MidiPort::setInputTrace +// + +int MidiPort::setInputTrace(int aState) { + return MidiInPort::setTrace(aState); +} + + + +////////////////////////////// +// +// MidiPort::setOutputPort +// + +void MidiPort::setOutputPort(int aPort) { + MidiOutPort::setPort(aPort); +} + + + +////////////////////////////// +// +// MidiPort::setOutputTrace +// + +int MidiPort::setOutputTrace(int aState) { + return MidiOutPort::setTrace(aState); +} + + + +////////////////////////////// +// +// MidiPort::toggleInputTrace +// + +void MidiPort::toggleInputTrace(void) { + MidiInPort::toggleTrace(); +} + + +////////////////////////////// +// +// MidiPort::toggleOutputTrace +// + +void MidiPort::toggleOutputTrace(void) { + MidiOutPort::toggleTrace(); +} + + + +// md5sum: c2583f3ed21e238ba6b298915cb728aa - MidiPort.cpp =css= 20030102 diff --git a/src/midiio/src/Options.cpp b/src/midiio/src/Options.cpp new file mode 100644 index 0000000..0341fe3 --- /dev/null +++ b/src/midiio/src/Options.cpp @@ -0,0 +1,887 @@ +// +// Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Apr 5 13:07:18 PDT 1998 +// Last Modified: Sat Mar 27 18:17:06 PST 1999 +// Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function) +// Last Modified: Fri May 5 17:52:01 PDT 2000 (added --options suppression) +// Last Modified: Tue May 1 01:25:58 PDT 2001 (fixed getArgumentCount()) +// Filename: ...sig/maint/code/sigBase/Options.cpp +// Web Address: http://sig.sapp.org/src/sigBase/Options.cpp +// Documentation: http://sig.sapp.org/doc/classes/Options +// Syntax: C++ +// +// Description: Handles command-line options in a graceful manner. +// + +int optionListCompare(const void* a, const void* b); + +#include "Options.h" +#include "Options_private.h" +#include +#include +#include +#include + + +////////////////////////////// +// +// Options::Options -- +// + +Options::Options(void) { + optionFlag = '-'; + gargc = -1; + gargv = NULL; + argument.setSize(0); + argument.allowGrowth(); + optionRegister.setSize(0); + optionRegister.allowGrowth(); + optionList.setSize(0); + optionList.allowGrowth(); + processedQ = 0; + sortedQ = 0; + commandString = NULL; + options_error_check = 1; + suppressQ = 0; + optionsArgument = 0; +} + + +Options::Options(int argc, char** argv) { + optionFlag = '-'; + gargc = -1; + gargv = NULL; + argument.setSize(0); + argument.allowGrowth(); + optionRegister.setSize(0); + optionRegister.allowGrowth(); + optionList.setSize(0); + optionList.allowGrowth(); + processedQ = 0; + sortedQ = 0; + commandString = NULL; + options_error_check = 1; + suppressQ = 0; + optionsArgument = 0; + + setOptions(argc, argv); +} + + + +////////////////////////////// +// +// Options::~Options -- +// + +Options::~Options() { + reset(); +} + + + +////////////////////////////// +// +// Options::argc -- returns the argument count as from main(). +// + +int Options::argc(void) const { + return gargc; +} + + + +////////////////////////////// +// +// Options::argv -- returns the arguments strings as from main(). +// + +char** Options::argv(void) const { + return gargv; +} + + + +////////////////////////////// +// +// Options::define -- define an option entry in the option register +// + +void Options::define(const char* aDefinition) { + sortedQ = 0; // have to sort option list later + option_register* definitionEntry; + option_list* optionListEntry; + + + // error if the definition string doesn't contain an equals sign. + if (strchr(aDefinition, '=') == NULL) { + std::cout << "Error: no \"=\" in option definition: " << aDefinition << std::endl; + exit(1); + } + + // get the length of the definition string + int len = strlen(aDefinition); + + // put space before and after the equals sign so that strtok works + char* definitionString; + definitionString = new char[len + 3]; + int i = 0; + while (aDefinition[i] != '=' && i < len) { + definitionString[i] = aDefinition[i]; + i++; + } + definitionString[i] = ' '; + i++; + definitionString[i] = '='; + i++; + definitionString[i] = ' '; + for (int k=i; ksetType(optionType); + i++; + + + // check to make sure that the type is correct. + if (optionType != OPTION_STRING_TYPE && + optionType != OPTION_INT_TYPE && + optionType != OPTION_FLOAT_TYPE && + optionType != OPTION_DOUBLE_TYPE && + optionType != OPTION_BOOLEAN_TYPE && + optionType != OPTION_CHAR_TYPE ) { + std::cout << "Error: unknown option type \'" << optionType + << "\' in defintion: " << aDefinition << std::endl; + exit(1); + } + + // skip any white space after option type. + while (isspace(definitionString[i]) && i < len) { + i++; + } + + + // there can only be two characters now: '\0' or ':' + if (i >= len || definitionString[i] == '\0') { + goto option_finish; + } else if (i= len || definitionString[i] == '\0') { + goto option_finish; + } + + + // now at beginnng of default option string which continues + // until the end of the definition string. + definitionEntry->setDefault(&definitionString[i]); + +option_finish: + + optionRegister.append(definitionEntry); + + + delete [] definitionString; + delete [] tempstr; + +} + + +void Options::define(const char* aDefinition, const char* description) { + define(aDefinition); + + // now find some place to store the description... +} + + + +////////////////////////////// +// +// Options::getArg -- returns the specified argument. +// argurment 0 is the command name. +// + +char* Options::getArg(int index) { + if (index < 0 || index >= argument.getSize()) { + std::cout << "Error: argument " << index << " does not exist." << std::endl; + exit(1); + } + return argument[index]; +} + + + +////////////////////////////// +// +// Options::getArgument -- same as getArg +// + +char* Options::getArgument(int index) { + return getArg(index); +} + + + +////////////////////////////// +// +// Options::getArgCount -- number of arguments on command line. +// does not count the options or the command name. +// + +int Options::getArgCount(void) { + return argument.getSize() - 1; +} + + + +////////////////////////////// +// +// Options::getArgumentCount -- Same as getArgCount(). +// + +int Options::getArgumentCount(void) { + return getArgCount(); +} + + + +////////////////////////////// +// +// Options::getBoolean -- returns true if the option was +// used on the command line. +// + +int Options::getBoolean(const char* optionName) { + int index = getRegIndex(optionName); + if (index < 0) { + return 0; + } + if (optionRegister[index]->getModifiedQ() == 1) { + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// Options::getCommand -- returns argv[0] +// + +const char* Options::getCommand(void) { + if (argument.getSize() == 0) { + return ""; + } else { + return argument[0]; + } +} + + + +////////////////////////////// +// +// Options::getCommandLine -- returns a string which contains the +// command-line call to the program. +// + +const char* Options::getCommandLine(void) { + if (commandString != NULL) { + return commandString; + } + + int length = 0; + int i; + for (i=0; igetName()) == 0) { + return optionRegister[optionList[i]->getIndex()]->getDefinition(); + } + } + return (const char*)NULL; +} + + + +////////////////////////////// +// +// Options::getDouble -- returns the double float associated +// with the given option. Returns 0 if there is no +// number associated with the option. +// + +double Options::getDouble(const char* optionName) { + return strtod(getString(optionName), (char**)NULL); +} + + + +////////////////////////////// +// +// Options::getFlag -- +// + +char Options::getFlag(void) { + return optionFlag; +} + + + +////////////////////////////// +// +// Options::getFloat -- returns the floating point number +// associated with the given option. +// + +float Options::getFloat(const char* optionName) { + return (float)getDouble(optionName); +} + + + +////////////////////////////// +// +// Options::getInt -- returns the integer argument. Can handle +// hexadecimal, decimal, and octal written in standard +// C syntax. +// + +int Options::getInt(const char* optionName) { + return (int)strtol(getString(optionName), (char**)NULL, 0); +} + +int Options::getInteger(const char* optionName) { + return getInt(optionName); +} + + + +////////////////////////////// +// +// Options::getString -- +// + +const char* Options::getString(const char* optionName) { + int index = getRegIndex(optionName); + if (index < 0) { + return "UNKNOWN OPTION"; + } else { + return optionRegister[index]->getOption(); + } +} + + + +////////////////////////////// +// +// Options::optionsArg -- returns true if the --options is present +// on the command line, otherwise returns false. +// + +int Options::optionsArg(void) { + return optionsArgument; +} + + + +////////////////////////////// +// +// Options::print -- +// + +void Options::print(void) { + for (int i=0; igetDefinition() << std::endl; + } +} + + + +////////////////////////////// +// +// Options::reset -- +// + +void Options::reset(void) { + int i; + for (i=0; isetModified(aString); +} + + + + +////////////////////////////// +// +// setOptions -- +// + +void Options::setOptions(int argc, char** argv) { + processedQ = 0; + + gargc = argc; + gargv = argv; +} + + + +////////////////////////////// +// +// Options:getType -- returns the type of the option +// + +char Options::getType(const char* optionName) { + int index = getRegIndex(optionName); + if (index < 0) { + return -1; + } else { + return optionRegister[getRegIndex(optionName)]->getType(); + } +} + + + +////////////////////////////// +// +// Options::process -- same as verify +// default values: error_check = 1, suppress = 0; +// + +void Options::process(int argc, char** argv, int error_check, int suppress) { + setOptions(argc, argv); + verify(error_check, suppress); +} + + +void Options::process(int error_check, int suppress) { + verify(error_check, suppress); +} + + + +////////////////////////////// +// +// Options::verify -- +// default value: error_check = 1, suppress = 0; +// + +void Options::verify(int error_check, int suppress) { + options_error_check = error_check; + int gargp = 1; + int optionend = 0; + + if (suppress) { + suppressQ = 1; + } else { + suppressQ = 0; + } + + // if calling verify again, must remove previous argument list. + if (argument.getSize() != 0) { + for (int j=0; jgetIndex(); + } else if (strcmp("options", optionName) == 0) { + print(); + exit(1); + } + + if (options_error_check) { + std::cout << "Error: unknown option \"" << optionName << "\"." << std::endl; + print(); + exit(1); + } + + return -1; +} + + + +////////////////////////////// +// +// optionQ -- returns true if the string is an option +// "--" is not an option, also '-' is not an option. +// aString is assumed to not be NULL. +// + +int Options::optionQ(const char* aString, int& argp) { + if (aString[0] == getFlag()) { + if (aString[1] == '\0') { + argp++; + return 0; + } else if (aString[1] == getFlag()) { + if (aString[2] == '\0') { + argp++; + return 0; + } else { + return 1; + } + } else { + return 1; + } + } else { + return 0; + } +} + + + + +////////////////////////////// +// +// sortOptionNames -- +// + +void Options::sortOptionNames(void) { + qsort(optionList.getBase(), optionList.getSize(), + sizeof(option_list*), optionListCompare); + sortedQ = 1; +} + + + +////////////////////////////// +// +// storeOption -- +// + +#define OPTION_FORM_SHORT 0 +#define OPTION_FORM_LONG 1 +#define OPTION_FORM_CONTINUE 2 + +int Options::storeOption(int gargp, int& position, int& running) { + int optionForm; + char tempname[1024]; + char optionType = '\0'; + + if (running) { + optionForm = OPTION_FORM_CONTINUE; + } else if (gargv[gargp][1] == getFlag()) { + optionForm = OPTION_FORM_LONG; + } else { + optionForm = OPTION_FORM_SHORT; + } + + switch (optionForm) { + case OPTION_FORM_CONTINUE: + position++; + tempname[0] = gargv[gargp][position]; + tempname[1] = '\0'; + optionType = getType(tempname); + if (optionType != OPTION_BOOLEAN_TYPE) { + running = 0; + position++; + } + break; + case OPTION_FORM_SHORT: + position = 1; + tempname[0] = gargv[gargp][position]; + tempname[1] = '\0'; + optionType = getType(tempname); + if (optionType != OPTION_BOOLEAN_TYPE) { + position++; + } + break; + case OPTION_FORM_LONG: + position = 2; + while (gargv[gargp][position] != '=' && + gargv[gargp][position] != '\0') { + tempname[position-2] = gargv[gargp][position]; + position++; + } + tempname[position-2] = '\0'; + optionType = getType(tempname); + if (optionType == -1) { // suppressed --options option + optionsArgument = 1; + break; + } + if (gargv[gargp][position] == '=') { + if (optionType == OPTION_BOOLEAN_TYPE) { + std::cout << "Error: boolean variable cannot have any options: " + << tempname << std::endl; + exit(1); + } + position++; + } + break; + } + + if (optionType == -1) { // suppressed --options option + optionsArgument = 1; + gargp++; + position = 0; + return gargp; + } + + if (gargv[gargp][position] == '\0' && + optionType != OPTION_BOOLEAN_TYPE) { + gargp++; + position = 0; + } + + if (optionForm != OPTION_FORM_LONG && optionType == OPTION_BOOLEAN_TYPE && + gargv[gargp][position+1] != '\0') { + running = 1; + } else if (optionType == OPTION_BOOLEAN_TYPE && + gargv[gargp][position+1] == '\0') { + running = 0; + } + + if (gargp >= gargc) { + std::cout << "Error: last option requires a parameter" << std::endl; + exit(1); + } + setModified(tempname, &gargv[gargp][position]); + + if (!running) { + gargp++; + } + return gargp; +} + + +/////////////////////////////////////////////////////////////////////////// +// +// helping function +// + +////////////////////////////// +// +// optionListCompare -- for sorting the option list +// + +int optionListCompare(const void* a, const void* b) { +//cerr << " comparing: " << (*((option_list**)a))->getName() +// << " i=" << (*((option_list**)a))->getIndex() +// << " :to: " +// << (*((option_list**)b))->getName() +// << " i=" << (*((option_list**)b))->getIndex() << std::endl; + return strcmp((*((option_list**)a))->getName(), + (*((option_list**)b))->getName()); +} + + + +// md5sum: 63584ffabc92170fdb9ef5caedb5a3f6 - Options.cpp =css= 20030102 diff --git a/src/midiio/src/Options_private.cpp b/src/midiio/src/Options_private.cpp new file mode 100644 index 0000000..5a875a8 --- /dev/null +++ b/src/midiio/src/Options_private.cpp @@ -0,0 +1,358 @@ +// +// Copyright 1998-1999 by Craig Stuart Sapp, All Rights Reserved. +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Apr 5 13:07:18 PDT 1998 +// Last Modified: Sun Jan 10 05:43:24 PST 1999 +// Filename: ...sig/maint/code/sigBase/Options_private.cpp +// Web Address: http://sig.sapp.org/src/sigBase/Options_private.cpp +// Syntax: C++ +// +// Description: A private set of functions for use in the Options class. +// + +#include "Options_private.h" +#include +#include +#include + + +////////////////////////////// +// +// option_register::option_register -- +// + +option_register::option_register(void) { + definition = NULL; + defaultOption = NULL; + modifiedOption = NULL; + type = 's'; +} + + +option_register::option_register(const char* aDefinition, char aType, + const char* aDefaultOption, const char* aModifiedOption) { + definition = NULL; + defaultOption = NULL; + modifiedOption = NULL; + + setType(aType); + setDefinition(aDefinition); + setDefault(aDefaultOption); + setModified(aModifiedOption); +} + + + +////////////////////////////// +// +// option_register::~option_register -- +// + +option_register::~option_register() { + if (definition != NULL) { + delete [] definition; + } + definition = NULL; + + if (defaultOption != NULL) { + delete [] defaultOption; + } + defaultOption = NULL; + + if (modifiedOption != NULL) { + delete [] modifiedOption; + } + modifiedOption = NULL; +} + + + +////////////////////////////// +// +// option_register::clearModified -- sets the modified string to +// NULL. +// + +void option_register::clearModified(void) { + if (modifiedOption != NULL) { + delete [] modifiedOption; + } + modifiedOption = NULL; +} + + + +////////////////////////////// +// +// option_register::getDefinition -- returns the initial definition +// string used to define this entry. +// + +const char* option_register::getDefinition(void) { + return definition; +} + + + +////////////////////////////// +// +// option_register::getDefault -- returns the default string +// to be returned. Will never return a NULL; +// + +const char* option_register::getDefault(void) { + return defaultOption; +} + + + +////////////////////////////// +// +// option_register::getModified -- return the modified +// option string +// + +const char* option_register::getModified(void) { + return modifiedOption; +} + + + +////////////////////////////// +// +// option_register::getModifiedQ -- returns true if +// modified string is not null, false otherwise. +// + +int option_register::getModifiedQ(void) { + if (modifiedOption == NULL) { + return 0; + } else { + return 1; + } +} + + + +////////////////////////////// +// +// option_register::getType -- +// + +char option_register::getType(void) { + return type; +} + + + +////////////////////////////// +// +// option_register::getOption -- return the modified option +// or the default option if no modified option. +// + +const char* option_register::getOption(void) { + if (getModifiedQ()) { + return getModified(); + } else { + return getDefault(); + } +} + + + +////////////////////////////// +// +// option_register::reset -- deallocate space for all +// strings in object. (but default string is set to "") +// + +void option_register::reset(void) { + if (definition != NULL) { + delete [] definition; + } + definition = NULL; + + if (defaultOption != NULL) { + delete [] defaultOption; + } + defaultOption = NULL; + defaultOption = new char[1]; + defaultOption[0] = '\0'; + + if (modifiedOption != NULL) { + delete [] modifiedOption; + } + modifiedOption = NULL; +} + + + +////////////////////////////// +// +// option_register::setDefault -- +// + +void option_register::setDefault(const char* aString) { + if (aString == NULL) { + std::cout << "Error: default string cannot be null" << std::endl; + exit(1); + } + + if (defaultOption != NULL) { + delete [] defaultOption; + } + if (aString == NULL) { + defaultOption = NULL; + } else { + defaultOption = new char[strlen(aString) + 1]; + strcpy(defaultOption, aString); + } +} + + + +////////////////////////////// +// +// option_register::setDefinition -- +// + +void option_register::setDefinition(const char* aString) { + + if (definition != NULL) { + delete [] definition; + } + if (aString == NULL) { + definition = NULL; + } else { + definition = new char[strlen(aString) + 1]; + strcpy(definition, aString); + } + +} + + + +////////////////////////////// +// +// option_register::setModified -- +// + +void option_register::setModified(const char* aString) { + if (modifiedOption != NULL) { + delete [] modifiedOption; + } + if (aString == NULL) { + modifiedOption = NULL; + } else { + modifiedOption = new char[strlen(aString) + 1]; + strcpy(modifiedOption, aString); + } +} + + + +////////////////////////////// +// +// option_register::setType -- +// + +void option_register::setType(char aType) { + type = aType; +} + + + +///////////////////////////////////////////////////////////////////////////// +/// option_list class definitions /////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +////////////////////////////// +// +// option_list::option_list -- +// + +option_list::option_list(void) { + name = NULL; + index = -1; +} + + + +////////////////////////////// +// +// option_list::option_list -- +// + +option_list::option_list(const char* optionName, int anIndex) { + name = NULL; + setIndex(anIndex); + setName(optionName); +} + + + +////////////////////////////// +// +// option_list::~option_list -- +// + +option_list::~option_list() { + if (name != NULL) { + delete [] name; + } + name = NULL; +} + + + +////////////////////////////// +// +// option_list::getIndex -- +// + +int option_list::getIndex(void) { + return index; +} + + + +////////////////////////////// +// +// option_list::getName -- +// + +const char* option_list::getName(void) { + return name; +} + + + +////////////////////////////// +// +// option_list::setName -- +// + +void option_list::setName(const char* aString) { + if (name != NULL) { + delete [] name; + } + name = new char[strlen(aString) + 1]; + strcpy(name, aString); +} + + + +////////////////////////////// +// +// option_list::setIndex -- +// + +void option_list::setIndex(int anIndex) { + index = anIndex; +} + + + +// md5sum: be3cc8ad0380820a9ea96739dc989657 - Options_private.cpp =css= 20030102 diff --git a/src/midiio/src/Sequencer_alsa.cpp b/src/midiio/src/Sequencer_alsa.cpp new file mode 100644 index 0000000..4c80e22 --- /dev/null +++ b/src/midiio/src/Sequencer_alsa.cpp @@ -0,0 +1,643 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Thu May 11 21:10:02 PDT 2000 +// Last Modified: Sat Oct 13 14:51:43 PDT 2001 (updated for ALSA 0.9 interface) +// Filename: ...sig/maint/code/control/Sequencer_alsa.cpp +// Web Address: http://sig.sapp.org/src/sig/Sequencer_alsa.cpp +// Syntax: C++ +// +// Description: Basic MIDI input/output functionality for the +// Linux ALSA raw midi devices. This class +// is inherited by the classes MidiInPort_alsa and +// MidiOutPort_alsa. +// + +#if defined(LINUX) && defined(ALSA) + +#include "Collection.h" +#include +#include +#include +#include +#include +#include +#include +#include /* for reading filename for MIDI info */ +#include "Sequencer_alsa.h" + +typedef unsigned char uchar; + +// define static variables: +int Sequencer_alsa::class_count = 0; +int Sequencer_alsa::initialized = 0; + +// static variables for MIDI I/O information database +int Sequencer_alsa::indevcount = 0; +int Sequencer_alsa::outdevcount = 0; + +Collection Sequencer_alsa::rawmidi_in; +Collection Sequencer_alsa::rawmidi_out; +Collection Sequencer_alsa::midiincard; +Collection Sequencer_alsa::midioutcard; +Collection Sequencer_alsa::midiindevice; +Collection Sequencer_alsa::midioutdevice; +Collection Sequencer_alsa::midiinname; +Collection Sequencer_alsa::midioutname; + + + +/////////////////////////////// +// +// Sequencer_alsa::Sequencer_alsa -- +// default value: autoOpen = 1; +// + +Sequencer_alsa::Sequencer_alsa(int autoOpen) { + if (class_count < 0) { + std::cerr << "Unusual class instantiation count: " << class_count << std::endl; + exit(1); + } else if (class_count == 0) { + buildInfoDatabase(); + } + + // will not autoOpen + + class_count++; +} + + + +////////////////////////////// +// +// Sequencer_alsa::~Sequencer_alsa -- +// + +Sequencer_alsa::~Sequencer_alsa() { + + if (class_count == 1) { + close(); + removeInfoDatabase(); + } else if (class_count <= 0) { + std::cerr << "Unusual class instantiation count: " << class_count << std::endl; + exit(1); + } + + class_count--; +} + + + +////////////////////////////// +// +// Sequencer_alsa::close -- close the sequencer device. The device +// automatically closes once the program ends. +// + +void Sequencer_alsa::close(void) { + int i; + + for (i=0; i= rawmidi_in.getSize()) { + return; + } + + if (rawmidi_in[index] != NULL) { + snd_rawmidi_close(rawmidi_in[index]); + rawmidi_in[index] = NULL; + } +} + + +void Sequencer_alsa::closeOutput(int index) { + if (index < 0 || index >= rawmidi_out.getSize()) { + return; + } + + if (rawmidi_out[index] != NULL) { + snd_rawmidi_close(rawmidi_out[index]); + rawmidi_out[index] = NULL; + } +} + + + +////////////////////////////// +// +// Sequencer_alsa::displayInputs -- display a list of the +// available MIDI input devices. +// default values: out = std::cout, initial = "\t" +// + +void Sequencer_alsa::displayInputs(std::ostream& out, char* initial) { + for (int i=0; i& cards, + Collection& devices) { + + cards.setSize(0); + devices.setSize(0); + cards.allowGrowth(1); + devices.allowGrowth(1); + + DIR* dir = opendir("/dev/snd"); + if (dir == NULL) { +// std::cout << "Error determining ALSA MIDI info: no directory called /dev/snd" +// << std::endl; +// exit(1); + } + + // read each file in the directory and store information if it is a MIDI dev + else { + int card; + int device; + struct dirent *dinfo; + dinfo = readdir(dir); + int count; + while (dinfo != NULL) { + if (strncmp(dinfo->d_name, "midi", 4) == 0) { + count = sscanf(dinfo->d_name, "midiC%dD%d", &card, &device); + if (count == 2) { + cards.append(card); + devices.append(device); + } + } + dinfo = readdir(dir); + } + + closedir(dir); + cards.allowGrowth(0); + devices.allowGrowth(0); + } +} + + +#endif /* LINUX and ALSA */ + +// md5sum: 8ccf0e750be06aeea90cdc8a7cc4499c - Sequencer_alsa.cpp =css= 20030102 diff --git a/src/midiio/src/Sequencer_alsa05.cpp b/src/midiio/src/Sequencer_alsa05.cpp new file mode 100644 index 0000000..ad4ef2d --- /dev/null +++ b/src/midiio/src/Sequencer_alsa05.cpp @@ -0,0 +1,518 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Thu May 11 21:10:02 PDT 2000 +// Last Modified: Wed Oct 3 22:18:27 PDT 2001 (frozen to ALSA 0.5) +// Filename: ...sig/maint/code/control/Sequencer_alsa05.cpp +// Web Address: http://sig.sapp.org/src/sig/Sequencer_alsa05.cpp +// Syntax: C++ +// +// Description: Basic MIDI input/output functionality for the +// Linux ALSA raw midi devices. This class +// is inherited by the classes MidiInPort_alsa05 and +// MidiOutPort_alsa05. +// + +#if defined(LINUX) && defined(ALSA05) + +#include "Collection.h" +#include +#include +#include +#include +#include +#include +#include +#include "Sequencer_alsa05.h" + +typedef unsigned char uchar; + +// define static variables: +int Sequencer_alsa05::class_count = 0; +int Sequencer_alsa05::initialized = 0; + +// static variables for MIDI I/O information database +int Sequencer_alsa05::indevcount = 0; +int Sequencer_alsa05::outdevcount = 0; + +Collection Sequencer_alsa05::rawmidi_in; +Collection Sequencer_alsa05::rawmidi_out; +Collection Sequencer_alsa05::midiincard; +Collection Sequencer_alsa05::midioutcard; +Collection Sequencer_alsa05::midiindevice; +Collection Sequencer_alsa05::midioutdevice; +Collection Sequencer_alsa05::midiinname; +Collection Sequencer_alsa05::midioutname; + + + +/////////////////////////////// +// +// Sequencer_alsa05::Sequencer_alsa05 -- +// default value: autoOpen = 1; +// + +Sequencer_alsa05::Sequencer_alsa05(int autoOpen) { + if (class_count < 0) { + cerr << "Unusual class instatiation count: " << class_count << endl; + exit(1); + } else if (class_count == 0) { + buildInfoDatabase(); + } + + if (autoOpen) { + open(); + } + + class_count++; +} + + + +////////////////////////////// +// +// Sequencer_alsa05::~Sequencer_alsa05 -- +// + +Sequencer_alsa05::~Sequencer_alsa05() { + + if (class_count == 1) { + close(); + removeInfoDatabase(); + } else if (class_count <= 0) { + cerr << "Unusual class instatiation count: " << class_count << endl; + exit(1); + } + + class_count--; +} + + + +////////////////////////////// +// +// Sequencer_alsa05::close -- close the sequencer device. The device +// automatically closes once the program ends. +// + +void Sequencer_alsa05::close(void) { + int i; + + for (i=0; i +// Creation Date: Sun Jan 3 21:02:02 PST 1999 +// Last Modified: Fri Jan 8 04:50:05 PST 1999 +// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss) +// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_oss.cpp +// Web Address: http://sig.sapp.org/src/sig/Sequencer_oss.cpp +// Syntax: C++ +// +// Description: Basic MIDI input/output functionality for the +// Linux OSS midi device /dev/sequencer. This class +// is inherited by the classes MidiInPort_oss and +// MidiOutPort_oss. +// + +#ifdef LINUX + +#include + + +#include +#include +#include +#include +#include +#include +#include "Sequencer_oss.h" + + +// define static variables: +const char* Sequencer_oss::sequencer = "/dev/sequencer"; +int Sequencer_oss::sequencer_fd = -1; +int Sequencer_oss::class_count = 0; +int Sequencer_oss::initialized = 0; +uchar Sequencer_oss::midi_write_packet[4] = {SEQ_MIDIPUTC, 0, 0, 0}; +uchar Sequencer_oss::midi_read_packet[4]; + + +// static variables for MIDI I/O information database +int Sequencer_oss::indevcount = 0; +int Sequencer_oss::outdevcount = 0; + +int* Sequencer_oss::indevnum = NULL; +int* Sequencer_oss::outdevnum = NULL; + +int* Sequencer_oss::indevtype = NULL; +int* Sequencer_oss::outdevtype = NULL; + +char** Sequencer_oss::indevnames = NULL; +char** Sequencer_oss::outdevnames = NULL; + + + +/////////////////////////////// +// +// Sequencer_oss::Sequencer_oss -- +// default value: autoOpen = 1; +// + +Sequencer_oss::Sequencer_oss(int autoOpen) { + if (autoOpen) { + open(); + } + + if (class_count < 0) { + std::cerr << "Unusual class instatiation count: " << class_count << std::endl; + exit(1); + } else if (class_count == 0) { + buildInfoDatabase(); + } + + class_count++; +} + + + +////////////////////////////// +// +// Sequencer_oss::~Sequencer_oss -- +// + +Sequencer_oss::~Sequencer_oss() { + class_count--; + + if (class_count == 0) { + close(); + removeInfoDatabase(); + } else if (class_count < 0) { + std::cerr << "Unusual class instatiation count: " << class_count << std::endl; + exit(1); + } +} + + + +////////////////////////////// +// +// Sequencer_oss::close -- close the sequencer device. The device +// automatically closes once the program ends, but you can close it +// so that other programs can use it. +// + +void Sequencer_oss::close(void) { + ::close(getFd()); +} + + + +////////////////////////////// +// +// Sequencer_oss::displayInputs -- display a list of the +// available MIDI input devices. +// default values: out = cout, initial = "\t" +// + +void Sequencer_oss::displayInputs(std::ostream& out, char* initial) { + for (int i=0; i= getNumInputs()) { + std::cerr << "Error: " << aDevice << " is greater than max in (" + << getNumInputs() << ")" << std::endl; + exit(1); + } + + return indevnames[aDevice]; +} + + + +////////////////////////////// +// +// Sequencer_oss::getNumInputs -- returns the total number of +// MIDI inputs that can be used. +// + +int Sequencer_oss::getNumInputs(void) { + if (initialized == 0) { + buildInfoDatabase(); + } + return indevcount; +} + + + +////////////////////////////// +// +// Sequencer_oss::getNumOutputs -- returns the total number of +// MIDI inputs that can be used. +// + +int Sequencer_oss::getNumOutputs(void) { + if (initialized == 0) { + buildInfoDatabase(); + } + return outdevcount; +} + + + +////////////////////////////// +// +// Sequencer_oss::getOutputName -- returns a string to the name of +// the specified output device. The string will remain valid as +// long as there are any sequencer devices in existence. +// + +const char* Sequencer_oss::getOutputName(int aDevice) { + if (initialized == 0) { + buildInfoDatabase(); + } + if (aDevice >= getNumOutputs()) { + std::cerr << "Error: " << aDevice << " is greater than max out (" + << getNumOutputs() << ")" << std::endl; + exit(1); + } + + return outdevnames[aDevice]; +} + + + +////////////////////////////// +// +// Sequencer_oss::is_open -- returns true if the +// sequencer device is open, false otherwise. +// + +int Sequencer_oss::is_open(void) { + if (getFd() > 0) { + return 1; + } else { + return 0; + } +} + + + +///////////////////////////// +// +// Sequencer_oss::open -- returns true if the device +// was successfully opended (or already opened) +// + +int Sequencer_oss::open(void) { + if (getFd() <= 0) { + setFd(::open(sequencer, O_RDWR, 0)); + } + + return is_open(); +} + + + +////////////////////////////// +// +// Sequencer_oss::read -- reads MIDI bytes and also stores the +// device from which the byte was read from. Timing is not +// saved from the device. If needed, then it would have to +// be saved in this function, or just return the raw packet +// data (use rawread function). +// + +void Sequencer_oss::read(uchar* buf, uchar* dev, int count) { + int i = 0; + while (i < count) { + ::read(getFd(), midi_read_packet, sizeof(midi_read_packet)); + if (midi_read_packet[1] == SEQ_MIDIPUTC) { + buf[i] = midi_read_packet[1]; + dev[i] = midi_read_packet[2]; + i++; + } + } +} + + + +////////////////////////////// +// +// Sequencer_oss::rawread -- read Input MIDI packets. +// each packet contains 4 bytes. +// + +void Sequencer_oss::rawread(uchar* buf, int packetCount) { + ::read(getFd(), buf, packetCount * 4); +} + + + +////////////////////////////// +// +// Sequencer_oss::rebuildInfoDatabase -- rebuild the internal +// database that keeps track of the MIDI input and output devices. +// + +void Sequencer_oss::rebuildInfoDatabase(void) { + removeInfoDatabase(); + buildInfoDatabase(); +} + + + +/////////////////////////////// +// +// Sequencer_oss::write -- Send a byte out the specified MIDI +// port which can be either an internal or an external synthesizer. +// + +int Sequencer_oss::write(int device, int aByte) { + int status = 0; + + switch (getOutputType(device)) { + case MIDI_EXTERNAL: + midi_write_packet[1] = (uchar) (0xff & aByte); + midi_write_packet[2] = getOutDeviceValue(device); + status = ::write(getFd(), midi_write_packet,sizeof(midi_write_packet)); + break; + case MIDI_INTERNAL: + status = writeInternal(getOutDeviceValue(device), aByte); + break; + } + + if (status > 0) { + return 1; + } else { + return 0; + } + +} + + +int Sequencer_oss::write(int device, uchar* bytes, int count) { + int status = 1; + for (int i=0; i= getNumInputs()) { + std::cerr << "Error: " << aDevice << " is greater than max in (" + << getNumInputs() << ")" << std::endl; + exit(1); + } + + return indevnum[aDevice]; +} + + + +////////////////////////////// +// +// Sequencer_oss::getInputType -- returns 1 = external MIDI, +// 2 = internal MIDI +// + +int Sequencer_oss::getInputType(int aDevice) const { + if (aDevice >= getNumInputs()) { + std::cerr << "Error: " << aDevice << " is greater than max in (" + << getNumInputs() << ")" << std::endl; + exit(1); + } + + return indevtype[aDevice]; +} + + + +////////////////////////////// +// +// Sequencer_oss::getOutDeviceValue -- +// + +int Sequencer_oss::getOutDeviceValue(int aDevice) const { + if (aDevice >= getNumOutputs()) { + std::cerr << "Error: " << aDevice << " is greater than max out (" + << getNumOutputs() << ")" << std::endl; + exit(1); + } + + return outdevnum[aDevice]; +} + + + +////////////////////////////// +// +// Sequencer_oss::getOutputType -- returns 1 = external MIDI, +// 2 = internal MIDI +// + +int Sequencer_oss::getOutputType(int aDevice) const { + if (aDevice >= getNumOutputs()) { + std::cerr << "Error: " << aDevice << " is greater than max out (" + << getNumOutputs() << ")" << std::endl; + exit(1); + } + + return outdevtype[aDevice]; +} + + + +////////////////////////////// +// +// Sequencer_oss::removeInfoDatabase -- +// + +void Sequencer_oss::removeInfoDatabase(void) { + initialized = 0; + + if (indevnum != NULL) delete [] indevnum; + if (outdevnum != NULL) delete [] outdevnum; + if (indevtype != NULL) delete [] indevtype; + if (outdevtype != NULL) delete [] outdevtype; + + int i; + if (indevnames != NULL) { + for (i=0; i 127) { + std::cerr << "Error: expecting MIDI data but got MIDI command: " + << aByte << std::endl; + exit(1); + } + + synth_message_buffer[synth_message_buffer_count++] = aByte; + } + + // check to see if the message is complete: + if (synth_message_bytes_expected == synth_message_buffer_count) { + status = transmitMessageToInternalSynth(); + synth_message_bytes_expected = 0; + synth_message_buffer_count = 0; + } + + return status; +} + + + +////////////////////////////// +// +// Sequencer_oss::transmitMessageToInternalSynth -- send the stored +// MIDI message to the internal synthesizer. +// + +int Sequencer_oss::transmitMessageToInternalSynth(void) { + int status; + switch (synth_message_buffer[0] & 0xf0) { + case 0x80: // Note-off + case 0x90: // Note-on + case 0xA0: // Aftertouch + status = transmitVoiceMessage(); + break; + case 0xB0: // Control change + case 0xC0: // Patch change + case 0xD0: // Channel pressure + case 0xE0: // Pitch wheel + status = transmitCommonMessage(); + break; + case 0xF0: + std::cerr << "Cannot handle 0xf0 commands yet" << std::endl; + exit(1); + break; + default: + std::cerr << "Error: unknown MIDI command" << std::endl; + exit(1); + } + + return status; +} + + + +////////////////////////////// +// +// Sequencer_oss::transmitVoiceMessage -- send a voice-type MIDI +// message to an internal synthesizer. +// + +int Sequencer_oss::transmitVoiceMessage(void) { + synth_write_message[0] = EV_CHN_VOICE; + synth_write_message[1] = synth_message_curr_device; + synth_write_message[2] = synth_message_buffer[0] & 0xf0; + synth_write_message[3] = synth_message_buffer[0] & 0x0f; + synth_write_message[4] = synth_message_buffer[1]; + synth_write_message[5] = synth_message_buffer[2]; + synth_write_message[6] = 0; + synth_write_message[7] = 0; + + int status; + status = ::write(getFd(), synth_write_message, sizeof(synth_write_message)); + + if (status > 0) { + return 1; + } else { + return 0; + } +} + + + +////////////////////////////// +// +// Sequencer_oss::transmitCommonMessage -- send a common-type MIDI +// message to an internal synthesizer. +// + +int Sequencer_oss::transmitCommonMessage(void) { + synth_write_message[0] = EV_CHN_COMMON; + synth_write_message[1] = synth_message_curr_device; + synth_write_message[2] = synth_message_buffer[0] & 0xf0; + synth_write_message[3] = synth_message_buffer[0] & 0x0f; + + switch (synth_write_message[2]) { + case 0xB0: // Control change + synth_write_message[4] = synth_message_buffer[1]; + synth_write_message[5] = 0; + synth_write_message[6] = synth_message_buffer[2]; + synth_write_message[7] = 0; + break; + case 0xC0: // Patch change + case 0xD0: // Channel pressure + synth_write_message[4] = synth_message_buffer[1]; + synth_write_message[5] = 0; + synth_write_message[6] = 0; + synth_write_message[7] = 0; + break; + case 0xE0: // Pitch wheel + synth_write_message[4] = 0; + synth_write_message[5] = 0; + synth_write_message[6] = synth_message_buffer[1]; + synth_write_message[7] = synth_message_buffer[2]; + break; + default: + std::cerr << "Unknown Common MIDI message" << std::endl; + exit(1); + } + + int status; + status = ::write(getFd(), synth_write_message, sizeof(synth_write_message)); + + if (status > 0) { + return 1; + } else { + return 0; + } +} + + + +#endif // LINUX +// md5sum: bc7b96041137b22f3d3c35376b5912c6 - Sequencer_oss.cpp =css= 20030102 diff --git a/src/midiio/src/SigTimer.cpp b/src/midiio/src/SigTimer.cpp new file mode 100644 index 0000000..5786098 --- /dev/null +++ b/src/midiio/src/SigTimer.cpp @@ -0,0 +1,498 @@ +// +// Programmer: Craig Stuart Sapp +// Thanks to: Erik Neuenschwander +// for Windows 95 assembly code for Pentium clock cycles. +// Ozgur Izmirli +// for concept of periodic timer. +// Creation Date: Mon Oct 13 11:34:57 GMT-0800 1997 +// Last Modified: Tue Feb 10 21:05:19 GMT-0800 1998 +// Last Modified: Sat Sep 19 15:56:48 PDT 1998 +// Last Modified: Mon Feb 22 04:44:25 PST 1999 +// Last Modified: Sun Nov 28 12:39:39 PST 1999 (added adjustPeriod()) +// Filename: .../sig/code/control/SigTimer/SigTimer.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/SigTimer.cpp +// Syntax: C++ +// +// Description: This class can only be used on Motorola Pentinum 75 Mhz +// chips or better because the timing information is +// extracted from the clock cycle count from a register +// on the CPU itself. This class will estimate the +// speed of the computer, but it would be better if there +// was a way of finding out the speed from some function. +// This class is used primarily for timing of MIDI input +// and output at a millisecond resolution. +// + + +#include "SigTimer.h" +#include +#include + + +// get Sleep or usleep function definition for measureCpu function: +#ifdef VISUAL + #define WIN32_LEAN_AND_MEAN + #include + #undef WIN32_LEAN_AND_MEAN +#else + #include +#endif + + +// declare static variables +int64bits SigTimer::globalOffset = 0; +int SigTimer::cpuSpeed = 0; // in cycles per second + + + +////////////////////////////// +// +// SigTimer::SigTimer +// + +SigTimer::SigTimer(void) { + if (globalOffset == 0) { // coordinate offset between timers + globalOffset = clockCycles(); + } + if (cpuSpeed <= 0) { // initialize CPU speed value + cpuSpeed = measureCpuSpeed(1); + if (cpuSpeed <= 0) { + cpuSpeed = 100000000; + } + } + + offset = globalOffset; // initialize the start time of timer + ticksPerSecond = 1000; // default of 1000 ticks per second + period = 1000.0; // default period of once per second +} + + +SigTimer::SigTimer(int aSpeed) { + if (globalOffset == 0) { + globalOffset = clockCycles(); + } + cpuSpeed = aSpeed; + + offset = globalOffset; + ticksPerSecond = 1000; + period = 1000.0; // default period of once per second +} + + +SigTimer::SigTimer(SigTimer& aTimer) { + offset = aTimer.offset; + ticksPerSecond = aTimer.ticksPerSecond; + period = aTimer.period; +} + + + +////////////////////////////// +// +// SigTimer::~SigTimer +// + +SigTimer::~SigTimer() { + // do nothing +} + + + +////////////////////////////// +// +// SigTimer::adjustPeriod -- adjust the period of the timer. +// + +void SigTimer::adjustPeriod(double periodDelta) { + offset -= (int64bits)(getCpuSpeed() * getPeriod() * periodDelta / + getTicksPerSecond()); +} + + + +////////////////////////////// +// +// SigTimer::clockCycles -- returns the number of clock cycles since last reboot +// HARDWARE DEPENDENT -- currently for Pentiums only. +// static function. +// + + +int64bits SigTimer::clockCycles() { +#ifndef VISUAL + int64bits output; + + // For Pentiums, you can get the number of clock cycles elapsed + // since the last reboot with the following assembler code: + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (output)); + +#else + int64bits output; + unsigned long high_end, low_end; + __asm { + __asm _emit 0x0f __asm _emit 0x31 + mov high_end, edx + mov low_end, eax + } + output = high_end; + output = output << 32; + output += low_end; +#endif + + return output; +} + + + +////////////////////////////// +// +// SigTimer::expired -- returns the integral number of periods +// That have passed since the last update or reset. +// See getPeriodCount which returns a floating point +// count of the period position. +// + + +int SigTimer::expired(void) const { + return (int)(getTime()/period); +} + + + +////////////////////////////// +// +// SigTimer::getCpuSpeed -- returns the CPU speed of the computer. +// (static function) +// + +int SigTimer::getCpuSpeed(void) { + return cpuSpeed; +} + + + +////////////////////////////// +// +// SigTimer::getPeriod -- returns the timing period of the timer, +// if the timer is being used as a periodic timer. +// + +double SigTimer::getPeriod(void) const { + return period; +} + + + +////////////////////////////// +// +// SigTimer::getPeriodCount -- returns the current period count +// of the timer as a double. Similar in behavior to expired +// function but lists the current fraction of a period. +// + +double SigTimer::getPeriodCount(void) const { + return (double)getTime()/period; +} + + + +////////////////////////////// +// +// SigTimer::getTempo -- returns the current tempo in terms +// of beats (ticks) per minute. +// + +double SigTimer::getTempo(void) const { + return getTicksPerSecond() * 60.0 / getPeriod(); +} + + + +////////////////////////////// +// +// SigTimer::getTicksPerSecond -- return the number of ticks per +// second. +// + +int SigTimer::getTicksPerSecond(void) const { + return ticksPerSecond; +} + + + +////////////////////////////// +// +// SigTimer::getTime -- returns time in milliseconds by default. +// time can be altered to be in some other unit of time +// by using the setTicksPerSecond function. +// (Default is 1000 ticks per second.) +// + +int SigTimer::getTime(void) const { + return (int)((clockCycles()-offset)/getFactor()); +} + + + +////////////////////////////// +// +// SigTimer::getTimeInSeconds +// + +double SigTimer::getTimeInSeconds(void) const { + return ((clockCycles()-offset)/(double)cpuSpeed); +} + + + +////////////////////////////// +// +// SigTimer::getTimeInTicks +// + +int SigTimer::getTimeInTicks(void) const { + return (int)((clockCycles()-offset)/getFactor()); +} + + + +////////////////////////////// +// +// SigTimer::measureCpuSpeed -- returns the number of clock cycles in +// one second. Accuracy to about +/- 5%. +// default value: quantize = 0. +// + +int SigTimer::measureCpuSpeed(int quantize) { + int64bits a, b; + a = clockCycles(); + #ifdef VISUAL + Sleep(1000/4); + #else + usleep(1000000/4); + #endif + b = clockCycles(); + + int output = (int)(4*(b-a-140100-450000)); + + if (quantize) { + // quantize to a known computer CPU speed + if (output < 78000000) { + output = 75000000; + } else if (output < 95000000) { + output = 90000000; + } else if (output < 110000000) { + output = 100000000; + } else if (output < 140000000) { + output = 133000000; + } else if (output < 155000000) { + output = 150000000; + } else if (output < 180000000) { + output = 166000000; + } else if (output < 215000000) { + output = 200000000; + } else if (output < 250000000) { + output = 233000000; + } else if (output < 280000000) { + output = 266000000; + } else if (output < 325000000) { + output = 300000000; + } else if (output < 375000000) { + output = 350000000; + } else if (output < 425000000) { + output = 400000000; + } else { + output = output; + } + } // end if quantize + + return output; +} + + + +////////////////////////////// +// +// SigTimer::reset -- set the timer to 0. +// + +void SigTimer::reset(void) { + offset = clockCycles(); +} + + + +////////////////////////////// +// +// SigTimer::setCpuSpeed -- You can also vary the CPU speed here to cause the +// getTime function to output different units of time, but the +// setTicksPerSecond is a more appropriate place to do such a thing. +// + +void SigTimer::setCpuSpeed(int aSpeed) { + if (aSpeed <= 0) { + std::cerr << "Error: Cannot set the cpu speed to be negative: " + << aSpeed << std::endl; + exit(1); + } + cpuSpeed = aSpeed; +} + + + +////////////////////////////// +// +// SigTimer::setPeriod -- sets the period length of the timer. +// input value cannot be less than 1.0. +// + +void SigTimer::setPeriod(double aPeriod) { + if (aPeriod < 1.0) { + std::cerr << "Error: period too small: " << aPeriod << std::endl; + exit(1); + } + period = aPeriod; +} + + + +////////////////////////////// +// +// SigTimer::setPeriodCount -- adjusts the offset time according +// to the current period to match the specified period count. +// + +void SigTimer::setPeriodCount(double aCount) { + offset = (int64bits)(clockCycles() - aCount * getPeriod() * + getCpuSpeed() / getTicksPerSecond()); +} + + + +////////////////////////////// +// +// SigTimer::setTempo -- sets the period length in terms of +// beats per minute. +// + +void SigTimer::setTempo(double beatsPerMinute) { + if (beatsPerMinute < 1.0) { + std::cerr << "Error: tempo is too slow: " << beatsPerMinute << std::endl; + exit(1); + } + double count = getPeriodCount(); + period = getTicksPerSecond() * 60.0 / beatsPerMinute; + setPeriodCount(count); +} + + + +////////////////////////////// +// +// SigTimer::setTicksPerSecond +// + +void SigTimer::setTicksPerSecond(int aTickRate) { + if (aTickRate <= 0) { + std::cerr << "Error: Cannot set the tick rate to be negative: " + << aTickRate << std::endl; + exit(1); + } + ticksPerSecond = aTickRate; +} + + + +////////////////////////////// +// +// SigTimer::start +// + +void SigTimer::start(void) { + reset(); +} + + + +////////////////////////////// +// +// SigTimer::sync +// + +void SigTimer::sync(SigTimer& aTimer) { + offset = aTimer.offset; +} + + + +////////////////////////////// +// +// SigTimer::update -- set the timer start to the next period. +// + +void SigTimer::update(void) { + if (getTime() >= getPeriod()) { + offset += (int64bits)(getPeriod() * getFactor()); + } +} + + +// update(int) will do nothing if the periodCount is greater than +// than the expired period count + +void SigTimer::update(int periodCount) { + if (periodCount > expired()) { + return; + } else { + offset += (int64bits)(getPeriod() * getFactor() * periodCount); + } +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// protected functions: +// + + +////////////////////////////// +// +// SigTimer::getFactor -- +// + +double SigTimer::getFactor(void) const { + return (double)((double)getCpuSpeed()/(double)getTicksPerSecond()); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Miscellaneous timing functions are located here untill a better +// place can be found: +// + +void millisleep(int milliseconds) { + #ifdef VISUAL + Sleep(milliseconds); + #else + usleep( milliseconds * 1000); + #endif +} + + +void millisleep(float milliseconds) { + #ifdef VISUAL + // cannot convert to microseconds in Visual C++ yet. + // Tell me how and I'll fix the following line + Sleep((unsigned long)milliseconds); + #else + usleep((int)(milliseconds * 1000.0)); + #endif +} + + + + +// md5sum: b35e9e6a8d6fd16636d7fca5d565f284 - SigTimer.cpp =css= 20030102 diff --git a/src/midiio/src/Voice.cpp b/src/midiio/src/Voice.cpp new file mode 100644 index 0000000..ed05bce --- /dev/null +++ b/src/midiio/src/Voice.cpp @@ -0,0 +1,334 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Sun Oct 11 18:39:14 PDT 1998 +// Last Modified: Sun Oct 11 18:39:18 PDT 1998 +// Filename: ...sig/maint/code/control/Voice/Voice.cpp +// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/Voice.cpp +// Syntax: C++ +// +// Description: The Voice class is a MIDI output class which keeps +// track of the last note played in to it. If the last +// note was not turned off when a new note is played, +// then the old note will be turned off before the +// new note is played. +// + +#include "Voice.h" + + +// declare static variables: +SigTimer Voice::timer; + +////////////////////////////// +// +// Voice::Voice +// + +Voice::Voice(int aChannel) { + chan = oldChan = aChannel; + vel = oldVel = key = oldKey = 0; +} + + +Voice::Voice(const Voice& aVoice) { + chan = aVoice.chan; + vel = aVoice.vel; + key = aVoice.key; + oldChan = 0; + oldVel = 0; + oldKey = 0; +} + + +Voice::Voice(void) { + chan = oldChan = key = oldKey = vel = oldVel = 0; +} + + +////////////////////////////// +// +// Voice::~Voice +// + +Voice::~Voice() { + off(); +} + + + +////////////////////////////// +// +// Voice::cont -- use default channel if none specified for +// the continuous controller message. +// + +void Voice::cont(int controller, int data) { + MidiOutput::cont(getChannel(), controller, data); +} + + + +////////////////////////////// +// +// Voice::getChan -- returns the channel of the voice. +// Synonym for getChannel. +// + +int Voice::getChan(void) const { + return chan; +} + + + +////////////////////////////// +// +// Voice::getChannel -- returs the channel of the voice. +// + +int Voice::getChannel(void) const { + return chan; +} + + + +////////////////////////////// +// +// Voice::getKey -- returns the current MIDI key number of the voice. +// Synonym for getKeynum. +// + +int Voice::getKey(void) const { + return key; +} + + + +////////////////////////////// +// +// Voice::getKeynum -- returns the current MIDI key number of the voice. +// + +int Voice::getKeynum(void) const { + return key; +} + + +////////////////////////////// +// +// Voice::getOffTime -- returns the last note off message sent +// out of the voice object +// + +int Voice::getOffTime(void) const { + return offTime; +} + + + +////////////////////////////// +// +// Voice::getOnTime -- returns the last note on message sent +// out of the voice object. +// + +int Voice::getOnTime(void) const { + return onTime; +} + + + +////////////////////////////// +// +// Voice::getVel -- returns the current velocity of the MIDI key. +// Synonym for getVelocity. +// + +int Voice::getVel(void) const { + return vel; +} + + + +////////////////////////////// +// +// Voice::getVelocity -- returns the current velocity of the MIDI key. +// + +int Voice::getVelocity(void) const { + return vel; +} + + + +////////////////////////////// +// +// Voice::off +// + +void Voice::off(void) { + if (status() != 0) { + offTime = timer.getTime(); + MidiOutput::play(oldChan, oldKey, 0); + oldVel = 0; + } +} + + + +////////////////////////////// +// +// Voice::pc -- use default channel if none is specified +// + +void Voice::pc(int aTimbre) { + MidiOutput::pc(getChannel(), aTimbre); +} + + + +////////////////////////////// +// +// Voice::play +// + +void Voice::play(int aChannel, int aKeyno, int aVelocity) { + off(); + MidiOutput::play(aChannel, aKeyno, aVelocity); + oldChan = aChannel; + oldKey = aKeyno; + oldVel = aVelocity; + setChannel(aChannel); + setKeynum(aKeyno); + setVelocity(aVelocity); + + if (aVelocity != 0) { + onTime = timer.getTime(); + } else { + offTime = timer.getTime(); + } +} + + +void Voice::play(int aKeyno, int aVelocity) { + off(); + MidiOutput::play(getChannel(), aKeyno, aVelocity); + oldChan = getChannel(); + oldKey = aKeyno; + oldVel = aVelocity; + setKeynum(aKeyno); + setVelocity(aVelocity); + + if (aVelocity != 0) { + onTime = timer.getTime(); + } else { + offTime = timer.getTime(); + } +} + + +void Voice::play(void) { + off(); + MidiOutput::play(getChannel(), getKey(), getVel()); + oldChan = getChannel(); + oldKey = getKey(); + oldVel = getVel(); + + if (getVel() != 0) { + onTime = timer.getTime(); + } else { + offTime = timer.getTime(); + } +} + + + +////////////////////////////// +// +// Voice::setChan -- set the MIDI channel. Synonym for setChannel. +// + +void Voice::setChan(int aChannel) { + chan = aChannel; +} + + + +////////////////////////////// +// +// Voice::setChannel -- set the MIDI channel of the voice. +// + +void Voice::setChannel(int aChannel) { + chan = aChannel; +} + + + +////////////////////////////// +// +// Voice::setKey -- set the keynumber of the voice +// Synonym for setKeyno. +// + +void Voice::setKey(int aKeynum) { + key = aKeynum; +} + + + +////////////////////////////// +// +// Voice::setKeynum -- set the keynumber of the voice +// + +void Voice::setKeynum(int aKeynum) { + key = aKeynum; +} + + + +////////////////////////////// +// +// Voice::setVel -- set the MIDI velocity of the voice. +// Synonym for setVelocity. +// + +void Voice::setVel(int aVelocity) { + vel = aVelocity; +} + + + +////////////////////////////// +// +// Voice::setVelocity +// + +void Voice::setVelocity(int aVelocity) { + vel = aVelocity; +} + + + +////////////////////////////// +// +// Voice::status -- returns zero if off or positive if on. +// + +int Voice::status(void) const { + return oldVel; +} + + + +////////////////////////////// +// +// Voice::sustain -- uses default channel if none specified. +// + +void Voice::sustain(int aStatus) { + MidiOutput::sustain(getChannel(), aStatus); +} + + +// md5sum: d02ca41ae3b4e07efe7fedc720e52573 - Voice.cpp =css= 20030102 -- cgit v1.2.1