1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-26 15:20:21 +01:00

Fixed MIDI playback on Linux. Still need configure files for libscorealign and portmidi. (I tweaked makefiles by hand to build and test with EXPERIMENTAL_MIDI_OUT and EXPERIMENTAL_SCOREALIGN.) Also, I updated portmidi files, including some bug fixes from the portmidi project.

This commit is contained in:
rbdannenberg
2010-10-01 17:59:18 +00:00
parent 576dfe6653
commit 6fa857c3ae
39 changed files with 375 additions and 5373 deletions

View File

@@ -1,188 +1,129 @@
# MAKEFILE FOR PORTMIDI AND PORTTIME
VFLAGS = -g
# For debugging, define PM_CHECK_ERRORS
PMFLAGS = -DPM_CHECK_ERRORS
# Otherwise do not define PM_CHECK_ERRORS
# PMFLAGS =
# Dynamic Lib is built without PM_CHECK_ERRORS
PMDLFLAGS =
# Path for installation of dynamic libraries
PF = /usr/local
# Architecture for static libs
ARCH = -arch ppc -arch i386
pmlib = pm_mac/libportmidi.a
CC = gcc $(VFLAGS) $(PMFLAGS) $(ARCH) -g -Ipm_common -Iporttime
MACLIB = -framework CoreMIDI -framework CoreFoundation -framework CoreAudio \
-framework CoreServices
PMSRC = pm_mac/pmmac.c pm_common/pmutil.c pm_common/portmidi.c \
pm_mac/pmmacosxcm.c pm_mac/readbinaryplist.c pm_mac/finddefault.c
PTSRC = porttime/porttime.c porttime/ptmacosx_mach.c
pmobjects = pm_common/pmutil.o pm_mac/pmmac.o \
pm_common/portmidi.o pm_mac/pmmacosxcm.o \
pm_mac/finddefault.o pm_mac/readbinaryplist.o \
porttime/porttime.o porttime/ptmacosx_mach.o
current: all
all: $(pmlib) $(ptlib) pm_test/test pm_test/sysex pm_test/midithread \
pm_test/latency pm_test/midithru pm_test/qtest pm_test/mm
echo $$'\n\
**** For instructions: make -f pm_mac\Makefile.osx help ****\n'
help:
echo $$'\n\n\
This is help for portmidi/pm_mac/Makefile.osx\n\n\
Flags for static library and apps are $(PMFLAGS)\n\
Flags for dynamic library are $(PMDLFLAGS)\n\
Installation path for dylib is $(PF)\n\
You might want to change these.\n\n\
To build a static library and test applications,\n \
make -f pm_mac/Makefile.osx\n\
To build and install dynamic library, note you must use\n\
"cleanest" to remove .o and dylib, especially if this\n\
library uses different compiler flags:\n \
make -f pm_mac/Makefile.osx cleanest\n \
make -f pm_mac/Makefile.osx dylib\n\
To install dynamic library to /usr/local,\n \
sudo make -f pm_mac/Makefile.osx install\n\
To install universal dynamic library with xcode,\n \
make -f pm_mac/Makefile.osx install-with-xcode\n\
To make dynamic library for Java,\n \
make -f pm_mac/Makefile.osx cleanest\n \
make -f pm_mac/Makefile.osx jni\n\
To make PmDefaults Java application,\n \
make -f pm_mac/Makefile.osx pmdefaults\n\n'
$(pmlib): pm_mac/Makefile.osx $(pmobjects)
rm -rf $(pmlib)
ar -crs $(pmlib) $(pmobjects)
pm_mac/pmmacosxcm.o: pm_mac/Makefile.osx pm_mac/pmmacosxcm.c pm_mac/pmmacosxcm.h
$(CC) -c pm_mac/pmmacosxcm.c -o pm_mac/pmmacosxcm.o
pm_mac/readbinaryplist.o: pm_mac/Makefile.osx pm_mac/readbinaryplist.c pm_mac/readbinaryplist.h
$(CC) -c -I/Developer/Headers/FlatCarbon \
pm_mac/readbinaryplist.c -o pm_mac/readbinaryplist.o
pm_mac/finddefault.o: pm_mac/Makefile.osx pm_mac/finddefault.c pm_mac/pmmacosxcm.h
$(CC) -c pm_mac/finddefault.c -o pm_mac/finddefault.o
pm_test/test: pm_mac/Makefile.osx pm_test/test.o $(pmlib)
$(CC) pm_test/test.o -o pm_test/test $(pmlib) $(MACLIB)
pm_test/sysex: pm_mac/Makefile.osx pm_test/sysex.o $(pmlib)
$(CC) pm_test/sysex.o -o pm_test/sysex $(pmlib) $(MACLIB)
pm_test/midithread: pm_mac/Makefile.osx pm_test/midithread.o $(pmlib)
$(CC) pm_test/midithread.o -o pm_test/midithread \
$(pmlib) $(MACLIB)
pm_test/latency: pm_mac/Makefile.osx $(pmlib) pm_test/latency.o
$(CC) pm_test/latency.o -o pm_test/latency $(pmlib) \
$(MACLIB) -lpthread -lm
pm_test/midithru: pm_mac/Makefile.osx $(pmlib) pm_test/midithru.o
$(CC) pm_test/midithru.o -o pm_test/midithru $(pmlib) \
$(MACLIB) -lpthread -lm
pm_test/mm: pm_mac/Makefile.osx pm_test/mm.o $(pmlib)
$(CC) pm_test/mm.o -o pm_test/mm $(pmlib) $(MACLIB)
porttime/ptlinux.o: pm_mac/Makefile.osx porttime/ptlinux.c
$(CC) -c porttime/ptlinux.c -o porttime/ptlinux.o
pm_test/qtest: pm_mac/Makefile.osx pm_test/qtest.o $(pmlib)
$(CC) pm_test/qtest.o -o pm_test/qtest $(pmlib) $(MACLIB)
clean:
rm -f *.o *~ core* */*.o */*~ */core* pm_test/*/pm_dll.dll
rm -f *.opt *.ncb *.plg pm_win/Debug/pm_dll.lib pm_win/Release/pm_dll.lib
rm -f pm_test/*.opt pm_test/*.ncb
rm -f pm_java/pmjni/*.o pm_java/pmjni/*~ pm_java/*.h
cleaner: clean
rm -rf pm_mac/build
rm -f *.dylib
rm -f pm_mac/*.dylib
rm -f pm_java/pmjni/*.jnilib
cleanest: cleaner
rm -f $(pmlib) porttime/libporttime.dylib pm_mac/libportmidi.dylib
rm -f pm_test/test pm_test/sysex pm_test/midithread
rm -f pm_test/latency pm_test/midithru pm_test/qtest pm_test/mm
rm -f pm_java/*/*.class
rm -f pm_java/pmjni/jportmidi_JPortMidiApi_PortMidiStream.h
backup: cleanest
cd ..; zip -r portmidi.zip portmidi
dylib: pm_mac/libportmidi.dylib
pm_mac/libportmidi.dylib: $(PMSRC) $(PTSRC)
cc -single_module -g $(PMDLFLAGS) -Iporttime -Ipm_common $(ARCH) \
-dynamiclib $(PMSRC) $(PTSRC) -o pm_mac/libportmidi.dylib \
-flat_namespace -undefined suppress \
-framework CoreMIDI -framework CoreFoundation \
-framework CoreAudio -framework CoreServices
install: porttime/porttime.h pm_common/portmidi.h \
pm_mac/libportmidi.dylib
install porttime/porttime.h $(PF)/include/
install pm_common/portmidi.h $(PF)/include
install pm_mac/libportmidi.dylib $(PF)/lib/
# note - this uses xcode to build and install portmidi universal binaries
install-with-xcode:
sudo xcodebuild -project pm_mac/pm_mac.xcodeproj \
-configuration Deployment install DSTROOT=/
##### build java interface and application ######
jni: pm_java/pmjni/libpmjni.jnilib
pm_java/pmjni/libpmjni.jnilib: $(PMSRC) pm_java/jportmidi/JPortMidiApi.class pm_java/pmjni/jportmidi_JPortMidiApi.h pm_java/pmjni/pmjni.c
cc -single_module -g -Iporttime -Ipm_common \
-Ipm_java/pmjni -I/System/Library/Frameworks/JavaVM.framework/Headers \
-I/Developer/Headers/FlatCarbon \
$(ARCH) -dynamiclib $(PMSRC) $(PTSRC) pm_java/pmjni/pmjni.c \
-o pm_java/pmjni/libpmjni.jnilib \
-flat_namespace -undefined suppress \
-framework CoreMIDI -framework CoreFoundation -framework CoreAudio \
-framework JavaVM
pm_java/pmjni/jportmidi_JPortMidiApi.h: pm_java/jportmidi/JPortMidiApi.class
cd pm_java; javah jportmidi.JPortMidiApi
mv pm_java/jportmidi_JportMidiApi.h pm_java/pmjni
JAVASRC = pmdefaults/PmDefaultsFrame.java \
pmdefaults/PmDefaults.java \
jportmidi/JPortMidiApi.java jportmidi/JPortMidi.java \
jportmidi/JPortMidiException.java
# this compiles ALL of the java code
pm_java/jportmidi/JPortMidiApi.class: $(JAVASRC:%=pm_java/%)
cd pm_java; javac $(JAVASRC)
pmdefaults: pm_java/pmjni/libpmjni.jnilib pm_java/jportmidi/JPortMidiApi.class
echo "pmdefaults java application is made"
###### test plist reader #######
PLHDR = pm_mac/readbinaryplist.h
PLSRC = pm_mac/plisttest.c pm_mac/readbinaryplist.c
pm_mac/plisttest: $(PLHDR) $(PLSRC)
cc -g -Ipm_mac \
-I/Developer/Headers/FlatCarbon \
-I/System/Library/Frameworks/CoreFoundation.framework/Headers \
-I/System/Library/Frameworks/CoreServices.framework/Headers \
$(PLSRC) -o pm_mac/plisttest \
-framework CoreFoundation -framework CoreServices
# MAKEFILE FOR PORTMIDI
# Roger B. Dannenberg
# Sep 2009
# NOTE: you can use
# make -f pm_osx/Makefile.osx configuration=Release
# to override the default Debug configuration
configuration=Release
PF=/usr/local
# For debugging, define PM_CHECK_ERRORS
ifeq ($(configuration),Release)
CONFIG = Release
else
CONFIG = Debug
endif
current: all
all: $(CONFIG)/CMakeCache.txt
cd $(CONFIG); make
$(CONFIG)/CMakeCache.txt:
rm -f CMakeCache.txt
mkdir -p $(CONFIG)
cd $(CONFIG); cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=$(CONFIG)
**** For instructions: make -f pm_mac\Makefile.osx help ****\n'
help:
echo $$'\n\n\
This is help for portmidi/pm_mac/Makefile.osx\n\n\
Installation path for dylib is $(PF)\n\
To build Release version libraries and test applications,\n \
make -f pm_mac/Makefile.osx\n\
To build Debug version libraries and test applications,\n \
make -f pm_mac/Makefile.osx configuration=Debug\n\
To install universal dynamic library,\n \
sudo make -f pm_mac/Makefile.osx install\n\
To install universal dynamic library with xcode,\n \
make -f pm_mac/Makefile.osx install-with-xcode\n\
To make PmDefaults Java application,\n \
make -f pm_mac/Makefile.osx pmdefaults\n\n \
configuration = $(configuration)\n'
clean:
rm -f *.o *~ core* */*.o */*/*.o */*~ */core* pm_test/*/pm_dll.dll
rm -f *.opt *.ncb *.plg pm_win/Debug/pm_dll.lib pm_win/Release/pm_dll.lib
rm -f pm_test/*.opt pm_test/*.ncb
rm -f pm_java/pmjni/*.o pm_java/pmjni/*~ pm_java/*.h
rm -rf Release/CMakeFiles Debug/CMakeFiles
rm -rf pm_mac/pmdefaults/lib pm_mac/pmdefaults/src
cleaner: clean
rm -rf pm_mac/build
rm -rf pm_mac/Debug pm_mac/Release pm_test/Debug pm_test/Release
rm -f Debug/*.dylib Release/*.dylib
rm -f pm_java/pmjni/Debug/*.jnilib
rm -f pm_java/pmjni/Release/*.jnilib
cleanest: cleaner
rm -f Debug/libportmidi_s.a Release/libportmidi_s.a
rm -f pm_test/Debug/test pm_test/Debug/sysex pm_test/Debug/midithread
rm -f pm_test/Debug/latency pm_test/Debug/midithru
rm -f pm_test/Debug/qtest pm_test/Debug/mm
rm -f pm_test/Release/test pm_test/Release/sysex pm_test/Release/midithread
rm -f pm_test/Release/latency pm_test/Release/midithru
rm -f pm_test/Release/qtest pm_test/Release/mm
rm -f pm_java/*/*.class
rm -f pm_java/pmjni/jportmidi_JPortMidiApi_PortMidiStream.h
backup: cleanest
cd ..; zip -r portmidi.zip portmidi
install: porttime/porttime.h pm_common/portmidi.h \
$(CONFIG)/libportmidi.dylib
install porttime/porttime.h $(PF)/include/
install pm_common/portmidi.h $(PF)/include
install $(CONFIG)/libportmidi.dylib $(PF)/lib/
# note - this uses xcode to build and install portmidi universal binaries
install-with-xcode:
sudo xcodebuild -project pm_mac/pm_mac.xcodeproj \
-configuration Release install DSTROOT=/
##### build pmdefault ######
pm_java/pmjni/jportmidi_JPortMidiApi.h: pm_java/jportmidi/JPortMidiApi.class
cd pm_java; javah jportmidi.JPortMidiApi
mv pm_java/jportmidi_JportMidiApi.h pm_java/pmjni
JAVASRC = pmdefaults/PmDefaultsFrame.java \
pmdefaults/PmDefaults.java \
jportmidi/JPortMidiApi.java jportmidi/JPortMidi.java \
jportmidi/JPortMidiException.java
# this compiles ALL of the java code
pm_java/jportmidi/JPortMidiApi.class: $(JAVASRC:%=pm_java/%)
cd pm_java; javac $(JAVASRC)
$(CONFIG)/libpmjni.dylib:
mkdir -p $(CONFIG)
cd $(CONFIG); make -f ../pm_mac/$(MAKEFILE)
pmdefaults: $(CONFIG)/libpmjni.dylib pm_java/jportmidi/JPortMidiApi.class
ifeq ($(CONFIG),Debug)
echo "Error: you cannot build pmdefaults in a Debug configuration \n\
You should use configuration=Release in the Makefile command line. "
@exit 2
endif
xcodebuild -project pm_mac/pm_mac.xcodeproj \
-configuration Release -target PmDefaults
echo "pmdefaults java application is made"
###### test plist reader #######
PLHDR = pm_mac/readbinaryplist.h
PLSRC = pm_mac/plisttest.c pm_mac/readbinaryplist.c
pm_mac/plisttest: $(PLHDR) $(PLSRC)
cc $(VFLAGS) -Ipm_mac \
-I/Developer/Headers/FlatCarbon \
-I/System/Library/Frameworks/CoreFoundation.framework/Headers \
-I/System/Library/Frameworks/CoreServices.framework/Headers \
$(PLSRC) -o pm_mac/$(CONFIG)/plisttest \
-framework CoreFoundation -framework CoreServices

View File

@@ -1,18 +1,30 @@
README_MAC.txt for PortMidi
Roger Dannenberg
20 nov 2009
revised 20 Sep 2010 for Xcode 3.2.4 and CMake 8.2-2
To build PortMidi for Mac OS X, you must install Xcode, and
if you want to build from the command line, you should install
To build PortMidi for Mac OS X, you must install Xcode and
CMake.
CMake can build either Makefiles or Xcode projects, or you
can use the pre-built Xcode project. These approaches are
described in separate sections below.
CMake can build either command-line Makefiles or Xcode projects.
These approaches are described in separate sections below.
==== CLEANING UP ====
You can remove previously built apps, object code, and libraries by
running "cd pm_mac; sh cleanslate.sh"
(Skip this for now, but later you might want start from a clean
slate.)
Start in the portmedia/portmidi directory.
make -f pm_mac/Makefile.osx clean
will remove .o, CMakeFiles, and other intermediate files.
Using "cleaner" instead of "clean" will also remove jni-related
intermediate files.
Using "cleanest" instead of "clean" or "cleaner" will also remove
application binaries and the portmidi libraries. (It will not
uninstall anything, however.)
==== USING CMAKE (AND COMMAND LINE TOOLS) ====
@@ -50,19 +62,41 @@ You should now make the pmdefaults.app:
make -f pm_mac/Makefile.osx pmdefaults
NOTES: xcode is likely to crash after building pmdefaults, but
pmdefaults should be OK (it will be in Release)
Once you get started, you can run make directly in the
Debug or Release directories
NOTE: pmdefaults.app will be in pm_mac/Release/.
Please copy pmdefaults.app to your Applications folder or wherever
you would normally expect to find it.
==== USING XCODE ====
==== USING CMAKE TO BUILD Xcode PROJECT ====
(1) Open portmidi/portmidi.xcodeproj with Xcode and
Before you can use Xcode, you need a portmidi.xcodeproj file.
CMake builds a location-dependent Xcode project, so unfortunately
it is not easy to provide an Xcode project that is ready to use.
Therefore, you should make your own. Once you have it, you can
use it almost like any other Xcode project, and you will not have
to go back to CMake.
(1) Install CMake if you do not have it already.
(2) Open portmedia/portmidi/CMakeLists.txt with CMake
(3) Use Configure and Generate buttons
(4) This creates portmedia/portmidi/portmidi.xcodeproj.
Note: You will also use pm_mac/pm_mac.xcodeproj, which
is not generated by CMake.
(5) Open portmidi/portmidi.xcodeproj with Xcode and
build what you need. The simplest thing is to build the
ALL_BUILD target. The default will be to build the Debug
version, but you may want to change this to Release.
NOTE: ALL_BUILD may report errors. Try simply building again
or rebuilding specific targets that fail until they build
without errors. There appears to be a race condition or
missing dependencies in the build system.
The Debug version is compiled with PM_CHECK_ERRORS, and the
Release version is not. PM_CHECK_ERRORS will print an error
message and exit your program if any error is returned from
@@ -78,24 +112,25 @@ want to build a Java application using PortMidi. Since I have
not figured out how to use CMake to make an OS X Java application,
use pm_mac/pm_mac.xcodeproj as follows:
(2) open pm_mac/pm_mac.xcodeproj
(6) open pm_mac/pm_mac.xcodeproj
(3) pm_java/pmjni/portmidi_JportmidiApi.h is needed
(7) pm_java/pmjni/portmidi_JportmidiApi.h is needed
by libpmjni.jnilib, the Java native interface library. Since
portmidi_JportmidiApi.h is included with PortMidi, you can skip
to step 4, but if you really want to rebuild everything from
scratch, build the JPortMidiHeaders project.
to step 8, but if you really want to rebuild everything from
scratch, build the JPortMidiHeaders project first, and continue
with step 8:
(4) If you did not build libpmjni.dylib using portmidi.xcodeproj,
(8) If you did not build libpmjni.dylib using portmidi.xcodeproj,
do it now. (It depends on portmidi_JportmidiApi.h, and the
PmDefaults project depends on libpmjni.dylib.)
(5) Returning to pm_mac.xcodeproj, build the PmDefaults program.
(9) Returning to pm_mac.xcodeproj, build the PmDefaults program.
(6) If you wish, copy pm_mac/build/Deployment/PmDefaults.app to
(10) If you wish, copy pm_mac/build/Deployment/PmDefaults.app to
your applications folder.
(7) If you want to install libportmidi.dylib, first make it with
(11) If you want to install libportmidi.dylib, first make it with
Xcode, then
sudo make -f pm_mac/Makefile.osx install
This command will install /usr/local/include/{porttime.h, portmidi.h}
@@ -104,36 +139,11 @@ Note that the "install" function of xcode creates portmidi/Release
and does not install the library to /usr/local/lib, so please use
the command line installer.
==== USING CMAKE TO BUILD Xcode PROJECT ====
(1) Install CMake if you do not have it already.
(2) Open portmedia/portmidi/CMakeLists.txt with CMake
(3) Use Configure and Generate buttons
(4) This creates portmedia/portmidi/portmidi.xcodeproj.
(5) Follow the directions above using Xcode to compile
PortMidi.
Notes:
(1) You will also use pm_mac/pm_mac.xcodeproj, which
is not generated by CMake.
(2) The portmidi.xcodeproj created by CMake will have absolute
paths and depend on CMake, so it will not be very portable to other
machines or even directories. You can cd to pm_mac and run
clean_up_project.sh to convert pm_mac.xcodeproj to use relative
paths and to remove the scripts that run CMake. You'll first have
to modify pm_mac/clean_up_project.awk to contain the particular
absolute path or your portmidi project. Also, this is a pretty simple
and probably fragile hack to make a stand-alone xcode project. I
don't recommend it. Instead, either use CMake all the time, or use
the portmidi.xcodeproj you get with the distribution.
CHANGELOG
20-Sep-2010 Roger B. Dannenberg
Adapted to Xcode 3.2.4
20-Nov-2009 Roger B. Dannenberg
Added some install instructions
26-Sep-2009 Roger B. Dannenberg

View File

@@ -5,7 +5,7 @@
* and subsequent work by Andrew Zeldis and Zico Kolter
* and Roger B. Dannenberg
*
* $Id: pmmacosxcm.c,v 1.1 2009-06-24 20:37:25 gswillia Exp $
* $Id: pmmacosx.c,v 1.17 2002/01/27 02:40:40 jon Exp $
*/
/* Notes:
@@ -38,17 +38,34 @@
#include <CoreServices/CoreServices.h>
#include <CoreMIDI/MIDIServices.h>
#include <CoreAudio/HostTime.h>
#include <unistd.h>
#define PACKET_BUFFER_SIZE 1024
/* maximum overall data rate (OS X limit is 15000 bytes/second) */
#define MAX_BYTES_PER_S 14000
/* this is very strange: if I put in a reasonable
number here, e.g. 128, which would allow sysex data
to be sent 128 bytes at a time, then I lose sysex
data in my loopback test. With a buffer size of 4,
we put at most 4 bytes in a packet (but maybe many
packets in a packetList), and everything works fine.
/* Apple reports that packets are dropped when the MIDI bytes/sec
exceeds 15000. This is computed by "tracking the number of MIDI
bytes scheduled into 1-second buckets over the last six seconds
and averaging these counts."
This is apparently based on timestamps, not on real time, so
we have to avoid constructing packets that schedule high speed
output even if the actual writes are delayed (which was my first
solution).
The LIMIT_RATE symbol, if defined, enables code to modify
timestamps as follows:
After each packet is formed, the next allowable timestamp is
computed as this_packet_time + this_packet_len * delay_per_byte
This is the minimum timestamp allowed in the next packet.
Note that this distorts accurate timestamps somewhat.
*/
#define SYSEX_BUFFER_SIZE 4
#define LIMIT_RATE 1
#define SYSEX_BUFFER_SIZE 128
#define VERBOSE_ON 1
#define VERBOSE if (VERBOSE_ON)
@@ -75,7 +92,7 @@ extern pm_fns_node pm_macosx_out_dictionary;
typedef struct midi_macosxcm_struct {
PmTimestamp sync_time; /* when did we last determine delta? */
UInt64 delta; /* difference between stream time and real time in ns */
UInt64 last_time; /* last output time */
UInt64 last_time; /* last output time in host units*/
int first_message; /* tells midi_write to sychronize timestamps */
int sysex_mode; /* middle of sending sysex */
uint32_t sysex_word; /* accumulate data when receiving sysex */
@@ -90,6 +107,11 @@ typedef struct midi_macosxcm_struct {
/* allow for running status (is running status possible here? -rbd): -cpr */
unsigned char last_command;
int32_t last_msg_length;
/* limit midi data rate (a CoreMidi requirement): */
UInt64 min_next_time; /* when can the next send take place? */
int byte_count; /* how many bytes in the next packet list? */
Float64 us_per_host_tick; /* host clock frequency, units of min_next_time */
UInt64 host_ticks_per_byte; /* host clock units per byte at maximum rate */
} midi_macosxcm_node, *midi_macosxcm_type;
/* private function declarations */
@@ -405,7 +427,11 @@ midi_out_open(PmInternal *midi, void *driverInfo)
m->packet = NULL;
m->last_command = 0;
m->last_msg_length = 0;
m->min_next_time = 0;
m->byte_count = 0;
m->us_per_host_tick = 1000000.0 / AudioGetHostClockFrequency();
m->host_ticks_per_byte = (UInt64) (1000000.0 /
(m->us_per_host_tick * MAX_BYTES_PER_S));
return pmNoError;
}
@@ -451,8 +477,17 @@ midi_write_flush(PmInternal *midi, PmTimestamp timestamp)
assert(endpoint);
if (m->packet != NULL) {
/* out of space, send the buffer and start refilling it */
/* before we can send, maybe delay to limit data rate. OS X allows
* 15KB/s. */
UInt64 now = AudioGetCurrentHostTime();
if (now < m->min_next_time) {
usleep((useconds_t)
((m->min_next_time - now) * m->us_per_host_tick));
}
macHostError = MIDISend(portOut, endpoint, m->packetList);
m->packet = NULL; /* indicate no data in packetList now */
m->min_next_time = now + m->byte_count * m->host_ticks_per_byte;
m->byte_count = 0;
if (macHostError != noErr) goto send_packet_error;
}
return pmNoError;
@@ -475,9 +510,11 @@ send_packet(PmInternal *midi, Byte *message, unsigned int messageLength,
midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor;
assert(m);
/* printf("add %d to packet %p len %d\n", message[0], m->packet, messageLength); */
m->packet = MIDIPacketListAdd(m->packetList, sizeof(m->packetBuffer),
m->packet, timestamp, messageLength,
message);
m->byte_count += messageLength;
if (m->packet == NULL) {
/* out of space, send the buffer and start refilling it */
/* make midi->packet non-null to fool midi_write_flush into sending */
@@ -522,9 +559,6 @@ midi_write_short(PmInternal *midi, PmEvent *event)
/* if latency == 0, midi->now is not valid. We will just set it to zero */
if (midi->latency == 0) when = 0;
when_ns = ((UInt64) (when + midi->latency) * (UInt64) 1000000) + m->delta;
/* make sure we don't go backward in time */
if (when_ns < m->last_time) when_ns = m->last_time;
m->last_time = when_ns;
timestamp = (MIDITimeStamp) AudioConvertNanosToHostTime(when_ns);
message[0] = Pm_MessageStatus(what);
@@ -532,6 +566,15 @@ midi_write_short(PmInternal *midi, PmEvent *event)
message[2] = Pm_MessageData2(what);
messageLength = midi_length(what);
/* make sure we go foreward in time */
if (timestamp < m->min_next_time) timestamp = m->min_next_time;
#ifdef LIMIT_RATE
if (timestamp < m->last_time)
timestamp = m->last_time;
m->last_time = timestamp + messageLength * m->host_ticks_per_byte;
#endif
/* Add this message to the packet list */
return send_packet(midi, message, messageLength, timestamp);
}
@@ -569,8 +612,16 @@ midi_end_sysex(PmInternal *midi, PmTimestamp when)
midi_macosxcm_type m = (midi_macosxcm_type) midi->descriptor;
assert(m);
/* make sure we don't go backward in time */
if (m->sysex_timestamp < m->last_time) m->sysex_timestamp = m->last_time;
/* make sure we go foreward in time */
if (m->sysex_timestamp < m->min_next_time)
m->sysex_timestamp = m->min_next_time;
#ifdef LIMIT_RATE
if (m->sysex_timestamp < m->last_time)
m->sysex_timestamp = m->last_time;
m->last_time = m->sysex_timestamp + m->sysex_byte_count *
m->host_ticks_per_byte;
#endif
/* now send what's in the buffer */
err = send_packet(midi, m->sysex_buffer, m->sysex_byte_count,